      1 var Type = require("./index").Type,
      2         comb = require("comb");
      3
      4 var stringDefaults = {
      5     allowNull : true,
      6     primaryKey : false,
      7     foreignKey : false,
      8     "default" : null,
      9     unique : false,
     10     description : ""
     11 };
     12
     13 var getStringType = function(cmpFun) {
     14     return function(val) {
     15         if (!val) {
     16             val = null;
     17         } else if (typeof val != "string") {
     18             val = "" + val;
     19         }
     20         cmpFun && cmpFun(val);
     21         return val;
     22     };
     23 };
     24
     25 var checkStringType = function(type, cmpFun) {
     26     return function(val) {
     27         if (typeof val != "string") throw new Error(type + " requires a string type.");
     28         cmpFun && cmpFun(val);
     29     };
     30 };
     31
     32 //String Types
     33 /**
     34  *
     35  *
     36  * Mysql CHAR datatype
     37  *
     38  * @function
     39  * @param {Object} options options for the CHAR data type.
     40  * @param {Number} [options.length=255] the length of the field
     41  * @param {Boolean} [options.allowNull=true] should the field allow null
     42  * @param {Boolean} [options.default = null] default value of the field
     43  * @param {Boolean} [options.description = ""] description fo the field.
     44  *
     45  * @return {Type} A Type representing a CHAR column.
     46  *
     47  * @name CHAR
     48  * @memberOf moose.adapters.mysql.types
     49  *
     50  */
     51 exports.CHAR = function(options) {
     52     var ops = comb.merge({}, stringDefaults, {length : 255, type : "CHAR"}, options || {});
     53     if (ops.length > 4294967295) {
     54         throw new Error("Max char type length is 255");
     55     }
     56     var cmpFun = function(val) {
     57         if (ops.length == undefined && val.length > 255) throw new Error("value not of length " + (ops.length || 255));
     58         else if (val && val.length != ops.length) throw new Error("value not of length " + (ops.length || 255));
     59     };
     60     ops.setSql = getStringType(cmpFun);
     61     ops.checkType = checkStringType(ops.type, cmpFun);
     62     return new Type(ops);
     63 };
     64
     65 /**
     66  *
     67  *
     68  * String alias for {@link varchar} datatype.
     69  *
     70  * @function
     71  * @param {Object} options options for the STRING data type.
     72  * @param {Number} [options.length=255] the length of the field
     73  * @param {Boolean} [options.allowNull=true] should the field allow null
     74  * @param {Boolean} [options.default = null] default value of the field
     75  * @param {Boolean} [options.description = ""] description fo the field.
     76  *
     77  * @return {Type} A Type representing a VARCHAR column.
     78  *
     79  * @name STRING
     80  * @memberOf moose.adapters.mysql.types
     81  *
     82  */
     83 exports.STRING = (exports.VARCHAR = function(options) {
     84     var ops = comb.merge({}, stringDefaults, {length : 255, type : "VARCHAR"}, options || {});
     85     if (ops.length > 4294967295) {
     86         throw new Error("Max char type length is 255 please use text");
     87     }
     88     var cmpFun = function(val) {
     89         if ((val.length > ops.length) || val.length > 255)
     90             throw new Error("value greater than valid varchar length of " + (ops.length || 255));
     91     };
     92     ops.setSql = getStringType(cmpFun);
     93     ops.checkType = checkStringType(ops.type, cmpFun);
     94     return new Type(ops);
     95 });
     96
     97 /**
     98  *
     99  * Mysql TINYTEXT datatype
    100  *
    101  * @function
    102  * @param {Object} options options for the TINYTEXT data type.
    103  * @param {Number} [options.length] the length of the field
    104  * @param {Boolean} [options.allowNull=true] should the field allow null
    105  * @param {Boolean} [options.default = null] default value of the field
    106  * @param {Boolean} [options.description = ""] description fo the field.
    107  *
    108  * @return {Type} A Type representing a TINYTEXT column.
    109  *
    110  * @name TINYTEXT
    111  * @memberOf moose.adapters.mysql.types
    112  *
    113  */
    114 exports.TINYTEXT = function(options) {
    115     var ops = comb.merge({}, stringDefaults, {length : null, type : "TINYTEXT"}, options || {});
    116     var cmpFun = function(val) {
    117         if (val.length > 255) throw new Error("value greater than valid tinytext length of 255");
    118     };
    119     ops.setSql = getStringType(cmpFun);
    120     ops.checkType = checkStringType(ops.type, cmpFun);
    121     return new Type(ops);
    122 };
    123
    124 /**
    125  *
    126  *
    127  * Mysql MEDIUMTEXT datatype
    128  *
    129  * @function
    130  * @param {Object} options options for the MEDIUMTEXT data type.
    131  * @param {Number} [options.length] the length of the field
    132  * @param {Boolean} [options.allowNull=true] should the field allow null
    133  * @param {Boolean} [options.default = null] default value of the field
    134  * @param {Boolean} [options.description = ""] description fo the field.
    135  *
    136  * @return {Type} A Type representing a MEDIUMTEXT column.
    137  *
    138  * @name MEDIUMTEXT
    139  * @memberOf moose.adapters.mysql.types
    140  *
    141  */
    142 exports.MEDIUMTEXT = function(options) {
    143     var ops = comb.merge({}, stringDefaults, {length : null, type : "MEDIUMTEXT"}, options || {});
    144     var cmpFun = function(val) {
    145         if (val.length > 16777215) throw new Error("value greater than valid tinytext length of 16777215");
    146     };
    147     ops.setSql = getStringType(cmpFun);
    148     ops.checkType = checkStringType(ops.type, cmpFun);
    149     return new Type(ops);
    150 };
    151
    152 /**
    153  *
    154  *
    155  * Mysql LONGTEXT datatype
    156  *
    157  * @function
    158  * @param {Object} options options for the LONGTEXT data type.
    159  * @param {Number} [options.length] the length of the field
    160  * @param {Boolean} [options.allowNull=true] should the field allow null
    161  * @param {Boolean} [options.default = null] default value of the field
    162  * @param {Boolean} [options.description = ""] description fo the field.
    163  *
    164  * @return {Type} A Type representing a LONGTEXT column.
    165  *
    166  * @name LONGTEXT
    167  * @memberOf moose.adapters.mysql.types
    168  *
    169  */
    170 exports.LONGTEXT = function(options) {
    171     var ops = comb.merge({}, stringDefaults, {length : null, type : "LONGTEXT"}, options || {});
    172     var cmpFun = function(val) {
    173         if (val.length > 4294967295) throw new Error("value greater than valid tinytext length of 4294967295");
    174     };
    175     ops.setSql = getStringType(cmpFun);
    176     ops.checkType = checkStringType(ops.type, cmpFun);
    177     return new Type(ops);
    178 };
    179
    180 /**
    181  *
    182  *
    183  * Mysql TEXT datatype
    184  *
    185  * @function
    186  * @param {Object} options options for the TEXT data type.
    187  * @param {Number} [options.length] the length of the field
    188  * @param {Boolean} [options.allowNull=true] should the field allow null
    189  * @param {Boolean} [options.default = null] default value of the field
    190  * @param {Boolean} [options.description = ""] description fo the field.
    191  *
    192  * @return {Type} A Type representing a TEXT column.
    193  *
    194  * @name TEXT
    195  * @memberOf moose.adapters.mysql.types
    196  *
    197  */
    198 exports.TEXT = function(options) {
    199     var ops = comb.merge({}, stringDefaults, {length : 4294967295, type : "TEXT"}, options || {});
    200     var cmpFun = function(val) {
    201         if (val.length > 65535) throw new Error("value greater than valid tinytext length of 65535");
    202     };
    203     ops.setSql = getStringType(cmpFun);
    204     ops.checkType = checkStringType(ops.type, cmpFun);
    205     return new Type(ops);
    206 };
    207
    208
    209 var checkEnumType = function(enumTypes, type) {
    210     var enums = comb.merge([], enumTypes);
    211     return function(val) {
    212         if (typeof val != "string" || enums.indexOf(val) == -1) {
    213             throw new Error(type + " value must be a string and contained in the enum set");
    214         }
    215     };
    216 };
    217
    218 var checkSetType = function(enumTypes, type) {
    219     var check = checkEnumType(enumTypes, type);
    220     return function(val) {
    221         if (typeof val == "string") {
    222             return check(val);
    223         }
    224         val.forEach(function(v) {
    225             return check(v);
    226         });
    227     };
    228 };
    229
    230
    231 var getSetType = function(cmpFunc) {
    232     return function(val) {
    233         if (typeof val == "string") {
    234             val = val.split(",");
    235         }
    236         cmpFunc && cmpFunc(val);
    237         return val;
    238     };
    239 };
    240
    241 /**
    242  *
    243  *
    244  * Mysql ENUM datatype
    245  *
    246  * @function
    247  * @param {Object} options options for the TINYTEXT data type.
    248  * @param {Array} options.enums the characters allowed for this ENUM
    249  * @param {Number} [options.length] the length of the field
    250  * @param {Boolean} [options.allowNull=true] should the field allow null
    251  * @param {Boolean} [options.default = null] default value of the field
    252  * @param {Boolean} [options.description = ""] description fo the field.
    253  *
    254  * @return {Type} A Type representing a ENUM column.
    255  *
    256  * @name ENUM
    257  * @memberOf moose.adapters.mysql.types
    258  *
    259  */
    260 exports.ENUM = function(options) {
    261     var ops = comb.merge({}, stringDefaults, {type : "ENUM", enums : []}, options || {});
    262     if (ops.enums && ops.enums.length > 65535) {
    263         throw new Error("Max number of enum values is 65535");
    264     }
    265     ops.setSql = getStringType(checkEnumType(ops.enums, ops.type));
    266     ops.checkType = checkEnumType(ops.enums, ops.type);
    267     return new Type(ops);
    268 };
    269
    270 /**
    271  *
    272  *
    273  * Mysql SET datatype
    274  *
    275  * @function
    276  * @param {Object} options options for the SET data type.
    277  * @param {Array} options.enums the characters  allowed in this SET
    278  * @param {Number} [options.length] the length of the field
    279  * @param {Boolean} [options.allowNull=true] should the field allow null
    280  * @param {Boolean} [options.default = null] default value of the field
    281  * @param {Boolean} [options.description = ""] description fo the field.
    282  *
    283  * @return {Type} A Type representing a SET column.
    284  *
    285  * @name SET
    286  * @memberOf moose.adapters.mysql.types
    287  *
    288  */
    289 exports.SET = function(options) {
    290     var ops = comb.merge({}, stringDefaults, {type : "SET", enums : []}, options || {});
    291     if (ops.enums && ops.enums.length > 64) {
    292         throw new Error("Max number of enum values is 64");
    293     }
    294     ops.setSql = getSetType(checkSetType(ops.enums, ops.type));
    295     ops.checkType = checkSetType(ops.enums, ops.type);
    296     return new Type(ops);
    297 };
    298