1 //
  2 // The Antville Project
  3 // http://code.google.com/p/antville
  4 //
  5 // Copyright 2001-2007 by The Antville People
  6 //
  7 // Licensed under the Apache License, Version 2.0 (the ``License'');
  8 // you may not use this file except in compliance with the License.
  9 // You may obtain a copy of the License at
 10 //
 11 //    http://www.apache.org/licenses/LICENSE-2.0
 12 //
 13 // Unless required by applicable law or agreed to in writing, software
 14 // distributed under the License is distributed on an ``AS IS'' BASIS,
 15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 16 // See the License for the specific language governing permissions and
 17 // limitations under the License.
 18 //
 19 // $Revision$
 20 // $LastChangedBy$
 21 // $LastChangedDate$
 22 // $URL$
 23 //
 24 
 25 /**
 26  * @fileOverview Defines the Sql prototype, a utility for relational queries
 27  */
 28 
 29 /**
 30  * @constructor
 31  */
 32 var Sql = function() {
 33    var db = getDBConnection("antville");
 34    var query;
 35 
 36    var SqlData = function(result) {
 37       var columns = [];
 38       this.values = {};
 39       
 40       for (var i=1; i<=result.getColumnCount(); i+=1) {
 41          columns.push(result.getColumnName(i));
 42       }
 43    
 44       this.update = function() {
 45          for each (var key in columns) {
 46             this.values[key] = result.getColumnItem(key);
 47          }
 48          return;
 49       }
 50       
 51       return this;
 52    }
 53 
 54    var quote = function(str) {
 55       if (str === null) {
 56          return str;
 57       }
 58       return "'" + str.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
 59    }
 60 
 61    var value = function(obj) {
 62       if (obj === null) {
 63          return obj;
 64       }
 65       if (obj === undefined) {
 66          obj = String(obj);
 67       }
 68       switch (obj.constructor) {
 69          case Number:
 70          return obj;
 71          case String:
 72          return quote(obj);
 73          case Date:
 74          return "from_unixtime(" + (obj.getTime() / 1000) + ")";
 75          case HopObject:
 76          case Object:
 77          return quote(obj.toSource());
 78       }
 79       return quote(String(obj));
 80    }
 81 
 82    var resolve = function(args) {
 83       var sql = args[0];
 84       if (args.length > 1) {
 85          var values = Array.prototype.splice.call(args, 1);
 86          if (typeof values[0] === "object") {
 87             values = values[0];
 88          }
 89          sql = sql.replace(/\$(\w*)/g, function() {
 90             return value(values[arguments[1]]);
 91          });
 92       }
 93       return sql;
 94    }
 95    
 96    /**
 97     * 
 98     * @param {String} sql
 99     * @returns {Object}
100     */
101    this.execute = function(sql) {
102       sql = resolve(arguments);
103       var error;
104       var result = db.executeCommand(sql);
105       if (error = db.getLastError()) {
106          app.log(error);
107       }
108       return result;
109    }
110    
111    /**
112     * @returns {String}
113     */
114    this.retrieve = function() {
115       return query = resolve(arguments);
116    }
117    
118    /**
119     * 
120     * @param {Function} callback
121     */
122    this.traverse = function(callback) {
123       var rows = db.executeRetrieval(query);
124       if (rows && rows.next()) {
125          do {
126             var sql = new SqlData(rows);
127             sql.update();
128             callback.call(sql.values, rows);
129          } while (record = rows.next());
130          rows.release();
131       }
132       return;
133    }
134    
135    /**
136     * @return {String}
137     */
138    this.toString = function() {
139       return query;
140    }
141    
142    return this;
143 }
144