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

Commit a8f6867c by Sascha Depold

Merge branch 'milestones/2.0.0' of github.com:sequelize/sequelize into milestones/2.0.0

2 parents 8031211a 281591fa
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
# v1.7.0 # # v1.7.0 #
- [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
- [BUG] Fix string escape with postgresql on raw SQL queries. [#586](https://github.com/sequelize/sequelize/pull/586). thanks to zanamixx - [BUG] Fix string escape with postgresql on raw SQL queries. [#586](https://github.com/sequelize/sequelize/pull/586). thanks to zanamixx
- [BUG] "order by" is now after "group by". [#585](https://github.com/sequelize/sequelize/pull/585). thanks to mekanics - [BUG] "order by" is now after "group by". [#585](https://github.com/sequelize/sequelize/pull/585). thanks to mekanics
- [BUG] Added decimal support for min/max. [#583](https://github.com/sequelize/sequelize/pull/583). thanks to durango - [BUG] Added decimal support for min/max. [#583](https://github.com/sequelize/sequelize/pull/583). thanks to durango
...@@ -15,6 +16,7 @@ ...@@ -15,6 +16,7 @@
- [BUG] Default ports are now declared in the connector manager, which means the default port for PG correctly becomes 5432. [#633](https://github.com/sequelize/sequelize/issues/633). durango - [BUG] Default ports are now declared in the connector manager, which means the default port for PG correctly becomes 5432. [#633](https://github.com/sequelize/sequelize/issues/633). durango
- [BUG] Columns with type BOOLEAN were always added to toJSON output, even if they were not selected [see](https://gist.github.com/gchaincl/45aca14e93934bf4a05e). janmeier - [BUG] Columns with type BOOLEAN were always added to toJSON output, even if they were not selected [see](https://gist.github.com/gchaincl/45aca14e93934bf4a05e). janmeier
- [BUG] Hstore is now fully supported [#695](https://github.com/sequelize/sequelize/pull/695). thanks to tadman - [BUG] Hstore is now fully supported [#695](https://github.com/sequelize/sequelize/pull/695). thanks to tadman
- [BUG] Correct join table name for tables with custom names [#698](https://github.com/sequelize/sequelize/pull/698). thanks to jjclark1982
- [FEATURE] Validate a model before it gets saved. [#601](https://github.com/sequelize/sequelize/pull/601). thanks to durango - [FEATURE] Validate a model before it gets saved. [#601](https://github.com/sequelize/sequelize/pull/601). thanks to durango
- [FEATURE] Schematics. [#564](https://github.com/sequelize/sequelize/pull/564). thanks to durango - [FEATURE] Schematics. [#564](https://github.com/sequelize/sequelize/pull/564). thanks to durango
- [FEATURE] Foreign key constraints. [#595](https://github.com/sequelize/sequelize/pull/595). thanks to optilude - [FEATURE] Foreign key constraints. [#595](https://github.com/sequelize/sequelize/pull/595). thanks to optilude
...@@ -29,6 +31,9 @@ ...@@ -29,6 +31,9 @@
- [FEATURE] Field and table comments for MySQL and PG. [#523](https://github.com/sequelize/sequelize/pull/523). MySQL by iamjochen. PG by janmeier - [FEATURE] Field and table comments for MySQL and PG. [#523](https://github.com/sequelize/sequelize/pull/523). MySQL by iamjochen. PG by janmeier
- [FEATURE] BigInts can now be used for autoincrement/serial columns. [#673](https://github.com/sequelize/sequelize/pull/673). thanks to sevastos - [FEATURE] BigInts can now be used for autoincrement/serial columns. [#673](https://github.com/sequelize/sequelize/pull/673). thanks to sevastos
- [REFACTORING] hasMany now uses a single SQL statement when creating and destroying associations, instead of removing each association seperately [690](https://github.com/sequelize/sequelize/pull/690). Inspired by [#104](https://github.com/sequelize/sequelize/issues/104). janmeier - [REFACTORING] hasMany now uses a single SQL statement when creating and destroying associations, instead of removing each association seperately [690](https://github.com/sequelize/sequelize/pull/690). Inspired by [#104](https://github.com/sequelize/sequelize/issues/104). janmeier
- [FEATURE] Use moment for better postgres timestamp strings. [#710](https://github.com/sequelize/sequelize/pull/710). Thanks to seth-admittedly
- [FEATURE] Keep milliseconds in timestamps for postgres. [#712](https://github.com/sequelize/sequelize/pull/712). Thanks to seth-admittedly
- [FEATURE] You can now set lingo's language through Sequelize. [#713](https://github.com/sequelize/sequelize/pull/713). Thanks to durango
# v1.6.0 # # v1.6.0 #
- [DEPENDENCIES] upgrade mysql to alpha7. You *MUST* use this version or newer for DATETIMEs to work - [DEPENDENCIES] upgrade mysql to alpha7. You *MUST* use this version or newer for DATETIMEs to work
......
...@@ -11,7 +11,7 @@ module.exports = (function() { ...@@ -11,7 +11,7 @@ module.exports = (function() {
this.isSelfAssociation = (this.source.tableName == this.target.tableName) this.isSelfAssociation = (this.source.tableName == this.target.tableName)
if (this.isSelfAssociation && !this.options.foreignKey && !!this.options.as) { if (this.isSelfAssociation && !this.options.foreignKey && !!this.options.as) {
this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.options.as) + "Id", this.source.options.underscored) this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.options.as, this.source.options.language) + "Id", this.source.options.underscored)
} }
this.associationAccessor = this.isSelfAssociation this.associationAccessor = this.isSelfAssociation
...@@ -23,7 +23,7 @@ module.exports = (function() { ...@@ -23,7 +23,7 @@ module.exports = (function() {
BelongsTo.prototype.injectAttributes = function() { BelongsTo.prototype.injectAttributes = function() {
var newAttributes = {} var newAttributes = {}
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.target.tableName) + "Id", this.source.options.underscored) this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.target.tableName, this.target.options.language) + "Id", this.source.options.underscored)
newAttributes[this.identifier] = { type: this.options.keyType || DataTypes.INTEGER } newAttributes[this.identifier] = { type: this.options.keyType || DataTypes.INTEGER }
Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.target, this.source, this.options) Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.target, this.source, this.options)
Utils._.defaults(this.source.rawAttributes, newAttributes) Utils._.defaults(this.source.rawAttributes, newAttributes)
...@@ -36,7 +36,7 @@ module.exports = (function() { ...@@ -36,7 +36,7 @@ module.exports = (function() {
BelongsTo.prototype.injectGetter = function(obj) { BelongsTo.prototype.injectGetter = function(obj) {
var self = this var self = this
, accessor = Utils._.camelize('get_' + (this.options.as || Utils.singularize(this.target.tableName))) , accessor = Utils._.camelize('get_' + (this.options.as || Utils.singularize(this.target.tableName, this.target.options.language)))
obj[accessor] = function(params) { obj[accessor] = function(params) {
var id = this[self.identifier] var id = this[self.identifier]
...@@ -59,7 +59,7 @@ module.exports = (function() { ...@@ -59,7 +59,7 @@ module.exports = (function() {
BelongsTo.prototype.injectSetter = function(obj) { BelongsTo.prototype.injectSetter = function(obj) {
var self = this var self = this
, accessor = Utils._.camelize('set_' + (this.options.as || Utils.singularize(this.target.tableName))) , accessor = Utils._.camelize('set_' + (this.options.as || Utils.singularize(this.target.tableName, this.target.options.language)))
obj[accessor] = function(associatedObject) { obj[accessor] = function(associatedObject) {
this[self.identifier] = associatedObject ? associatedObject.id : null this[self.identifier] = associatedObject ? associatedObject.id : null
......
...@@ -19,15 +19,16 @@ module.exports = (function() { ...@@ -19,15 +19,16 @@ module.exports = (function() {
this.isSelfAssociation ? (this.options.as || this.target.tableName) : this.target.tableName this.isSelfAssociation ? (this.options.as || this.target.tableName) : this.target.tableName
) )
this.associationAccessor = this.combinedName = (this.options.joinTableName || combinedTableName) this.associationAccessor = this.combinedName = (this.options.joinTableName || combinedTableName)
this.options.tableName = this.combinedName
var as = (this.options.as || Utils.pluralize(this.target.tableName)) var as = (this.options.as || Utils.pluralize(this.target.tableName, this.target.options.language))
this.accessors = { this.accessors = {
get: Utils._.camelize('get_' + as), get: Utils._.camelize('get_' + as),
set: Utils._.camelize('set_' + as), set: Utils._.camelize('set_' + as),
add: Utils._.camelize(Utils.singularize('add_' + as)), add: Utils._.camelize(Utils.singularize('add_' + as, this.target.options.language)),
remove: Utils._.camelize(Utils.singularize('remove_' + as)), remove: Utils._.camelize(Utils.singularize('remove_' + as, this.target.options.language)),
hasSingle: Utils._.camelize(Utils.singularize('has_' + as)), hasSingle: Utils._.camelize(Utils.singularize('has_' + as, this.target.options.language)),
hasAll: Utils._.camelize('has_' + as) hasAll: Utils._.camelize('has_' + as)
} }
} }
...@@ -36,7 +37,7 @@ module.exports = (function() { ...@@ -36,7 +37,7 @@ module.exports = (function() {
// or in an extra table which connects two tables // or in an extra table which connects two tables
HasMany.prototype.injectAttributes = function() { HasMany.prototype.injectAttributes = function() {
var multiAssociation = this.target.associations.hasOwnProperty(this.associationAccessor) var multiAssociation = this.target.associations.hasOwnProperty(this.associationAccessor)
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.source.tableName) + "Id", this.options.underscored) this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.source.tableName, this.source.options.language) + "Id", this.options.underscored)
// is there already a single sided association between the source and the target? // is there already a single sided association between the source and the target?
// or is the association on the model itself? // or is the association on the model itself?
......
...@@ -11,7 +11,7 @@ module.exports = (function() { ...@@ -11,7 +11,7 @@ module.exports = (function() {
this.isSelfAssociation = (this.source.tableName == this.target.tableName) this.isSelfAssociation = (this.source.tableName == this.target.tableName)
if (this.isSelfAssociation && !this.options.foreignKey && !!this.options.as) { if (this.isSelfAssociation && !this.options.foreignKey && !!this.options.as) {
this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.options.as) + "Id", this.options.underscored) this.options.foreignKey = Utils._.underscoredIf(Utils.singularize(this.options.as, this.target.options.language) + "Id", this.options.underscored)
} }
this.associationAccessor = this.isSelfAssociation this.associationAccessor = this.isSelfAssociation
...@@ -19,8 +19,8 @@ module.exports = (function() { ...@@ -19,8 +19,8 @@ module.exports = (function() {
: this.options.as || this.target.tableName : this.options.as || this.target.tableName
this.accessors = { this.accessors = {
get: Utils._.camelize('get_' + (this.options.as || Utils.singularize(this.target.tableName))), get: Utils._.camelize('get_' + (this.options.as || Utils.singularize(this.target.tableName, this.target.options.language))),
set: Utils._.camelize('set_' + (this.options.as || Utils.singularize(this.target.tableName))) set: Utils._.camelize('set_' + (this.options.as || Utils.singularize(this.target.tableName, this.target.options.language)))
} }
} }
...@@ -28,7 +28,7 @@ module.exports = (function() { ...@@ -28,7 +28,7 @@ module.exports = (function() {
HasOne.prototype.injectAttributes = function() { HasOne.prototype.injectAttributes = function() {
var newAttributes = {} var newAttributes = {}
this.identifier = this.options.foreignKey || Utils._.underscoredIf(Utils.singularize(this.source.tableName) + "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 || DataTypes.INTEGER } newAttributes[this.identifier] = { type: this.options.keyType || DataTypes.INTEGER }
Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.source, this.target, this.options) Helpers.addForeignKeyConstraints(newAttributes[this.identifier], this.source, this.target, this.options)
Utils._.defaults(this.target.rawAttributes, newAttributes) Utils._.defaults(this.target.rawAttributes, newAttributes)
......
...@@ -18,7 +18,8 @@ module.exports = (function() { ...@@ -18,7 +18,8 @@ module.exports = (function() {
paranoid: false, paranoid: false,
whereCollection: null, whereCollection: null,
schema: null, schema: null,
schemaDelimiter: '' schemaDelimiter: '',
language: 'en'
}, options || {}) }, options || {})
// error check options // error check options
...@@ -31,7 +32,7 @@ module.exports = (function() { ...@@ -31,7 +32,7 @@ module.exports = (function() {
this.name = name this.name = name
if (!this.options.tableName) { if (!this.options.tableName) {
this.tableName = this.options.freezeTableName ? name : Utils.pluralize(name) this.tableName = this.options.freezeTableName ? name : Utils.pluralize(name, this.options.language)
} else { } else {
this.tableName = this.options.tableName this.tableName = this.options.tableName
} }
......
...@@ -108,6 +108,8 @@ var prepareValidationOfAttribute = function(value, details, validatorType, optio ...@@ -108,6 +108,8 @@ var prepareValidationOfAttribute = function(value, details, validatorType, optio
if (!Array.isArray(validatorArgs)) { if (!Array.isArray(validatorArgs)) {
validatorArgs = [validatorArgs] validatorArgs = [validatorArgs]
} else {
validatorArgs = validatorArgs.slice(0);
} }
// extract the error msg // extract the error msg
......
...@@ -138,7 +138,7 @@ module.exports = (function() { ...@@ -138,7 +138,7 @@ module.exports = (function() {
} }
if (this.__options.timestamps && this.dataValues.hasOwnProperty(updatedAtAttr)) { if (this.__options.timestamps && this.dataValues.hasOwnProperty(updatedAtAttr)) {
this.dataValues[updatedAtAttr] = values[updatedAtAttr] = Utils.now() this.dataValues[updatedAtAttr] = values[updatedAtAttr] = Utils.now(this.sequelize.options.dialect)
} }
return new Utils.CustomEventEmitter(function(emitter) { return new Utils.CustomEventEmitter(function(emitter) {
...@@ -367,8 +367,8 @@ module.exports = (function() { ...@@ -367,8 +367,8 @@ module.exports = (function() {
} }
if (this.__options.timestamps) { if (this.__options.timestamps) {
defaults[this.__options.underscored ? 'created_at' : 'createdAt'] = Utils.now() defaults[this.__options.underscored ? 'created_at' : 'createdAt'] = Utils.now(this.sequelize.options.dialect)
defaults[this.__options.underscored ? 'updated_at' : 'updatedAt'] = Utils.now() defaults[this.__options.underscored ? 'updated_at' : 'updatedAt'] = Utils.now(this.sequelize.options.dialect)
if (this.__options.paranoid) { if (this.__options.paranoid) {
defaults[this.__options.underscored ? 'deleted_at' : 'deletedAt'] = null defaults[this.__options.underscored ? 'deleted_at' : 'deletedAt'] = null
......
...@@ -302,11 +302,12 @@ module.exports = (function() { ...@@ -302,11 +302,12 @@ module.exports = (function() {
var buildAssociatedDaoInstances = function(tableName, associationData, dao) { var buildAssociatedDaoInstances = function(tableName, associationData, dao) {
var associatedDaoFactory = this.sequelize.daoFactoryManager.getDAO(tableName, { attribute: 'tableName' }) var associatedDaoFactory = this.sequelize.daoFactoryManager.getDAO(tableName, { attribute: 'tableName' })
, association = null , association = null
, self = this
if (!!associatedDaoFactory) { if (!!associatedDaoFactory) {
association = this.callee.getAssociation(associatedDaoFactory) association = this.callee.getAssociation(associatedDaoFactory)
} else { } else {
associatedDaoFactory = this.sequelize.daoFactoryManager.getDAO(Utils.pluralize(tableName), { attribute: 'tableName' }) associatedDaoFactory = this.sequelize.daoFactoryManager.getDAO(Utils.pluralize(tableName, this.sequelize.language), { attribute: 'tableName' })
if (!!associatedDaoFactory) { if (!!associatedDaoFactory) {
association = this.callee.getAssociation(associatedDaoFactory) association = this.callee.getAssociation(associatedDaoFactory)
...@@ -326,7 +327,7 @@ module.exports = (function() { ...@@ -326,7 +327,7 @@ module.exports = (function() {
, isEmpty = !Utils.firstValueOfHash(daoInstance.identifiers) , isEmpty = !Utils.firstValueOfHash(daoInstance.identifiers)
if (['BelongsTo', 'HasOne'].indexOf(association.associationType) > -1) { if (['BelongsTo', 'HasOne'].indexOf(association.associationType) > -1) {
accessor = Utils.singularize(accessor) accessor = Utils.singularize(accessor, self.sequelize.language)
dao[accessor] = isEmpty ? null : daoInstance dao[accessor] = isEmpty ? null : daoInstance
} else { } else {
dao[accessor] = dao[accessor] || [] dao[accessor] = dao[accessor] || []
......
...@@ -3,6 +3,7 @@ var Utils = require("../../utils") ...@@ -3,6 +3,7 @@ var Utils = require("../../utils")
, DataTypes = require("../../data-types") , DataTypes = require("../../data-types")
, tables = {} , tables = {}
, primaryKeys = {} , primaryKeys = {}
, moment = require("moment")
module.exports = (function() { module.exports = (function() {
var QueryGenerator = { var QueryGenerator = {
...@@ -495,7 +496,7 @@ module.exports = (function() { ...@@ -495,7 +496,7 @@ module.exports = (function() {
result = smth result = smth
} }
else if (Array.isArray(smth)) { else if (Array.isArray(smth)) {
result = Utils.format(smth) result = Utils.format(smth, "postgres")
} }
return result return result
...@@ -680,9 +681,7 @@ module.exports = (function() { ...@@ -680,9 +681,7 @@ module.exports = (function() {
}, },
pgSqlDate: function (dt) { pgSqlDate: function (dt) {
var date = [ dt.getUTCFullYear(), this.padInt(dt.getUTCMonth()+1), this.padInt(dt.getUTCDate()) ].join('-') return moment(dt).format("YYYY-MM-DD HH:mm:ss.SSS Z")
var time = [ dt.getUTCHours(), this.padInt(dt.getUTCMinutes()), this.padInt(dt.getUTCSeconds())].join(':')
return date + ' ' + time + '.' + ((dt.getTime() % 1000) * 1000) + 'Z'
}, },
pgDataTypeMapping: function (tableName, attr, dataType) { pgDataTypeMapping: function (tableName, attr, dataType) {
......
...@@ -79,7 +79,8 @@ module.exports = (function() { ...@@ -79,7 +79,8 @@ module.exports = (function() {
native: false, native: false,
replication: false, replication: false,
pool: {}, pool: {},
quoteIdentifiers: true quoteIdentifiers: true,
language: 'en'
}, options || {}) }, options || {})
if (this.options.logging === true) { if (this.options.logging === true) {
...@@ -172,7 +173,9 @@ module.exports = (function() { ...@@ -172,7 +173,9 @@ module.exports = (function() {
} }
}) })
} }
options.omitNull = globalOptions.omitNull options.omitNull = globalOptions.omitNull
options.language = globalOptions.language
// if you call "define" multiple times for the same daoName, do not clutter the factory // if you call "define" multiple times for the same daoName, do not clutter the factory
if(this.isDefined(daoName)) { if(this.isDefined(daoName)) {
......
...@@ -72,12 +72,12 @@ var Utils = module.exports = { ...@@ -72,12 +72,12 @@ var Utils = module.exports = {
return (tableName1.toLowerCase() < tableName2.toLowerCase()) ? (tableName1 + tableName2) : (tableName2 + tableName1) return (tableName1.toLowerCase() < tableName2.toLowerCase()) ? (tableName1 + tableName2) : (tableName2 + tableName1)
}, },
singularize: function(s) { singularize: function(s, language) {
return Utils.Lingo.en.isSingular(s) ? s : Utils.Lingo.en.singularize(s) return Utils.Lingo[language || 'en'].isSingular(s) ? s : Utils.Lingo[language || 'en'].singularize(s)
}, },
pluralize: function(s) { pluralize: function(s, language) {
return Utils.Lingo.en.isPlural(s) ? s : Utils.Lingo.en.pluralize(s) return Utils.Lingo[language || 'en'].isPlural(s) ? s : Utils.Lingo[language || 'en'].pluralize(s)
}, },
removeCommentsFromFunctionString: function(s) { removeCommentsFromFunctionString: function(s) {
...@@ -164,9 +164,9 @@ var Utils = module.exports = { ...@@ -164,9 +164,9 @@ var Utils = module.exports = {
return subClass; return subClass;
}, },
now: function() { now: function(dialect) {
var now = new Date() var now = new Date()
now.setMilliseconds(0) if(dialect != "postgres") now.setMilliseconds(0)
return now return now
}, },
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
"jasmine-node": "1.5.0", "jasmine-node": "1.5.0",
"sqlite3": "~2.1.5", "sqlite3": "~2.1.5",
"mysql": "~2.0.0-alpha7", "mysql": "~2.0.0-alpha7",
"pg": "~0.10.2", "pg": "~2.0.0",
"buster": "~0.6.3", "buster": "~0.6.3",
"watchr": "~2.2.0", "watchr": "~2.2.0",
"yuidocjs": "~0.3.36" "yuidocjs": "~0.3.36"
......
...@@ -338,7 +338,7 @@ describe('QueryGenerator', function() { ...@@ -338,7 +338,7 @@ describe('QueryGenerator', function() {
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;') RETURNING *;"
}, { }, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}], arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.0Z') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00') RETURNING *;"
}, { }, {
arguments: ['myTable', {name: 'foo', foo: 1}], arguments: ['myTable', {name: 'foo', foo: 1}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1) RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1) RETURNING *;"
...@@ -379,7 +379,7 @@ describe('QueryGenerator', function() { ...@@ -379,7 +379,7 @@ describe('QueryGenerator', function() {
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}], arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}],
expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.0Z') RETURNING *;", expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00') RETURNING *;",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', foo: 1}], arguments: ['myTable', {name: 'foo', foo: 1}],
...@@ -426,7 +426,7 @@ describe('QueryGenerator', function() { ...@@ -426,7 +426,7 @@ describe('QueryGenerator', function() {
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;'),('bar') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;'),('bar') RETURNING *;"
}, { }, {
arguments: ['myTable', [{name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {name: 'bar', birthday: new Date(Date.UTC(2012, 2, 27, 10, 1, 55))}]], arguments: ['myTable', [{name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {name: 'bar', birthday: new Date(Date.UTC(2012, 2, 27, 10, 1, 55))}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.0Z'),('bar','2012-03-27 10:01:55.0Z') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00') RETURNING *;"
}, { }, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]], arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1),('bar',2) RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1),('bar',2) RETURNING *;"
...@@ -467,7 +467,7 @@ describe('QueryGenerator', function() { ...@@ -467,7 +467,7 @@ describe('QueryGenerator', function() {
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', [{name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {name: 'bar', birthday: new Date(Date.UTC(2012, 2, 27, 10, 1, 55))}]], arguments: ['myTable', [{name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {name: 'bar', birthday: new Date(Date.UTC(2012, 2, 27, 10, 1, 55))}]],
expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.0Z'),('bar','2012-03-27 10:01:55.0Z') RETURNING *;", expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00') RETURNING *;",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]], arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
...@@ -507,10 +507,10 @@ describe('QueryGenerator', function() { ...@@ -507,10 +507,10 @@ describe('QueryGenerator', function() {
updateQuery: [ updateQuery: [
{ {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}], arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.0Z' WHERE \"id\"=2 RETURNING *" expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *"
}, { }, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, 2], arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, 2],
expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.0Z' WHERE \"id\"=2 RETURNING *" expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *"
}, { }, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}], arguments: ['myTable', {bar: 2}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *" expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *"
...@@ -534,7 +534,7 @@ describe('QueryGenerator', function() { ...@@ -534,7 +534,7 @@ describe('QueryGenerator', function() {
context: {options: {omitNull: true}} context: {options: {omitNull: true}}
}, { }, {
arguments: ['mySchema.myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}], arguments: ['mySchema.myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.0Z' WHERE \"id\"=2 RETURNING *" expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *"
}, { }, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}], arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}],
expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo'';DROP TABLE mySchema.myTable;' WHERE \"name\"='foo' RETURNING *" expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo'';DROP TABLE mySchema.myTable;' WHERE \"name\"='foo' RETURNING *"
...@@ -543,11 +543,11 @@ describe('QueryGenerator', function() { ...@@ -543,11 +543,11 @@ describe('QueryGenerator', function() {
// Variants when quoteIdentifiers is false // Variants when quoteIdentifiers is false
{ {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}], arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.0Z' WHERE id=2 RETURNING *", expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, 2], arguments: ['myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, 2],
expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.0Z' WHERE id=2 RETURNING *", expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}], arguments: ['myTable', {bar: 2}, {name: 'foo'}],
...@@ -575,7 +575,7 @@ describe('QueryGenerator', function() { ...@@ -575,7 +575,7 @@ describe('QueryGenerator', function() {
context: {options: {omitNull: true, quoteIdentifiers: false}}, context: {options: {omitNull: true, quoteIdentifiers: false}},
}, { }, {
arguments: ['mySchema.myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}], arguments: ['mySchema.myTable', {name: 'foo', birthday: new Date(Date.UTC(2011, 2, 27, 10, 1, 55))}, {id: 2}],
expectation: "UPDATE mySchema.myTable SET name='foo',birthday='2011-03-27 10:01:55.0Z' WHERE id=2 RETURNING *", expectation: "UPDATE mySchema.myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}], arguments: ['mySchema.myTable', {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}],
......
...@@ -415,6 +415,43 @@ describe(Helpers.getTestDialectTeaser("HasMany"), function() { ...@@ -415,6 +415,43 @@ describe(Helpers.getTestDialectTeaser("HasMany"), function() {
}.bind(this)) }.bind(this))
}) })
}) // end optimization using bulk create, destroy and update }) // end optimization using bulk create, destroy and update
describe('join table creation', function () {
before(function (done) {
this.User = this.sequelize.define('User',
{ username: Sequelize.STRING },
{ tableName: 'users'}
)
this.Task = this.sequelize.define('Task',
{ title: Sequelize.STRING },
{ tableName: 'tasks' }
)
this.User.hasMany(this.Task,
{ joinTableName: 'user_has_tasks' }
)
this.Task.hasMany(this.User)
this.sequelize.sync({force: true}).success(done)
})
it('uses the specified joinTableName or a reasonable default', function(done) {
for (var associationName in this.User.associations) {
expect(associationName).not.toEqual(this.User.tableName)
expect(associationName).not.toEqual(this.Task.tableName)
var joinTableName = this.User.associations[associationName].options.joinTableName
if (typeof joinTableName !== 'undefined') {
expect(joinTableName).toEqual(associationName)
}
var tableName = this.User.associations[associationName].options.tableName
if (typeof tableName !== 'undefined') {
expect(tableName).toEqual(associationName)
}
}
done()
})
})
}) })
describe("Foreign key constraints", function() { describe("Foreign key constraints", function() {
...@@ -572,4 +609,4 @@ describe(Helpers.getTestDialectTeaser("HasMany"), function() { ...@@ -572,4 +609,4 @@ describe(Helpers.getTestDialectTeaser("HasMany"), function() {
}) })
}) })
}) })
}) })
\ No newline at end of file
...@@ -368,5 +368,26 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() { ...@@ -368,5 +368,26 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() {
}) })
}) })
}) })
it('validates model with a validator whose arg is an Array successfully twice in a row', function(done){
var Foo = this.sequelize.define('Foo' + Math.random(), {
bar: {
type: Sequelize.STRING,
validate: {
isIn: [['a', 'b']]
}
}
}), foo;
foo = Foo
.build({bar:'a'});
foo.validate().success(function(errors){
expect(errors).not.toBeDefined()
foo.validate().success(function(errors){
expect(errors).not.toBeDefined()
done();
});
});
});
}) })
}) })
if(typeof require === 'function') {
const buster = require("buster")
, Sequelize = require("../index")
, Helpers = require('./buster-helpers')
, dialect = Helpers.getTestDialect()
}
buster.spec.expose()
buster.testRunner.timeout = 1000
describe(Helpers.getTestDialectTeaser("Language Util"), function() {
describe("Plural", function(){
before(function(done) {
Helpers.initTests({
dialect: dialect,
onComplete: function(sequelize) {
this.sequelize = sequelize
this.sequelize.options.language = 'es'
done()
}.bind(this)
})
})
it("should rename tables to their plural form...", function(done){
var table = this.sequelize.define('arbol', {name: Sequelize.STRING})
var table2 = this.sequelize.define('androide', {name: Sequelize.STRING})
expect(table.tableName).toEqual('arboles')
expect(table2.tableName).toEqual('androides')
done()
})
it("should be able to pluralize/singularize associations...", function(done){
var table = this.sequelize.define('arbol', {name: Sequelize.STRING})
var table2 = this.sequelize.define('androide', {name: Sequelize.STRING})
var table3 = this.sequelize.define('hombre', {name: Sequelize.STRING})
table.hasOne(table2)
table2.belongsTo(table)
table3.hasMany(table2)
expect(table.associations.androides.identifier).toEqual('arbolId')
expect(table2.associations.arboles).toBeDefined()
expect(table3.associations.androideshombres).toBeDefined()
done()
})
})
})
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!