UNPKG

sequelize

Version:

Multi dialect ORM for Node.JS/io.js

994 lines (860 loc) 26.8 kB
'use strict'; /*jshint -W110 */ var util = require('util') , _ = require('lodash') , Wkt = require('terraformer-wkt-parser') , sequelizeErrors = require('./errors') , warnings = {} , Validator = require('validator') , momentTz = require('moment-timezone') , moment = require('moment'); /** * A convenience class holding commonly used data types. The datatypes are used when defining a new model using `Sequelize.define`, like this: * ```js * sequelize.define('model', { * column: DataTypes.INTEGER * }) * ``` * When defining a model you can just as easily pass a string as type, but often using the types defined here is beneficial. For example, using `DataTypes.BLOB`, mean * that that column will be returned as an instance of `Buffer` when being fetched by sequelize. * * Some data types have special properties that can be accessed in order to change the data type. * For example, to get an unsigned integer with zerofill you can do `DataTypes.INTEGER.UNSIGNED.ZEROFILL`. * The order you access the properties in do not matter, so `DataTypes.INTEGER.ZEROFILL.UNSIGNED` is fine as well. The available properties are listed under each data type. * * To provide a length for the data type, you can invoke it like a function: `INTEGER(2)` * * Three of the values provided here (`NOW`, `UUIDV1` and `UUIDV4`) are special default values, that should not be used to define types. Instead they are used as shorthands for * defining default values. For example, to get a uuid field with a default value generated following v1 of the UUID standard: * ```js * sequelize.define('model', { * uuid: { * type: DataTypes.UUID, * defaultValue: DataTypes.UUIDV1, * primaryKey: true * } * }) * ``` * There may be times when you want to generate your own UUID conforming to some other algorithm. This is accomplised * using the defaultValue property as well, but instead of specifying one of the supplied UUID types, you return a value * from a function. * ```js * sequelize.define('model', { * uuid: { * type: DataTypes.UUID, * defaultValue: function() { * return generateMyId() * }, * primaryKey: true * } * }) * ``` * * @class DataTypes */ var ABSTRACT = function(options) { }; ABSTRACT.prototype.dialectTypes = ''; ABSTRACT.prototype.toString = function(options) { return this.toSql(options); }; ABSTRACT.prototype.toSql = function() { return this.key; }; ABSTRACT.warn = function(link, text) { if (!warnings[text]) { warnings[text] = true; console.warn('>> WARNING:', text, '\n>> Check:', link); } }; ABSTRACT.prototype.stringify = function (value, options) { if (this.$stringify) { return this.$stringify(value, options); } return value; }; ABSTRACT.inherits = function (Constructor) { var baseType = this; if (!Constructor) { Constructor = function () { if (!(this instanceof Constructor)) { var args = [null].concat(arguments); var FactoryFunction = Constructor.bind.apply(Constructor, args); return new FactoryFunction(); } baseType.apply(this, arguments); }; } util.inherits(Constructor, baseType); // Instance (prototype) methods _.extend(Constructor, this); // Static methods return Constructor; }; /** * A variable length string. Default length 255 * * Available properties: `BINARY` * * @property STRING */ var STRING = ABSTRACT.inherits(function(length, binary) { var options = typeof length === 'object' && length || { length: length, binary: binary }; if (!(this instanceof STRING)) return new STRING(options); this.options = options; this._binary = options.binary; this._length = options.length || 255; }); STRING.prototype.key = STRING.key = 'STRING'; STRING.prototype.toSql = function() { return 'VARCHAR(' + this._length + ')' + ((this._binary) ? ' BINARY' : ''); }; STRING.prototype.validate = function(value) { if (Object.prototype.toString.call(value) !== '[object String]') { if ((this.options.binary && Buffer.isBuffer(value)) || _.isNumber(value)) { return true; } throw new sequelizeErrors.ValidationError(util.format('%j is not a valid string', value)); } return true; }; Object.defineProperty(STRING.prototype, 'BINARY', { get: function() { this._binary = true; this.options.binary = true; return this; } }); /** * A fixed length string. Default length 255 * * Available properties: `BINARY` * * @property CHAR */ var CHAR = STRING.inherits(function(length, binary) { var options = typeof length === 'object' && length || { length: length, binary: binary }; if (!(this instanceof CHAR)) return new CHAR(options); STRING.apply(this, arguments); }); CHAR.prototype.key = CHAR.key = 'CHAR'; CHAR.prototype.toSql = function() { return 'CHAR(' + this._length + ')' + ((this._binary) ? ' BINARY' : ''); }; /** * An (un)limited length text column. Available lengths: `tiny`, `medium`, `long` * @property TEXT */ var TEXT = ABSTRACT.inherits(function(length) { var options = typeof length === 'object' && length || { length: length }; if (!(this instanceof TEXT)) return new TEXT(options); this.options = options; this._length = options.length || ''; }); TEXT.prototype.key = TEXT.key = 'TEXT'; TEXT.prototype.toSql = function() { switch (this._length.toLowerCase()) { case 'tiny': return 'TINYTEXT'; case 'medium': return 'MEDIUMTEXT'; case 'long': return 'LONGTEXT'; default: return this.key; } }; TEXT.prototype.validate = function(value) { if (!_.isString(value)) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid string', value)); } return true; }; var NUMBER = ABSTRACT.inherits(function(options) { this.options = options; this._length = options.length; this._zerofill = options.zerofill; this._decimals = options.decimals; this._precision = options.precision; this._scale = options.scale; this._unsigned = options.unsigned; }); NUMBER.prototype.key = NUMBER.key = 'NUMBER'; NUMBER.prototype.toSql = function() { var result = this.key; if (this._length) { result += '(' + this._length; if (typeof this._decimals === 'number') { result += ',' + this._decimals; } result += ')'; } if (this._unsigned) { result += ' UNSIGNED'; } if (this._zerofill) { result += ' ZEROFILL'; } return result; }; NUMBER.prototype.validate = function(value) { if (!Validator.isFloat(String(value))) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid number', value)); } return true; }; Object.defineProperty(NUMBER.prototype, 'UNSIGNED', { get: function() { this._unsigned = true; this.options.unsigned = true; return this; } }); Object.defineProperty(NUMBER.prototype, 'ZEROFILL', { get: function() { this._zerofill = true; this.options.zerofill = true; return this; } }); /** * A 32 bit integer. * * Available properties: `UNSIGNED`, `ZEROFILL` * * @property INTEGER */ var INTEGER = NUMBER.inherits(function(length) { var options = typeof length === 'object' && length || { length: length }; if (!(this instanceof INTEGER)) return new INTEGER(options); NUMBER.call(this, options); }); INTEGER.prototype.key = INTEGER.key = 'INTEGER'; INTEGER.prototype.validate = function(value) { if (!Validator.isInt(String(value))) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid integer', value)); } return true; }; /** * A 64 bit integer. * * Note: an attribute defined as `BIGINT` will be treated like a `string` due this [feature from node-postgres](https://github.com/brianc/node-postgres/pull/353) to prevent precision loss. To have this attribute as a `number`, this is a possible [workaround](https://github.com/sequelize/sequelize/issues/2383#issuecomment-58006083). * * Available properties: `UNSIGNED`, `ZEROFILL` * * @property BIGINT */ var BIGINT = NUMBER.inherits(function(length) { var options = typeof length === 'object' && length || { length: length }; if (!(this instanceof BIGINT)) return new BIGINT(options); NUMBER.call(this, options); }); BIGINT.prototype.key = BIGINT.key = 'BIGINT'; BIGINT.prototype.validate = function(value) { if (!Validator.isInt(String(value))) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid bigint', value)); } return true; }; /** * Floating point number (4-byte precision). Accepts one or two arguments for precision * * Available properties: `UNSIGNED`, `ZEROFILL` * * @property FLOAT */ var FLOAT = NUMBER.inherits(function(length, decimals) { var options = typeof length === 'object' && length || { length: length, decimals: decimals }; if (!(this instanceof FLOAT)) return new FLOAT(options); NUMBER.call(this, options); }); FLOAT.prototype.key = FLOAT.key = 'FLOAT'; FLOAT.prototype.validate = function(value) { if (!Validator.isFloat(String(value))) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid float', value)); } return true; }; /** * Floating point number (4-byte precision). Accepts one or two arguments for precision * * Available properties: `UNSIGNED`, `ZEROFILL` * * @property REAL */ var REAL = NUMBER.inherits(function(length, decimals) { var options = typeof length === 'object' && length || { length: length, decimals: decimals }; if (!(this instanceof REAL)) return new REAL(options); NUMBER.call(this, options); }); REAL.prototype.key = REAL.key = 'REAL'; /** * Floating point number (8-byte precision). Accepts one or two arguments for precision * * Available properties: `UNSIGNED`, `ZEROFILL` * * @property DOUBLE */ var DOUBLE = NUMBER.inherits(function(length, decimals) { var options = typeof length === 'object' && length || { length: length, decimals: decimals }; if (!(this instanceof DOUBLE)) return new DOUBLE(options); NUMBER.call(this, options); }); DOUBLE.prototype.key = DOUBLE.key = 'DOUBLE PRECISION'; /** * Decimal number. Accepts one or two arguments for precision * * Available properties: `UNSIGNED`, `ZEROFILL` * * @property DECIMAL */ var DECIMAL = NUMBER.inherits(function(precision, scale) { var options = typeof precision === 'object' && precision || { precision: precision, scale: scale }; if (!(this instanceof DECIMAL)) return new DECIMAL(options); NUMBER.call(this, options); }); DECIMAL.prototype.key = DECIMAL.key = 'DECIMAL'; DECIMAL.prototype.toSql = function() { if (this._precision || this._scale) { return 'DECIMAL(' + [this._precision, this._scale].filter(_.identity).join(',') + ')'; } return 'DECIMAL'; }; DECIMAL.prototype.validate = function(value) { if (!Validator.isDecimal(String(value))) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid decimal', value)); } return true; }; [FLOAT, DOUBLE, REAL].forEach(function (floating) { floating.prototype.escape = false; floating.prototype.$stringify = function (value) { if (isNaN(value)) { return "'NaN'"; } else if (!isFinite(value)) { var sign = value < 0 ? '-' : ''; return "'" + sign + "Infinity'"; } return value; }; }); /** * A boolean / tinyint column, depending on dialect * @property BOOLEAN */ var BOOLEAN = ABSTRACT.inherits(); BOOLEAN.prototype.key = BOOLEAN.key = 'BOOLEAN'; BOOLEAN.prototype.toSql = function() { return 'TINYINT(1)'; }; BOOLEAN.prototype.validate = function(value) { if (!Validator.isBoolean(String(value))) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid boolean', value)); } return true; }; /** * A time column * @property TIME */ var TIME = ABSTRACT.inherits(); TIME.prototype.key = TIME.key = 'TIME'; TIME.prototype.toSql = function() { return 'TIME'; }; /** * A datetime column * @property DATE */ var DATE = ABSTRACT.inherits(function (length) { var options = typeof length === 'object' && length || { length: length }; if (!(this instanceof DATE)) return new DATE(options); this.options = options; this._length = options.length || ''; }); DATE.prototype.key = DATE.key = 'DATE'; DATE.prototype.toSql = function() { return 'DATETIME'; }; DATE.prototype.validate = function(value) { if (!Validator.isDate(String(value))) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid date', value)); } return true; }; DATE.prototype.$applyTimezone = function (date, options) { if (options.timezone) { if (momentTz.tz.zone(options.timezone)) { date = momentTz(date).tz(options.timezone); } else { date = moment(date).utcOffset(options.timezone); } } else { date = momentTz(date); } return date; }; DATE.prototype.$stringify = function (date, options) { date = this.$applyTimezone(date, options); // Z here means current timezone, _not_ UTC return date.format('YYYY-MM-DD HH:mm:ss.SSS Z'); }; /** * A date only column * @property DATEONLY */ var DATEONLY = function() { if (!(this instanceof DATEONLY)) return new DATEONLY(); ABSTRACT.apply(this, arguments); }; util.inherits(DATEONLY, ABSTRACT); DATEONLY.prototype.key = DATEONLY.key = 'DATEONLY'; DATEONLY.prototype.toSql = function() { return 'DATE'; }; /** * A key / value column. Only available in postgres. * @property HSTORE */ var HSTORE = ABSTRACT.inherits(); HSTORE.prototype.key = HSTORE.key = 'HSTORE'; HSTORE.prototype.validate = function(value) { if (!_.isPlainObject(value)) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid hstore', value)); } return true; }; /** * A JSON string column. Only available in postgres. * @property JSON */ var JSONTYPE = function() { if (!(this instanceof JSONTYPE)) return new JSONTYPE(); ABSTRACT.apply(this, arguments); }; util.inherits(JSONTYPE, ABSTRACT); JSONTYPE.prototype.key = JSONTYPE.key = 'JSON'; JSONTYPE.prototype.validate = function(value) { return true; }; JSONTYPE.prototype.$stringify = function (value, options) { return JSON.stringify(value); }; /** * A pre-processed JSON data column. Only available in postgres. * @property JSONB */ var JSONB = function() { if (!(this instanceof JSONB)) return new JSONB(); JSONTYPE.apply(this, arguments); }; util.inherits(JSONB, JSONTYPE); JSONB.prototype.key = JSONB.key = 'JSONB'; /** * A default value of the current timestamp * @property NOW */ var NOW = ABSTRACT.inherits(); NOW.prototype.key = NOW.key = 'NOW'; /** * Binary storage. Available lengths: `tiny`, `medium`, `long` * * @property BLOB */ var BLOB = ABSTRACT.inherits(function(length) { var options = typeof length === 'object' && length || { length: length }; if (!(this instanceof BLOB)) return new BLOB(options); this.options = options; this._length = options.length || ''; }); BLOB.prototype.key = BLOB.key = 'BLOB'; BLOB.prototype.toSql = function() { switch (this._length.toLowerCase()) { case 'tiny': return 'TINYBLOB'; case 'medium': return 'MEDIUMBLOB'; case 'long': return 'LONGBLOB'; default: return this.key; } }; BLOB.prototype.validate = function(value) { if (!_.isString(value) && !Buffer.isBuffer(value)) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid blob', value)); } return true; }; BLOB.prototype.escape = false; BLOB.prototype.$stringify = function (value) { if (!Buffer.isBuffer(value)) { if (Array.isArray(value)) { value = new Buffer(value); } else { value = new Buffer(value.toString()); } } var hex = value.toString('hex'); return this.$hexify(hex); }; BLOB.prototype.$hexify = function (hex) { return "X'" + hex + "'"; }; /** * Range types are data types representing a range of values of some element type (called the range's subtype). * Only available in postgres. * See {@link http://www.postgresql.org/docs/9.4/static/rangetypes.html|Postgres documentation} for more details * @property RANGE */ var RANGE = ABSTRACT.inherits(function (subtype) { var options = _.isPlainObject(subtype) ? subtype : { subtype: subtype }; if (!options.subtype) options.subtype = new INTEGER(); if (_.isFunction(options.subtype)) { options.subtype = new options.subtype(); } if (!(this instanceof RANGE)) return new RANGE(options); ABSTRACT.apply(this, arguments); this._subtype = options.subtype.key; this.options = options; }); var pgRangeSubtypes = { integer: 'int4range', bigint: 'int8range', decimal: 'numrange', dateonly: 'daterange', date: 'tstzrange', datenotz: 'tsrange' }; RANGE.prototype.key = RANGE.key = 'RANGE'; RANGE.prototype.toSql = function() { return pgRangeSubtypes[this._subtype.toLowerCase()]; }; RANGE.prototype.validate = function(value) { if (_.isPlainObject(value) && value.inclusive) { value = value.inclusive; } if (!_.isArray(value)) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid range', value)); } if (value.length !== 2) { throw new sequelizeErrors.ValidationError('A range must be an array with two elements'); } return true; }; /** * A column storing a unique universal identifier. Use with `UUIDV1` or `UUIDV4` for default values. * @property UUID */ var UUID = ABSTRACT.inherits(); UUID.prototype.key = UUID.key = 'UUID'; UUID.prototype.validate = function(value, options) { if (!_.isString(value) || !Validator.isUUID(value) && (!options || !options.acceptStrings)) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid uuid', value)); } return true; }; /** * A default unique universal identifier generated following the UUID v1 standard * @property UUIDV1 */ var UUIDV1 = function() { if (!(this instanceof UUIDV1)) return new UUIDV1(); ABSTRACT.apply(this, arguments); }; util.inherits(UUIDV1, ABSTRACT); UUIDV1.prototype.key = UUIDV1.key = 'UUIDV1'; UUIDV1.prototype.validate = function(value, options) { if (!_.isString(value) || !Validator.isUUID(value) && (!options || !options.acceptStrings)) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid uuid', value)); } return true; }; /** * A default unique universal identifier generated following the UUID v4 standard * @property UUIDV4 */ var UUIDV4 = function() { if (!(this instanceof UUIDV4)) return new UUIDV4(); ABSTRACT.apply(this, arguments); }; util.inherits(UUIDV4, ABSTRACT); UUIDV4.prototype.key = UUIDV4.key = 'UUIDV4'; UUIDV4.prototype.validate = function(value, options) { if (!_.isString(value) || !Validator.isUUID(value, 4) && (!options || !options.acceptStrings)) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid uuidv4', value)); } return true; }; /** * A virtual value that is not stored in the DB. This could for example be useful if you want to provide a default value in your model that is returned to the user but not stored in the DB. * * You could also use it to validate a value before permuting and storing it. Checking password length before hashing it for example: * ```js * sequelize.define('user', { * password_hash: DataTypes.STRING, * password: { * type: DataTypes.VIRTUAL, * set: function (val) { * this.setDataValue('password', val); // Remember to set the data value, otherwise it won't be validated * this.setDataValue('password_hash', this.salt + val); * }, * validate: { * isLongEnough: function (val) { * if (val.length < 7) { * throw new Error("Please choose a longer password") * } * } * } * } * }) * ``` * In the above code the password is stored plainly in the password field so it can be validated, but is never stored in the DB. * * VIRTUAL also takes a return type and dependency fields as arguments * If a virtual attribute is present in `attributes` it will automatically pull in the extra fields as well. * Return type is mostly useful for setups that rely on types like GraphQL. * ```js * { * active: { * type: new DataTypes.VIRTUAL(DataTypes.BOOLEAN, ['createdAt']), * get: function() { * return this.get('createdAt') > Date.now() - (7 * 24 * 60 * 60 * 1000) * } * } * } * ``` * * @property VIRTUAL * @alias NONE */ var VIRTUAL = function(ReturnType, fields) { if (!(this instanceof VIRTUAL)) return new VIRTUAL(ReturnType, fields); if (typeof ReturnType === 'function') ReturnType = new ReturnType(); this.returnType = ReturnType; this.fields = fields; }; util.inherits(VIRTUAL, ABSTRACT); VIRTUAL.prototype.key = VIRTUAL.key = 'VIRTUAL'; /** * An enumeration. `DataTypes.ENUM('value', 'another value')`. * * @property ENUM */ var ENUM = ABSTRACT.inherits(function(value) { var options = typeof value === 'object' && !Array.isArray(value) && value || { values: Array.prototype.slice.call(arguments).reduce(function(result, element) { return result.concat(Array.isArray(element) ? element : [element]); }, []) }; if (!(this instanceof ENUM)) return new ENUM(options); this.values = options.values; this.options = options; }); ENUM.prototype.key = ENUM.key = 'ENUM'; ENUM.prototype.validate = function(value) { if (!_.includes(this.values, value)) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid choice in %j', value, this.values)); } return true; }; /** * An array of `type`, e.g. `DataTypes.ARRAY(DataTypes.DECIMAL)`. Only available in postgres. * @property ARRAY */ var ARRAY = function(type) { var options = _.isPlainObject(type) ? type : { type: type }; if (!(this instanceof ARRAY)) return new ARRAY(options); this.type = typeof options.type === 'function' ? new options.type() : options.type; }; util.inherits(ARRAY, ABSTRACT); ARRAY.prototype.key = ARRAY.key = 'ARRAY'; ARRAY.prototype.toSql = function() { return this.type.toSql() + '[]'; }; ARRAY.prototype.validate = function(value) { if (!_.isArray(value)) { throw new sequelizeErrors.ValidationError(util.format('%j is not a valid array', value)); } return true; }; ARRAY.is = function(obj, type) { return obj instanceof ARRAY && obj.type instanceof type; }; var helpers = { BINARY: [STRING, CHAR], UNSIGNED: [NUMBER, INTEGER, BIGINT, FLOAT, DOUBLE, REAL], ZEROFILL: [NUMBER, INTEGER, BIGINT, FLOAT, DOUBLE, REAL], PRECISION: [DECIMAL], SCALE: [DECIMAL] }; /** * A column storing Geometry information. * * Only available in PostgreSQL (with PostGIS) or MySQL. * In MySQL, allowable Geometry types are 'POINT', 'LINESTRING', 'POLYGON'. * * When using, GeoJSON is accepted as input and returned as output. * In PostGIS, the GeoJSON is parsed using the PostGIS function `ST_GeomFromGeoJSON`. * In MySQL it is parsed using the function `GeomFromText`. * Therefore, one can just follow the [GeoJSON spec](http://geojson.org/geojson-spec.html) for handling geometry objects. See the following examples: * * ```js * // Create a new point: * var point = { type: 'Point', coordinates: [39.807222,-76.984722]}; * * User.create({username: 'username', geometry: point }).then(function(newUser) { * ... * }); * * // Create a new linestring: * var line = { type: 'LineString', 'coordinates': [ [100.0, 0.0], [101.0, 1.0] ] }; * * User.create({username: 'username', geometry: line }).then(function(newUser) { * ... * }); * * // Create a new polygon: * var polygon = { type: 'Polygon', coordinates: [ * [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], * [100.0, 1.0], [100.0, 0.0] ] * ]}; * * User.create({username: 'username', geometry: polygon }).then(function(newUser) { * ... * }); * // Create a new point with a custom SRID: * var point = { * type: 'Point', * coordinates: [39.807222,-76.984722], * crs: { type: 'name', properties: { name: 'EPSG:4326'} } * }; * * User.create({username: 'username', geometry: point }).then(function(newUser) { * ... * }); * ``` * * @property GEOMETRY */ var GEOMETRY = ABSTRACT.inherits(function(type, srid) { var options = _.isPlainObject(type) ? type : { type: type, srid: srid }; if (!(this instanceof GEOMETRY)) return new GEOMETRY(options); this.options = options; this.type = options.type; this.srid = options.srid; }); GEOMETRY.prototype.key = GEOMETRY.key = 'GEOMETRY'; GEOMETRY.prototype.escape = false; GEOMETRY.prototype.$stringify = function (value, options) { return 'GeomFromText(' + options.escape(Wkt.convert(value)) + ')'; }; /** * A geography datatype represents two dimensional spacial objects in an elliptic coord system. * @property GEOGRAPHY */ var GEOGRAPHY = ABSTRACT.inherits(function(type, srid) { var options = _.isPlainObject(type) ? type : { type: type, srid: srid }; if (!(this instanceof GEOGRAPHY)) return new GEOGRAPHY(options); this.options = options; this.type = options.type; this.srid = options.srid; }); GEOGRAPHY.prototype.key = GEOGRAPHY.key = 'GEOGRAPHY'; GEOGRAPHY.prototype.escape = false; GEOGRAPHY.prototype.$stringify = function (value, options) { return 'GeomFromText(' + options.escape(Wkt.convert(value)) + ')'; }; Object.keys(helpers).forEach(function (helper) { helpers[helper].forEach(function (DataType) { if (!DataType[helper]) { Object.defineProperty(DataType, helper, { get: function() { var dataType = new DataType(); if (typeof dataType[helper] === 'object') { return dataType; } return dataType[helper].apply(dataType, arguments); } }); } }); }); var dataTypes = { ABSTRACT: ABSTRACT, STRING: STRING, CHAR: CHAR, TEXT: TEXT, NUMBER: NUMBER, INTEGER: INTEGER, BIGINT: BIGINT, FLOAT: FLOAT, TIME: TIME, DATE: DATE, DATEONLY: DATEONLY, BOOLEAN: BOOLEAN, NOW: NOW, BLOB: BLOB, DECIMAL: DECIMAL, NUMERIC: DECIMAL, UUID: UUID, UUIDV1: UUIDV1, UUIDV4: UUIDV4, HSTORE: HSTORE, JSON: JSONTYPE, JSONB: JSONB, VIRTUAL: VIRTUAL, ARRAY: ARRAY, NONE: VIRTUAL, ENUM: ENUM, RANGE: RANGE, REAL: REAL, DOUBLE: DOUBLE, 'DOUBLE PRECISION': DOUBLE, GEOMETRY: GEOMETRY, GEOGRAPHY: GEOGRAPHY }; _.each(dataTypes, function (dataType) { dataType.types = {}; }); dataTypes.postgres = require('./dialects/postgres/data-types')(dataTypes); dataTypes.mysql = require('./dialects/mysql/data-types')(dataTypes); dataTypes.mariadb = dataTypes.mysql; dataTypes.sqlite = require('./dialects/sqlite/data-types')(dataTypes); dataTypes.mssql = require('./dialects/mssql/data-types')(dataTypes); module.exports = dataTypes;