      1 var comb = require("comb"),
      2         Client = require("mysql").Client;
      3
      4 var toSqlDate = function(date, type) {
      5     var pad = comb.string.pad, ret, format = comb.date.format;
      6     switch (type) {
      7         case "DATE" :
      8             ret = format(date, "yyyy-MM-dd");
      9             break;
     10         case "DATETIME" :
     11         case "TIMESTAMP" :
     12             ret = format(date, "yyyy-MM-dd h:m:s");
     13             break;
     14         case "TIME" :
     15             ret = format(date, "h:m:s");
     16
     17             break;
     18         case "YEAR" :
     19             ret = format(date, "yyyy");
     20             break;
     21     }
     22     return ret;
     23 };
     24
     25 var genStringColumnDef = function(ops) {
     26     var numberTypes = ["TINYINT", "SMALLINT", "MEDIUMINT", "INT", "BIGINT", "FLOAT", "DOUBLE", "DECIMAL"];
     27     var colDef = "";
     28     if (ops.type) {
     29         colDef += ops.type.toUpperCase();
     30     } else {
     31         throw new Error("A type is required in a column definition");
     32     }
     33     if ((ops.type != "ENUM" && ops.type != "SET") && (ops.length != undefined || ops.size != undefined)) {
     34         colDef += "(" + (numberTypes.indexOf(ops.type) < 0 ? ops.length : ops.size);
     35         if (["FLOAT", "DOUBLE", "DECIMAL"].indexOf(ops.type) >= 0 && ops.digits) {
     36             colDef += "," + ops.digits;
     37         }
     38         colDef += ")";
     39     } else if (ops.type == "ENUM" || ops.type == "SET") {
     40         if (!ops.enums || !(ops.enums instanceof Array)) {
     41             throw new Error("and array of enum values required when using an enum type");
     42         } else {
     43             colDef += "(" + new Client().format(ops.enums.map(
     44                     function() {
     45                         return "?";
     46                     }).join(","), ops.enums.slice()) + ")";
     47         }
     48     }
     49     if (typeof ops.unsigned == "boolean" && numberTypes.indexOf(ops.type) >= 0) {
     50         colDef += ops.unsigned ? " UNSIGNED" : " SIGNED";
     51     }
     52     if (typeof ops.allowNull == "boolean") {
     53         colDef += ops.allowNull ? " NULL" : " NOT NULL";
     54     }
     55     if (ops.autoIncrement) {
     56         colDef += " AUTO_INCREMENT";
     57     }
     58     if (ops["default"] != undefined) {
     59         colDef += new Client().format(" DEFAULT ?", [ops["default"]]);
     60     }
     61     if (ops.unique) {
     62         colDef += " UNIQUE";
     63     }
     64     return colDef;
     65 };
     66 /* { Field: 'id',
     67  Type: 'int(11)',
     68  Null: 'NO',
     69  Key: 'PRI',
     70  Default: null,
     71  Extra: 'auto_increment' }*/
     72 var fromColumnDef = function(o) {
     73     var numberTypes = ["TINYINT", "SMALLINT", "MEDIUMINT", "INT", "BIGINT", "FLOAT", "DOUBLE", "DECIMAL"];
     74     var params = {};
     75     var colDef = "";
     76
     77     var type = o.Type;
     78     var parts = type.split(/\(|,|\)/);
     79     if (parts.length > 1) {
     80         //remove the blank value at the end
     81         var i;
     82         if ((i = parts.indexOf("")) > 1) {
     83             parts.splice(i, 1);
     84         }
     85         //then we know it has a size, length and or digits
     86         type = parts.shift().toUpperCase();
     87         if (numberTypes.indexOf(type) >= 0) {
     88             params.size = parseInt(parts.shift());
     89             var digits = parts.shift();
     90             if (digits) {
     91                 if (["FLOAT", "DOUBLE", "DECIMAL"].indexOf(type) >= 0 && !isNaN(parseInt(digits))) {
     92                     params.digits = parseInt(digits);
     93                     digits = parts.shift();
     94                     //grab signed prop
     95                     if (digits && (digits === "signed" || digits === "unsigned")) {
     96                         params.unsigned = (digits == "unsigned");
     97                     }
     98                 } else if (digits === " signed" || digits === " unsigned") {
     99                     params.unsigned = (digits == " unsigned");
    100                 }
    101             }
    102         } else {
    103             if (parts.length && type == "ENUM" || type == "SET") {
    104                 //assign the enums
    105                 parts = parts.map(function(p) {
    106                     return p.replace(/\\|'/g, "");
    107                 });
    108                 params.enums = parts;
    109             } else if (parts.length) {
    110                 params.length = parseInt(parts[0]);
    111             }
    112         }
    113     } else {
    114         type = type.toUpperCase();
    115     }
    116     if (o.Null) {
    117         params.allowNull = o.Null === "YES";
    118     }
    119     if (o.Key) {
    120         if (o.Key == "PRI") {
    121             params.primaryKey = true;
    122         }
    123     }
    124     if (o.Extra) {
    125         var extras = o.Extra.split(" ");
    126         params.autoIncrement = extras.indexOf("auto_increment") >= 0;
    127
    128     }
    129     if (o["Default"]) {
    130         params["default"] = o["Default"];
    131     }
    132     return exports.types[type](params);
    133 };
    134
    135 /**
    136  * @class
    137  * Represents a mysql datatype. This Class should not be instantiated directly!
    138  *
    139  *
    140  * @property {String} sql the column definition of this Type.
    141  *
    142  * @name Type
    143  */
    144 exports.Type = comb.define(null, {
    145     instance : {
    146         /**@lends Type.prototype*/
    147
    148         constructor : function(options) {
    149             this.__options = options;
    150         },
    151
    152         /**
    153          * Set a property on this Type, such as isNull, unique, default etc...
    154          *
    155          * @param {String} name the name of the property.
    156          * @param {*} value the value to set it to.
    157          */
    158         set : function(name, value) {
    159             this.__options[name] = value;
    160         },
    161
    162
    163         /**
    164          * Is this Type a primary key.
    165          *
    166          * @return {Boolean} true if this Type is a primary key.
    167          */
    168         isPrimaryKey : function() {
    169             if (this.__options.primaryKey) {
    170                 return true;
    171             } else {
    172                 false;
    173             }
    174         },
    175
    176         /**
    177          * Convert an SQL value to the javascript equivalent. This method will do a type check after the conversionn.
    178          *
    179          * @param {String} val the sql string to convert.
    180          *
    181          * @return {*} the javascript value.
    182          */
    183         fromSql : function(val) {
    184             var ret = (val == "null" || val == "NULL") ? null : val;
    185             if (ret != null) {
    186                 ret = this.__options.setSql(ret);
    187             }
    188             return ret;
    189         },
    190
    191         /**
    192          * Converts a javacript value to the corresponding sql equivalent.
    193          * This function does a type check on the value before conversion, if it is not the right type an error is thrown.
    194          * @param {*} val the javacript value to convert
    195          *
    196          * @return {String} the sql value.
    197          */
    198         toSql : function(val) {
    199             this.check(val);
    200             if (val instanceof Date) {
    201                 val = toSqlDate(val, this.__options.type);
    202             } else if (val instanceof Array) {
    203                 val = val.join(",");
    204             } else if (val == null || val == undefined) {
    205                 val = null;
    206             }
    207             return val;
    208         },
    209
    210         /**
    211          * Checks a value against this Type column definition.
    212          *
    213          * @param {*} value the value to check.
    214          *
    215          * @return {Boolean} true if the value is valid.
    216          */
    217         check : function(value) {
    218             if ((value == null && !this.__options.allowNull) && !(this.primaryKey && this.__options.autoIncrement)) {
    219                 throw new Error("value is not allowed to be null");
    220             } else if (value != null) {
    221                 this.__options.checkType(value);
    222             }
    223             return true;
    224         },
    225
    226         getters : {
    227             sql : function() {
    228                 return genStringColumnDef(this.__options);
    229             }
    230         }
    231
    232     }
    233 });
    234
    235
    236 /**
    237  * @function
    238  * Creates foreign key syntax
    239  *
    240  * @example
    241  *
    242  * //FOREIGN KEY (myColumn) REFERENCES otherTable (otherTableColumn)
    243  * moose.adapters.mysql.foreignKey("myColumn", {otherTable : "otherTableColumn"});
    244  *
    245  * //FOREIGN KEY (myColumn, myColumn2)
    246  * //     REFERENCES otherTable (otherTableColumn, otherTableColumn2)
    247  * moose.adapters.mysql.foreignKey([myColumn, myColumn2], {
    248  *              otherTable : ["otherTableColumn", "otherTableColumn2"]
    249  * });
    250  *
    251  * //FOREIGN KEY (myColumn) REFERENCES otherTable (otherTableColumn),
    252  * //FOREIGN KEY (myColumn2) REFERENCES otherTable2 (otherTableColumn2)
    253  * moose.adapters.mysql.foreignKey({
    254  *              myColumn : {otherTable : "otherTableColumn"},
    255  *              myColumn2 : {otherTable2 : "otherTableColumn2"}
    256  * });
    257  *
    258  * @param {String|Array|Object} name
    259  * <ul>
    260  *     <li>If a String is provided then it is assumed to be the name of the column</li>
    261  *     <li>If an array is provided then it assumed to be an array of columns that reference the columns specified in the foreign table.</li>
    262  *     <li>If an object is specified then its treated as multiple foreign keys against multiple tables.</li>
    263  * </ul>
    264  * @param {Object} options object containg the foreignTable as the key and the value should be either a string or array,
    265  *                 depending on the name parameter, see the example.
    266  *
    267  * @return {String} the sql
    268  *
    269  * @name foreignKey
    270  * @memberOf moose.adapters.mysql
    271  */
    272
    273 exports.foreignKey = function(name, options) {
    274     var sql, i;
    275     if (name instanceof Array) {
    276         if (typeof options != "object") throw new Error("when calling foreign key options must be an object");
    277         var fkName = createContraintName("fk", name);
    278         sql = "CONSTRAINT " + fkName + " FOREIGN KEY (" + name.join(",") + ")";
    279         var otherTable, columns = null;
    280         for (i in options) {
    281             otherTable = i;
    282             columns = options[i];
    283         }
    284         if (columns.length == name.length) {
    285             sql += " REFERENCES " + otherTable + " (" + columns.join(",") + ")";
    286         } else {
    287             throw new Error("parent table columns must be the same length as the table columns");
    288         }
    289     } else if (typeof name == "object") {
    290         var fKeys = [];
    291         for (i in name) {
    292             fKeys.push(exports.foreignKey(i, name[i]));
    293         }
    294         sql = fKeys.join(",");
    295     } else if (typeof name == "string") {
    296         if (typeof options != "object") throw new Error("when calling foreign key options must be an object");
    297         sql = "FOREIGN KEY (" + name + ")",count = 0;
    298         for (i in options) {
    299             if (count != 0) throw new Error("when calling foreing key with a string for the column name, you options must be a one deep object");
    300             if (typeof options[i] == "string") {
    301                 sql += " REFERENCES " + i + " (" + options[i] + ")";
    302             } else {
    303                 throw new Error("parents column name must be a string when calling foreign key with a string for column name");
    304             }
    305         }
    306     } else {
    307         throw new Error("When calling foreign key you must pass an array, object, or string as columnName");
    308     }
    309     return sql;
    310 };
    311
    312 /**
    313  * @function
    314  * Creates alter table foreign key syntax
    315  *
    316  * @example
    317  *
    318  * //ADD FOREIGN KEY (myColumn) REFERENCES otherTable (otherTableColumn)
    319  * moose.adapters.mysql.addForeignKey("myColumn", {otherTable : "otherTableColumn"}
    320  *
    321  * //ADD CONSTRAINT fk_myColumnMyColumn2... FOREIGN KEY (myColumn, myColumn2)
    322  * //             REFERENCES otherTable (otherTableColumn, otherTableColumn2)
    323  * moose.adapters.mysql.addForeignKey([myColumn, myColumn2], {
    324  *                  otherTable : ["otherTableColumn", "otherTableColumn2"]
    325  * });
    326  *
    327  * //ADD FOREIGN KEY (myColumn) REFERENCES otherTable (otherTableColumn),
    328  * //ADD FOREIGN KEY (myColumn2) REFERENCES otherTable2 (otherTableColumn2)
    329  * moose.adapters.mysql.addForeignKey({
    330  *                  myColumn : {otherTable : "otherTableColumn"},
    331  *                  myColumn2 : {otherTable2 : "otherTableColumn2"}
    332  *});
    333  *
    334  *
    335  * @param {String|Array|Object} name
    336  * <ul>
    337  *     <li>If a String is provided then it is assumed to be the name of the column</li>
    338  *     <li>If an array is provided then it assumed to be an array of columns that reference the columns specified in the foreign table.</li>
    339  *     <li>If an object is specified then its treated as multiple foreign keys against multiple tables.</li>
    340  * </ul>
    341  * @param {Object} options object containg the foreignTable as the key and the value should be either a string or array,
    342  *                 depending on the name parameter, see the example.
    343  * @return {String} the sql
    344  *
    345  * @name addForeignKey
    346  * @memberOf moose.adapters.mysql
    347  **/
    348
    349 exports.addForeignKey = function(name, options) {
    350     var sql, i;
    351     if (name instanceof Array) {
    352         if (typeof options != "object") throw new Error("when calling foreign key options must be an object");
    353         var fkName = createContraintName("fk", name);
    354         sql = "ADD CONSTRAINT " + fkName + " FOREIGN KEY (" + name.join(",") + ")";
    355         var otherTable, columns = null;
    356         for (i in options) {
    357             otherTable = i;
    358             columns = options[i];
    359         }
    360         if (columns.length == name.length) {
    361             sql += " REFERENCES " + otherTable + " (" + columns.join(",") + ")";
    362         } else {
    363             throw new Error("parent table columns must be the same length as the table columns");
    364         }
    365     } else if (typeof name == "object") {
    366         var fKeys = [];
    367         for (i in name) {
    368             fKeys.push(exports.addForeignKey(i, name[i]));
    369         }
    370         sql = fKeys.join(",");
    371     } else if (typeof name == "string") {
    372         if (typeof options != "object") throw new Error("when calling foreign key options must be an object");
    373         sql = "ADD FOREIGN KEY (" + name + ")",count = 0;
    374         for (i in options) {
    375             if (count != 0) throw new Error("when calling foreing key with a string for the column name, you options must be a one deep object");
    376             if (typeof options[i] == "string") {
    377                 sql += " REFERENCES " + i + " (" + options[i] + ")";
    378             } else {
    379                 throw new Error("parents column name must be a string when calling foreign key with a string for column name");
    380             }
    381         }
    382     } else {
    383         throw new Error("When calling addForeign key you must pass an array, object, or string as columnName");
    384     }
    385     return sql;
    386 };
    387
    388
    389 /**
    390  * @function
    391  * Creates drop foreign key syntax
    392  *
    393  * @example
    394  *
    395  * //DROP FOREIGN KEY myColumn
    396  * moose.adapters.mysql.dropForeignKey("myColumn", {otherTable : "otherTableColumn"}
    397  *
    398  * //DROP FOREIGN KEY fk_myColumnMyColumn2
    399  * moose.adapters.mysql.foreignKey([myColumn, myColumn2], {
    400  *              otherTable : ["otherTableColumn", "otherTableColumn2"]
    401  * });
    402  *
    403  * //DROP FOREIGN KEY myColumn,
    404  * //DROP FOREIGN KEY myColumn2
    405  * moose.adapters.mysql.foreignKey({
    406  *              myColumn : {otherTable : "otherTableColumn"},
    407  *              myColumn2 : {otherTable2 : "otherTableColumn2"}
    408  * });
    409  *
    410  *
    411  * @param {String|Array|Object} name
    412  * <ul>
    413  *     <li>If a String is provided then it is assumed to be the name of the column</li>
    414  *     <li>If an array is provided then it assumed to be an array of columns that reference the columns specified in the foreign table.</li>
    415  *     <li>If an object is specified then its treated as multiple foreign keys against multiple tables.</li>
    416  * </ul>
    417  * @param {Object} options object containg the foreignTable as the key and the value should be either a string or array,
    418  *                 depending on the name parameter, see the example.
    419  * @return {String} the sql
    420  *
    421  * @name dropForeignKey
    422  * @memberOf moose.adapters.mysql
    423  **/
    424 exports.dropForeignKey = function(name, options) {
    425     var sql;
    426     if (name instanceof Array) {
    427         if (typeof options != "object") throw new Error("when calling foreign key options must be an object");
    428         var fkName = createContraintName("fk", name);
    429         sql = "DROP FOREIGN KEY " + fkName;
    430     } else if (typeof name == "object") {
    431         var fKeys = [];
    432         for (var i in name) {
    433             fKeys.push(exports.dropForeignKey(i, name[i]));
    434         }
    435         sql = fKeys.join(",");
    436     } else if (typeof name == "string") {
    437         if (typeof options != "object") throw new Error("when calling foreign key options must be an object");
    438         sql = "DROP FOREIGN KEY " + name;
    439     } else {
    440         throw new Error("When calling dropForeign key you must pass an array, object, or string as columnName");
    441     }
    442     return sql;
    443 };
    444
    445 var createContraintName = function(prefix, names, postFix) {
    446     postFix = postFix || "",prefix = prefix || "";
    447     var ret = names.map(
    448             function(p, i) {
    449                 if (i) {
    450                     return p.charAt(0).toUpperCase() + p.substr(1);
    451                 } else {
    452                     return p;
    453                 }
    454             }).join("");
    455     prefix && (ret = prefix + "_" + ret);
    456     postFix && (ret += "_" + postFix);
    457     return ret;
    458 };
    459
    460
    461 /**
    462  * @function
    463  * Creates primary key syntax
    464  *
    465  * @example
    466  *
    467  * //PRIMARY KEY (myColumn)
    468  * moose.adapters.mysql.primaryKey("myColumn"}
    469  *
    470  * //PRIMARY KEY (myColumn, myColumn2, ...)
    471  * moose.adapters.mysql.primaryKey([myColumn, myColumn2, ...]);
    472  *
    473  * @param {String|Array} name name or names of columns to create a primary key.
    474  *
    475  * @return {String} the sql
    476  *
    477  * @name primaryKey
    478  * @memberOf moose.adapters.mysql
    479  **/
    480 exports.primaryKey = function(name) {
    481     var sql;
    482     if (name instanceof Array) {
    483         var pkName = createContraintName("pk", name);
    484         sql = "CONSTRAINT " + pkName + " PRIMARY KEY (" + name.join(",") + ")";
    485     } else if (typeof name == "string") {
    486         sql = "PRIMARY KEY (" + name + ")";
    487     } else {
    488         throw new Error("When calling primaryKey the key must be a string or array");
    489     }
    490     return sql;
    491 };
    492
    493 /**
    494  * @function
    495  * Creates add primary key syntax
    496  *
    497  * @example
    498  *
    499  * //ADD PRIMARY KEY (myColumn)
    500  * moose.adapters.mysql.addPrimaryKey("myColumn"}
    501  *
    502  * //ADD CONSTRAINT pk_myColumnMyColumn2... PRIMARY KEY (myColumn, myColumn2, ...)
    503  * moose.adapters.mysql.addPrimaryKey([myColumn, myColumn2, ...]);
    504  *
    505  * @param {String|Array} name name or names of columns to create a primary key.
    506  *
    507  * @return {String} the sql
    508  *
    509  * @name addPrimaryKey
    510  * @memberOf moose.adapters.mysql
    511  **/
    512 exports.addPrimaryKey = function(name) {
    513     var sql;
    514     if (name instanceof Array) {
    515         var pkName = createContraintName("pk", name);
    516         sql = "ADD CONSTRAINT " + pkName + " PRIMARY KEY (" + name.join(",") + ")";
    517     } else if (typeof name == "string") {
    518         sql = "ADD PRIMARY KEY (" + name + ")";
    519     } else {
    520         throw new Error("When calling addPrimaryKey the key must be a string or array");
    521     }
    522     return sql;
    523 };
    524
    525 /**
    526  * @function
    527  * Creates drop primary key syntax
    528  *
    529  * @example
    530  *  //DROP PRIMARY KEY
    531  * dropPrimaryKey()
    532  *
    533  * @return {String} the sql
    534  *
    535  * @name dropPrimaryKey
    536  * @memberOf moose.adapters.mysql
    537  **/
    538 exports.dropPrimaryKey = function(name) {
    539     return "DROP PRIMARY KEY";
    540 };
    541
    542 /**
    543  * @function
    544  * Creates unique syntax
    545  *
    546  * @example
    547  * //UNIQUE (myColumn)
    548  * moose.adapters.mysql.unique("myColumn"}
    549  *
    550  * //CONSTRAINT uc_myColumnMyColumn2... UNIQUE (myColumn, myColumn2, ...)
    551  * moose.adapters.mysql.unique([myColumn, myColumn2, ...]);
    552  *
    553  * @param {String|Array} name name or names of columns to create a unique constraint.
    554  *
    555  * @return {String} the sql
    556  *
    557  * @name unique
    558  * @memberOf moose.adapters.mysql
    559  **/
    560 exports.unique = function(name) {
    561     var sql;
    562     if (name instanceof Array) {
    563         var ucName = createContraintName("uc", name);
    564         sql = "CONSTRAINT " + ucName + " UNIQUE (" + name.join(",") + ")";
    565     } else if (typeof name == "string") {
    566         sql = "UNIQUE (" + name + ")";
    567     } else {
    568         throw new Error("When calling unique the key must be a string or array");
    569     }
    570     return sql;
    571 };
    572
    573 /**
    574  * @function
    575  * Creates add unique syntax
    576  *
    577  * @example
    578  *
    579  * //ADD UNIQUE (myColumn)
    580  * moose.adapters.mysql.addUnique("myColumn"}
    581  *
    582  * //ADD CONSTRAINT uc_myColumnMyColumn2... UNIQUE (myColumn, myColumn2, ...)
    583  * moose.adapters.mysql.addUnique([myColumn, myColumn2, ...]);
    584  *
    585  * @param {String|Array} name name or names of columns to create a unique constraint.
    586  *
    587  * @return {String} the sql
    588  *
    589  * @name addUnique
    590  * @memberOf moose.adapters.mysql
    591  **/
    592 exports.addUnique = function(name) {
    593     var sql;
    594     if (name instanceof Array) {
    595         var ucName = createContraintName("uc", name);
    596         sql = "ADD CONSTRAINT " + ucName + " UNIQUE (" + name.join(",") + ")";
    597         + ")";
    598     } else if (typeof name == "string") {
    599         sql = "ADD UNIQUE (" + name + ")";
    600     } else {
    601         throw new Error("When calling addUnique the key must be a string or array");
    602     }
    603     return sql;
    604 };
    605
    606 /**
    607  * @function
    608  * Creates drop unique syntax
    609  *
    610  *
    611  * @example
    612  *
    613  * //DROP INDEX myColumn
    614  * moose.adapters.mysql.dropUnique("myColumn")
    615  *
    616  * //DROP INDEX uc_myColumnMyColumn2
    617  * moose.adapters.mysql.dropUnique([myColumn, myColumn2, ...]);
    618  *
    619  * @param {String|Array} name name or names of columns to create a unique constraint.
    620  *
    621  * @return {String} the sql
    622  *
    623  * @name dropUnique
    624  * @memberOf moose.adapters.mysql
    625  **/
    626 exports.dropUnique = function(name) {
    627     var sql;
    628     if (name instanceof Array) {
    629         var ucName = createContraintName("uc", name);
    630         sql = "DROP INDEX " + ucName;
    631         + ")";
    632     } else if (typeof name == "string") {
    633         sql = "DROP INDEX " + name;
    634     } else {
    635         throw new Error("When calling dropUnique the key must be a string or array");
    636     }
    637     return sql;
    638 };
    639
    640 /**
    641  * Create the column definition of a type
    642  *
    643  * @function
    644  *
    645  * @param {String} name the name of the column
    646  * @param {Type} type the Type object of the column
    647  *
    648  * @return {String} the sql
    649  *
    650  * @name column
    651  * @memberOf moose.adapters.mysql
    652  */
    653 exports.column = function(name, type) {
    654     var sql = "";
    655     if (!name) throw new Error("when calling alterColumn columnName is required.");
    656     return name + " " + type.sql;
    657 };
    658
    659 /**
    660  * Creates the alter column syntax.
    661  *
    662  * @function
    663  *
    664  * @param {String} name the name of the column
    665  * @param {Object} options parameters representing how to transform the column
    666  * @param {Type} [options.type] the Type object of the column.
    667  * @param {String} [options.newName] the new name of the column.
    668  * @param {Type} [options.original] the original type of the column
    669  * @prams {Boolean} [options.allowNull] the change the column to allow null
    670  * @param {*} [options.default] change the default value of the column.
    671  *
    672  * @return {String} the sql
    673  *
    674  * @name alterColumn
    675  * @memberOf moose.adapters.mysql
    676  */
    677 exports.alterColumn = function(name, options) {
    678     var sql = "";
    679     if (!name) throw new Error("when calling alterColumn columnName is required.");
    680     if (options.type) {
    681         if (options.newName) {
    682             sql += "CHANGE COLUMN " + name + " " + options.newName;
    683         } else {
    684             sql += "MODIFY COLUMN " + name;
    685         }
    686         //the type is being changed
    687         sql += " " + options.type.sql;
    688     } else {
    689         var original = options.original;
    690         if (original) {
    691             if (options.newName) {
    692                 sql += "CHANGE COLUMN " + name + " " + options.newName;
    693             } else {
    694                 sql += "MODIFY COLUMN " + name;
    695             }
    696             if (options.allowNull != undefined) {
    697                 original.set("allowNull", options.allowNull);
    698             }
    699             if (options["default"] != undefined) {
    700                 original.set("default", options["default"]);
    701             }
    702             sql += " " + original.sql;
    703         }
    704
    705     }
    706     return sql;
    707 };
    708
    709 /**
    710  * Create add column syntax.
    711  *
    712  * @function
    713  *
    714  * @param {String} name name of the column
    715  * @param {Type} type the Type object representing the column
    716  *
    717  * @return {String} the sql
    718  *
    719  * @name addColumn
    720  * @memberOf moose.adapters.mysql
    721  *
    722  */
    723 exports.addColumn = function(name, type) {
    724     var sql = "";
    725     if (!name) throw new Error("when calling alterColumn columnName is required.");
    726     return "ADD COLUMN " + name + " " + type.sql;
    727 };
    728
    729 /**
    730  * Create drop column syntax.
    731  *
    732  * @function
    733  *
    734  * @param {String} name name of the column being dropped.
    735  *
    736  *@return {String} the sql
    737  *
    738  * @name dropColumn
    739  * @memberOf moose.adapters.mysql
    740  */
    741 exports.dropColumn = function(name) {
    742     return "DROP COLUMN " + name;
    743 };
    744
    745 /**
    746  * @name types
    747  * @memberOf moose.adapters.mysql
    748  * @namespace
    749  */
    750 exports.types = comb.merge({}, require("./string"), require("./number"), require("./boolean"), require("./date"));
    751 exports.isValidType = function(o) {
    752     return o instanceof exports.Type;
    753 };
    754
    755
    756 /**
    757  * Creates a {@link Type} from a column defintion
    758  *
    759  * @function
    760  * @param {Object} sql the sql type definition returned from a table query.
    761  *
    762  * @return {Type} The Type
    763  *
    764  * @name fromColDef
    765  * @memberOf moose.adapters.mysql
    766  */
    767 exports.fromColDef = fromColumnDef;
    768
    769