      1 var comb = require("comb"),
      2         Promise = comb.Promise,
      3         PromiseList = comb.PromiseList,
      4         hitch = comb.hitch;
      5
      6 var escape = function(val, includeTicks) {
      7     if (val === undefined || val === null) {
      8         return 'NULL';
      9     }
     10     switch (typeof val) {
     11         case 'boolean': return (val) ? 'true' : 'false';
     12         case 'number': return val + '';
     13     }
     14
     15     if (typeof val === 'object') {
     16         val = val.toString();
     17     }
     18
     19     val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
     20         switch (s) {
     21             case "\0": return "\\0";
     22             case "\n": return "\\n";
     23             case "\r": return "\\r";
     24             case "\b": return "\\b";
     25             case "\t": return "\\t";
     26             case "\x1a": return "\\Z";
     27             default: return "\\" + s;
     28         }
     29     });
     30     return  includeTicks ? "'" + val + "'" : val;
     31 };
     32
     33 var format = function(sql, params) {
     34     sql = sql.replace(/\?/g, function() {
     35         if (params.length == 0) {
     36             throw new Error('too few parameters given');
     37         }
     38         return escape(params.shift(), true);
     39     });
     40     return sql;
     41 };
     42
     43 var sqlKeys = ["select", "update", "delete", "count", "set", "from", "where", "group", "having", "order", "limit", "offset"];
     44 var getSQLSection = function(key, sql) {
     45     var index = sqlKeys.indexOf(key);
     46     if (index != -1) {
     47         if ((sqlIndex = sql.search(key)) != -1) {
     48             var newKeys = sqlKeys.slice(index + 1), l = newKeys.length;
     49             for (var j = 0; j < l; j++) {
     50                 var newKey = newKeys[j];
     51                 if ((nextIndex = sql.search(newKey)) != -1) {
     52                     return sql.substr(sqlIndex, nextIndex - sqlIndex);
     53                 }
     54             }
     55             return sql.substr(sqlIndex, sql.length - sqlIndex);
     56         }
     57     } else {
     58         throw new Error("sql section does not exists");
     59     }
     60     return null;
     61 };
     62
     63 var splitSQL = function(sql) {
     64     var ret = {sql : sql};
     65     sqlKeys.forEach(function(key, i) {
     66         ret[key] = getSQLSection(key, sql);
     67     });
     68     return ret;
     69 };
     70
     71 var createSQLFromSplit = function(object) {
     72     var sql = "", keys = sqlKeys;
     73     if (object.update) {
     74         keys = keys.slice(1);
     75     } else if (object["delete"]) {
     76         keys = keys.slice(2);
     77     }
     78     keys.forEach(function(key, i) {
     79         if (object[key] != null) {
     80             if (i > 0 && sql.charAt(sql.length - 1) != ' ') {
     81                 sql += " ";
     82             }
     83             sql += object[key];
     84         }
     85     });
     86     return sql;
     87 };
     88
     89 /**
     90  * @class Base class for all SQL database query types.
     91  * This class is an abstract class for all SQL adapter implementations.
     92  *
     93  * An instance of SQL provides methods for querying, updating and removing a datase
     94  * @name SQL
     95  * @property {String} sql the current sql query string.
     96  */
     97 module.exports = exports = comb.define(null, {
     98     instance : {
     99         /**@lends SQL.prototype*/
    100
    101         sqlObject : null,
    102
    103         _needLogic : false,
    104
    105         table : null,
    106
    107         db : null,
    108
    109         constructor: function(table, db) {
    110             this.sqlObject = {
    111                 "select" : null,
    112                 "update" : null,
    113                 "delete" : null,
    114                 "count" : null,
    115                 "set" : null,
    116                 "from" : null,
    117                 "where" : null,
    118                 "group" : null,
    119                 "having" : null,
    120                 "order" : null,
    121                 "limit" : null,
    122                 "offset" : null
    123             };
    124             this._needLogic = false;
    125             this.table = table;
    126             this.db = db;
    127         },
    128
    129         /**
    130          * Clear the current query.
    131          */
    132         clear : function() {
    133             this.sqlObject = {
    134                 "select" : null,
    135                 "update" : null,
    136                 "delete" : null,
    137                 "count" : null,
    138                 "set" : null,
    139                 "from" : null,
    140                 "where" : null,
    141                 "group" : null,
    142                 "having" : null,
    143                 "order" : null,
    144                 "limit" : null,
    145                 "offset" : null
    146             };
    147         },
    148
    149         /**
    150          * Formats and escapes query string.
    151          *
    152          * @function
    153          * @param {String} sql the sql to format
    154          * @param {Array} array of values to place in the query.
    155          *
    156          * @return {String} the formatted string.
    157          */
    158         format : format,
    159
    160         _from : function(sql) {
    161             var sqlObject = this.sqlObject;
    162             if (!sqlObject.from) {
    163                 sqlObject.from = "from " + this.table;
    164             }
    165             return this;
    166         },
    167
    168         _parseObjectAndCreateSQL : function(options) {
    169             if (options) {
    170                 /*if (typeof options == "string") {
    171                  var args = Array.prototype.slice.call(arguments);
    172                  if (args.length > 1) {
    173                  var sql = args.shift;
    174                  this.sql += this.format(sql, args);
    175                  } else {
    176                  //assume it is raw sql
    177                  this.sql += options;
    178                  }
    179                  } else */
    180                 if (typeof options == "object") {
    181                     var params = [], count = 0;
    182                     for (var i in options) {
    183                         if (count) {
    184                             var opts = {};
    185                             opts[i] = options[i];
    186                             this.and(opts);
    187                         } else {
    188                             this._createSQLFromObject(i, options[i]);
    189                         }
    190                         count++;
    191                     }
    192                 } else {
    193                     throw new Error("Options must be of type string or object");
    194                 }
    195             }
    196         },
    197
    198         _createSQLFromObject : function(key, val) {
    199             var params = [], count = 0, opts;
    200             if (val instanceof Array) {
    201                 //assume its an in
    202                 opts = {};
    203                 opts[key] = val;
    204                 this["in"](opts);
    205             } else if (typeof val === "object") {
    206                 for (var j in val) {
    207                     if (j in this) {
    208                         opts = {};
    209                         opts[key] = val[j];
    210                         this[j](opts);
    211                     } else {
    212                         throw new Error("Operation " + j + " is not supported");
    213                     }
    214                 }
    215             } else {
    216                 //assume its equals
    217                 opts = {};
    218                 opts[key] = val;
    219                 this.eq(opts);
    220
    221             }
    222             return this;
    223         },
    224
    225         /**
    226          * Set the where clause of the query.
    227          * This is different fron find in that it can be used with updates, and deletions.
    228          *
    229          * @example
    230          * QUERYING
    231          *
    232          * var sql = new SQL("test", db);
    233          *
    234          * //select * from test where id = 1
    235          * sql.where({id : 1});
    236          * //select * from test where id in (1,2,3,4,5)
    237          * sql.where({id : [1,2,3,4,5]});
    238          * //select * from test where x != 0
    239          * sql.where({x : {neq : 0}});
    240          * //select distinct * from test where id = 1
    241          * sql.where({id : 1}).distinct();
    242          * //select * from test where a >= 'b' limit 1
    243          * sql.where({a : {gte : "b"}}).limit(1);
    244          * //select * from test where flag is unknown
    245          * sql.where({flag : {is : "unknown"}});
    246          * //select * from test where flag is not unknown
    247          * sql.where({flag : {isNot : "unknown"}});
    248          * //select * from test where flag is false and flag is not unknown and anotherFlag is null and yetAnotherFlag is not null
    249          * sql.where({flag : {is : false}, flag2 : {isNot : "unknown"}, anotherFlag : {isNull : true}, yetAnotherFlag : {isNotNull : true}});
    250          * //select * from test where firstName like 'bob' and lastName not like 'henry'
    251          * sql.where({firstName : {like : 'bob'}, lastName : {notLike : "henry"}});
    252          * //select * from test where firstName like 'bob' and lastName not like 'henry'
    253          * sql.where({firstName : {like : 'bob'}, lastName : {notLike : "henry"}});
    254          *
    255          * @example
    256          * UPDATES
    257          *
    258          * //update test set x=1 where x >= 1 and x <= 5
    259          * sql.update({x : 1}).where({x : {between : [1,5]}});
    260          *
    261          * @example
    262          * DELETIONS
    263          *
    264          * //delete from test where x >= 1 and x <= 5
    265          * sql.remove().where({x : {between : [1,5]}});
    266          *
    267          * @param {Object} options See {@link SQL#find}
    268          *
    269          * @return {SQL} this to allow chaining of query elements.
    270          */
    271         where : function(options) {
    272             throw new Error("Not Implemented!");
    273         },
    274
    275         /**
    276          * Use to return particular columns from a query, i.e. select clause in sql.
    277          *
    278          * @example
    279          * var sql = new SQL("test", db);
    280          *
    281          * //select a, b, c from testTable;
    282          * sql.select(["a", "b", "c"]);
    283          * //select a from testTable;
    284          * sql.select("a");
    285          * //select a from test where x = 1 and y >=1 and y <= 10
    286          * sql.select("a", {x : 1, y : {between : [1,10]}});
    287          *
    288          * @param {String|Array} columns the columns to select
    289          * @param {Object} options query {@link SQL#find}
    290          *
    291          * @return {SQL} this to allow chaining of query elements.
    292          */
    293         select : function(values, options) {
    294             throw new Error("Not Implemented!");
    295         },
    296
    297         /**
    298          * Select on dinstict results, same is distinct clause in SQL statment.
    299          *
    300          * @example
    301          * //select distinct * from test where id = 1
    302          * sql.find({id : 1}).distinct();
    303          * //select distinct test.* from test inner join test2 on test.id=test2.id where test2.other = 1
    304          * sql.join("test2", {id : "id"}).where({"test2.other" : 1}).select("test.*").distinct();
    305          *
    306          * @return {SQL} this to allow chaining of query elements.
    307          */
    308         distinct : function() {
    309             throw new Error("Not Implemented!");
    310         },
    311
    312         /**
    313          * Signify this SQL instance as an update statement.
    314          *
    315          * <p><b>Cannot be used in combination with remove, or find queries.</b></p>
    316          *
    317          * @example
    318          * //update test set x=1
    319          * sql.update({x : 1});
    320          * //update test set x=1 where x >= 1 and x <= 5
    321          * sql.update({x : 1}, {x : {between : [1,5]}});
    322          * //update test set x=1 where x >= 1 and x <= 5
    323          * sql.update({x : 1}).where({x : {between : [1,5]}});
    324          * //update test set x=1 where x >= 1 and x <= 5
    325          * sql.update({x : 1}).find({x : {between : [1,5]}});
    326          * //update test inner join test2 on test.flag=test2.false set x=1
    327          * sql.update({x : 1}).join("test2", {flag : false});
    328          * @param {Object} values key value pairs of columns, and values to update.
    329          * @param {Object} [query] optional query to allow limiting of rows to update {@link SQL#where}
    330          *
    331          * @return {SQL} this to allow chaining of query elements.
    332          */
    333         update : function(values, options) {
    334             throw new Error("Not Implemented!");
    335         },
    336
    337         /**
    338          *  Signify this SQL instance as a delete statement
    339          *
    340          *  <p><b>Cannot be used in combination with update, or find queries.</b></p>
    341          *
    342          * @example
    343          * //delete from test
    344          * sql.remove();
    345          * //delete from test where x >= 1 and x <= 5
    346          * sql.remove(null, {x : {between : [1,5]}});
    347          * //delete from test where x >= 1 and x <= 5
    348          * sql.remove().where({x : {between : [1,5]}});
    349          * //delete from test where x >= 1 and x <= 5
    350          * sql.remove().find({x : {between : [1,5]}});
    351          * //delete test from test inner join test2 on test.flag=test2.false
    352          * sql.remove().join("test2", {flag : false});
    353          * //delete test, test2 from test inner join test2 on test.flag=test2.false
    354          * sql.remove("test2").join("test2", {flag : false});
    355          *
    356          * @param {String|Array} [tables=null] Should only be used to specify the removal of items from multiple tables.
    357          * @param {Object} [query] Use to limit the rows deleted {@link SQL#where}
    358          *
    359          * @return {SQL} this to allow chaining of query elements.
    360          */
    361         remove : function(values, options) {
    362             throw new Error("Not Implemented!");
    363         },
    364
    365         /**
    366          * This is a wrapper to enable using an object to query a dataset.
    367          * The hash can contain the name of any querying function as a key,
    368          * and the value to look for as the value. When using find it signifies
    369          * this SQL instance as a query.
    370          *
    371          *  <p><b>Cannot be used in combination with update, or remove queries.</b></p>
    372          *
    373          * @example
    374          *  {nameOfColumn : {queryOp : value}};
    375          * @example
    376          *  var sql = new SQL("test", db);
    377          *
    378          * //select * from test
    379          * sql.find();
    380          * //select * from test where id = 1;
    381          * sql.find({id : 1});
    382          * //select * from test where x != 0
    383          * sql.find({x : {neq : 0}});
    384          * //select * from test where id in (1,2,3,4,5)
    385          * sql.find({id : [1,2,3,4,5]});
    386          *  //select distinct * from test where id = 1
    387          * sql.find({id : 1}).distinct();
    388          * //select * from test where a >= 'b' limit 1
    389          * sql.find({a : {gte : "b"}}).limit(1);
    390          * //select * from test where flag is unknown
    391          * sql.find({flag : {is : "unknown"}});
    392          * //select * from test where flag is not unknown
    393          * sql.find({flag : {isNot : "unknown"}});
    394          * //select * from test where flag is false and flag is not unknown and anotherFlag is null and yetAnotherFlag is not null
    395          * sql.find({flag : {is : false}, flag2 : {isNot : "unknown"}, anotherFlag : {isNull : true}, yetAnotherFlag : {isNotNull : true}});
    396          * //select * from test where firstName like 'bob' and lastName not like 'henry'
    397          * sql.find({firstName : {like : 'bob'}, lastName : {notLike : "henry"}});
    398          * //select * from test where firstName like 'bob' and lastName not like 'henry'
    399          * sql.find({firstName : {like : 'bob'}, lastName : {notLike : "henry"}});
    400          *
    401          * @param {Object} [query] query to limit result set.
    402          *
    403          * @return {SQL} this to allow chaining of query elements.
    404          */
    405         find : function(options) {
    406             throw new Error("Not Implemented!");
    407         },
    408
    409         /**
    410          * To be used with queries to specify an order of the result set.
    411          *
    412          * @example
    413          * //select * from test order by x
    414          * sql.order("x");
    415          * //select * from test order by x desc
    416          * sql.order({x : "desc"});
    417          * //select * from test order by x, y
    418          * sql.order(["x", "y"]);
    419          * //select * from test order by x, y desc
    420          * sql.order(["x", {y : "desc"}]);
    421          * //select * from test order by x desc, y desc
    422          * sql.order([{x : "desc"},{y : "desc"}]);
    423          * //select * from test order by x, y, z desc
    424          * sql.order("x").order("y").order({z : "desc"});
    425          *
    426          * @param {String|Array|Object} options see example for uses of each.
    427          *
    428          * @return {SQL} this to allow chaining of query elements.
    429          */
    430         order : function(options) {
    431             throw new Error("Not Implemented!");
    432         },
    433
    434         /**
    435          * {@link SQL#order}
    436          * @param options
    437          *
    438          * @return {SQL} this to allow chaining of query elements.
    439          */
    440         orderBy : function(options) {
    441             return this.order(options);
    442         },
    443
    444         /**
    445          * Clears the order clause
    446          *
    447          * @return {SQL} this to allow chaining of query elements.
    448          */
    449         clearOrder : function() {
    450             var sqlObject = this.sqlObject;
    451             delete sqlObject.order;
    452             return this;
    453         },
    454
    455         /**
    456          * Use to limit the number of results returned.
    457          *
    458          * @example
    459          * //select * from test limit 1
    460          * sql.limit(1);
    461          * //select * from test limit 1 offset 10
    462          * sql.limit(1, 10);
    463          * //select * from test where a >= 'b' limit 1
    464          * sql.find({a : {gte : "b"}}).limit(1);
    465          *
    466          * @param {Number} limit the limit to specify on the query
    467          * @param {Number} [offset] {@link SQL#offset}
    468          *
    469          * @return {SQL} this to allow chaining of query elements.
    470          */
    471         limit : function(limit, offset) {
    472             throw new Error("Not Implemented!");
    473         },
    474
    475         /**
    476          * Clear the limit clause on this SQL query
    477          *
    478          * @return {SQL} this to allow chaining of query elements.
    479          */
    480         clearLimit : function() {
    481             var sqlObject = this.sqlObject;
    482             delete sqlObject.limit;
    483             return this;
    484         },
    485
    486         /**
    487          * Specify an offset, offset says to skip that many rows
    488          * before beginning to return rows to the client. If both
    489          * offset and limit are used, then offset rows are skipped
    490          * before starting to count the limit rows that are returned
    491          *
    492          * @example
    493          * //select * from test where a >= 'b' offset 10
    494          * sql.find({a : {gte : "b"}}).offset(10);
    495          * @param {Number} offset the number to offset the result set by.
    496          *
    497          * @return {SQL} this to allow chaining of query elements.
    498          */
    499         offset : function(offset) {
    500             throw new Error("Not Implemented!");
    501         },
    502
    503         /**
    504          * Removes the offset clause from a query.
    505          *
    506          * @return {SQL} this to allow chaining of query elements.
    507          */
    508         clearOffset : function() {
    509             var sqlObject = this.sqlObject;
    510             delete sqlObject.offset;
    511             return this;
    512         },
    513
    514         /**
    515          * Perform a group operation.
    516          *
    517          * @example
    518          * //select * from test group by name
    519          * sql.group("name");
    520          * //select * from test group by name, age
    521          * sql.group(["name", "age"]);
    522          * //select * from test group by name having name = 'bob'
    523          * sql.group("name", {name : "bob"});
    524          * //select * from test group by name, age having age >= 10 and age <= 20
    525          * sql.group(["name", "age"], {age : {between : [10, 20]}});
    526          *
    527          * @param {String|Array} key specify the columns to group on.
    528          * @param {Object} having specify a having clause {@link SQL#having}.
    529          *
    530          * @return {SQL} this to allow chaining of query elements.
    531          */
    532         group : function(key, options) {
    533             throw new Error("Not Implemented!");
    534         },
    535
    536         /**
    537          * Add a having clause, this is only valid on queries that contain a group clause.
    538          *
    539          * Once a having clause has been added all query operations will be added to the having clause.
    540          *
    541          * @example
    542          * //select * from test group by name, age having age >= 10 and age <= 20
    543          * sql.group(["name", "age"]).having({age : {between : [10, 20]}});
    544          * //select * from test group by name, age having age >= 10 and age <= 20
    545          * sql.group(["name", "age"]).having().find({age : {between : [10, 20]}});
    546          * //select * from test group by name, age having age is null
    547          * sql.group(["name", "age"]).having().isNull("age");
    548          *
    549          * @param {Object} [options] the query use on the having clause, same syntax as {@link SQL#find}, {@link SQL#where};
    550          *
    551          * @return {SQL} this to allow chaining of query elements.
    552          */
    553         having : function(options) {
    554             throw new Error("Not Implemented!");
    555         },
    556
    557         /**
    558          * Clear the having clause from the query.
    559          *
    560          * @return {SQL} this to allow chaining of query elements.
    561          */
    562         clearHaving : function() {
    563             var sqlObject = this.sqlObject;
    564             delete sqlObject.having;
    565             return this;
    566         },
    567
    568         /**
    569          * Add a logic group to a query. The query that is passed in will be wrapped in parens.
    570          *
    571          * @example
    572          * //select * from test where (flag is not null and x = 1) or (x = 2)
    573          * sql.logicGroup({flag : {isNot : null}, x : 1}).or().logicGroup({x : 2});
    574          *
    575          * @param {Object} query query to group as one logical group;
    576          *
    577          * @return {SQL} this to allow chaining of query elements.
    578          */
    579         logicGroup : function(options) {
    580             throw new Error("Not Implemented!");
    581         },
    582
    583         /**
    584          * Specify an is clause.
    585          *
    586          * @example
    587          * //select * from test where flag is true
    588          * sql.is({flag : true});
    589          * //select * from test where flag is false
    590          * sql.is({flag : false});
    591          * //select * from test where flag is null
    592          * sql.is({flag : null});
    593          * //select * from test where flag is unknown
    594          * sql.is({flag : "unknown"});
    595          * //select * from test where flag is true and otherFlag is false and anotherFlag is unknown and yetAnotherFlag is null
    596          * sql.is({flag : true, otherFlag : false, anotherFlag : "unknown", yetAnotherFlag : null});
    597          * //select * from test where flag is unknown
    598          * sql.find({flag : {is : "unknown"}});
    599          * //select * from test where flag is false and flag is not unknown and anotherFlag is null and yetAnotherFlag is not null
    600          * sql.is({flag : false}).isNot({flag : "unknown"}).isNull("anotherFlag").isNotNull("yetAnotherFlag
    601          * //select * from test where flag is not null and flag is true or flag is false
    602          * sql.isNotNull("flag").is({flag : true}).or({flag : {is : false}});
    603          *
    604          * @param {Object} options key value pairs to add is clauses for.
    605          *
    606          * @return {SQL} this to allow chaining of query elements.
    607          */
    608         is: function(options) {
    609             throw new Error("Not Implemented")
    610         },
    611
    612         /**
    613          * Add is not clause
    614          *
    615          * @example
    616          *
    617          * //select * from test where flag is not true
    618          * sql.isNot({flag : true});
    619          * //select * from test where flag is not false
    620          * sql.isNot({flag : false});
    621          *  //select * from test where flag is not null
    622          * sql.isNot({flag : null});
    623          * //select * from test where flag is not unknown
    624          * sql.isNot({flag : "unknown"});
    625          * //select * from test where flag is not true and otherFlag is not false and anotherFlag is not unknown and yetAnotherFlag is not null
    626          * sql.isNot({flag : true, otherFlag : false, anotherFlag : "unknown", yetAnotherFlag : null});
    627          * //select * from test where flag is not unknown
    628          * sql.find({flag : {isNot : "unknown"}});
    629          * //select * from test where flag is false and flag is not unknown and anotherFlag is null and yetAnotherFlag is not null
    630          * sql.is({flag : false}).isNot({flag : "unknown"}).isNull("anotherFlag").isNotNull("yetAnotherFlag");
    631          * sql.find({flag : {is : false}, flag2 : {isNot : "unknown"}, anotherFlag : {isNull : true}, yetAnotherFlag : {isNotNull : true}});
    632          * //select * from test where flag is not null and flag is true or flag is false
    633          * sql.isNotNull("flag").is({flag : true}).or({flag : {is : false}});
    634          *
    635          * @param {Object} options key value pairs to add is not clauses for.
    636          *
    637          * @return {SQL} this to allow chaining of query elements.
    638          */
    639         isNot: function(options) {
    640             throw new Error("Not Implemented")
    641         },
    642
    643         /**
    644          * Add is null check
    645          *
    646          * @example
    647          *  //select * from test where flag is null
    648          * sql.isNull("flag");
    649          * //select * from test where flag is false and flag is not unknown and anotherFlag is null and yetAnotherFlag is not null
    650          * sql.is({flag : false}).isNot({flag : "unknown"}).isNull("anotherFlag").isNotNull("yetAnotherFlag
    651          * //select * from test where flag is not null and flag is true or flag is false
    652          * sql.isNotNull("flag").is({flag : true}).or({flag : {is : false}});
    653          *
    654          * @param {String} options column to check is not null.
    655          *
    656          * @return {SQL} this to allow chaining of query elements.
    657          */
    658         isNull: function(options) {
    659             throw new Error("Not Implemented")
    660         },
    661
    662         /**
    663          * Check if a column is not null.
    664          *
    665          * @example
    666          * //select * from test where flag is not null
    667          * sql.isNotNull("flag");
    668          * //select * from test where flag is false and flag is not unknown and anotherFlag is null and yetAnotherFlag is not null
    669          * sql.is({flag : false}).isNot({flag : "unknown"}).isNull("anotherFlag").isNotNull("yetAnotherFlag
    670          * //select * from test where flag is not null and flag is true or flag is false
    671          * sql.isNotNull("flag").is({flag : true}).or({flag : {is : false}});
    672          *
    673          * @param {String} options name of column to check.
    674          *
    675          * @return {SQL} this to allow chaining of query elements.
    676          */
    677         isNotNull: function(options) {
    678             throw new Error("Not Implemented")
    679         },
    680
    681         /**
    682          * Add and operator, one does not need to call this but it is provided for clarity.
    683          *
    684          * @example
    685          * //select * from test where x <= 1 and y >= 1
    686          * sql.lte({x : 1}).gte({y : 1});
    687          * sql.lte({x : 1}).and({y : { gte : 1}});
    688          * sql.lte({x : 1}).and().gte({y : 1});
    689          *
    690          * @param {Object} [options] query to append after the and.
    691          *
    692          * @return {SQL} this to allow chaining of query elements.
    693          */
    694         and: function(options) {
    695             throw new Error("Not Implemented")
    696         },
    697
    698         /**
    699          * Use to add an or clause
    700          * @example
    701          * //select * from test where x <= 1 and y >= 1
    702          *  sql.lte({x : 1}).or({y : {gte : 1}});
    703          *  sql.lte({x : 1}).or().gte({y : 1});
    704          * @param {Object} query added after the or clause
    705          */
    706         or: function(options) {
    707             throw new Error("Not Implemented")
    708         },
    709
    710         /**
    711          * Use to find rows that are greater than a particular value
    712          *
    713          * @example
    714          * //select * from test where x > 0
    715          *sql.gt({x : 0});
    716          *sql.find({x : {gt : 0}});
    717          * @param {Object} options keys values to add greater than checks for.
    718          *
    719          * @return {SQL} this to allow chaining of query elements.
    720          */
    721         gt: function(options) {
    722             throw new Error("Not Implemented")
    723         },
    724
    725         /**
    726          * Add a check for a value greater than or equal to a particular value.
    727          *
    728          * @example
    729          * //select * from test where x >= 0
    730          * sql.gte({x : 0});
    731          * sql.find({x : {gte : 0}});
    732          *
    733          * @param {Object} options key values to add greater than or equal to checks.
    734          *
    735          * @return {SQL} this to allow chaining of query elements.
    736          */
    737         gte: function(options) {
    738             throw new Error("Not Implemented")
    739         },
    740
    741         /**
    742          * Add a check for a value less than a particular value.
    743          *
    744          * @example
    745          * //select * from test where x < 1
    746          * sql.lt({x : 1});
    747          * sql.find({x : {lt : 1}});
    748          * @param {Object} options key values to add less than checks.
    749          *
    750          * @return {SQL} this to allow chaining of query elements.
    751          */
    752         lt: function(options) {
    753             throw new Error("Not Implemented")
    754         },
    755
    756         /**
    757          * Add a check for a value less than or equal to a particular value.
    758          *
    759          * @example
    760          * //select * from test where x <= 1
    761          * sql.lte({x : 1});
    762          * sql.find({x : {lte : 1}});
    763          * @param {Object} options key values to add less than or equal to checks.
    764          *
    765          * @return {SQL} this to allow chaining of query elements.
    766          */
    767         lte: function(options) {
    768             throw new Error("Not Implemented")
    769         },
    770
    771         /**
    772          * Use to find rows that equal a particular value
    773          *
    774          * @example
    775          * //select * from test where x = 0");
    776          * sql.eq({x : 0});
    777          * sql.find({x : 0});
    778          * @param {Object} options object with key\<column\> and value\<value it should equal\>
    779          *
    780          *  @return {SQL} this to allow chaining of query elements.
    781          */
    782         eq: function(options) {
    783             throw new Error("Not Implemented")
    784         },
    785
    786         /**
    787          * Use to find rows that have a column that do not equal a particular value.
    788          *
    789          * @example
    790          * //select * from test where x != 0;
    791          * sql.neq({x : 0});
    792          * sql.find({x : {neq : 0}});
    793          *
    794          * @param {Object} options key value pairs to find columns no equal to a value
    795          *
    796          * @return {SQL} this to allow chaining of query elements.
    797          */
    798         neq: function(options) {
    799             throw new Error("Not Implemented")
    800         },
    801
    802         /**
    803          * This is an alias for an inner join.
    804          *
    805          * @example
    806          *
    807          * //select * from test inner join test2 on test.id=test2.id
    808          *  sql.join("test2", {id : "id"});
    809          * //select * from test inner join test2 using (id, name)
    810          *  sql.join("test2", ["id", "name"]);
    811          *  //select * from test inner join test2 on test.id=test2.id left join test3 using (name)
    812          * sql.join("test2", {id : "id"}).leftJoin("test3", ["name"]);
    813          * //select * from test inner join test2 using (id, name) natural join test3
    814          * sql.join("test2", ["id", "name"]).naturalJoin("test3
    815          * //select * from test inner join test2 on test.id=test2.id left join test3 using (name) where x = 2 or x = 3
    816          * sql.join("test2", {id : "id"}).leftJoin("test3", ["name"]).eq({x : 2}).or({x : 3});
    817          *
    818          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    819          * @param {Array|Object} options When an array is passed in the a using clause is used
    820          *          to specify the columns to join on, of an object is passed in then it is the same as using an on clause;
    821          *
    822          * @return {SQL} this to allow chaining of query elements.
    823          */
    824         join : function(table, options) {
    825             throw new Error("Not Implemented!");
    826         },
    827
    828         /**
    829          * Add an inner join to another table
    830          *
    831          * @example
    832          * //select * from test inner join test2 on test.id=test2.id
    833          * sql.innerJoin("test2", {id : "id"});
    834          * //select * from test inner join test2 using (id, name)
    835          * sql.innerJoin("test2", ["id", "name"]);
    836          *
    837          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    838          * @param {Array|Object} options When an array is passed in the a using clause is used
    839          *          to specify the columns to join on, of an object is passed in then it is the same as using an on clause;
    840          *
    841          * @return {SQL} this to allow chaining of query elements.
    842          */
    843         innerJoin: function(tableName, options) {
    844             throw new Error("Not Implemented")
    845         },
    846
    847         /**
    848          * Add a full outer join to another table
    849          *
    850          * @example
    851          * //select * from test full outer join test2 on test.id=test2.id
    852          * sql.fullOuterJoin("test2", {id : "id"});
    853          * //select * from test full outer join test2 using (id, name)
    854          * sql.fullOuterJoin("test2", ["id", "name"]);
    855          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    856          * @param {Array|Object} options When an array is passed in the a using clause is used
    857          *          to specify the columns to join on, of an object is passed in then it is the same as using an on clause;
    858          *
    859          * @return {SQL} this to allow chaining of query elements.
    860          */
    861         fullOuterJoin: function(tableName, options) {
    862             throw new Error("Not Implemented")
    863         },
    864
    865         /**
    866          * Add a right outer join to another table
    867          *
    868          * @example
    869          * sql.rightOuterJoin("test2", {id : "id"});
    870          * //select * from test right outer join test2 on test.id=test2.id
    871          * sql.rightOuterJoin("test2", ["id", "name"]);
    872          * //select * from test right outer join test2 using (id, name);
    873          *
    874          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    875          * @param {Array|Object} options When an array is passed in the a using clause is used
    876          *          to specify the columns to join on, of an object is passed in then it is the same as using an on clause;
    877          *
    878          * @return {SQL} this to allow chaining of query elements.
    879          */
    880         rightOuterJoin: function(tableName, options) {
    881             throw new Error("Not Implemented")
    882         },
    883
    884         /**
    885          * Add a left outer join to another table
    886          *
    887          * @example
    888          * //select * from test left outer join test2 on test.id=test2.id
    889          * sql.leftOuterJoin("test2", {id : "id"});
    890          * //select * from test left outer join test2 using (id, name)
    891          * sql.leftOuterJoin("test2", ["id", "name"]);
    892          *
    893          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    894          * @param {Array|Object} options When an array is passed in the a using clause is used
    895          *          to specify the columns to join on, of an object is passed in then it is the same as using an on clause;
    896          *
    897          * @return {SQL} this to allow chaining of query elements.
    898          */
    899         leftOuterJoin: function(tableName, options) {
    900             throw new Error("Not Implemented")
    901         },
    902
    903         /**
    904          * Add a full join to another table
    905          *
    906          * @example
    907          * //select * from test full join test2 on test.id=test2.id
    908          * sql.fullJoin("test2", {id : "id"});
    909          * //select * from test full join test2 using (id, name)
    910          * sql.fullJoin("test2", ["id", "name"]);
    911          *
    912          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    913          * @param {Array|Object} options When an array is passed in the a using clause is used
    914          *          to specify the columns to join on, of an object is passed in then it is the same as using an on clause;
    915          *
    916          * @return {SQL} this to allow chaining of query elements.
    917          */
    918         fullJoin: function(tableName, options) {
    919             throw new Error("Not Implemented")
    920         },
    921
    922         /**
    923          * Add a right join to another table
    924          *
    925          * @example
    926          * //select * from test right join test2 on test.id=test2.id
    927          * sql.rightJoin("test2", {id : "id"});
    928          * //select * from test right join test2 using (id, name)
    929          * sql.rightJoin("test2", ["id", "name"]);
    930          *
    931          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    932          * @param {Array|Object} options When an array is passed in the a using clause is used
    933          *          to specify the columns to join on, of an object is passed in then it is the same as using an on clause;
    934          *
    935          * @return {SQL} this to allow chaining of query elements.
    936          */
    937         rightJoin: function(tableName, options) {
    938             throw new Error("Not Implemented")
    939         },
    940
    941         /**
    942          * Add a left join to another table
    943          *
    944          * @example
    945          * //select * from test left join test2 on test.id=test2.id
    946          * sql.leftJoin("test2", {id : "id"});
    947          * //select * from test left join test2 using (id, name)
    948          * sql.leftJoin("test2", ["id", "name"]);
    949          *
    950          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    951          * @param {Array|Object} options When an array is passed in the a using clause is used
    952          *          to specify the columns to join on, of an object is passed in then it is the same as using an on clause;
    953          *
    954          * @return {SQL} this to allow chaining of query elements.
    955          */
    956         leftJoin: function(tableName, options) {
    957             throw new Error("Not Implemented")
    958         },
    959
    960         /**
    961          * Add a natural join to another table
    962          *
    963          * @example
    964          * //select * from test natural full join test2
    965          * sql.naturalFullJoin("test2");
    966          *
    967          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    968          *
    969          * @return {SQL} this to allow chaining of query elements.
    970          */
    971         naturalJoin: function(tableName) {
    972             throw new Error("Not Implemented")
    973         },
    974
    975         /**
    976          * Add a natural left join to another table
    977          *
    978          * @example
    979          * //select * from test natural left join test2
    980          * sql.naturalLeftJoin("test2");
    981          * //select * from test natural join test2
    982          * sql.naturalJoin("test2");
    983          *
    984          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    985          *
    986          * @return {SQL} this to allow chaining of query elements.
    987          */
    988         naturalLeftJoin: function(tableName) {
    989             throw new Error("Not Implemented")
    990         },
    991
    992         /**
    993          * Add a natural right join to another table
    994          *
    995          * @example
    996          * //select * from test natural right join test2
    997          * sql.naturalRightJoin("test2");
    998          *
    999          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    1000          *
    1001          * @return {SQL} this to allow chaining of query elements.
    1002          */
    1003         naturalRightJoin: function(tableName) {
    1004             throw new Error("Not Implemented")
    1005         },
    1006         naturalFullJoin: function(tableName) {
    1007             throw new Error("Not Implemented")
    1008         },
    1009
    1010         /**
    1011          * Add a cross join to another table
    1012          *
    1013          * @example
    1014          * //select * from test cross join test2
    1015          * sql.crossJoin("test2");
    1016          *
    1017          * @param {String|SQL} table the table or SQL clause that specifies the joining table.
    1018          *
    1019          * @return {SQL} this to allow chaining of query elements.
    1020          */
    1021         crossJoin: function(tableName) {
    1022             throw new Error("Not Implemented")
    1023         },
    1024
    1025         /**
    1026          * Add an in clause
    1027          *
    1028          * @example
    1029          * //select * from test where id in (1,2,3,4,5)
    1030          * sql.in({id : [1,2,3,4,5]});
    1031          * sql.find({id : [1,2,3,4,5]});
    1032          * //select * from test where id in (1,2,3,4,5) and id2 in (6,7,8,9,10)
    1033          * sql.find({id : [1,2,3,4,5], id2 : [6,7,8,9,10]});
    1034          * //select * from test where id in (1,2,3,4,5) and id2 not in (6,7,8,9,10)
    1035          * sql.in({id : [1,2,3,4,5]}).notIn({id2 : [6,7,8,9,10]});
    1036          * //select * from test where id in (1,2,3,4,5) and id2 in (6,7,8,9,10)
    1037          * sql.in({id : [1,2,3,4,5], id2 : [6,7,8,9,10]});
    1038          * //select * from test where id in (select id2 from test2 where name >= 'A' and name <= 'B')
    1039          * sql.in({id : new Mysql("test2", db).select("id2").between({name : ["A", "B"]})});
    1040          *
    1041          * @param {Object} options key value pairs where the key is coulmn name and the value is an array of values.
    1042          *
    1043          * @return {SQL} this to allow chaining of query elements.
    1044          */
    1045         "in": function(options) {
    1046             throw new Error("Not Implemented")
    1047         },
    1048
    1049         /**
    1050          * Add a not in clause
    1051          *
    1052          * @example
    1053          * //select * from test where id not in (1,2,3,4,5)
    1054          * sql.notIn({id : [1,2,3,4,5]});
    1055          * sql.find({id : {notIn : [1,2,3,4,5]}});
    1056          * //select * from test where id not in (1,2,3,4,5) and id2 in (6,7,8,9,10)
    1057          * sql.notIn({id : [1,2,3,4,5]}).in({id2 : [6,7,8,9,10]});
    1058          * //select * from test where id not in (1,2,3,4,5) and id2 not in (6,7,8,9,10)
    1059          * sql.notIn({id : [1,2,3,4,5], id2 : [6,7,8,9,10]});
    1060          * //select * from test where id not in (select id2 from test2 where name >= 'A' and name <= 'B')
    1061          * sql.notIn({id : new Mysql("test2", db).select("id2").between({name : ["A", "B"]})});
    1062          * @param {Object} options options key value pairs where the key is coulmn name and the value is an array of values.
    1063          *
    1064          * @return {SQL} this to allow chaining of query elements.
    1065          */
    1066         notIn: function(options) {
    1067             throw new Error("Not Implemented")
    1068         },
    1069
    1070         /**
    1071          * Add a between check for a column.
    1072          *
    1073          * @example
    1074          * //select * from test where x >= 1 and x <= 5
    1075          * sql.between({x : [1,5]});
    1076          * //select * from test where x >= 'a' and x <= 'b'
    1077          * sql.find({x : {between : ["a","b"]}});
    1078          *
    1079          * @param options options key value pairs where the
    1080          * key is coulmn name and the value is an array of two
    1081          * values, first value in the array represents the gte
    1082          * value and the second value being the lte value.
    1083          *
    1084          * @return {SQL} this to allow chaining of query elements.
    1085          */
    1086         between: function(options) {
    1087             throw new Error("Not Implemented")
    1088         },
    1089
    1090         /**
    1091          * Add a not between check for a column.
    1092          * @example
    1093          * //select * from test where x <= 1 and x >= 5
    1094          * sql.notBetween({x : [1,5]});
    1095          * //select * from test where x <= 'a' and x >= 'b'
    1096          * sql.notBetween({x : ["a","b"]});
    1097          * //select * from test where x <= 'a' and x >= 'b'
    1098          * sql.find({x : {notBetween : ["a","b"]}});
    1099          *
    1100          * @param @param options options key value pairs where the
    1101          * key is coulmn name and the value is an array of two
    1102          * values, first value in the array represents the lte
    1103          * value and the second value being the gte value.
    1104          *
    1105          * @return {SQL} this to allow chaining of query elements.
    1106          */
    1107         notBetween: function(options) {
    1108             throw new Error("Not Implemented")
    1109         },
    1110
    1111         /**
    1112          * Add a count cause to the select portion of the query.
    1113          *
    1114          * @example
    1115          * //select count(name) as name_count from test
    1116          * sql.count("name");
    1117          * //select count(*) as count from test
    1118          * sql.count();
    1119
    1120          * @param {String|Array} [options="*"] if a string is supplied
    1121          * then a count is added for that particular columns, an array
    1122          * adds a count for each column in the array.
    1123          *
    1124          * @return {SQL} this to allow chaining of query elements.
    1125          */
    1126         count: function(options) {
    1127             throw new Error("Not Implemented")
    1128         },
    1129
    1130
    1131         /**
    1132          * Helper to add a group and count clause.
    1133          *
    1134          * @example
    1135          * //select *, count(name) as name_count from test group by name
    1136          * sql.groupAndCount("name");
    1137          * @param {String|Array} key specify the columns to group and count on.
    1138          * @param {Object} having specify a having clause {@link SQL#having}.
    1139          *
    1140          * @return {SQL} this to allow chaining of query elements.
    1141          */
    1142         groupAndCount: function() {
    1143             throw new Error("Not Implemented");
    1144         },
    1145
    1146         /**
    1147          * Helper to add a group and sum clause.
    1148          *
    1149          * @example
    1150          * sql.groupAndSum("name");
    1151          * //select *, sum(name) as name_sum from test group by name
    1152          *
    1153          * @param {String|Array} key specify the columns to group and sum on.
    1154          * @param {Object} having specify a having clause {@link SQL#having}.
    1155          *
    1156          * @return {SQL} this to allow chaining of query elements.
    1157          */
    1158         groupAndSum: function() {
    1159             throw new Error("Not Implemented");
    1160         },
    1161
    1162         /**
    1163          * Helper to add a group and avg clause.
    1164          *
    1165          *  @example
    1166          * //select *, avg(name) as name_avg from test group by name
    1167          * sql.groupAndAvg("name");
    1168          *
    1169          * @param {String|Array} key specify the columns to group and avg on.
    1170          * @param {Object} having specify a having clause {@link SQL#having}.
    1171          *
    1172          * @return {SQL} this to allow chaining of query elements.
    1173          */
    1174         groupAndAvg: function() {
    1175             throw new Error("Not Implemented");
    1176         },
    1177
    1178         /**
    1179          * Helper to add a group and min clause.
    1180          *
    1181          * @example
    1182          * //select *, min(name) as name_min from test group by name
    1183          * sql.groupAndMin("name");
    1184          *
    1185          * @param {String|Array} key specify the columns to group and min on.
    1186          * @param {Object} having specify a having clause {@link SQL#having}.
    1187          *
    1188          * @return {SQL} this to allow chaining of query elements.
    1189          */
    1190         groupAndMin: function() {
    1191             throw new Error("Not Implemented");
    1192         },
    1193
    1194         /**
    1195          * Helper to add a group and max clause.
    1196          *
    1197          * @example
    1198          * //select *, max(name) as name_max from test group by name
    1199          * sql.groupAndMax("name");
    1200          *
    1201          * @param {String|Array} key specify the columns to group and max on.
    1202          * @param {Object} having specify a having clause {@link SQL#having}.
    1203          *
    1204          * @return {SQL} this to allow chaining of query elements.
    1205          */
    1206         groupAndMax: function() {
    1207             throw new Error("Not Implemented");
    1208         },
    1209
    1210         /**
    1211          * Helper to add a group and bit and clause.
    1212          *
    1213          * @example
    1214          * //select *, bit_and(name) as name_bit_and from test group by name
    1215          * sql.groupAndBitAnd("name");
    1216          *
    1217          * @param {String|Array} key specify the columns to group and bit and on.
    1218          * @param {Object} having specify a having clause {@link SQL#having}.
    1219          *
    1220          * @return {SQL} this to allow chaining of query elements.
    1221          */
    1222         groupAndBitAnd: function() {
    1223             throw new Error("Not Implemented");
    1224         },
    1225
    1226         /**
    1227          * Helper to add a group and bit or clause.
    1228          *
    1229          * @example
    1230          * //select *, bit_or(name) as name_bit_or from test group by name
    1231          * sql.groupAndBitOr("name");
    1232          *
    1233          * @param {String|Array} key specify the columns to group and bit or on.
    1234          * @param {Object} having specify a having clause {@link SQL#having}.
    1235          *
    1236          * @return {SQL} this to allow chaining of query elements.
    1237          */
    1238         groupAndBitOr: function() {
    1239             throw new Error("Not Implemented");
    1240         },
    1241
    1242         /**
    1243          * Helper to add a group and bit xor clause.
    1244          *
    1245          * @example
    1246          * //select *, bit_xor(name) as name_bit_xor from test group by name
    1247          * sql.groupAndBitXor("name");
    1248          *
    1249          * @param {String|Array} key specify the columns to group and bit xor on.
    1250          * @param {Object} having specify a having clause {@link SQL#having}.
    1251          *
    1252          * @return {SQL} this to allow chaining of query elements.
    1253          */
    1254         groupAndBitXor: function() {
    1255             throw new Error("Not Implemented");
    1256         },
    1257
    1258         /**
    1259          * Helper to add a group and std clause.
    1260          *
    1261          * @example
    1262          * //select *, std(name) as name_std from test group by name
    1263          * sql.groupAndStd("name");
    1264          *
    1265          * @param {String|Array} key specify the columns to group and std on.
    1266          * @param {Object} having specify a having clause {@link SQL#having}.
    1267          *
    1268          * @return {SQL} this to allow chaining of query elements.
    1269          */
    1270         groupAndStd: function() {
    1271             throw new Error("Not Implemented");
    1272         },
    1273
    1274         /**
    1275          * Helper to add a group and std dev pop clause.
    1276          *
    1277          * @example
    1278          * //select *, stddev_pop(name) as name_stddev_pop from test group by name
    1279          * sql.groupAndStdDevPop("name");
    1280          *
    1281          * @param {String|Array} key specify the columns to group and std dev pop on.
    1282          * @param {Object} having specify a having clause {@link SQL#having}.
    1283          *
    1284          * @return {SQL} this to allow chaining of query elements.
    1285          */
    1286         groupAndStdDevPop: function() {
    1287             throw new Error("Not Implemented");
    1288         },
    1289
    1290         /**
    1291          * Helper to add a group and std dev samp clause.
    1292          *
    1293          * @example
    1294          * //select *, stddev_samp(name) as name_stddev_samp from test group by name
    1295          * sql.groupAndStdDevSamp("name");
    1296          *
    1297          * @param {String|Array} key specify the columns to group and std dev samp on.
    1298          * @param {Object} having specify a having clause {@link SQL#having}.
    1299          *
    1300          * @return {SQL} this to allow chaining of query elements.
    1301          */
    1302         groupAndStdDevSamp: function() {
    1303             throw new Error("Not Implemented");
    1304         },
    1305
    1306         /**
    1307          * Helper to add a group and std dev clause.
    1308          *
    1309          * @example
    1310          * //select *, stddev(name) as name_stddev from test group by name
    1311          * sql.groupAndStdDev("name");
    1312          *
    1313          * @param {String|Array} key specify the columns to group and std dev on.
    1314          * @param {Object} having specify a having clause {@link SQL#having}.
    1315          *
    1316          * @return {SQL} this to allow chaining of query elements.
    1317          */
    1318         groupAndStdDev: function() {
    1319             throw new Error("Not Implemented");
    1320         },
    1321
    1322         /**
    1323          * Helper to add a group and var pop clause.
    1324          *
    1325          * @example
    1326          * //select *, var_pop(name) as name_var_pop from test group by name
    1327          * sql.groupAndVarPop("name");
    1328          *
    1329          * @param {String|Array} key specify the columns to group and var pop on.
    1330          * @param {Object} having specify a having clause {@link SQL#having}.
    1331          *
    1332          * @return {SQL} this to allow chaining of query elements.
    1333          */
    1334         groupAndVarPop: function() {
    1335             throw new Error("Not Implemented");
    1336         },
    1337
    1338         /**
    1339          * Helper to add a group and var samp clause.
    1340          *
    1341          * @example
    1342          * //select *, var_samp(name) as name_var_samp from test group by name
    1343          * sql.groupAndVarSamp("name");
    1344          *
    1345          * @param {String|Array} key specify the columns to group and var samp on.
    1346          * @param {Object} having specify a having clause {@link SQL#having}.
    1347          *
    1348          * @return {SQL} this to allow chaining of query elements.
    1349          */
    1350         groupAndVarSamp: function() {
    1351             throw new Error("Not Implemented");
    1352         },
    1353
    1354         /**
    1355          * Helper to add a group and variance clause.
    1356          *
    1357          * @example
    1358          * //select *, variance(name) as name_variance from test group by name
    1359          * sql.groupAndVariance("name");
    1360          *
    1361          * @param {String|Array} key specify the columns to group and variance on.
    1362          * @param {Object} having specify a having clause {@link SQL#having}.
    1363          *
    1364          * @return {SQL} this to allow chaining of query elements.
    1365          */
    1366         groupAndVariance: function() {
    1367             throw new Error("Not Implemented");
    1368         },
    1369
    1370         /**
    1371          * Helper to add a sum clause.
    1372          *
    1373          * @example
    1374          * //select sum(name) as name_sum from test
    1375          * sql.sum("name");
    1376          *
    1377          * @param {String|Array} [options="*"] if a string is supplied
    1378          * then a sum is added for that particular columns, an array
    1379          * adds a sum for each column in the array.
    1380          *
    1381          * @return {SQL} this to allow chaining of query elements.
    1382          */
    1383         sum: function(options) {
    1384             throw new Error("Not Implemented")
    1385         },
    1386
    1387         /**
    1388          * @example
    1389          * //select avg(name) as name_avg from test
    1390          * sql.avg("name");
    1391          * @param {String|Array} [options="*"] if a string is supplied
    1392          * then a avg is added for that particular columns, an array
    1393          * adds a avg for each column in the array.
    1394          *
    1395          * @return {SQL} this to allow chaining of query elements.
    1396          */
    1397         avg: function(options) {
    1398             throw new Error("Not Implemented")
    1399         },
    1400
    1401         /**
    1402          * Helper to add a min clause.
    1403          *
    1404          * @example
    1405          * //select min(name) as name_min from test
    1406          * sql.min("name");
    1407          * @param {String|Array} [options="*"] if a string is supplied
    1408          * then a min is added for that particular columns, an array
    1409          * adds a min for each column in the array.
    1410          *
    1411          * @return {SQL} this to allow chaining of query elements.
    1412          */
    1413         min: function(options) {
    1414             throw new Error("Not Implemented")
    1415         },
    1416
    1417         /**
    1418          * Helper to add a max clause.
    1419          *
    1420          * @example
    1421          * //select max(name) as name_max from test
    1422          * sql.max("name");
    1423          * @param {String|Array} [options="*"] if a string is supplied
    1424          * then a max is added for that particular columns, an array
    1425          * adds a max for each column in the array.
    1426          *
    1427          * @return {SQL} this to allow chaining of query elements.
    1428          */
    1429         max: function(options) {
    1430             throw new Error("Not Implemented")
    1431         },
    1432
    1433         /**
    1434          * Helper to add a bit and clause.
    1435          *
    1436          * @example
    1437          * //select bit_and(name) as name_bit_and from test
    1438          * sql.bitAnd("name");
    1439          * @param {String|Array} [options="*"] if a string is supplied
    1440          * then a bit and is added for that particular columns, an array
    1441          * adds a bit and for each column in the array.
    1442          *
    1443          * @return {SQL} this to allow chaining of query elements.
    1444          */
    1445         bitAnd: function(options) {
    1446             throw new Error("Not Implemented")
    1447         },
    1448
    1449         /**
    1450          * @example
    1451          * //select bit_or(name) as name_bit_or from test
    1452          * sql.bitOr("name");
    1453          * @param {String|Array} [options="*"] if a string is supplied
    1454          * then a bit or is added for that particular columns, an array
    1455          * adds a count for each column in the array.
    1456          *
    1457          * @return {SQL} this to allow chaining of query elements.
    1458          */
    1459         bitOr: function(options) {
    1460             throw new Error("Not Implemented")
    1461         },
    1462
    1463         /**
    1464          * Helper to add a bit xor clause.
    1465          *
    1466          * @example
    1467          * //select bit_xor(name) as name_bit_xor from test
    1468          * sql.bitXor("name");
    1469          * @param {String|Array} [options="*"] if a string is supplied
    1470          * then a bit xor is added for that particular columns, an array
    1471          * adds a bit xor for each column in the array.
    1472          *
    1473          * @return {SQL} this to allow chaining of query elements.
    1474          */
    1475         bitXor: function(options) {
    1476             throw new Error("Not Implemented")
    1477         },
    1478
    1479         /**
    1480          * Helper to add a std clause.
    1481          *
    1482          * @example
    1483          * //select std(name) as name_std from test
    1484          * sql.std("name");
    1485          * @param {String|Array} [options="*"] if a string is supplied
    1486          * then a std is added for that particular columns, an array
    1487          * adds a std for each column in the array.
    1488          *
    1489          * @return {SQL} this to allow chaining of query elements.
    1490          */
    1491         std: function(options) {
    1492             throw new Error("Not Implemented")
    1493         },
    1494
    1495         /**
    1496          * Helper to add a std dev clause.
    1497          *
    1498          * @example
    1499          * //select stddev_pop(name) as name_stddev_pop from test
    1500          * sql.stdDevPop("name");
    1501          * @param {String|Array} [options="*"] if a string is supplied
    1502          * then a std dev pop is added for that particular columns, an array
    1503          * adds a std dev pop for each column in the array.
    1504          *
    1505          * @return {SQL} this to allow chaining of query elements.
    1506          */
    1507         stdDevPop: function(options) {
    1508             throw new Error("Not Implemented")
    1509         },
    1510
    1511         /**
    1512          * Helper to add a std dev samp clause.
    1513          *
    1514          * @example
    1515          * //select stddev_samp(name) as name_stddev_samp from test
    1516          * sql.stdDevSamp("name");
    1517          * @param {String|Array} [options="*"] if a string is supplied
    1518          * then a std dev samp is added for that particular columns, an array
    1519          * adds a std dev samp for each column in the array.
    1520          *
    1521          * @return {SQL} this to allow chaining of query elements.
    1522          */
    1523         stdDevSamp: function(options) {
    1524             throw new Error("Not Implemented")
    1525         },
    1526
    1527         /**
    1528          * Helper to add a std dev clause.
    1529          *
    1530          * @example
    1531          * //select stddev(name) as name_stddev from test
    1532          * sql.stdDev("name");
    1533          * @param {String|Array} [options="*"] if a string is supplied
    1534          * then a std dev is added for that particular columns, an array
    1535          * adds a std dev for each column in the array.
    1536          *
    1537          * @return {SQL} this to allow chaining of query elements.
    1538          */
    1539         stdDev: function(options) {
    1540             throw new Error("Not Implemented")
    1541         },
    1542
    1543         /**
    1544          * Helper to add a var pop clause.
    1545          *
    1546          * @example
    1547          * //select var_pop(name) as name_var_pop from test
    1548          * sql.varPop("name");
    1549          * @param {String|Array} [options="*"] if a string is supplied
    1550          * then a var pop is added for that particular columns, an array
    1551          * adds a var pop for each column in the array.
    1552          *
    1553          * @return {SQL} this to allow chaining of query elements.
    1554          */
    1555         varPop: function(options) {
    1556             throw new Error("Not Implemented")
    1557         },
    1558
    1559         /**
    1560          * Helper to add a var samp clause.
    1561          *
    1562          * @example
    1563          * //select var_samp(name) as name_var_samp from test
    1564          * sql.varSamp("name");
    1565          * @param options
    1566          *
    1567          * @param {String|Array} [options="*"] if a string is supplied
    1568          * then a var samp is added for that particular columns, an array
    1569          * adds a var samp for each column in the array.
    1570          *
    1571          * @return {SQL} this to allow chaining of query elements.
    1572          */
    1573         varSamp: function(options) {
    1574             throw new Error("Not Implemented")
    1575         },
    1576
    1577         /**
    1578          * Helper to add a variance clause.
    1579          *
    1580          * @example
    1581          * //select variance(name) as name_variance from test
    1582          * sql.variance("name");
    1583          * @param {String|Array} [options="*"] if a string is supplied
    1584          * then a variance is added for that particular columns, an array
    1585          * adds a variance for each column in the array.
    1586          *
    1587          * @return {SQL} this to allow chaining of query elements.
    1588          */
    1589         variance: function(options) {
    1590             throw new Error("Not Implemented")
    1591         },
    1592
    1593         /**
    1594          * Add a like clause.
    1595          *
    1596          * @example
    1597          * //select * from test where name like 'bob'
    1598          * sql.like({name : "bob"});
    1599          * //select * from test where firstName like 'bob' and lastName not like 'henry'
    1600          * sql.find({firstName : {like : 'bob'}, lastName : {notLike : "henry"}});
    1601          *
    1602          * @param {Object} options key, value pairs with the key representing a column,
    1603          * and the key represents the like condition.
    1604          *
    1605          * @return {SQL} this to allow chaining of query elements.
    1606          */
    1607         like: function(options) {
    1608             throw new Error("Not Implemented")
    1609         },
    1610
    1611         /**
    1612          *  Add a not like clause.
    1613          *
    1614          * @example
    1615          * //select * from test where name not like 'bob'
    1616          * sql.notLike({name : "bob"});
    1617          * //select * from test where firstName like 'bob' and lastName not like 'henry'
    1618          * sql.find({firstName : {like : 'bob'}, lastName : {notLike : "henry"}});
    1619          *
    1620          * @param {Object} options key, value pairs with the key representing a column,
    1621          * and the key represents the not like condition.
    1622          *
    1623          * @return {SQL} this to allow chaining of query elements.
    1624          */
    1625         notLike: function(options) {
    1626             throw new Error("Not Implemented")
    1627         },
    1628
    1629
    1630         /**
    1631          * Performs clean up to add any needed protions of a query if not provided.
    1632          *
    1633          * @return {SQL} this to allow chaining of query elements.
    1634          */
    1635         end : function() {
    1636             throw new Error("Not Implemented!");
    1637         },
    1638
    1639         /**
    1640          * Executes the query, when finished the promise callback is called
    1641          * if the query errors then the promise error is called.
    1642          *
    1643          * @return {comb.Promise} called back with results or the error call back is called with an error.
    1644          */
    1645         exec : function() {
    1646             this.end();
    1647             return this.db.query(this.sql);
    1648         },
    1649
    1650         /**
    1651          * Close the connection.
    1652          */
    1653         close : function() {
    1654             this.db.close();
    1655         },
    1656
    1657         getters : {
    1658             sql : function() {
    1659                 return createSQLFromSplit(this.sqlObject);
    1660             }
    1661         }
    1662     },
    1663
    1664     static : {
    1665         /**@lends SQL*/
    1666
    1667         /**
    1668          * Create a table.
    1669          *
    1670          * @param {moose.Table} table the table to create on the database
    1671          * @param {moose.adapters.client.Query|moose.adapters.client.TransactionQuery} db the conneciton to the database.
    1672          *
    1673          * @return {comb.Promise} called back with results or the error call back is called with an error.
    1674          */
    1675         createTable : function(table, db) {
    1676             var promise = new Promise();
    1677             db.query(table.createTableSql).then(hitch(promise, "callback", true), hitch(promise, "errback"));
    1678             return promise;
    1679         },
    1680
    1681         /**
    1682          * Alter a table.
    1683          *
    1684          * @param {moose.Table} table the table to alter on the database
    1685          * @param {moose.adapters.client.Query|moose.adapters.client.TransactionQuery} db the conneciton to the database.
    1686          *
    1687          * @return {comb.Promise} called back with results or the error call back is called with an error.
    1688          */
    1689         alterTable : function(table, db) {
    1690             throw new Error("Not Implemented!");
    1691         },
    1692
    1693         /**
    1694          * Drop a table.
    1695          *
    1696          * @param {moose.Table} table the table to drop on the database
    1697          * @param {moose.adapters.client.Query|moose.adapters.client.TransactionQuery} db the conneciton to the database.
    1698          *
    1699          * @return {comb.Promise} called back with results or the error call back is called with an error.
    1700          */
    1701         dropTable : function(table, db) {
    1702             throw new Error("Not Implemented!");
    1703         },
    1704
    1705         /**
    1706          * Perform a batch insert into a table the objects.
    1707          *
    1708          * @param {String} table the name of the table
    1709          * @param {Object} object the values to insert into the table
    1710          * @param {moose.adapters.client.Query|moose.adapters.client.TransactionQuery} db the conneciton to the database.
    1711          *
    1712          * @return {comb.Promise} called back with results or the error call back is called with an error.
    1713          */
    1714         save : function(table, object, db) {
    1715             throw new Error("Not Implemented!");
    1716         },
    1717
    1718         /**
    1719          * Retrieve and create a {@link moose.Table} from a schema stored in the database.
    1720          *
    1721          * @param {String} tableName name of the table
    1722          * @param {moose.adapters.client.Query|moose.adapters.client.TransactionQuery} db the conneciton to the database.
    1723          *
    1724          * @return {comb.Promise} called back with {@link moose.Table} or the error call back is called with an error.
    1725          */
    1726         schema : function(tableName, db) {
    1727             throw new Error("Not Implemented!");
    1728         },
    1729
    1730         /**
    1731          * Retrieve the last inserted id on a database.
    1732          *
    1733          * @param {moose.adapters.client.Query|moose.adapters.client.TransactionQuery} db the conneciton to the database.
    1734          *
    1735          * @return {comb.Promise} called back with id or the error call back is called with an error.
    1736          */
    1737         getLastInsertId : function(db) {
    1738             throw new Error("Not Implemented!");
    1739         },
    1740
    1741         /**
    1742          * Create a foreign key statement
    1743          * <p><b>See your client adpater for parameters!</b></p>
    1744          */
    1745         foreignKey : function() {
    1746             throw new Error("Not Implemented!");
    1747         },
    1748
    1749         /**
    1750          * Create a add foreign key statement
    1751          * <p><b>See your client adpater for parameters!</b></p>
    1752          */
    1753         addForeignKey :function() {
    1754             throw new Error("Not Implemented!");
    1755         },
    1756
    1757         /**
    1758          * Create a drop foreign key statement
    1759          * <p><b>See your client adpater for parameters!</b></p>
    1760          */
    1761         dropForeignKey : function() {
    1762             throw new Error("Not Implemented!");
    1763         },
    1764
    1765         /**
    1766          * Create a primary key statement
    1767          * <p><b>See your client adpater for parameters!</b></p>
    1768          */
    1769         primaryKey : function() {
    1770             throw new Error("Not Implemented!");
    1771         },
    1772
    1773         /**
    1774          * Create a add primary key statement
    1775          * <p><b>See your client adpater for parameters!</b></p>
    1776          */
    1777         addPrimaryKey : function() {
    1778             throw new Error("Not Implemented!");
    1779         },
    1780
    1781         /**
    1782          * Create a drop primary key statement
    1783          * <p><b>See your client adpater for parameters!</b></p>
    1784          */
    1785         dropPrimaryKey : function() {
    1786             throw new Error("Not Implemented!");
    1787         },
    1788
    1789         /**
    1790          * Create a unique constraint statement
    1791          * <p><b>See your client adpater for parameters!</b></p>
    1792          */
    1793         unique : function() {
    1794             throw new Error("Not Implemented!");
    1795         },
    1796
    1797         /**
    1798          * Create a add unique constraint statement
    1799          * <p><b>See your client adpater for parameters!</b></p>
    1800          */
    1801         addUnique : function() {
    1802             throw new Error("Not Implemented!");
    1803         },
    1804
    1805         /**
    1806          * Create a drop unique constraint statement
    1807          * <p><b>See your client adpater for parameters!</b></p>
    1808          */
    1809         dropUnique : function() {
    1810             throw new Error("Not Implemented!");
    1811         },
    1812
    1813         /**
    1814          * Create a drop column statement
    1815          * <p><b>See your client adpater for parameters!</b></p>
    1816          */
    1817         dropColumn : function() {
    1818             throw new Error("Not Implemented!");
    1819         },
    1820
    1821         /**
    1822          * Create an alter column statement
    1823          * <p><b>See your client adpater for parameters!</b></p>
    1824          */
    1825         alterColumn : function() {
    1826             throw new Error("Not Implemented!");
    1827         },
    1828
    1829         /**
    1830          * Create a column statement
    1831          * <p><b>See your client adpater for parameters!</b></p>
    1832          */
    1833         column : function() {
    1834             throw new Error("Not Implemented!");
    1835         },
    1836
    1837         /**
    1838          * Create an add column statement
    1839          * <p><b>See your client adpater for parameters!</b></p>
    1840          */
    1841         addColumn : function() {
    1842             throw new Error("Not Implemented!");
    1843         },
    1844
    1845         /**
    1846          * Check if a type is a valid type for this adapter.
    1847          * @return {Boolean} true if it is a valid type, false otherwise.
    1848          */
    1849         isValidType : function() {
    1850             throw new Error("Not Implemented!");
    1851         },
    1852         client : null,
    1853         types : null,
    1854
    1855         /**
    1856          * Formats and escapes query string.
    1857          * @function
    1858          * @param {String} sql the sql to format
    1859          * @param {Array} array of values to place in the query.
    1860          *
    1861          * @return {String} the formatted string.
    1862          */
    1863         format : format
    1864
    1865     }
    1866 });
    1867
    1868
    1869