不要怂,就是干,撸起袖子干!

Commit 0234f990 by Mick Hansen

Merge

2 parents cc287b03 ab8850e6
...@@ -30,7 +30,7 @@ branches: ...@@ -30,7 +30,7 @@ branches:
only: only:
- master - master
- milestones/2.0.0 - milestones/2.0.0
cache: cache:
directories: directories:
- node_modules - node_modules
...@@ -16,11 +16,10 @@ To install 2.x.x branch - which has a unstable API and will break backwards comp ...@@ -16,11 +16,10 @@ To install 2.x.x branch - which has a unstable API and will break backwards comp
- [Getting Started](http://sequelizejs.com/articles/getting-started) - [Getting Started](http://sequelizejs.com/articles/getting-started)
- [Documentation](http://sequelizejs.com/docs) - [Documentation](http://sequelizejs.com/docs)
<<<<<<< HEAD - [API Reference](https://github.com/sequelize/sequelize/wiki/API-Reference) *Work in progress*
======= - [Changelog](https://github.com/sequelize/sequelize/blob/master/changelog.md)
- [Collaboration and pull requests](https://github.com/sequelize/sequelize/wiki/Collaboration) - [Collaboration and pull requests](https://github.com/sequelize/sequelize/wiki/Collaboration)
- [Roadmap](https://github.com/sequelize/sequelize/wiki/Roadmap) - [Roadmap](https://github.com/sequelize/sequelize/wiki/Roadmap)
>>>>>>> master
## Important Notes ## ## Important Notes ##
......
Notice: All 1.7.x changed are present in 2.0.x aswell
# v2.0.0 (alpha1) # # v2.0.0 (alpha1) #
- [FEATURE] async validations. [#580](https://github.com/sequelize/sequelize/pull/580). thanks to Interlock - [FEATURE] async validations. [#580](https://github.com/sequelize/sequelize/pull/580). thanks to Interlock
# v1.7.0 # # v1.7.0-beta8
- max()/min() now supports dates [#1200](https://github.com/sequelize/sequelize/pull/1200)
- findAndCountAll now supports the include option
#### Backwards compatibility changes
- You will now need to include the relevant subtables to query on them in finders (find/findAll)
- Subquery logic no longer depends on where objects with keys containing '.', instead where options on the include options [#1199](https://github.com/sequelize/sequelize/pull/1199)
# v1.7.0-beta7 #
- Nested eager loading / prefetching is now supported. [Docs](http://sequelizejs.com/docs/latest/models#nested-eager-loading)
- Eager loading / prefetching now supports inner joins and extending the ON statement [#1199](https://github.com/sequelize/sequelize/pull/1199)
- Eager loading / prefetching now returns the attributes of through models aswell [#1198](https://github.com/sequelize/sequelize/pull/1198)
- New set/get/changed/previous feature [#1182](https://github.com/sequelize/sequelize/pull/1182)
- Various bug fixes
#### Backwards compatibility changes
None
# v1.7.0-beta1 #
- [DEPENDENCIES] Upgraded validator for IPv6 support. [#603](https://github.com/sequelize/sequelize/pull/603). thanks to durango - [DEPENDENCIES] Upgraded validator for IPv6 support. [#603](https://github.com/sequelize/sequelize/pull/603). thanks to durango
- [DEPENDENCIES] replaced underscore by lodash. [#954](https://github.com/sequelize/sequelize/pull/594). thanks to durango - [DEPENDENCIES] replaced underscore by lodash. [#954](https://github.com/sequelize/sequelize/pull/594). thanks to durango
- [DEPENDENCIES] Upgraded pg to 2.0.0. [#711](https://github.com/sequelize/sequelize/pull/711). thanks to durango - [DEPENDENCIES] Upgraded pg to 2.0.0. [#711](https://github.com/sequelize/sequelize/pull/711). thanks to durango
......
...@@ -39,8 +39,8 @@ module.exports = (function() { ...@@ -39,8 +39,8 @@ module.exports = (function() {
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.source.tableName, this.source.options.language) + "Id", this.options.underscored) this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.source.tableName, this.source.options.language) + "Id", this.options.underscored)
newAttributes[this.identifier] = { type: this.options.keyType || keyType } newAttributes[this.identifier] = { type: this.options.keyType || keyType }
Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.source, this.target, this.options)
Utils._.defaults(this.target.rawAttributes, newAttributes) Utils._.defaults(this.target.rawAttributes, newAttributes)
Helpers.addForeignKeyConstraints(this.target.rawAttributes[this.identifier], this.source, this.target, this.options)
// Sync attributes and setters/getters to DAO prototype // Sync attributes and setters/getters to DAO prototype
this.target.refreshAttributes() this.target.refreshAttributes()
......
...@@ -66,6 +66,10 @@ module.exports = (function() { ...@@ -66,6 +66,10 @@ module.exports = (function() {
} }
}) })
Object.defineProperty(DAOFactory.prototype, 'sequelize', {
get: function() { return this.daoFactoryManager.sequelize }
})
Object.defineProperty(DAOFactory.prototype, 'QueryInterface', { Object.defineProperty(DAOFactory.prototype, 'QueryInterface', {
get: function() { return this.daoFactoryManager.sequelize.getQueryInterface() } get: function() { return this.daoFactoryManager.sequelize.getQueryInterface() }
}) })
...@@ -535,69 +539,84 @@ module.exports = (function() { ...@@ -535,69 +539,84 @@ module.exports = (function() {
}, queryOptions)) }, queryOptions))
} }
DAOFactory.prototype.count = function(options) { DAOFactory.prototype.aggregate = function(field, aggregateFunction, options) {
var tableField;
if (field == '*') {
tableField = field
} else {
tableField = this.QueryInterface.QueryGenerator.quoteIdentifier(field)
}
options = Utils._.extend({ attributes: [] }, options || {}) options = Utils._.extend({ attributes: [] }, options || {})
options.attributes.push(['count(*)', 'count']) options.attributes.push([aggregateFunction + '(' + tableField + ')', aggregateFunction])
options.parseInt = true
if (!options.dataType) {
if (this.rawAttributes[field]) {
options.dataType = this.rawAttributes[field]
} else {
// Use FLOAT as fallback
options.dataType = DataTypes.FLOAT
}
}
options = paranoidClause.call(this, options) options = paranoidClause.call(this, options)
return this.QueryInterface.rawSelect(this.getTableName(), options, 'count') return this.QueryInterface.rawSelect(this.getTableName(), options, aggregateFunction)
} }
DAOFactory.prototype.findAndCountAll = function(options, queryOptions) { DAOFactory.prototype.count = function(options) {
options = Utils._.clone(options || {})
return new Utils.CustomEventEmitter(function (emitter) {
options.attributes = [
[this.sequelize.fn('COUNT', this.sequelize.col(this.tableName+'.*')), 'count']
]
options.includeIgnoreAttributes = false
this.find(options, {raw: true, transaction: options.transaction}).proxy(emitter, {events: ['sql', 'error']}).success(function (result) {
emitter.emit('success', parseInt(result.count, 10))
})
}.bind(this)).run()
}
DAOFactory.prototype.findAndCountAll = function(findOptions, queryOptions) {
var self = this var self = this
// no limit, offset, order, attributes or include for the options given to count() // no limit, offset, order, attributes for the options given to count()
, copts = Utils._.omit(options || {}, ['offset', 'limit', 'order', 'include', 'attributes']) , countOptions = Utils._.omit(findOptions || {}, ['offset', 'limit', 'order', 'attributes'])
return new Utils.CustomEventEmitter(function (emitter) { return new Utils.CustomEventEmitter(function (emitter) {
var emit = { var emit = {
err : function(e) { // emit error okay : function(count, results) { // emit success
emitter.emit('error', e); emitter.emit('success', {
} count: count || 0,
, okay : function(c, r) { // emit success rows : (results && Array.isArray(results) ? results : [])
emitter.emit('success', { })
count: c || 0,
rows : (r && Array.isArray(r) ? r : [])
});
}
, sql : function(s) { // emit SQL
emitter.emit('sql', s);
}
} }
}
self.count(copts) self.count(countOptions)
.on('sql', emit.sql) .proxy(emitter, {events: ['sql', 'error']})
.error(emit.err) .success(function(count) {
.success(function(cnt) { if (count === 0) {
if (cnt === 0) { return emit.okay(count) // no records, no need for another query
return emit.okay(cnt) // no records, no need for another query
} }
self.findAll(options, queryOptions) self.findAll(findOptions, queryOptions)
.on('sql', emit.sql) .proxy(emitter, {events: ['sql', 'error']})
.error(emit.err) .success(function(results) {
.success(function(rows) { emit.okay(count, results)
emit.okay(cnt, rows) })
})
}) })
}).run() }).run()
} }
DAOFactory.prototype.max = function(field, options) { DAOFactory.prototype.max = function(field, options) {
options = Utils._.extend({ attributes: [] }, options || {}) return this.aggregate(field, 'max', options)
options.attributes.push(['max(' + this.QueryInterface.QueryGenerator.quoteIdentifier(field) + ')', 'max'])
options.parseFloat = true
return this.QueryInterface.rawSelect(this.getTableName(), options, 'max')
} }
DAOFactory.prototype.min = function(field, options) {
options = Utils._.extend({ attributes: [] }, options || {})
options.attributes.push(['min(' + this.QueryInterface.QueryGenerator.quoteIdentifier(field) + ')', 'min'])
options.parseFloat = true
return this.QueryInterface.rawSelect(this.getTableName(), options, 'min') DAOFactory.prototype.min = function(field, options) {
return this.aggregate(field, 'min', options)
} }
DAOFactory.prototype.build = function(values, options) { DAOFactory.prototype.build = function(values, options) {
...@@ -1270,11 +1289,15 @@ module.exports = (function() { ...@@ -1270,11 +1289,15 @@ module.exports = (function() {
options.include = options.include.map(function(include) { options.include = options.include.map(function(include) {
include = validateIncludedElement.call(this, include, options.daoFactory) include = validateIncludedElement.call(this, include, options.daoFactory)
options.includeMap[include.as] = include
options.includeNames.push(include.as)
if (include.association.isMultiAssociation) options.hasMultiAssociation = true if (include.association.isMultiAssociation) options.hasMultiAssociation = true
if (include.association.isSingleAssociation) options.hasSingleAssociation = true if (include.association.isSingleAssociation) options.hasSingleAssociation = true
options.includeMap[include.as] = include options.hasIncludeWhere = options.hasIncludeWhere || include.hasIncludeWhere || !!include.where
options.includeNames.push(include.as) options.hasIncludeRequired = options.hasIncludeRequired || include.hasIncludeRequired || !!include.required
return include return include
}.bind(this)) }.bind(this))
}; };
......
...@@ -608,14 +608,6 @@ module.exports = (function() { ...@@ -608,14 +608,6 @@ module.exports = (function() {
return result return result
} }
DAO.prototype.addAttribute = function(attribute, value) {
if (this.booleanValues.length && this.booleanValues.indexOf(attribute) !== -1 && value != null) { // transform integer 0,1 into boolean
value = !!value
}
this[attribute] = value;
}
DAO.prototype.setValidators = function(attribute, validators) { DAO.prototype.setValidators = function(attribute, validators) {
this.validators[attribute] = validators this.validators[attribute] = validators
} }
......
...@@ -46,6 +46,10 @@ var BLOB = function() { ...@@ -46,6 +46,10 @@ var BLOB = function() {
return BLOB.prototype.construct.apply(this, [BLOB].concat(Array.prototype.slice.apply(arguments))) return BLOB.prototype.construct.apply(this, [BLOB].concat(Array.prototype.slice.apply(arguments)))
} }
var DECIMAL = function() {
return DECIMAL.prototype.construct.apply(this, [DECIMAL].concat(Array.prototype.slice.apply(arguments)))
}
FLOAT._type = FLOAT FLOAT._type = FLOAT
FLOAT._typeName = 'FLOAT' FLOAT._typeName = 'FLOAT'
INTEGER._type = INTEGER INTEGER._type = INTEGER
...@@ -56,8 +60,11 @@ STRING._type = STRING ...@@ -56,8 +60,11 @@ STRING._type = STRING
STRING._typeName = 'VARCHAR' STRING._typeName = 'VARCHAR'
BLOB._type = BLOB BLOB._type = BLOB
BLOB._typeName = 'BLOB' BLOB._typeName = 'BLOB'
DECIMAL._type = DECIMAL
DECIMAL._typeName = 'DECIMAL'
BLOB.toString = STRING.toString = INTEGER.toString = FLOAT.toString = BIGINT.toString = function() { BLOB.toString = STRING.toString = INTEGER.toString = FLOAT.toString = BIGINT.toString = DECIMAL.toString = function() {
return new this._type().toString() return new this._type().toString()
} }
...@@ -145,6 +152,47 @@ FLOAT.prototype = BIGINT.prototype = INTEGER.prototype = { ...@@ -145,6 +152,47 @@ FLOAT.prototype = BIGINT.prototype = INTEGER.prototype = {
} }
} }
DECIMAL.prototype = {
construct: function(RealType, precision, scale) {
if (this instanceof RealType) {
this._typeName = RealType._typeName
if (typeof precision === 'number') {
this._precision = precision
} else {
this._precision = 0
}
if (typeof scale === 'number') {
this._scale = scale
} else {
this._scale = 0
}
} else {
return new RealType(precision, scale)
}
},
get type() {
return this.toString()
},
get PRECISION() {
return this._precision
},
get SCALE() {
return this._scale
},
toString: function() {
if (this._precision || this._scale) {
return 'DECIMAL(' + this._precision + ',' + this._scale + ')'
}
return 'DECIMAL'
}
}
var unsignedDesc = { var unsignedDesc = {
get: function() { get: function() {
return new this._type(undefined, undefined, true) return new this._type(undefined, undefined, true)
...@@ -163,11 +211,18 @@ var typeDesc = { ...@@ -163,11 +211,18 @@ var typeDesc = {
} }
} }
var decimalDesc = {
get: function() {
return new this._type(undefined, undefined, undefined)
}
}
Object.defineProperty(STRING, 'type', typeDesc) Object.defineProperty(STRING, 'type', typeDesc)
Object.defineProperty(INTEGER, 'type', typeDesc) Object.defineProperty(INTEGER, 'type', typeDesc)
Object.defineProperty(BIGINT, 'type', typeDesc) Object.defineProperty(BIGINT, 'type', typeDesc)
Object.defineProperty(FLOAT, 'type', typeDesc) Object.defineProperty(FLOAT, 'type', typeDesc)
Object.defineProperty(BLOB, 'type', typeDesc) Object.defineProperty(BLOB, 'type', typeDesc)
Object.defineProperty(DECIMAL, 'type', typeDesc)
Object.defineProperty(INTEGER, 'UNSIGNED', unsignedDesc) Object.defineProperty(INTEGER, 'UNSIGNED', unsignedDesc)
Object.defineProperty(BIGINT, 'UNSIGNED', unsignedDesc) Object.defineProperty(BIGINT, 'UNSIGNED', unsignedDesc)
...@@ -177,6 +232,9 @@ Object.defineProperty(INTEGER, 'ZEROFILL', zerofillDesc) ...@@ -177,6 +232,9 @@ Object.defineProperty(INTEGER, 'ZEROFILL', zerofillDesc)
Object.defineProperty(BIGINT, 'ZEROFILL', zerofillDesc) Object.defineProperty(BIGINT, 'ZEROFILL', zerofillDesc)
Object.defineProperty(FLOAT, 'ZEROFILL', zerofillDesc) Object.defineProperty(FLOAT, 'ZEROFILL', zerofillDesc)
Object.defineProperty(DECIMAL, 'PRECISION', decimalDesc)
Object.defineProperty(DECIMAL, 'SCALE', decimalDesc)
module.exports = { module.exports = {
STRING: STRING, STRING: STRING,
...@@ -188,6 +246,7 @@ module.exports = { ...@@ -188,6 +246,7 @@ module.exports = {
FLOAT: FLOAT, FLOAT: FLOAT,
NOW: 'NOW', NOW: 'NOW',
BLOB: BLOB, BLOB: BLOB,
DECIMAL: DECIMAL,
UUID: 'UUID', UUID: 'UUID',
UUIDV1: 'UUIDV1', UUIDV1: 'UUIDV1',
UUIDV4: 'UUIDV4', UUIDV4: 'UUIDV4',
...@@ -207,16 +266,6 @@ module.exports = { ...@@ -207,16 +266,6 @@ module.exports = {
return result return result
}, },
get DECIMAL() {
var result = function(precision, scale) {
return 'DECIMAL(' + precision + ',' + scale + ')'
}
result.toString = result.valueOf = function() { return 'DECIMAL' }
return result
},
ARRAY: function(type) { return type + '[]' }, ARRAY: function(type) { return type + '[]' },
get HSTORE() { get HSTORE() {
......
...@@ -364,6 +364,7 @@ module.exports = (function() { ...@@ -364,6 +364,7 @@ module.exports = (function() {
}) })
delete result.__children delete result.__children
}) })
return results return results
} }
......
var _ = require('lodash') var _ = require('lodash')
, MySQL = require('./mysql') , MySQL = require('../mysql')
var MariaDialect = function(sequelize) { var MariaDialect = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize
...@@ -9,4 +9,4 @@ MariaDialect.prototype = _.extend({ ...@@ -9,4 +9,4 @@ MariaDialect.prototype = _.extend({
}, MySQL.prototype) }, MySQL.prototype)
module.exports = MariaDialect module.exports = MariaDialect
\ No newline at end of file
var _ = require('lodash') var _ = require('lodash')
, Abstract = require('./abstract/dialect') , Abstract = require('../abstract')
var MysqlDialect = function(sequelize) { var MysqlDialect = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize
...@@ -9,4 +9,4 @@ MysqlDialect.prototype.supports = _.extend(Abstract.prototype.supports, { ...@@ -9,4 +9,4 @@ MysqlDialect.prototype.supports = _.extend(Abstract.prototype.supports, {
'VALUES ()': true 'VALUES ()': true
}) })
module.exports = MysqlDialect module.exports = MysqlDialect
\ No newline at end of file
...@@ -374,6 +374,7 @@ module.exports = (function() { ...@@ -374,6 +374,7 @@ module.exports = (function() {
}, },
addLimitAndOffset: function(options, query){ addLimitAndOffset: function(options, query){
query = query || ""
if (options.offset && !options.limit) { if (options.offset && !options.limit) {
query += " LIMIT " + options.offset + ", " + 18440000000000000000; query += " LIMIT " + options.offset + ", " + 18440000000000000000;
} else if (options.limit && !(options.include && (options.limit === 1))) { } else if (options.limit && !(options.include && (options.limit === 1))) {
...@@ -387,6 +388,7 @@ module.exports = (function() { ...@@ -387,6 +388,7 @@ module.exports = (function() {
}, },
quoteIdentifier: function(identifier, force) { quoteIdentifier: function(identifier, force) {
if (identifier === '*') return identifier
return Utils.addTicks(identifier, "`") return Utils.addTicks(identifier, "`")
}, },
......
var _ = require('lodash') var _ = require('lodash')
, Abstract = require('./abstract/dialect') , Abstract = require('../abstract')
var PostgresDialect = function(sequelize) { var PostgresDialect = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize
...@@ -10,4 +10,4 @@ PostgresDialect.prototype.supports = _.extend(Abstract.prototype.supports, { ...@@ -10,4 +10,4 @@ PostgresDialect.prototype.supports = _.extend(Abstract.prototype.supports, {
'DEFAULT VALUES': true 'DEFAULT VALUES': true
}) })
module.exports = PostgresDialect module.exports = PostgresDialect
\ No newline at end of file
...@@ -389,6 +389,7 @@ module.exports = (function() { ...@@ -389,6 +389,7 @@ module.exports = (function() {
}, },
addLimitAndOffset: function(options, query){ addLimitAndOffset: function(options, query){
query = query || ""
if (!(options.include && (options.limit === 1))) { if (!(options.include && (options.limit === 1))) {
if (options.limit) { if (options.limit) {
query += " LIMIT " + options.limit query += " LIMIT " + options.limit
...@@ -774,6 +775,7 @@ module.exports = (function() { ...@@ -774,6 +775,7 @@ module.exports = (function() {
}, },
quoteIdentifier: function(identifier, force) { quoteIdentifier: function(identifier, force) {
if (identifier === '*') return identifier
if(!force && this.options && this.options.quoteIdentifiers === false) { // default is `true` if(!force && this.options && this.options.quoteIdentifiers === false) { // default is `true`
// In Postgres, if tables or attributes are created double-quoted, // In Postgres, if tables or attributes are created double-quoted,
// they are also case sensitive. If they contain any uppercase // they are also case sensitive. If they contain any uppercase
......
var _ = require('lodash') var _ = require('lodash')
, Abstract = require('./abstract/dialect') , Abstract = require('../abstract')
var SqliteDialect = function(sequelize) { var SqliteDialect = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize
...@@ -10,4 +10,4 @@ SqliteDialect.prototype.supports = _.extend(Abstract.prototype.supports, { ...@@ -10,4 +10,4 @@ SqliteDialect.prototype.supports = _.extend(Abstract.prototype.supports, {
'DEFAULT VALUES': true 'DEFAULT VALUES': true
}) })
module.exports = SqliteDialect module.exports = SqliteDialect
\ No newline at end of file
...@@ -132,6 +132,7 @@ module.exports = (function() { ...@@ -132,6 +132,7 @@ module.exports = (function() {
}, },
addLimitAndOffset: function(options, query){ addLimitAndOffset: function(options, query){
query = query || ""
if (options.offset && !options.limit) { if (options.offset && !options.limit) {
query += " LIMIT " + options.offset + ", " + 10000000000000; query += " LIMIT " + options.offset + ", " + 10000000000000;
} else if (options.limit && !(options.include && (options.limit === 1))) { } else if (options.limit && !(options.include && (options.limit === 1))) {
...@@ -380,6 +381,7 @@ module.exports = (function() { ...@@ -380,6 +381,7 @@ module.exports = (function() {
}, },
quoteIdentifier: function(identifier, force) { quoteIdentifier: function(identifier, force) {
if (identifier === '*') return identifier
return Utils.addTicks(identifier, "`") return Utils.addTicks(identifier, "`")
}, },
......
...@@ -5,10 +5,11 @@ var Utils = require(__dirname + '/utils') ...@@ -5,10 +5,11 @@ var Utils = require(__dirname + '/utils')
module.exports = (function() { module.exports = (function() {
var QueryInterface = function(sequelize) { var QueryInterface = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize
this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator') this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
this.QueryGenerator.options = this.sequelize.options this.QueryGenerator.options = this.sequelize.options
this.QueryGenerator._dialect = this.sequelize.dialect this.QueryGenerator._dialect = this.sequelize.dialect
this.QueryGenerator.sequelize = this.sequelize
} }
Utils.addEventEmitter(QueryInterface) Utils.addEventEmitter(QueryInterface)
...@@ -686,12 +687,18 @@ module.exports = (function() { ...@@ -686,12 +687,18 @@ module.exports = (function() {
.success(function(data) { .success(function(data) {
var result = data ? data[attributeSelector] : null var result = data ? data[attributeSelector] : null
if (options && options.parseInt) { if (options && options.dataType) {
result = parseInt(result, 10) var dataType = options.dataType;
}
if (dataType instanceof DataTypes.DECIMAL || dataType instanceof DataTypes.FLOAT) {
if (options && options.parseFloat) { result = parseFloat(result);
result = parseFloat(result) } else if (dataType === DataTypes.INTEGER || dataType instanceof DataTypes.BIGINT) {
result = parseInt(result, 10);
} else if (dataType === DataTypes.DATE) {
result = new Date(result + 'Z');
} else if (dataType === DataTypes.STRING) {
// Nothing to do, result is already a string.
}
} }
self.emit('rawSelect', null) self.emit('rawSelect', null)
......
...@@ -113,7 +113,8 @@ module.exports = (function() { ...@@ -113,7 +113,8 @@ module.exports = (function() {
} }
try { try {
this.dialect = new (require("./dialects/" + this.getDialect()))(this) var Dialect = require("./dialects/" + this.getDialect())
this.dialect = new Dialect(this)
} catch(err) { } catch(err) {
throw new Error("The dialect " + this.getDialect() + " is not supported.") throw new Error("The dialect " + this.getDialect() + " is not supported.")
} }
...@@ -395,22 +396,26 @@ module.exports = (function() { ...@@ -395,22 +396,26 @@ module.exports = (function() {
}).run() }).run()
} }
Sequelize.prototype.fn = function (fn) { Sequelize.fn = Sequelize.prototype.fn = function (fn) {
return new Utils.fn(fn, Array.prototype.slice.call(arguments, 1)) return new Utils.fn(fn, Array.prototype.slice.call(arguments, 1))
} }
Sequelize.prototype.col = function (col) { Sequelize.col = Sequelize.prototype.col = function (col) {
return new Utils.col(col) return new Utils.col(col)
} }
Sequelize.prototype.cast = function (val, type) { Sequelize.cast = Sequelize.prototype.cast = function (val, type) {
return new Utils.cast(val, type) return new Utils.cast(val, type)
} }
Sequelize.prototype.literal = function (val) { Sequelize.literal = Sequelize.prototype.literal = function (val) {
return new Utils.literal(val) return new Utils.literal(val)
} }
Sequelize.asIs = Sequelize.prototype.asIs = function (val) {
return new Utils.asIs(val)
}
Sequelize.prototype.transaction = function(_options, _callback) { Sequelize.prototype.transaction = function(_options, _callback) {
var options = (typeof _options === 'function') ? {} : _options var options = (typeof _options === 'function') ? {} : _options
, callback = (typeof _options === 'function') ? _options : _callback , callback = (typeof _options === 'function') ? _options : _callback
......
...@@ -450,7 +450,9 @@ var Utils = module.exports = { ...@@ -450,7 +450,9 @@ var Utils = module.exports = {
var _hash = {} var _hash = {}
for (var key in hash) { for (var key in hash) {
if (key.indexOf('.') === -1) { if (key instanceof Utils.literal) {
_hash[key] = hash[key]
} else if (key.indexOf('.') === -1) {
_hash[tableName + '.' + key] = hash[key] _hash[tableName + '.' + key] = hash[key]
} else { } else {
_hash[key] = hash[key] _hash[key] = hash[key]
...@@ -540,6 +542,10 @@ var Utils = module.exports = { ...@@ -540,6 +542,10 @@ var Utils = module.exports = {
this.val = val this.val = val
}, },
asIs: function(val) {
this.val = val
},
generateUUID: function() { generateUUID: function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8) var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8)
...@@ -558,6 +564,7 @@ var Utils = module.exports = { ...@@ -558,6 +564,7 @@ var Utils = module.exports = {
Utils.literal.prototype.toString = function() { Utils.literal.prototype.toString = function() {
return this.val return this.val
} }
Utils.asIs.prototype = Utils.literal.prototype
Utils.cast.prototype.toString = function(queryGenerator) { Utils.cast.prototype.toString = function(queryGenerator) {
if (!this.val instanceof Utils.fn && !this.val instanceof Utils.col && !this.val instanceof Utils.literal) { if (!this.val instanceof Utils.fn && !this.val instanceof Utils.col && !this.val instanceof Utils.literal) {
...@@ -580,6 +587,7 @@ Utils.fn.prototype.toString = function(queryGenerator) { ...@@ -580,6 +587,7 @@ Utils.fn.prototype.toString = function(queryGenerator) {
} }
Utils.col.prototype.toString = function (queryGenerator) { Utils.col.prototype.toString = function (queryGenerator) {
if (this.col.indexOf('*') !== -1) return '*'
return queryGenerator.quote(this.col) return queryGenerator.quote(this.col)
} }
......
...@@ -47,12 +47,12 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -47,12 +47,12 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
Task.findAll({ Task.findAll({
where: { where: {
'project.user.username': 'leia' 'project.user.username': 'leia'
}/*, },
include: [ include: [
{model: Project, include: [ {model: Project, include: [
User User
]} ]}
]*/ ]
}).done(function(err, tasks){ }).done(function(err, tasks){
expect(err).not.to.be.ok expect(err).not.to.be.ok
...@@ -113,12 +113,12 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -113,12 +113,12 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
where: { where: {
'project.user.username': 'leia', 'project.user.username': 'leia',
'project.user.id': 1 'project.user.id': 1
}/*, },
include: [ include: [
{model: Project, include: [ {model: Project, include: [
User User
]} ]}
]*/ ]
}).success(function(tasks){ }).success(function(tasks){
try{ try{
expect(tasks.length).to.be.equal(2); expect(tasks.length).to.be.equal(2);
...@@ -175,12 +175,12 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -175,12 +175,12 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
User.findAll({ User.findAll({
where: { where: {
'projects.tasks.title': 'fight empire' 'projects.tasks.title': 'fight empire'
}/*, },
include: [ include: [
{model: Project, include: [ {model: Project, include: [
Task Task
]} ]}
]*/ ]
}).done(function(err, users){ }).done(function(err, users){
try{ try{
expect(users.length).to.be.equal(1); expect(users.length).to.be.equal(1);
...@@ -224,10 +224,10 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() { ...@@ -224,10 +224,10 @@ describe(Support.getTestDialectTeaser("Multiple Level Filters"), function() {
User.findAll({ User.findAll({
where: { where: {
'projects.title': 'republic' 'projects.title': 'republic'
}/*, },
include: [ include: [
{model: Project} {model: Project}
]*/ ]
}).success(function(users){ }).success(function(users){
try{ try{
expect(users.length).to.be.equal(1); expect(users.length).to.be.equal(1);
......
...@@ -1036,6 +1036,27 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () { ...@@ -1036,6 +1036,27 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
}) })
}) })
}) })
it("should allow strings in min", function(done) {
var self = this
this.User.bulkCreate([{username: 'bbb'}, {username: 'yyy'}]).success(function(){
self.User.min('username').success(function(min){
expect(min).to.equal('bbb')
done()
})
})
})
it("should allow dates in min", function(done){
var self = this
this.User.bulkCreate([{theDate: new Date(2000, 01, 01)}, {theDate: new Date(1990, 01, 01)}]).success(function(){
self.User.min('theDate').success(function(min){
expect(min).to.be.a('Date');
expect(new Date(1990, 01, 01)).to.equalDate(min)
done()
})
})
})
}) })
describe('max', function() { describe('max', function() {
...@@ -1107,6 +1128,27 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () { ...@@ -1107,6 +1128,27 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
}) })
}) })
it("should allow dates in max", function(done) {
var self = this
this.User.bulkCreate([{theDate: new Date(2013, 12, 31)}, {theDate: new Date(2000, 01, 01)}]).success(function(){
self.User.max('theDate').success(function(max){
expect(max).to.be.a('Date');
expect(max).to.equalDate(new Date(2013, 12, 31))
done()
})
})
})
it("should allow strings in max", function(done) {
var self = this
this.User.bulkCreate([{username: 'aaa'}, {username: 'zzz'}]).success(function(){
self.User.max('username').success(function(max){
expect(max).to.equal('zzz')
done()
})
})
})
it('allows sql logging', function(done) { it('allows sql logging', function(done) {
this.UserWithAge.max('age').on('sql', function(sql) { this.UserWithAge.max('age').on('sql', function(sql) {
expect(sql).to.exist expect(sql).to.exist
......
...@@ -6,13 +6,43 @@ var chai = require('chai') ...@@ -6,13 +6,43 @@ var chai = require('chai')
chai.Assertion.includeStack = true chai.Assertion.includeStack = true
describe(Support.getTestDialectTeaser('DataTypes'), function() { describe(Support.getTestDialectTeaser('DataTypes'), function() {
it('should return DECIMAL for the default decimal type', function(done) { it('should return false when comparing DECIMAL and DECIMAL(10,2)', function(done) {
expect(Sequelize.DECIMAL.toString()).to.equal('DECIMAL') expect(Sequelize.DECIMAL).to.not.equal(Sequelize.DECIMAL(10,2))
done() done()
}) })
it('should return DECIMAL(10,2) for the default decimal type with arguments', function(done) { it('DECIMAL(10,2) should be an instance of DECIMAL', function(done) {
expect(Sequelize.DECIMAL(10, 2)).to.equal('DECIMAL(10,2)') expect(Sequelize.DECIMAL(10,2)).to.be.an.instanceof(Sequelize.DECIMAL)
done()
})
it('should return false when comparing FLOAT and FLOAT(11)', function(done) {
expect(Sequelize.FLOAT).to.not.equal(Sequelize.FLOAT(11))
done()
})
it('FLOAT(11) should be an instance of FLOAT', function(done) {
expect(Sequelize.FLOAT(11)).to.be.an.instanceof(Sequelize.FLOAT)
done()
})
it('should return false when comparing STRING and STRING(4096)', function(done) {
expect(Sequelize.STRING).to.not.equal(Sequelize.STRING(4096))
done()
})
it('STRING(4096) should be an instance of STRING', function(done) {
expect(Sequelize.STRING(4096)).to.be.an.instanceof(Sequelize.STRING)
done()
})
it('should return false when comparing BIGINT and BIGINT(11)', function(done) {
expect(Sequelize.BIGINT).to.not.equal(Sequelize.BIGINT(11))
done()
})
it('BIGINT(11) should be an instance of BIGINT', function(done) {
expect(Sequelize.BIGINT(11)).to.be.an.instanceof(Sequelize.BIGINT)
done() done()
}) })
...@@ -61,7 +91,10 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() { ...@@ -61,7 +91,10 @@ describe(Support.getTestDialectTeaser('DataTypes'), function() {
[Sequelize.FLOAT(11, 12).UNSIGNED, 'FLOAT(11,12).UNSIGNED', 'FLOAT(11,12) UNSIGNED'], [Sequelize.FLOAT(11, 12).UNSIGNED, 'FLOAT(11,12).UNSIGNED', 'FLOAT(11,12) UNSIGNED'],
[Sequelize.FLOAT(11, 12).UNSIGNED.ZEROFILL,'FLOAT(11,12).UNSIGNED.ZEROFILL','FLOAT(11,12) UNSIGNED ZEROFILL'], [Sequelize.FLOAT(11, 12).UNSIGNED.ZEROFILL,'FLOAT(11,12).UNSIGNED.ZEROFILL','FLOAT(11,12) UNSIGNED ZEROFILL'],
[Sequelize.FLOAT(11, 12).ZEROFILL,'FLOAT(11,12).ZEROFILL', 'FLOAT(11,12) ZEROFILL'], [Sequelize.FLOAT(11, 12).ZEROFILL,'FLOAT(11,12).ZEROFILL', 'FLOAT(11,12) ZEROFILL'],
[Sequelize.FLOAT(11, 12).ZEROFILL.UNSIGNED,'FLOAT(11,12).ZEROFILL.UNSIGNED', 'FLOAT(11,12) UNSIGNED ZEROFILL'] [Sequelize.FLOAT(11, 12).ZEROFILL.UNSIGNED,'FLOAT(11,12).ZEROFILL.UNSIGNED', 'FLOAT(11,12) UNSIGNED ZEROFILL'],
[Sequelize.DECIMAL, 'DECIMAL', 'DECIMAL'],
[Sequelize.DECIMAL(10,2), 'DECIMAL(10,2)','DECIMAL(10,2)']
] ]
tests.forEach(function(test) { tests.forEach(function(test) {
......
...@@ -23,7 +23,6 @@ describe(Support.getTestDialectTeaser("Hooks"), function () { ...@@ -23,7 +23,6 @@ describe(Support.getTestDialectTeaser("Hooks"), function () {
}, { }, {
hooks: { hooks: {
beforeValidate: function(user, fn) { beforeValidate: function(user, fn) {
console.log("beforeValidate")
user.mood = 'happy' user.mood = 'happy'
fn(null, user) fn(null, user)
}, },
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!