1 var Type = require("./index").Type,
  2  comb = require("comb");
  3 
  4 //Number Types
  5 
  6 var numberDefaults = {
  7     allowNull : true,
  8     primaryKey : false,
  9     foreignKey : false,
 10     "default" : null,
 11     unique : false,
 12     unsigned : false,
 13     description : ""
 14 };
 15 
 16 var setNumberType = function(cmpFun, parse) {
 17     return function(val) {
 18         if (typeof val != "number") {
 19             val = parse(val);
 20         }
 21         cmpFun && cmpFun(val);
 22         return val;
 23     };
 24 };
 25 var checkNumberType = function(type, cmpFun) {
 26     return function(val) {
 27         if (typeof val != "number" || isNaN(val)) {
 28             throw new Error(type + " requires a number");
 29         }
 30         cmpFun && cmpFun(val);
 31     };
 32 };
 33 
 34 
 35 /**
 36  * Mysql INT datatype
 37  *
 38  * @function
 39  * @param {Object} options options for the INT data type.
 40  * @param {Boolean} [options.allowNull=true] should the field allow null
 41  * @param {Number} [options.size] max size of the number
 42  * @param {Boolean} [options.default = null] default value of the field
 43  * @param {Boolean} [options.unsigned = false] unsigned number
 44  * @param {Boolean} [options.description = ""] description fo the field.
 45  *
 46  * @return {Type} A Type representing a INT column.
 47  *
 48  * @name INT
 49  * @memberOf moose.adapters.mysql.types
 50  *
 51  */
 52  exports.INT = function(options) {
 53     var ops = comb.merge({}, numberDefaults, {type : "INT"}, options || {});
 54     var cmpFun = function(val) {
 55         if (ops.unsigned) {
 56             if (val < 0 || val > 4294967295) throw new Error("Int out of range");
 57         } else {
 58             if (val < -2147483648 || val > 2147483647) throw new Error("Int out of range");
 59         }
 60         return true;
 61     };
 62     ops.setSql = setNumberType(checkNumberType(ops.type, cmpFun), parseInt);
 63     ops.checkType = checkNumberType(ops.type, cmpFun);
 64     return new Type(ops);
 65 };
 66 
 67 /**
 68  * @see {moose.adapters.mysql.types.INT}
 69  * @name NUMBER
 70  * @memberOf moose.adapters.mysql.types
 71  */
 72 exports.NUMBER = exports.INT;
 73 
 74 
 75 /**
 76  * Mysql TINYINT datatype
 77  *
 78  * @function
 79  * @param {Object} options options for the TINYINT data type.
 80  * @param {Number} [options.size] max size of the number
 81  * @param {Boolean} [options.allowNull=true] should the field allow null
 82  * @param {Boolean} [options.default = null] default value of the field
 83  * @param {Boolean} [options.unsigned = false] unsigned number
 84  * @param {Boolean} [options.description = ""] description fo the field.
 85  *
 86  * @return {Type} A Type representing a TINYINT column.
 87  *
 88  * @name TINYINT
 89  * @memberOf moose.adapters.mysql.types
 90  *
 91  */
 92 exports.TINYINT = function(options) {
 93     var ops = comb.merge({}, numberDefaults, {type : "TINYINT"}, options || {});
 94     var cmpFun = function(val) {
 95         if (ops.unsigned) {
 96             if (val < 0 || val > 255) throw new Error("tinyint out of range");
 97         } else {
 98             if (val < -128 || val > 127) throw new Error("tinyInt out of range");
 99         }
100     };
101 
102     ops.setSql = setNumberType(checkNumberType(ops.type, cmpFun), parseInt);
103     ops.checkType = checkNumberType(ops.type, cmpFun);
104     return new Type(ops);
105 };
106 
107 /**
108  * Mysql SMALLINT datatype
109  *
110  * @function
111  * @param {Object} options options for the SMALLINT data type.
112  * @param {Number} [options.size] max size of the number
113  * @param {Boolean} [options.allowNull=true] should the field allow null
114  * @param {Boolean} [options.default = null] default value of the field
115  * @param {Boolean} [options.unsigned = false] unsigned number
116  * @param {Boolean} [options.description = ""] description fo the field.
117  *
118  * @return {Type} A Type representing a SMALLINT column.
119  *
120  * @name SMALLINT
121  * @memberOf moose.adapters.mysql.types
122  *
123  */
124 exports.SMALLINT = function(options) {
125     var ops = comb.merge({}, numberDefaults, {type : "SMALLINT"}, options || {});
126     var cmpFun = function(val) {
127         if (ops.unsigned) {
128             if (val < 0 || val > 65535) throw new Error("smallint out of range");
129         } else {
130             if (val < -32768 || val > 32767) throw new Error("smallint out of range");
131         }
132     };
133     ops.setSql = setNumberType(checkNumberType(ops.type, cmpFun), parseInt);
134     ops.checkType = checkNumberType(ops.type, cmpFun);
135     return new Type(ops);
136 };
137 
138 
139 /**
140  * Mysql MEDIUMINT datatype
141  *
142  * @function
143  * @param {Object} options options for the MEDIUMINT data type.
144  * @param {Number} [options.size] max size of the number
145  * @param {Boolean} [options.allowNull=true] should the field allow null
146  * @param {Boolean} [options.default = null] default value of the field
147  * @param {Boolean} [options.unsigned = false] unsigned number
148  * @param {Boolean} [options.description = ""] description fo the field.
149  *
150  * @return {Type} A Type representing a MEDIUMINT column.
151  *
152  * @name MEDIUMINT
153  * @memberOf moose.adapters.mysql.types
154  *
155  */
156 exports.MEDIUMINT = function(options) {
157     var ops = comb.merge({}, numberDefaults, {type : "MEDIUMINT"}, options || {});
158     var cmpFun = function(val) {
159         if (ops.unsigned) {
160             if (val < 0 || val > 16777215) throw new Error("mediumint out of range");
161         } else {
162             if (val < -8388608 || val > 8388607) throw new Error("mediumint out of range");
163         }
164     };
165     ops.setSql = setNumberType(checkNumberType(ops.type, cmpFun), parseInt);
166     ops.checkType = checkNumberType(ops.type, cmpFun);
167     return new Type(ops);
168 };
169 
170 
171 /**
172  * Mysql BIGINT datatype
173  *
174  * @function
175  * @param {Object} options options for the BIGINT data type.
176  * @param {Number} [options.size] max size of the number
177  * @param {Boolean} [options.allowNull=true] should the field allow null
178  * @param {Boolean} [options.default = null] default value of the field
179  * @param {Boolean} [options.unsigned = false] unsigned number
180  * @param {Boolean} [options.description = ""] description fo the field.
181  *
182  * @return {Type} A Type representing a BIGINT column.
183  *
184  * @name BIGINT
185  * @memberOf moose.adapters.mysql.types
186  *
187  */
188 exports.BIGINT = function(options) {
189     var ops = comb.merge({}, numberDefaults, {type : "BIGINT"}, options || {});
190     var cmpFun = function(val) {
191         if (ops.unsigned) {
192             if (val < 0 || val > 18446744073709551615) throw new Error("bigint out of range");
193         } else {
194             if (val < -9223372036854775808 || val > 9223372036854775807) throw new Error("bigint out of range");
195         }
196     };
197     ops.setSql = setNumberType(checkNumberType(ops.type, cmpFun), parseInt);
198     ops.checkType = checkNumberType(ops.type, cmpFun);
199     return new Type(ops);
200 };
201 
202 /**
203  * Mysql FLOAT datatype
204  *
205  * @function
206  * @param {Object} options options for the FLOAT data type.
207  * @param {Number} [options.size] max size of the number
208  * @param {Number} [options.digits] number of places right of the decimal
209  * @param {Boolean} [options.allowNull=true] should the field allow null
210  * @param {Boolean} [options.default = null] default value of the field
211  * @param {Boolean} [options.unsigned = false] unsigned number
212  * @param {Boolean} [options.description = ""] description fo the field.
213  *
214  * @return {Type} A Type representing a FLOAT column.
215  *
216  * @name FLOAT
217  * @memberOf moose.adapters.mysql.types
218  *
219  */
220 exports.FLOAT = function(options) {
221     var ops = comb.merge({}, numberDefaults, {type : "FLOAT"}, options || {});
222     ops.setSql = setNumberType(checkNumberType(ops.type), parseInt);
223     ops.checkType = checkNumberType(ops.type);
224     return new Type(ops);
225 };
226 
227 /**
228  * Mysql DOUBLE datatype
229  *
230  * @function
231  * @param {Object} options options for the DOUBLE data type.
232  * @param {Number} [options.size] max size of the number
233  * @param {Number} [options.digits] number of places right of the decimal
234  * @param {Boolean} [options.allowNull=true] should the field allow null
235  * @param {Boolean} [options.default = null] default value of the field
236  * @param {Boolean} [options.unsigned = false] unsigned number
237  * @param {Boolean} [options.description = ""] description fo the field.
238  *
239  * @return {Type} A Type representing a DOUBLE column.
240  *
241  * @name DOUBLE
242  * @memberOf moose.adapters.mysql.types
243  *
244  */
245 exports.DOUBLE = function(options) {
246     var ops = comb.merge({}, numberDefaults, {type : "DOUBLE"}, options || {});
247     ops.setSql = setNumberType(checkNumberType(ops.type), parseInt);
248     ops.checkType = checkNumberType(ops.type);
249     return new Type(ops);
250 };
251 
252 
253 /**
254  * Mysql DECIMAL datatype
255  *
256  * @function
257  * @param {Object} options options for the DOUBLE data type.
258  * @param {Number} [options.size] max size of the number
259  * @param {Number} [options.digits] number of places right of the decimal
260  * @param {Boolean} [options.allowNull=true] should the field allow null
261  * @param {Boolean} [options.default = null] default value of the field
262  * @param {Boolean} [options.unsigned = false] unsigned number
263  * @param {Boolean} [options.description = ""] description fo the field.
264  *
265  * @return {Type} A Type representing a DOUBLE column.
266  *
267  * @name DECIMAL
268  * @memberOf moose.adapters.mysql.types
269  *
270  */
271 exports.DECIMAL = function(options) {
272     var ops = comb.merge({}, numberDefaults, {type : "DECIMAL"}, options || {});
273     ops.setSql = setNumberType(checkNumberType(ops.type), parseInt);
274     ops.checkType = checkNumberType(ops.type);
275     return new Type(ops);
276 };