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

Commit 46887666 by Mick Hansen

Merge pull request #3549 from BridgeAR/propper-sql-logging

Proper sql logging
2 parents cc439041 ee7099a6
# Next # Next
- [BUG] Enable standards conforming strings on connection in postgres. Adresses [#3545](https://github.com/sequelize/sequelize/issues/3545) - [BUG] Enable standards conforming strings on connection in postgres. Adresses [#3545](https://github.com/sequelize/sequelize/issues/3545)
- [BUG] instance.removeAssociation(s) do not fire the select query twice anymore
- [BUG] Error messages thrown by the db in languages other than english do not crash the app anymore (mysql, mariadb and postgres only) [#3567](https://github.com/sequelize/sequelize/pull/3567)
- [FEATURE] All querys can be logged individually by inserting `logging: fn` in the query option.
- The query-chainer is deprecated and will be removed in version 2.2. Please use promises instead.
# 2.0.6 # 2.0.6
- [BUG] Don't update virtual attributes in Model.update. Fixes [#2860](https://github.com/sequelize/sequelize/issues/2860) - [BUG] Don't update virtual attributes in Model.update. Fixes [#2860](https://github.com/sequelize/sequelize/issues/2860)
...@@ -12,6 +17,11 @@ ...@@ -12,6 +17,11 @@
+ inflection@1.6.0 + inflection@1.6.0
+ lodash@3.5.0 + lodash@3.5.0
+ validator@3.34 + validator@3.34
+ generic-pool@2.2.0
- [INTERNALS] Updated devDependencies.
+ coffee-script@1.9.1
+ dox@0.7.1
+ mysql@2.6.2
# 2.0.5 # 2.0.5
- [FEATURE] Highly experimental support for nested creation [#3386](https://github.com/sequelize/sequelize/pull/3386) - [FEATURE] Highly experimental support for nested creation [#3386](https://github.com/sequelize/sequelize/pull/3386)
......
...@@ -126,7 +126,7 @@ migration.createTable( ...@@ -126,7 +126,7 @@ migration.createTable(
) )
``` ```
### dropTable(tableName) ### dropTable(tableName, options)
This method allows deletion of an existing table. This method allows deletion of an existing table.
...@@ -134,7 +134,7 @@ This method allows deletion of an existing table. ...@@ -134,7 +134,7 @@ This method allows deletion of an existing table.
migration.dropTable('nameOfTheExistingTable') migration.dropTable('nameOfTheExistingTable')
``` ```
### dropAllTables() ### dropAllTables(options)
This method allows deletion of all existing tables in the database. This method allows deletion of all existing tables in the database.
...@@ -142,7 +142,7 @@ This method allows deletion of all existing tables in the database. ...@@ -142,7 +142,7 @@ This method allows deletion of all existing tables in the database.
migration.dropAllTables() migration.dropAllTables()
``` ```
### renameTable(before, after) ### renameTable(before, after, options)
This method allows renaming of an existing table. This method allows renaming of an existing table.
...@@ -150,7 +150,7 @@ This method allows renaming of an existing table. ...@@ -150,7 +150,7 @@ This method allows renaming of an existing table.
migration.renameTable('Person', 'User') migration.renameTable('Person', 'User')
``` ```
### showAllTables() ### showAllTables(options)
This method returns the name of all existing tables in the database. This method returns the name of all existing tables in the database.
...@@ -158,7 +158,7 @@ This method returns the name of all existing tables in the database. ...@@ -158,7 +158,7 @@ This method returns the name of all existing tables in the database.
migration.showAllTables().success(function(tableNames) {}) migration.showAllTables().success(function(tableNames) {})
``` ```
### describeTable(tableName) ### describeTable(tableName, options)
This method returns an array of hashes containing information about all attributes in the table. This method returns an array of hashes containing information about all attributes in the table.
...@@ -183,7 +183,7 @@ migration.describeTable('Person').success(function(attributes) { ...@@ -183,7 +183,7 @@ migration.describeTable('Person').success(function(attributes) {
}) })
``` ```
### addColumn(tableName, attributeName, dataTypeOrOptions) ### addColumn(tableName, attributeName, dataTypeOrOptions, options)
This method allows adding columns to an existing table. The data type can be simple or complex. This method allows adding columns to an existing table. The data type can be simple or complex.
...@@ -206,7 +206,7 @@ migration.addColumn( ...@@ -206,7 +206,7 @@ migration.addColumn(
) )
``` ```
### removeColumn(tableName, attributeName) ### removeColumn(tableName, attributeName, options)
This method allows deletion of a specific column of an existing table. This method allows deletion of a specific column of an existing table.
...@@ -214,7 +214,7 @@ This method allows deletion of a specific column of an existing table. ...@@ -214,7 +214,7 @@ This method allows deletion of a specific column of an existing table.
migration.removeColumn('Person', 'signature') migration.removeColumn('Person', 'signature')
``` ```
### changeColumn(tableName, attributeName, dataTypeOrOptions) ### changeColumn(tableName, attributeName, dataTypeOrOptions, options)
This method changes the meta data of an attribute. It is possible to change the default value, allowance of null or the data type. Please make sure, that you are completely describing the new data type. Missing information are expected to be defaults. This method changes the meta data of an attribute. It is possible to change the default value, allowance of null or the data type. Please make sure, that you are completely describing the new data type. Missing information are expected to be defaults.
...@@ -238,7 +238,7 @@ migration.changeColumn( ...@@ -238,7 +238,7 @@ migration.changeColumn(
) )
``` ```
### renameColumn(tableName, attrNameBefore, attrNameAfter) ### renameColumn(tableName, attrNameBefore, attrNameAfter, options)
This methods allows renaming attributes. This methods allows renaming attributes.
...@@ -260,6 +260,7 @@ migration.addIndex('Person', ['firstname', 'lastname']) ...@@ -260,6 +260,7 @@ migration.addIndex('Person', ['firstname', 'lastname'])
// - indexName: The name of the index. Default is __ // - indexName: The name of the index. Default is __
// - parser: For FULLTEXT columns set your parser // - parser: For FULLTEXT columns set your parser
// - indexType: Set a type for the index, e.g. BTREE. See the documentation of the used dialect // - indexType: Set a type for the index, e.g. BTREE. See the documentation of the used dialect
// - logging: A function that receives the sql query, e.g. console.log
migration.addIndex( migration.addIndex(
'Person', 'Person',
['firstname', 'lastname'], ['firstname', 'lastname'],
...@@ -270,7 +271,7 @@ migration.addIndex( ...@@ -270,7 +271,7 @@ migration.addIndex(
) )
``` ```
### removeIndex(tableName, indexNameOrAttributes) ### removeIndex(tableName, indexNameOrAttributes, options)
This method deletes an existing index of a table. This method deletes an existing index of a table.
......
...@@ -415,41 +415,48 @@ module.exports = (function() { ...@@ -415,41 +415,48 @@ module.exports = (function() {
var association = this var association = this
, primaryKeyAttribute = association.target.primaryKeyAttribute; , primaryKeyAttribute = association.target.primaryKeyAttribute;
obj[this.accessors.set] = function(newAssociatedObjects, additionalAttributes) { obj[this.accessors.set] = function(newAssociatedObjects, options) {
additionalAttributes = additionalAttributes || {}; options = options || {};
if (newAssociatedObjects === null) {
newAssociatedObjects = [];
} else {
newAssociatedObjects = newAssociatedObjects.map(function(newAssociatedObject) {
if (!(newAssociatedObject instanceof association.target.Instance)) {
var tmpInstance = {};
tmpInstance[primaryKeyAttribute] = newAssociatedObject;
return association.target.build(tmpInstance, {
isNewRecord: false
});
}
return newAssociatedObject;
});
}
var instance = this; var instance = this;
return instance[association.accessors.get]({}, { return instance[association.accessors.get]({}, {
transaction: additionalAttributes.transaction transaction: options.transaction,
logging: options.logging
}).then(function(oldAssociatedObjects) { }).then(function(oldAssociatedObjects) {
var foreignIdentifier = association.foreignIdentifier var foreignIdentifier = association.foreignIdentifier
, sourceKeys = Object.keys(association.source.primaryKeys) , sourceKeys = Object.keys(association.source.primaryKeys)
, targetKeys = Object.keys(association.target.primaryKeys) , targetKeys = Object.keys(association.target.primaryKeys)
, obsoleteAssociations = [] , obsoleteAssociations = []
, changedAssociations = [] , changedAssociations = []
, defaultAttributes = additionalAttributes , defaultAttributes = options
, options = additionalAttributes
, promises = [] , promises = []
, unassociatedObjects; , unassociatedObjects;
if (newAssociatedObjects === null) {
newAssociatedObjects = [];
} else {
if (!Array.isArray(newAssociatedObjects)) {
newAssociatedObjects = [newAssociatedObjects];
}
newAssociatedObjects = newAssociatedObjects.map(function(newAssociatedObject) {
if (!(newAssociatedObject instanceof association.target.Instance)) {
var tmpInstance = {};
tmpInstance[primaryKeyAttribute] = newAssociatedObject;
return association.target.build(tmpInstance, {
isNewRecord: false
});
}
return newAssociatedObject;
});
}
if (options.remove) {
oldAssociatedObjects = newAssociatedObjects;
newAssociatedObjects = [];
}
// Don't try to insert the transaction as an attribute in the through table // Don't try to insert the transaction as an attribute in the through table
defaultAttributes = Utils._.omit(defaultAttributes, ['transaction', 'hooks', 'individualHooks', 'ignoreDuplicates', 'validate', 'fields']); defaultAttributes = Utils._.omit(defaultAttributes, ['transaction', 'hooks', 'individualHooks', 'ignoreDuplicates', 'validate', 'fields', 'logging']);
unassociatedObjects = newAssociatedObjects.filter(function(obj) { unassociatedObjects = newAssociatedObjects.filter(function(obj) {
return !Utils._.find(oldAssociatedObjects, function(old) { return !Utils._.find(oldAssociatedObjects, function(old) {
...@@ -536,16 +543,16 @@ module.exports = (function() { ...@@ -536,16 +543,16 @@ module.exports = (function() {
// If newInstance is null or undefined, no-op // If newInstance is null or undefined, no-op
if (!newInstance) return Utils.Promise.resolve(); if (!newInstance) return Utils.Promise.resolve();
var instance = this
, primaryKeyAttribute = association.target.primaryKeyAttribute;
additionalAttributes = additionalAttributes || {};
if (association.through && association.through.scope) { if (association.through && association.through.scope) {
Object.keys(association.through.scope).forEach(function (attribute) { Object.keys(association.through.scope).forEach(function (attribute) {
additionalAttributes[attribute] = association.through.scope[attribute]; additionalAttributes[attribute] = association.through.scope[attribute];
}); });
} }
var instance = this
, primaryKeyAttribute = association.target.primaryKeyAttribute
, options = additionalAttributes = additionalAttributes || {};
if (Array.isArray(newInstance)) { if (Array.isArray(newInstance)) {
var newInstances = newInstance.map(function(newInstance) { var newInstances = newInstance.map(function(newInstance) {
if (!(newInstance instanceof association.target.Instance)) { if (!(newInstance instanceof association.target.Instance)) {
...@@ -563,14 +570,13 @@ module.exports = (function() { ...@@ -563,14 +570,13 @@ module.exports = (function() {
, targetKeys = Object.keys(association.target.primaryKeys) , targetKeys = Object.keys(association.target.primaryKeys)
, obsoleteAssociations = [] , obsoleteAssociations = []
, changedAssociations = [] , changedAssociations = []
, defaultAttributes = additionalAttributes || {} , defaultAttributes = additionalAttributes
, options = defaultAttributes
, promises = [] , promises = []
, oldAssociations = [] , oldAssociations = []
, unassociatedObjects; , unassociatedObjects;
// Don't try to insert the transaction as an attribute in the through table // Don't try to insert the transaction as an attribute in the through table
defaultAttributes = Utils._.omit(defaultAttributes, ['transaction', 'hooks', 'individualHooks', 'ignoreDuplicates', 'validate', 'fields']); defaultAttributes = Utils._.omit(defaultAttributes, ['transaction', 'hooks', 'individualHooks', 'ignoreDuplicates', 'validate', 'fields', 'logging']);
unassociatedObjects = newInstances.filter(function(obj) { unassociatedObjects = newInstances.filter(function(obj) {
return !Utils._.find(oldAssociations, function(old) { return !Utils._.find(oldAssociations, function(old) {
...@@ -664,19 +670,18 @@ module.exports = (function() { ...@@ -664,19 +670,18 @@ module.exports = (function() {
return instance[association.accessors.get]({ return instance[association.accessors.get]({
where: newInstance.primaryKeyValues where: newInstance.primaryKeyValues
}, { }, {
transaction: (additionalAttributes || {}).transaction transaction: (additionalAttributes || {}).transaction,
logging: options.logging
}).then(function(currentAssociatedObjects) { }).then(function(currentAssociatedObjects) {
additionalAttributes = additionalAttributes || {};
var attributes = {} var attributes = {}
, foreignIdentifier = association.foreignIdentifier , foreignIdentifier = association.foreignIdentifier;
, options = additionalAttributes;
var sourceKeys = Object.keys(association.source.primaryKeys); var sourceKeys = Object.keys(association.source.primaryKeys);
var targetKeys = Object.keys(association.target.primaryKeys); var targetKeys = Object.keys(association.target.primaryKeys);
// Don't try to insert the transaction as an attribute in the through table // Don't try to insert the transaction as an attribute in the through table
additionalAttributes = Utils._.omit(additionalAttributes, ['transaction', 'hooks', 'individualHooks', 'ignoreDuplicates', 'validate', 'fields']); additionalAttributes = Utils._.omit(additionalAttributes, ['transaction', 'hooks', 'individualHooks', 'ignoreDuplicates', 'validate', 'fields', 'logging']);
attributes[association.identifier] = ((sourceKeys.length === 1) ? instance[sourceKeys[0]] : instance.id); attributes[association.identifier] = ((sourceKeys.length === 1) ? instance[sourceKeys[0]] : instance.id);
attributes[foreignIdentifier] = ((targetKeys.length === 1) ? newInstance[targetKeys[0]] : newInstance.id); attributes[foreignIdentifier] = ((targetKeys.length === 1) ? newInstance[targetKeys[0]] : newInstance.id);
...@@ -706,62 +711,10 @@ module.exports = (function() { ...@@ -706,62 +711,10 @@ module.exports = (function() {
} }
}; };
obj[this.accessors.remove] = function(oldAssociatedObject, options) { obj[this.accessors.removeMultiple] = obj[this.accessors.remove] = function(oldAssociatedObject, options) {
var instance = this; options = options || {};
return instance[association.accessors.get]({}, options).then(function(currentAssociatedObjects) { options.remove = true;
var newAssociations = []; return this[association.accessors.set](oldAssociatedObject, options);
if (!(oldAssociatedObject instanceof association.target.Instance)) {
var tmpInstance = {};
tmpInstance[primaryKeyAttribute] = oldAssociatedObject;
oldAssociatedObject = association.target.build(tmpInstance, {
isNewRecord: false
});
}
currentAssociatedObjects.forEach(function(association) {
if (!Utils._.isEqual(oldAssociatedObject.identifiers, association.identifiers)) {
newAssociations.push(association);
}
});
return instance[association.accessors.set](newAssociations, options);
});
};
obj[this.accessors.removeMultiple] = function(oldAssociatedObjects, options) {
var instance = this;
return instance[association.accessors.get]({}, options).then(function(currentAssociatedObjects) {
var newAssociations = [];
// Ensure the oldAssociatedObjects array is an array of target instances
oldAssociatedObjects = oldAssociatedObjects.map(function(oldAssociatedObject) {
if (!(oldAssociatedObject instanceof association.target.Instance)) {
var tmpInstance = {};
tmpInstance[primaryKeyAttribute] = oldAssociatedObject;
oldAssociatedObject = association.target.build(tmpInstance, {
isNewRecord: false
});
}
return oldAssociatedObject;
});
currentAssociatedObjects.forEach(function(association) {
// Determine is this is an association we want to remove
var obj = Utils._.find(oldAssociatedObjects, function(oldAssociatedObject) {
return Utils._.isEqual(oldAssociatedObject.identifiers, association.identifiers);
});
// This is not an association we want to remove. Add it back
// to the set of associations we will associate our instance with
if (!obj) {
newAssociations.push(association);
}
});
return instance[association.accessors.set](newAssociations, options);
});
}; };
return this; return this;
......
...@@ -20,13 +20,17 @@ module.exports = { ...@@ -20,13 +20,17 @@ module.exports = {
@param {String} tableName The name of the table. @param {String} tableName The name of the table.
@param {String} attributeName The name of the attribute that we want to remove. @param {String} attributeName The name of the attribute that we want to remove.
@param {Object} options
@param {Boolean|Function} [options.logging] A function that logs the sql queries, or false for explicitly not logging these queries
@param {CustomEventEmitter} emitter The EventEmitter from outside. @param {CustomEventEmitter} emitter The EventEmitter from outside.
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered. @param {Function} queryAndEmit The function from outside that triggers some events to get triggered.
@since 1.6.0 @since 1.6.0
*/ */
removeColumn: function(tableName, attributeName) { removeColumn: function(tableName, attributeName, options) {
var self = this; var self = this;
options = options || {};
return this.describeTable(tableName).then(function(fields) { return this.describeTable(tableName).then(function(fields) {
delete fields[attributeName]; delete fields[attributeName];
...@@ -34,7 +38,7 @@ module.exports = { ...@@ -34,7 +38,7 @@ module.exports = {
, subQueries = sql.split(';').filter(function(q) { return q !== ''; }); , subQueries = sql.split(';').filter(function(q) { return q !== ''; });
return Promise.each(subQueries, function(subQuery) { return Promise.each(subQueries, function(subQuery) {
return self.sequelize.query(subQuery + ';', null, { raw: true}); return self.sequelize.query(subQuery + ';', { raw: true, logging: options.logging });
}); });
}); });
}, },
...@@ -49,14 +53,17 @@ module.exports = { ...@@ -49,14 +53,17 @@ module.exports = {
@param {String} tableName The name of the table. @param {String} tableName The name of the table.
@param {Object} attributes An object with the attribute's name as key and it's options as value object. @param {Object} attributes An object with the attribute's name as key and it's options as value object.
@param {Object} options
@param {Boolean|Function} [options.logging] A function that logs the sql queries, or false for explicitly not logging these queries
@param {CustomEventEmitter} emitter The EventEmitter from outside. @param {CustomEventEmitter} emitter The EventEmitter from outside.
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered. @param {Function} queryAndEmit The function from outside that triggers some events to get triggered.
@since 1.6.0 @since 1.6.0
*/ */
changeColumn: function(tableName, attributes) { changeColumn: function(tableName, attributes, options) {
var attributeName = Utils._.keys(attributes)[0] var attributeName = Utils._.keys(attributes)[0]
, self = this; , self = this;
options = options || {};
return this.describeTable(tableName).then(function(fields) { return this.describeTable(tableName).then(function(fields) {
fields[attributeName] = attributes[attributeName]; fields[attributeName] = attributes[attributeName];
...@@ -65,7 +72,7 @@ module.exports = { ...@@ -65,7 +72,7 @@ module.exports = {
, subQueries = sql.split(';').filter(function(q) { return q !== ''; }); , subQueries = sql.split(';').filter(function(q) { return q !== ''; });
return Promise.each(subQueries, function(subQuery) { return Promise.each(subQueries, function(subQuery) {
return self.sequelize.query(subQuery + ';', null, { raw: true}); return self.sequelize.query(subQuery + ';', { raw: true, logging: options.logging });
}); });
}); });
}, },
...@@ -81,13 +88,17 @@ module.exports = { ...@@ -81,13 +88,17 @@ module.exports = {
@param {String} tableName The name of the table. @param {String} tableName The name of the table.
@param {String} attrNameBefore The name of the attribute before it was renamed. @param {String} attrNameBefore The name of the attribute before it was renamed.
@param {String} attrNameAfter The name of the attribute after it was renamed. @param {String} attrNameAfter The name of the attribute after it was renamed.
@param {Object} options
@param {Boolean|Function} [options.logging] A function that logs the sql queries, or false for explicitly not logging these queries
@param {CustomEventEmitter} emitter The EventEmitter from outside. @param {CustomEventEmitter} emitter The EventEmitter from outside.
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered. @param {Function} queryAndEmit The function from outside that triggers some events to get triggered.
@since 1.6.0 @since 1.6.0
*/ */
renameColumn: function(tableName, attrNameBefore, attrNameAfter) { renameColumn: function(tableName, attrNameBefore, attrNameAfter, options) {
var self = this; var self = this;
options = options || {};
return this.describeTable(tableName).then(function(fields) { return this.describeTable(tableName).then(function(fields) {
fields[attrNameAfter] = Utils._.clone(fields[attrNameBefore]); fields[attrNameAfter] = Utils._.clone(fields[attrNameBefore]);
delete fields[attrNameBefore]; delete fields[attrNameBefore];
...@@ -96,7 +107,7 @@ module.exports = { ...@@ -96,7 +107,7 @@ module.exports = {
, subQueries = sql.split(';').filter(function(q) { return q !== ''; }); , subQueries = sql.split(';').filter(function(q) { return q !== ''; });
return Promise.each(subQueries, function(subQuery) { return Promise.each(subQueries, function(subQuery) {
return self.sequelize.query(subQuery + ';', null, { raw: true}); return self.sequelize.query(subQuery + ';', { raw: true, logging: options.logging });
}); });
}); });
} }
......
...@@ -265,7 +265,7 @@ module.exports = (function() { ...@@ -265,7 +265,7 @@ module.exports = (function() {
, i , i
, length; , length;
if (typeof key === 'object') { if (typeof key === 'object' && key !== null) {
values = key; values = key;
options = value || {}; options = value || {};
......
...@@ -409,7 +409,7 @@ module.exports = (function() { ...@@ -409,7 +409,7 @@ module.exports = (function() {
var self = this var self = this
, attributes = this.tableAttributes; , attributes = this.tableAttributes;
return Promise.resolve().then(function () { return Promise.try(function () {
if (options.force) { if (options.force) {
return self.drop(options); return self.drop(options);
} }
...@@ -537,7 +537,7 @@ module.exports = (function() { ...@@ -537,7 +537,7 @@ module.exports = (function() {
self.scoped = true; self.scoped = true;
// Set defaults // Set defaults
scopeOptions = (typeof lastArg === 'object' && !Array.isArray(lastArg) ? lastArg : {}) || {}; // <-- for no arguments scopeOptions = typeof lastArg === 'object' && !Array.isArray(lastArg) && lastArg || {};
scopeOptions.silent = (scopeOptions !== null && scopeOptions.hasOwnProperty('silent') ? scopeOptions.silent : true); scopeOptions.silent = (scopeOptions !== null && scopeOptions.hasOwnProperty('silent') ? scopeOptions.silent : true);
// Clear out any predefined scopes... // Clear out any predefined scopes...
......
'use strict'; 'use strict';
var Utils = require(__dirname + '/utils'); var Utils = require(__dirname + '/utils')
, deprecatedSeen = {}
, deprecated = function(message) {
if (deprecatedSeen[message]) return;
console.warn(message);
deprecatedSeen[message] = true;
};
module.exports = (function() { module.exports = (function() {
/** /**
...@@ -12,6 +18,8 @@ module.exports = (function() { ...@@ -12,6 +18,8 @@ module.exports = (function() {
var QueryChainer = function(emitters) { var QueryChainer = function(emitters) {
var self = this; var self = this;
deprecated('The query chainer is deprecated, and due for removal in v. 2.2. Please use promises (http://sequelize.readthedocs.org/en/latest/api/promise/) instead!');
this.finishedEmits = 0; this.finishedEmits = 0;
this.emitters = []; this.emitters = [];
this.serials = []; this.serials = [];
......
...@@ -18,24 +18,27 @@ module.exports = (function() { ...@@ -18,24 +18,27 @@ module.exports = (function() {
this.QueryGenerator = this.sequelize.dialect.QueryGenerator; this.QueryGenerator = this.sequelize.dialect.QueryGenerator;
}; };
QueryInterface.prototype.createSchema = function(schema) { QueryInterface.prototype.createSchema = function(schema, options) {
options = options || {};
var sql = this.QueryGenerator.createSchema(schema); var sql = this.QueryGenerator.createSchema(schema);
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
}; };
QueryInterface.prototype.dropSchema = function(schema) { QueryInterface.prototype.dropSchema = function(schema, options) {
options = options || {};
var sql = this.QueryGenerator.dropSchema(schema); var sql = this.QueryGenerator.dropSchema(schema);
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
}; };
QueryInterface.prototype.dropAllSchemas = function() { QueryInterface.prototype.dropAllSchemas = function(options) {
var self = this; options = options || {};
var self = this;
if (!this.QueryGenerator._dialect.supports.schemas) { if (!this.QueryGenerator._dialect.supports.schemas) {
return this.sequelize.drop(); return this.sequelize.drop({ logging: options.logging });
} else { } else {
return this.showAllSchemas().map(function(schemaName) { return this.showAllSchemas(options).map(function(schemaName) {
return self.dropSchema(schemaName); return self.dropSchema(schemaName, { logging: options.logging });
}); });
} }
}; };
...@@ -45,7 +48,8 @@ module.exports = (function() { ...@@ -45,7 +48,8 @@ module.exports = (function() {
options = Utils._.extend({ options = Utils._.extend({
raw: true, raw: true,
type: this.sequelize.QueryTypes.SELECT type: this.sequelize.QueryTypes.SELECT,
logging: false
}, options || {}); }, options || {});
var showSchemasSql = self.QueryGenerator.showSchemasQuery(); var showSchemasSql = self.QueryGenerator.showSchemasQuery();
...@@ -59,10 +63,12 @@ module.exports = (function() { ...@@ -59,10 +63,12 @@ module.exports = (function() {
}); });
}; };
QueryInterface.prototype.databaseVersion = function() { QueryInterface.prototype.databaseVersion = function(options) {
return this.sequelize.query(this.QueryGenerator.versionQuery(), null, { options = options || {};
return this.sequelize.query(this.QueryGenerator.versionQuery(), {
raw: true, raw: true,
type: QueryTypes.VERSION type: QueryTypes.VERSION,
logging: options.logging
}); });
}; };
...@@ -73,6 +79,8 @@ module.exports = (function() { ...@@ -73,6 +79,8 @@ module.exports = (function() {
, sql = '' , sql = ''
, i = 0; , i = 0;
options = options || {};
attributes = Utils._.mapValues(attributes, function(attribute) { attributes = Utils._.mapValues(attributes, function(attribute) {
if (!Utils._.isPlainObject(attribute)) { if (!Utils._.isPlainObject(attribute)) {
attribute = { type: attribute, allowNull: true }; attribute = { type: attribute, allowNull: true };
...@@ -102,10 +110,6 @@ module.exports = (function() { ...@@ -102,10 +110,6 @@ module.exports = (function() {
return attribute; return attribute;
}); });
options = Utils._.extend({
logging: this.sequelize.options.logging,
}, options || {});
// Postgres requires a special SQL command for enums // Postgres requires a special SQL command for enums
if (self.sequelize.options.dialect === 'postgres') { if (self.sequelize.options.dialect === 'postgres') {
var promises = [] var promises = []
...@@ -116,7 +120,7 @@ module.exports = (function() { ...@@ -116,7 +120,7 @@ module.exports = (function() {
for (i = 0; i < keyLen; i++) { for (i = 0; i < keyLen; i++) {
if (attributes[keys[i]].type instanceof DataTypes.ENUM) { if (attributes[keys[i]].type instanceof DataTypes.ENUM) {
sql = self.QueryGenerator.pgListEnums(getTableName, attributes[keys[i]].field || keys[i], options); sql = self.QueryGenerator.pgListEnums(getTableName, attributes[keys[i]].field || keys[i], options);
promises.push(self.sequelize.query(sql, null, { plain: true, raw: true, type: QueryTypes.SELECT, logging: options.logging })); promises.push(self.sequelize.query(sql, { plain: true, raw: true, type: QueryTypes.SELECT, logging: options.logging }));
} }
} }
...@@ -133,7 +137,7 @@ module.exports = (function() { ...@@ -133,7 +137,7 @@ module.exports = (function() {
// If the enum type doesn't exist then create it // If the enum type doesn't exist then create it
if (!results[enumIdx]) { if (!results[enumIdx]) {
sql = self.QueryGenerator.pgEnum(getTableName, attributes[keys[i]].field || keys[i], attributes[keys[i]], options); sql = self.QueryGenerator.pgEnum(getTableName, attributes[keys[i]].field || keys[i], attributes[keys[i]], options);
promises.push(self.sequelize.query(sql, null, { raw: true, logging: options.logging })); promises.push(self.sequelize.query(sql, { raw: true, logging: options.logging }));
} else if (!!results[enumIdx] && !!daoTable) { } else if (!!results[enumIdx] && !!daoTable) {
var enumVals = self.QueryGenerator.fromArray(results[enumIdx].enum_value) var enumVals = self.QueryGenerator.fromArray(results[enumIdx].enum_value)
, vals = daoTable.rawAttributes[keys[i]].values; , vals = daoTable.rawAttributes[keys[i]].values;
...@@ -150,8 +154,7 @@ module.exports = (function() { ...@@ -150,8 +154,7 @@ module.exports = (function() {
else if (!!vals[idx - 1]) { else if (!!vals[idx - 1]) {
options.after = vals[idx - 1]; options.after = vals[idx - 1];
} }
promises.push(self.sequelize.query(self.QueryGenerator.pgEnumAdd(getTableName, keys[i], value, options), options));
promises.push(self.sequelize.query(self.QueryGenerator.pgEnumAdd(getTableName, keys[i], value, options)));
} }
}); });
enumIdx++; enumIdx++;
...@@ -172,7 +175,7 @@ module.exports = (function() { ...@@ -172,7 +175,7 @@ module.exports = (function() {
sql = self.QueryGenerator.createTableQuery(tableName, attributes, options); sql = self.QueryGenerator.createTableQuery(tableName, attributes, options);
return Promise.all(promises).then(function() { return Promise.all(promises).then(function() {
return self.sequelize.query(sql, null, options); return self.sequelize.query(sql, options);
}); });
}); });
} else { } else {
...@@ -188,7 +191,7 @@ module.exports = (function() { ...@@ -188,7 +191,7 @@ module.exports = (function() {
}); });
sql = self.QueryGenerator.createTableQuery(tableName, attributes, options); sql = self.QueryGenerator.createTableQuery(tableName, attributes, options);
return self.sequelize.query(sql, null, options); return self.sequelize.query(sql, options);
} }
}; };
...@@ -200,7 +203,7 @@ module.exports = (function() { ...@@ -200,7 +203,7 @@ module.exports = (function() {
var sql = this.QueryGenerator.dropTableQuery(tableName, options) var sql = this.QueryGenerator.dropTableQuery(tableName, options)
, self = this; , self = this;
return this.sequelize.query(sql, null, options).then(function() { return this.sequelize.query(sql, options).then(function() {
var promises = []; var promises = [];
// Since postgres has a special case for enums, we should drop the related // Since postgres has a special case for enums, we should drop the related
...@@ -218,7 +221,7 @@ module.exports = (function() { ...@@ -218,7 +221,7 @@ module.exports = (function() {
for (i = 0; i < keyLen; i++) { for (i = 0; i < keyLen; i++) {
if (daoTable.rawAttributes[keys[i]].type instanceof DataTypes.ENUM) { if (daoTable.rawAttributes[keys[i]].type instanceof DataTypes.ENUM) {
promises.push(self.sequelize.query(self.QueryGenerator.pgEnumDrop(getTableName, keys[i]), null, {logging: options.logging, raw: true})); promises.push(self.sequelize.query(self.QueryGenerator.pgEnumDrop(getTableName, keys[i]), {logging: options.logging, raw: true}));
} }
} }
} }
...@@ -237,7 +240,7 @@ module.exports = (function() { ...@@ -237,7 +240,7 @@ module.exports = (function() {
return Promise.each(tableNames, function(tableName) { return Promise.each(tableNames, function(tableName) {
// if tableName is not in the Array of tables names then dont drop it // if tableName is not in the Array of tables names then dont drop it
if (skip.indexOf(tableName.tableName || tableName) === -1) { if (skip.indexOf(tableName.tableName || tableName) === -1) {
return self.dropTable(tableName, { cascade: true }); return self.dropTable(tableName, { cascade: true, logging: options.logging });
} }
}); });
}; };
...@@ -245,13 +248,13 @@ module.exports = (function() { ...@@ -245,13 +248,13 @@ module.exports = (function() {
var skip = options.skip || []; var skip = options.skip || [];
return self.showAllTables().then(function(tableNames) { return self.showAllTables().then(function(tableNames) {
if (self.sequelize.options.dialect === 'sqlite') { if (self.sequelize.options.dialect === 'sqlite') {
return self.sequelize.query('PRAGMA foreign_keys;').then(function(result) { return self.sequelize.query('PRAGMA foreign_keys;', options).then(function(result) {
var foreignKeysAreEnabled = result.foreign_keys === 1; var foreignKeysAreEnabled = result.foreign_keys === 1;
if (foreignKeysAreEnabled) { if (foreignKeysAreEnabled) {
return self.sequelize.query('PRAGMA foreign_keys = OFF').then(function() { return self.sequelize.query('PRAGMA foreign_keys = OFF', options).then(function() {
return dropAllTables(tableNames).then(function() { return dropAllTables(tableNames).then(function() {
return self.sequelize.query('PRAGMA foreign_keys = ON'); return self.sequelize.query('PRAGMA foreign_keys = ON', options);
}); });
}); });
} else { } else {
...@@ -270,7 +273,7 @@ module.exports = (function() { ...@@ -270,7 +273,7 @@ module.exports = (function() {
foreignKeys[normalizedTableName].forEach(function(foreignKey) { foreignKeys[normalizedTableName].forEach(function(foreignKey) {
var sql = self.QueryGenerator.dropForeignKeyQuery(tableName, foreignKey); var sql = self.QueryGenerator.dropForeignKeyQuery(tableName, foreignKey);
promises.push(self.sequelize.query(sql)); promises.push(self.sequelize.query(sql, options));
}); });
}); });
...@@ -292,18 +295,18 @@ module.exports = (function() { ...@@ -292,18 +295,18 @@ module.exports = (function() {
var self = this var self = this
, sql = this.QueryGenerator.pgListEnums(); , sql = this.QueryGenerator.pgListEnums();
return this.sequelize.query(sql, null, { plain: false, raw: true, type: QueryTypes.SELECT, logging: options.logging }).map(function(result) { return this.sequelize.query(sql, { plain: false, raw: true, type: QueryTypes.SELECT, logging: options.logging }).map(function(result) {
return self.sequelize.query( return self.sequelize.query(
self.QueryGenerator.pgEnumDrop(null, null, self.QueryGenerator.pgEscapeAndQuote(result.enum_name)), self.QueryGenerator.pgEnumDrop(null, null, self.QueryGenerator.pgEscapeAndQuote(result.enum_name)),
null,
{logging: options.logging, raw: true} {logging: options.logging, raw: true}
); );
}); });
}; };
QueryInterface.prototype.renameTable = function(before, after) { QueryInterface.prototype.renameTable = function(before, after, options) {
options = options || {};
var sql = this.QueryGenerator.renameTableQuery(before, after); var sql = this.QueryGenerator.renameTableQuery(before, after);
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, { logging: options.logging });
}; };
QueryInterface.prototype.showAllTables = function(options) { QueryInterface.prototype.showAllTables = function(options) {
...@@ -314,7 +317,7 @@ module.exports = (function() { ...@@ -314,7 +317,7 @@ module.exports = (function() {
}, options || {}); }, options || {});
var showTablesSql = self.QueryGenerator.showTablesQuery(); var showTablesSql = self.QueryGenerator.showTablesQuery();
return self.sequelize.query(showTablesSql, null, options).then(function(tableNames) { return self.sequelize.query(showTablesSql, options).then(function(tableNames) {
return Utils._.flatten(tableNames); return Utils._.flatten(tableNames);
}); });
}; };
...@@ -325,19 +328,19 @@ module.exports = (function() { ...@@ -325,19 +328,19 @@ module.exports = (function() {
if (typeof options === 'string') { if (typeof options === 'string') {
schema = options; schema = options;
} else if (typeof options === 'object') { } else if (typeof options === 'object' && options !== null) {
schema = options.schema || null; schema = options.schema || null;
schemaDelimiter = options.schemaDelimiter || null; schemaDelimiter = options.schemaDelimiter || null;
} }
if (typeof tableName === 'object') { if (typeof tableName === 'object' && tableName !== null) {
schema = tableName.schema; schema = tableName.schema;
tableName = tableName.tableName; tableName = tableName.tableName;
} }
var sql = this.QueryGenerator.describeTableQuery(tableName, schema, schemaDelimiter); var sql = this.QueryGenerator.describeTableQuery(tableName, schema, schemaDelimiter);
return this.sequelize.query(sql, { type: QueryTypes.DESCRIBE }).then(function(data) { return this.sequelize.query(sql, { type: QueryTypes.DESCRIBE, logging: options && options.logging }).then(function(data) {
// If no data is returned from the query, then the table name may be wrong. // If no data is returned from the query, then the table name may be wrong.
// Query generators that use information_schema for retrieving table info will just return an empty result set, // Query generators that use information_schema for retrieving table info will just return an empty result set,
// it will not throw an error like built-ins do (e.g. DESCRIBE on MySql). // it will not throw an error like built-ins do (e.g. DESCRIBE on MySql).
...@@ -349,23 +352,26 @@ module.exports = (function() { ...@@ -349,23 +352,26 @@ module.exports = (function() {
}); });
}; };
QueryInterface.prototype.addColumn = function(table, key, attribute) { QueryInterface.prototype.addColumn = function(table, key, attribute, options) {
options = options || {};
attribute = this.sequelize.normalizeAttribute(attribute); attribute = this.sequelize.normalizeAttribute(attribute);
return this.sequelize.query(this.QueryGenerator.addColumnQuery(table, key, attribute), null, {logging: this.sequelize.options.logging}); return this.sequelize.query(this.QueryGenerator.addColumnQuery(table, key, attribute), { logging: options.logging });
}; };
QueryInterface.prototype.removeColumn = function(tableName, attributeName) { QueryInterface.prototype.removeColumn = function(tableName, attributeName, options) {
options = options || {};
if (this.sequelize.options.dialect === 'sqlite') { if (this.sequelize.options.dialect === 'sqlite') {
// sqlite needs some special treatment as it cannot drop a column // sqlite needs some special treatment as it cannot drop a column
return SQLiteQueryInterface.removeColumn.call(this, tableName, attributeName); return SQLiteQueryInterface.removeColumn.call(this, tableName, attributeName, {logging: options.logging});
} else { } else {
var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName); var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName);
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
} }
}; };
QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) { QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions, options) {
var attributes = {}; var attributes = {};
options = options || {};
if (Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1) { if (Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1) {
attributes[attributeName] = { type: dataTypeOrOptions, allowNull: true }; attributes[attributeName] = { type: dataTypeOrOptions, allowNull: true };
...@@ -377,22 +383,23 @@ module.exports = (function() { ...@@ -377,22 +383,23 @@ module.exports = (function() {
if (this.sequelize.options.dialect === 'sqlite') { if (this.sequelize.options.dialect === 'sqlite') {
// sqlite needs some special treatment as it cannot change a column // sqlite needs some special treatment as it cannot change a column
return SQLiteQueryInterface.changeColumn.call(this, tableName, attributes); return SQLiteQueryInterface.changeColumn.call(this, tableName, attributes, {logging: options.logging});
} else { } else {
var options = this.QueryGenerator.attributesToSQL(attributes) var query = this.QueryGenerator.attributesToSQL(attributes)
, sql = this.QueryGenerator.changeColumnQuery(tableName, options); , sql = this.QueryGenerator.changeColumnQuery(tableName, query);
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
} }
}; };
QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter) { QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter, options) {
return this.describeTable(tableName).then(function(data) { options = options || {};
return this.describeTable(tableName, options).then(function(data) {
data = data[attrNameBefore] || {}; data = data[attrNameBefore] || {};
var options = {}; var _options = {};
options[attrNameAfter] = { _options[attrNameAfter] = {
attribute: attrNameAfter, attribute: attrNameAfter,
type: data.type, type: data.type,
allowNull: data.allowNull, allowNull: data.allowNull,
...@@ -401,30 +408,29 @@ module.exports = (function() { ...@@ -401,30 +408,29 @@ module.exports = (function() {
// fix: a not-null column cannot have null as default value // fix: a not-null column cannot have null as default value
if (data.defaultValue === null && !data.allowNull) { if (data.defaultValue === null && !data.allowNull) {
delete options[attrNameAfter].defaultValue; delete _options[attrNameAfter].defaultValue;
} }
if (this.sequelize.options.dialect === 'sqlite') { if (this.sequelize.options.dialect === 'sqlite') {
// sqlite needs some special treatment as it cannot rename a column // sqlite needs some special treatment as it cannot rename a column
return SQLiteQueryInterface.renameColumn.call(this, tableName, attrNameBefore, attrNameAfter); return SQLiteQueryInterface.renameColumn.call(this, tableName, attrNameBefore, attrNameAfter, {logging: options.logging});
} else { } else {
var sql = this.QueryGenerator.renameColumnQuery( var sql = this.QueryGenerator.renameColumnQuery(
tableName, tableName,
attrNameBefore, attrNameBefore,
this.QueryGenerator.attributesToSQL(options) this.QueryGenerator.attributesToSQL(_options)
); );
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
} }
}.bind(this)); }.bind(this));
}; };
QueryInterface.prototype.addIndex = function(tableName, _attributes, _options, _rawTablename) { QueryInterface.prototype.addIndex = function(tableName, _attributes, options, _rawTablename) {
var attributes, options, rawTablename; var attributes, rawTablename;
// Support for passing tableName, attributes, options or tableName, options (with a fields param which is the attributes) // Support for passing tableName, attributes, options or tableName, options (with a fields param which is the attributes)
if (Array.isArray(_attributes)) { if (Array.isArray(_attributes)) {
attributes = _attributes; attributes = _attributes;
options = _options;
rawTablename = _rawTablename; rawTablename = _rawTablename;
} else { } else {
...@@ -432,7 +438,7 @@ module.exports = (function() { ...@@ -432,7 +438,7 @@ module.exports = (function() {
options = _attributes; options = _attributes;
attributes = options.fields; attributes = options.fields;
rawTablename = _options; rawTablename = options;
} }
if (!rawTablename) { if (!rawTablename) {
...@@ -443,14 +449,14 @@ module.exports = (function() { ...@@ -443,14 +449,14 @@ module.exports = (function() {
options = options || {}; options = options || {};
options.fields = attributes; options.fields = attributes;
var sql = this.QueryGenerator.addIndexQuery(tableName, options, rawTablename); var sql = this.QueryGenerator.addIndexQuery(tableName, options, rawTablename);
return this.sequelize.query(sql, null, {logging: options.hasOwnProperty('logging') ? options.logging : this.sequelize.options.logging}); return this.sequelize.query(sql, { logging: options.logging });
}; };
QueryInterface.prototype.showIndex = function(tableName, options) { QueryInterface.prototype.showIndex = function(tableName, options) {
var sql = this.QueryGenerator.showIndexesQuery(tableName, options); var sql = this.QueryGenerator.showIndexesQuery(tableName, options);
options = options || {}; options = options || {};
return this.sequelize.query(sql, null, { return this.sequelize.query(sql, {
logging: options.hasOwnProperty('logging') ? options.logging : this.sequelize.options.logging, logging: options.logging,
type: QueryTypes.SHOWINDEXES type: QueryTypes.SHOWINDEXES
}); });
}; };
...@@ -459,15 +465,16 @@ module.exports = (function() { ...@@ -459,15 +465,16 @@ module.exports = (function() {
return this.QueryGenerator.nameIndexes(indexes, rawTablename); return this.QueryGenerator.nameIndexes(indexes, rawTablename);
}; };
QueryInterface.prototype.getForeignKeysForTables = function(tableNames) { QueryInterface.prototype.getForeignKeysForTables = function(tableNames, options) {
var self = this; var self = this;
options = options || {};
if (tableNames.length === 0) { if (tableNames.length === 0) {
return Promise.resolve({}); return Promise.resolve({});
} }
return Promise.map(tableNames, function(tableName) { return Promise.map(tableNames, function(tableName) {
return self.sequelize.query(self.QueryGenerator.getForeignKeysQuery(tableName, self.sequelize.config.database)).get(0); return self.sequelize.query(self.QueryGenerator.getForeignKeysQuery(tableName, self.sequelize.config.database), {logging: options.logging}).get(0);
}).then(function(results) { }).then(function(results) {
var result = {}; var result = {};
...@@ -485,16 +492,18 @@ module.exports = (function() { ...@@ -485,16 +492,18 @@ module.exports = (function() {
}); });
}; };
QueryInterface.prototype.removeIndex = function(tableName, indexNameOrAttributes) { QueryInterface.prototype.removeIndex = function(tableName, indexNameOrAttributes, options) {
options = options || {};
var sql = this.QueryGenerator.removeIndexQuery(tableName, indexNameOrAttributes); var sql = this.QueryGenerator.removeIndexQuery(tableName, indexNameOrAttributes);
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
}; };
QueryInterface.prototype.insert = function(dao, tableName, values, options) { QueryInterface.prototype.insert = function(dao, tableName, values, options) {
var sql = this.QueryGenerator.insertQuery(tableName, values, dao && dao.Model.rawAttributes, options); var sql = this.QueryGenerator.insertQuery(tableName, values, dao && dao.Model.rawAttributes, options);
options.type = QueryTypes.INSERT; options.type = QueryTypes.INSERT;
return this.sequelize.query(sql, dao, options).then(function(result) { options.instance = dao;
return this.sequelize.query(sql, options).then(function(result) {
if (dao) result.isNewRecord = false; if (dao) result.isNewRecord = false;
return result; return result;
}); });
...@@ -564,7 +573,7 @@ module.exports = (function() { ...@@ -564,7 +573,7 @@ module.exports = (function() {
} }
var sql = this.QueryGenerator.upsertQuery(tableName, values, updateValues, where, model.rawAttributes, options); var sql = this.QueryGenerator.upsertQuery(tableName, values, updateValues, where, model.rawAttributes, options);
return this.sequelize.query(sql, null, options).then(function (rowCount) { return this.sequelize.query(sql, options).then(function (rowCount) {
if (rowCount === undefined) { if (rowCount === undefined) {
return rowCount; return rowCount;
} }
...@@ -578,7 +587,7 @@ module.exports = (function() { ...@@ -578,7 +587,7 @@ module.exports = (function() {
QueryInterface.prototype.bulkInsert = function(tableName, records, options, attributes) { QueryInterface.prototype.bulkInsert = function(tableName, records, options, attributes) {
options.type = QueryTypes.INSERT; options.type = QueryTypes.INSERT;
var sql = this.QueryGenerator.bulkInsertQuery(tableName, records, options, attributes); var sql = this.QueryGenerator.bulkInsertQuery(tableName, records, options, attributes);
return this.sequelize.query(sql, null, options); return this.sequelize.query(sql, options);
}; };
QueryInterface.prototype.update = function(dao, tableName, values, identifier, options) { QueryInterface.prototype.update = function(dao, tableName, values, identifier, options) {
...@@ -601,7 +610,8 @@ module.exports = (function() { ...@@ -601,7 +610,8 @@ module.exports = (function() {
} }
} }
return this.sequelize.query(sql, dao, options); options.instance = dao;
return this.sequelize.query(sql, options);
}; };
QueryInterface.prototype.bulkUpdate = function(tableName, values, identifier, options, attributes) { QueryInterface.prototype.bulkUpdate = function(tableName, values, identifier, options, attributes) {
...@@ -609,8 +619,10 @@ module.exports = (function() { ...@@ -609,8 +619,10 @@ module.exports = (function() {
, table = Utils._.isObject(tableName) ? tableName : { tableName: tableName } , table = Utils._.isObject(tableName) ? tableName : { tableName: tableName }
, daoTable = Utils._.find(this.sequelize.daoFactoryManager.daos, { tableName: table.tableName }); , daoTable = Utils._.find(this.sequelize.daoFactoryManager.daos, { tableName: table.tableName });
options = options || {};
daoTable.__options = daoTable.options; daoTable.__options = daoTable.options;
return this.sequelize.query(sql, daoTable, options); options.instance = daoTable;
return this.sequelize.query(sql, options);
}; };
QueryInterface.prototype.delete = function(dao, tableName, identifier, options) { QueryInterface.prototype.delete = function(dao, tableName, identifier, options) {
...@@ -618,6 +630,8 @@ module.exports = (function() { ...@@ -618,6 +630,8 @@ module.exports = (function() {
, cascades = [] , cascades = []
, sql = self.QueryGenerator.deleteQuery(tableName, identifier, null, dao.Model); , sql = self.QueryGenerator.deleteQuery(tableName, identifier, null, dao.Model);
options = options || {};
// Check for a restrict field // Check for a restrict field
if (!!dao.Model && !!dao.Model.associations) { if (!!dao.Model && !!dao.Model.associations) {
var keys = Object.keys(dao.Model.associations) var keys = Object.keys(dao.Model.associations)
...@@ -634,24 +648,27 @@ module.exports = (function() { ...@@ -634,24 +648,27 @@ module.exports = (function() {
return Promise.each(cascades, function (cascade) { return Promise.each(cascades, function (cascade) {
return dao[cascade]({ return dao[cascade]({
transaction: options.transaction transaction: options.transaction,
logging: options.logging
}).then(function (instances) { }).then(function (instances) {
if (!Array.isArray(instances)) instances = [instances]; if (!Array.isArray(instances)) instances = [instances];
return Promise.each(instances, function (instance) { return Promise.each(instances, function (instance) {
return instance.destroy({ return instance.destroy({
transaction: options.transaction transaction: options.transaction,
logging: options.logging
}); });
}); });
}); });
}).then(function () { }).then(function () {
return self.sequelize.query(sql, dao, options); options.instance = dao;
return self.sequelize.query(sql, options);
}); });
}; };
QueryInterface.prototype.bulkDelete = function(tableName, identifier, options, model) { QueryInterface.prototype.bulkDelete = function(tableName, identifier, options, model) {
var sql = this.QueryGenerator.deleteQuery(tableName, identifier, Utils._.defaults(options || {}, {limit: null}), model); var sql = this.QueryGenerator.deleteQuery(tableName, identifier, Utils._.defaults(options || {}, {limit: null}), model);
return this.sequelize.query(sql, null, options); return this.sequelize.query(sql, options);
}; };
QueryInterface.prototype.select = function(model, tableName, options, queryOptions) { QueryInterface.prototype.select = function(model, tableName, options, queryOptions) {
...@@ -679,9 +696,9 @@ module.exports = (function() { ...@@ -679,9 +696,9 @@ module.exports = (function() {
}); });
} }
options.instance = model;
return this.sequelize.query( return this.sequelize.query(
this.QueryGenerator.selectQuery(tableName, options, model), this.QueryGenerator.selectQuery(tableName, options, model),
model,
options options
); );
}; };
...@@ -689,8 +706,11 @@ module.exports = (function() { ...@@ -689,8 +706,11 @@ module.exports = (function() {
QueryInterface.prototype.increment = function(dao, tableName, values, identifier, options) { QueryInterface.prototype.increment = function(dao, tableName, values, identifier, options) {
var sql = this.QueryGenerator.incrementQuery(tableName, values, identifier, options.attributes); var sql = this.QueryGenerator.incrementQuery(tableName, values, identifier, options.attributes);
options = options || {};
options.type = QueryTypes.RAW; options.type = QueryTypes.RAW;
return this.sequelize.query(sql, dao, options); options.instance = dao;
return this.sequelize.query(sql, options);
}; };
QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector, Model) { QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector, Model) {
...@@ -704,13 +724,13 @@ module.exports = (function() { ...@@ -704,13 +724,13 @@ module.exports = (function() {
options.plain = options.plain === undefined ? true : options.plain; options.plain = options.plain === undefined ? true : options.plain;
var sql = this.QueryGenerator.selectQuery(tableName, options, Model) var sql = this.QueryGenerator.selectQuery(tableName, options, Model)
, queryOptions = Utils._.extend({ transaction: options.transaction, plain: options.plain }, { raw: true, type: QueryTypes.SELECT }); , queryOptions = Utils._.extend({ transaction: options.transaction, plain: options.plain, logging: options.logging }, { raw: true, type: QueryTypes.SELECT });
if (attributeSelector === undefined) { if (attributeSelector === undefined) {
throw new Error('Please pass an attribute selector!'); throw new Error('Please pass an attribute selector!');
} }
return this.sequelize.query(sql, null, queryOptions).then(function(data) { return this.sequelize.query(sql, queryOptions).then(function(data) {
if (!queryOptions.plain) { if (!queryOptions.plain) {
return data; return data;
} }
...@@ -737,30 +757,33 @@ module.exports = (function() { ...@@ -737,30 +757,33 @@ module.exports = (function() {
}); });
}; };
QueryInterface.prototype.createTrigger = function(tableName, triggerName, timingType, fireOnArray, QueryInterface.prototype.createTrigger = function(tableName, triggerName, timingType, fireOnArray, functionName, functionParams, optionsArray, options) {
functionName, functionParams, optionsArray) { var sql = this.QueryGenerator.createTrigger(tableName, triggerName, timingType, fireOnArray, functionName, functionParams, optionsArray);
var sql = this.QueryGenerator.createTrigger(tableName, triggerName, timingType, fireOnArray, functionName options = options || {};
, functionParams, optionsArray);
if (sql) { if (sql) {
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
}; };
QueryInterface.prototype.dropTrigger = function(tableName, triggerName) { QueryInterface.prototype.dropTrigger = function(tableName, triggerName, options) {
var sql = this.QueryGenerator.dropTrigger(tableName, triggerName); var sql = this.QueryGenerator.dropTrigger(tableName, triggerName);
options = options || {};
if (sql) { if (sql) {
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
}; };
QueryInterface.prototype.renameTrigger = function(tableName, oldTriggerName, newTriggerName) { QueryInterface.prototype.renameTrigger = function(tableName, oldTriggerName, newTriggerName, options) {
var sql = this.QueryGenerator.renameTrigger(tableName, oldTriggerName, newTriggerName); var sql = this.QueryGenerator.renameTrigger(tableName, oldTriggerName, newTriggerName);
options = options || {};
if (sql) { if (sql) {
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
...@@ -768,26 +791,32 @@ module.exports = (function() { ...@@ -768,26 +791,32 @@ module.exports = (function() {
QueryInterface.prototype.createFunction = function(functionName, params, returnType, language, body, options) { QueryInterface.prototype.createFunction = function(functionName, params, returnType, language, body, options) {
var sql = this.QueryGenerator.createFunction(functionName, params, returnType, language, body, options); var sql = this.QueryGenerator.createFunction(functionName, params, returnType, language, body, options);
options = options || {};
if (sql) { if (sql) {
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
}; };
QueryInterface.prototype.dropFunction = function(functionName, params) { QueryInterface.prototype.dropFunction = function(functionName, params, options) {
var sql = this.QueryGenerator.dropFunction(functionName, params); var sql = this.QueryGenerator.dropFunction(functionName, params);
options = options || {};
if (sql) { if (sql) {
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
}; };
QueryInterface.prototype.renameFunction = function(oldFunctionName, params, newFunctionName) { QueryInterface.prototype.renameFunction = function(oldFunctionName, params, newFunctionName, options) {
var sql = this.QueryGenerator.renameFunction(oldFunctionName, params, newFunctionName); var sql = this.QueryGenerator.renameFunction(oldFunctionName, params, newFunctionName);
options = options || {};
if (sql) { if (sql) {
return this.sequelize.query(sql, null, {logging: this.sequelize.options.logging}); return this.sequelize.query(sql, {logging: options.logging});
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
...@@ -835,7 +864,7 @@ module.exports = (function() { ...@@ -835,7 +864,7 @@ module.exports = (function() {
var sql = this.QueryGenerator.setAutocommitQuery(value, options); var sql = this.QueryGenerator.setAutocommitQuery(value, options);
if (sql) { if (sql) {
return this.sequelize.query(sql, null, { transaction: transaction }); return this.sequelize.query(sql, { transaction: transaction, logging: options.logging });
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
...@@ -853,7 +882,7 @@ module.exports = (function() { ...@@ -853,7 +882,7 @@ module.exports = (function() {
var sql = this.QueryGenerator.setIsolationLevelQuery(value, options); var sql = this.QueryGenerator.setIsolationLevelQuery(value, options);
if (sql) { if (sql) {
return this.sequelize.query(sql, null, { transaction: transaction }); return this.sequelize.query(sql, { transaction: transaction, logging: options.logging });
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
...@@ -870,7 +899,7 @@ module.exports = (function() { ...@@ -870,7 +899,7 @@ module.exports = (function() {
}, options || {}); }, options || {});
var sql = this.QueryGenerator.startTransactionQuery(transaction, options); var sql = this.QueryGenerator.startTransactionQuery(transaction, options);
return this.sequelize.query(sql, null, options); return this.sequelize.query(sql, options);
}; };
QueryInterface.prototype.commitTransaction = function(transaction, options) { QueryInterface.prototype.commitTransaction = function(transaction, options) {
...@@ -886,7 +915,7 @@ module.exports = (function() { ...@@ -886,7 +915,7 @@ module.exports = (function() {
var sql = this.QueryGenerator.commitTransactionQuery(options); var sql = this.QueryGenerator.commitTransactionQuery(options);
if (sql) { if (sql) {
return this.sequelize.query(sql, null, options); return this.sequelize.query(sql, options);
} else { } else {
return Promise.resolve(); return Promise.resolve();
} }
...@@ -903,7 +932,7 @@ module.exports = (function() { ...@@ -903,7 +932,7 @@ module.exports = (function() {
}, options || {}); }, options || {});
var sql = this.QueryGenerator.rollbackTransactionQuery(transaction, options); var sql = this.QueryGenerator.rollbackTransactionQuery(transaction, options);
return this.sequelize.query(sql, null, options); return this.sequelize.query(sql, options);
}; };
// private // private
......
...@@ -184,7 +184,6 @@ module.exports = (function() { ...@@ -184,7 +184,6 @@ module.exports = (function() {
var Dialect = require('./dialects/' + this.getDialect()); var Dialect = require('./dialects/' + this.getDialect());
this.dialect = new Dialect(this); this.dialect = new Dialect(this);
} catch (err) { } catch (err) {
console.log(err.stack);
throw new Error('The dialect ' + this.getDialect() + ' is not supported. ('+err+')'); throw new Error('The dialect ' + this.getDialect() + ' is not supported. ('+err+')');
} }
...@@ -668,19 +667,17 @@ module.exports = (function() { ...@@ -668,19 +667,17 @@ module.exports = (function() {
*/ */
Sequelize.prototype.query = function(sql, callee, options, replacements) { Sequelize.prototype.query = function(sql, callee, options, replacements) {
var self = this; var self = this;
if (arguments.length === 4) { if (arguments.length === 2) {
deprecated('passing raw query replacements as the 4th argument to sequelize.query is deprecated. Please use options.replacements instead');
options.replacements = replacements;
} else if (arguments.length === 3) {
options = options;
} else if (arguments.length === 2) {
if (callee instanceof Sequelize.Model) { if (callee instanceof Sequelize.Model) {
options = {}; options = {};
} else { } else {
options = callee; options = callee;
callee = undefined; callee = options.instance || undefined;
} }
} else { } else if (arguments.length === 4) {
deprecated('passing raw query replacements as the 4th argument to sequelize.query is deprecated. Please use options.replacements instead');
options.replacements = replacements;
} else if (arguments.length !== 3) {
options = { raw: true }; options = { raw: true };
} }
...@@ -790,7 +787,7 @@ module.exports = (function() { ...@@ -790,7 +787,7 @@ module.exports = (function() {
return '@'+k +' := '+ ( typeof v === 'string' ? '"'+v+'"' : v ); return '@'+k +' := '+ ( typeof v === 'string' ? '"'+v+'"' : v );
}).join(', '); }).join(', ');
return this.query(query, null, options); return this.query(query, options);
}; };
/** /**
...@@ -811,10 +808,12 @@ module.exports = (function() { ...@@ -811,10 +808,12 @@ module.exports = (function() {
* *
* @see {Model#schema} * @see {Model#schema}
* @param {String} schema Name of the schema * @param {String} schema Name of the schema
* @param {Object} options={}
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise} * @return {Promise}
*/ */
Sequelize.prototype.createSchema = function(schema) { Sequelize.prototype.createSchema = function(schema, options) {
return this.getQueryInterface().createSchema(schema); return this.getQueryInterface().createSchema(schema, options);
}; };
/** /**
...@@ -822,10 +821,12 @@ module.exports = (function() { ...@@ -822,10 +821,12 @@ module.exports = (function() {
* *
* Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html), * Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
* not a database table. In mysql and sqlite, this will show all tables. * not a database table. In mysql and sqlite, this will show all tables.
* @param {Object} options={}
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise} * @return {Promise}
*/ */
Sequelize.prototype.showAllSchemas = function() { Sequelize.prototype.showAllSchemas = function(options) {
return this.getQueryInterface().showAllSchemas(); return this.getQueryInterface().showAllSchemas(options);
}; };
/** /**
...@@ -834,10 +835,12 @@ module.exports = (function() { ...@@ -834,10 +835,12 @@ module.exports = (function() {
* Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html), * Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
* not a database table. In mysql and sqlite, this drop a table matching the schema name * not a database table. In mysql and sqlite, this drop a table matching the schema name
* @param {String} schema Name of the schema * @param {String} schema Name of the schema
* @param {Object} options={}
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise} * @return {Promise}
*/ */
Sequelize.prototype.dropSchema = function(schema) { Sequelize.prototype.dropSchema = function(schema, options) {
return this.getQueryInterface().dropSchema(schema); return this.getQueryInterface().dropSchema(schema, options);
}; };
/** /**
...@@ -845,10 +848,12 @@ module.exports = (function() { ...@@ -845,10 +848,12 @@ module.exports = (function() {
* *
* Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html), * Note,that this is a schema in the [postgres sense of the word](http://www.postgresql.org/docs/9.1/static/ddl-schemas.html),
* not a database table. In mysql and sqlite, this is the equivalent of drop all tables. * not a database table. In mysql and sqlite, this is the equivalent of drop all tables.
* @param {Object} options={}
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise} * @return {Promise}
*/ */
Sequelize.prototype.dropAllSchemas = function() { Sequelize.prototype.dropAllSchemas = function(options) {
return this.getQueryInterface().dropAllSchemas(); return this.getQueryInterface().dropAllSchemas(options);
}; };
/** /**
...@@ -904,6 +909,7 @@ module.exports = (function() { ...@@ -904,6 +909,7 @@ module.exports = (function() {
* @see {Model#drop} for options * @see {Model#drop} for options
* *
* @param {object} options The options passed to each call to Model.drop * @param {object} options The options passed to each call to Model.drop
* @param {Boolean|function} options.logging A function that logs sql queries, or false for no logging
* @return {Promise} * @return {Promise}
*/ */
Sequelize.prototype.drop = function(options) { Sequelize.prototype.drop = function(options) {
...@@ -929,13 +935,13 @@ module.exports = (function() { ...@@ -929,13 +935,13 @@ module.exports = (function() {
* @return {Promise} * @return {Promise}
*/ */
Sequelize.prototype.authenticate = function() { Sequelize.prototype.authenticate = function() {
return this.query('SELECT 1+1 AS result', null, { raw: true, plain: true }).return().catch(function(err) { return this.query('SELECT 1+1 AS result', { raw: true, plain: true }).return().catch(function(err) {
throw new Error(err); throw new Error(err);
}); });
}; };
Sequelize.prototype.databaseVersion = function() { Sequelize.prototype.databaseVersion = function(options) {
return this.queryInterface.databaseVersion(); return this.queryInterface.databaseVersion(options);
}; };
Sequelize.prototype.validate = Sequelize.prototype.authenticate; Sequelize.prototype.validate = Sequelize.prototype.authenticate;
......
...@@ -31,14 +31,14 @@ SqlString.escapeId = function(val, forbidQualified) { ...@@ -31,14 +31,14 @@ SqlString.escapeId = function(val, forbidQualified) {
}; };
SqlString.escape = function(val, stringifyObjects, timeZone, dialect, field) { SqlString.escape = function(val, stringifyObjects, timeZone, dialect, field) {
if (arguments.length === 1 && typeof arguments[0] === 'object') { if (arguments.length === 1 && typeof val === 'object' && val !== null) {
val = val.val || val.value || null; val = val.val || val.value || null;
stringifyObjects = val.stringifyObjects || val.objects || undefined; stringifyObjects = val.stringifyObjects || val.objects || undefined;
timeZone = val.timeZone || val.zone || null; timeZone = val.timeZone || val.zone || null;
dialect = val.dialect || null; dialect = val.dialect || null;
field = val.field || null; field = val.field || null;
} }
else if (arguments.length < 3 && typeof arguments[1] === 'object') { else if (arguments.length === 2 && typeof stringifyObjects === 'object' && stringifyObjects !== null) {
timeZone = stringifyObjects.timeZone || stringifyObjects.zone || null; timeZone = stringifyObjects.timeZone || stringifyObjects.zone || null;
dialect = stringifyObjects.dialect || null; dialect = stringifyObjects.dialect || null;
field = stringifyObjects.field || null; field = stringifyObjects.field || null;
...@@ -73,7 +73,7 @@ SqlString.escape = function(val, stringifyObjects, timeZone, dialect, field) { ...@@ -73,7 +73,7 @@ SqlString.escape = function(val, stringifyObjects, timeZone, dialect, field) {
return SqlString.arrayToList(val, timeZone, dialect, field); return SqlString.arrayToList(val, timeZone, dialect, field);
} }
if (typeof val === 'object') { if (typeof val === 'object' && val !== null) {
if (stringifyObjects) { if (stringifyObjects) {
val = val.toString(); val = val.toString();
} else { } else {
......
...@@ -130,7 +130,7 @@ var Utils = module.exports = { ...@@ -130,7 +130,7 @@ var Utils = module.exports = {
if (merge === true && !!scope.where && !!self.scopeObj.where) { if (merge === true && !!scope.where && !!self.scopeObj.where) {
var scopeKeys = Object.keys(scope.where); var scopeKeys = Object.keys(scope.where);
self.scopeObj.where = self.scopeObj.where.map(function(scopeObj) { self.scopeObj.where = self.scopeObj.where.map(function(scopeObj) {
if (!Array.isArray(scopeObj) && typeof scopeObj === 'object') { if (!Array.isArray(scopeObj) && typeof scopeObj === 'object' && scopeObj !== null) {
return lodash.omit.apply(undefined, [scopeObj].concat(scopeKeys)); return lodash.omit.apply(undefined, [scopeObj].concat(scopeKeys));
} else { } else {
return scopeObj; return scopeObj;
...@@ -270,7 +270,7 @@ var Utils = module.exports = { ...@@ -270,7 +270,7 @@ var Utils = module.exports = {
_where._.bindings = _where._.bindings.concat(values); _where._.bindings = _where._.bindings.concat(values);
} }
} }
else if (typeof where === 'object') { else if (typeof where === 'object' && where !== null) {
// First iteration is trying to compress IN and NOT IN as much as possible... // First iteration is trying to compress IN and NOT IN as much as possible...
// .. reason being is that WHERE username IN (?) AND username IN (?) != WHERE username IN (?,?) // .. reason being is that WHERE username IN (?) AND username IN (?) != WHERE username IN (?,?)
Object.keys(where).forEach(function(i) { Object.keys(where).forEach(function(i) {
......
...@@ -22,8 +22,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -22,8 +22,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
this.User = this.sequelize.define('User', { username: DataTypes.STRING }); this.User = this.sequelize.define('User', { username: DataTypes.STRING });
this.Task = this.sequelize.define('Task', { title: DataTypes.STRING, active: DataTypes.BOOLEAN }); this.Task = this.sequelize.define('Task', { title: DataTypes.STRING, active: DataTypes.BOOLEAN });
this.User.belongsToMany(this.Task); this.User.belongsToMany(this.Task, { through: 'UserTasks' });
this.Task.belongsToMany(this.User); this.Task.belongsToMany(this.User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return Promise.all([ return Promise.all([
...@@ -54,8 +54,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -54,8 +54,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
this.Article = sequelize.define('Article', { 'title': DataTypes.STRING }); this.Article = sequelize.define('Article', { 'title': DataTypes.STRING });
this.Label = sequelize.define('Label', { 'text': DataTypes.STRING }); this.Label = sequelize.define('Label', { 'text': DataTypes.STRING });
this.Article.belongsToMany(this.Label); this.Article.belongsToMany(this.Label, { through: 'ArticleLabels' });
this.Label.belongsToMany(this.Article); this.Label.belongsToMany(this.Article, { through: 'ArticleLabels' });
return sequelize.sync({ force: true }); return sequelize.sync({ force: true });
}).then(function() { }).then(function() {
...@@ -417,8 +417,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -417,8 +417,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING }) var User = this.sequelize.define('User', { username: DataTypes.STRING })
, Task = this.sequelize.define('Task', { title: DataTypes.STRING }); , Task = this.sequelize.define('Task', { title: DataTypes.STRING });
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return Promise.all([ return Promise.all([
...@@ -445,8 +445,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -445,8 +445,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var User = this.sequelize.define('User', { uid: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, username: DataTypes.STRING }) var User = this.sequelize.define('User', { uid: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, username: DataTypes.STRING })
, Task = this.sequelize.define('Task', { tid: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, title: DataTypes.STRING }); , Task = this.sequelize.define('Task', { tid: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, title: DataTypes.STRING });
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return Promise.all([ return Promise.all([
...@@ -503,8 +503,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -503,8 +503,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING }) var User = this.sequelize.define('User', { username: DataTypes.STRING })
, Task = this.sequelize.define('Task', { title: DataTypes.STRING }); , Task = this.sequelize.define('Task', { title: DataTypes.STRING });
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return Promise.all([ return Promise.all([
...@@ -532,8 +532,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -532,8 +532,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING }) var User = this.sequelize.define('User', { username: DataTypes.STRING })
, Task = this.sequelize.define('Task', { title: DataTypes.STRING }); , Task = this.sequelize.define('Task', { title: DataTypes.STRING });
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return Task.create({ title: 'task' }); return Task.create({ title: 'task' });
...@@ -555,8 +555,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -555,8 +555,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
this.User = sequelize.define('User', { username: DataTypes.STRING }); this.User = sequelize.define('User', { username: DataTypes.STRING });
this.Task = sequelize.define('Task', { title: DataTypes.STRING }); this.Task = sequelize.define('Task', { title: DataTypes.STRING });
this.User.belongsToMany(this.Task); this.User.belongsToMany(this.Task, { through: 'UserTasks' });
this.Task.belongsToMany(this.User); this.Task.belongsToMany(this.User, { through: 'UserTasks' });
this.sequelize = sequelize; this.sequelize = sequelize;
return sequelize.sync({ force: true }); return sequelize.sync({ force: true });
...@@ -617,8 +617,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -617,8 +617,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING }) var User = this.sequelize.define('User', { username: DataTypes.STRING })
, Task = this.sequelize.define('Task', { title: DataTypes.STRING }); , Task = this.sequelize.define('Task', { title: DataTypes.STRING });
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return Task.create({ title: 'task' }); return Task.create({ title: 'task' });
...@@ -640,8 +640,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -640,8 +640,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING }) var User = this.sequelize.define('User', { username: DataTypes.STRING })
, Task = this.sequelize.define('Task', { title: DataTypes.STRING }); , Task = this.sequelize.define('Task', { title: DataTypes.STRING });
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return Promise.all([ return Promise.all([
...@@ -669,8 +669,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -669,8 +669,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
this.User = sequelize.define('User', { username: DataTypes.STRING }); this.User = sequelize.define('User', { username: DataTypes.STRING });
this.Task = sequelize.define('Task', { title: DataTypes.STRING }); this.Task = sequelize.define('Task', { title: DataTypes.STRING });
this.User.belongsToMany(this.Task); this.User.belongsToMany(this.Task, { through: 'UserTasks' });
this.Task.belongsToMany(this.User); this.Task.belongsToMany(this.User, { through: 'UserTasks' });
this.sequelize = sequelize; this.sequelize = sequelize;
return sequelize.sync({ force: true }); return sequelize.sync({ force: true });
...@@ -740,8 +740,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -740,8 +740,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING }) var User = this.sequelize.define('User', { username: DataTypes.STRING })
, Task = this.sequelize.define('Task', { title: DataTypes.STRING }); , Task = this.sequelize.define('Task', { title: DataTypes.STRING });
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return Promise.all([ return Promise.all([
...@@ -785,8 +785,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -785,8 +785,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
] ]
}); });
//create associations //create associations
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }); return this.sequelize.sync({ force: true });
}); });
}); });
...@@ -796,8 +796,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -796,8 +796,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING }) var User = this.sequelize.define('User', { username: DataTypes.STRING })
, Task = this.sequelize.define('Task', { title: DataTypes.STRING }); , Task = this.sequelize.define('Task', { title: DataTypes.STRING });
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return Promise.all([ return Promise.all([
...@@ -823,8 +823,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -823,8 +823,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var User = this.sequelize.define('User', { username: DataTypes.STRING }) var User = this.sequelize.define('User', { username: DataTypes.STRING })
, Task = this.sequelize.define('Task', { title: DataTypes.STRING }); , Task = this.sequelize.define('Task', { title: DataTypes.STRING });
User.belongsToMany(Task); User.belongsToMany(Task, { through: 'UserTasks' });
Task.belongsToMany(User); Task.belongsToMany(User, { through: 'UserTasks' });
return this.sequelize.sync({ force: true }).then(function() { return this.sequelize.sync({ force: true }).then(function() {
return User.bulkCreate([ return User.bulkCreate([
...@@ -856,8 +856,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -856,8 +856,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
this.User = this.sequelize.define('User', { username: DataTypes.STRING }, {timestamps: false}); this.User = this.sequelize.define('User', { username: DataTypes.STRING }, {timestamps: false});
this.Task = this.sequelize.define('Task', { title: DataTypes.STRING }, {timestamps: false}); this.Task = this.sequelize.define('Task', { title: DataTypes.STRING }, {timestamps: false});
this.User.belongsToMany(this.Task); this.User.belongsToMany(this.Task, { through: 'UserTasks' });
this.Task.belongsToMany(this.User); this.Task.belongsToMany(this.User, { through: 'UserTasks' });
return this.sequelize.sync({force: true}); return this.sequelize.sync({force: true});
}); });
...@@ -870,9 +870,11 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -870,9 +870,11 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
this.Task.create({ id: 12, title: 'task1' }), this.Task.create({ id: 12, title: 'task1' }),
this.Task.create({ id: 15, title: 'task2' }) this.Task.create({ id: 15, title: 'task2' })
]).spread(function(user, task1, task2) { ]).spread(function(user, task1, task2) {
return user.setTasks([task1, task2]).on('sql', spy); return user.setTasks([task1, task2], {
logging: spy
});
}).then(function() { }).then(function() {
expect(spy.calledTwice).to.be.ok; // Once for SELECT, once for INSERT expect(spy.calledTwice).to.be.ok;
}); });
}); });
...@@ -886,9 +888,11 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -886,9 +888,11 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
]).spread(function(user, task1, task2) { ]).spread(function(user, task1, task2) {
return user.setTasks([task1, task2]).return (user); return user.setTasks([task1, task2]).return (user);
}).then(function(user) { }).then(function(user) {
return user.setTasks(null).on('sql', spy); return user.setTasks(null, {
logging: spy
});
}).then(function() { }).then(function() {
expect(spy.calledTwice).to.be.ok; // Once for SELECT, once for DELETE expect(spy.calledTwice).to.be.ok;
}); });
}); });
}); // end optimization using bulk create, destroy and update }); // end optimization using bulk create, destroy and update
...@@ -929,8 +933,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -929,8 +933,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
} }
}); });
Beacons.belongsToMany(Users); Beacons.belongsToMany(Users, { through: 'UserBeacons' });
Users.belongsToMany(Beacons); Users.belongsToMany(Beacons, { through: 'UserBeacons' });
return this.sequelize.sync({force: true}); return this.sequelize.sync({force: true});
}); });
...@@ -960,8 +964,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -960,8 +964,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
, ParanoidUser = paranoidSequelize.define('ParanoidUser', {}) , ParanoidUser = paranoidSequelize.define('ParanoidUser', {})
, ParanoidTask = paranoidSequelize.define('ParanoidTask', {}); , ParanoidTask = paranoidSequelize.define('ParanoidTask', {});
ParanoidUser.belongsToMany(ParanoidTask); ParanoidUser.belongsToMany(ParanoidTask, { through: 'UserTasks' });
ParanoidTask.belongsToMany(ParanoidUser); ParanoidTask.belongsToMany(ParanoidUser, { through: 'UserTasks' });
expect(ParanoidUser.options.paranoid).to.be.ok; expect(ParanoidUser.options.paranoid).to.be.ok;
expect(ParanoidTask.options.paranoid).to.be.ok; expect(ParanoidTask.options.paranoid).to.be.ok;
...@@ -1066,6 +1070,7 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1066,6 +1070,7 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
it('should correctly get associations even after a child instance is deleted', function() { it('should correctly get associations even after a child instance is deleted', function() {
var self = this; var self = this;
var spy = sinon.spy();
return this.sequelize.sync({force: true}).then(function() { return this.sequelize.sync({force: true}).then(function() {
return Promise.join( return Promise.join(
...@@ -1074,13 +1079,20 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1074,13 +1079,20 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
self.Project.create({name: 'The Departed'}) self.Project.create({name: 'The Departed'})
); );
}).spread(function(user, project1, project2) { }).spread(function(user, project1, project2) {
return user.addProjects([project1, project2]).return (user); return user.addProjects([project1, project2], {
logging: spy
}).return (user);
}).then(function(user) { }).then(function(user) {
expect(spy.calledOnce).to.be.ok;
spy.reset();
return Promise.join( return Promise.join(
user, user,
user.getProjects() user.getProjects({
logging: spy
})
); );
}).spread(function(user, projects) { }).spread(function(user, projects) {
expect(spy.calledOnce).to.be.ok;
var project = projects[0]; var project = projects[0];
expect(project).to.be.ok; expect(project).to.be.ok;
return project.destroy().return (user); return project.destroy().return (user);
...@@ -1099,6 +1111,7 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1099,6 +1111,7 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
it('should correctly get associations when doubly linked', function() { it('should correctly get associations when doubly linked', function() {
var self = this; var self = this;
var spy = sinon.spy();
return this.sequelize.sync({force: true}).then(function() { return this.sequelize.sync({force: true}).then(function() {
return Promise.all([ return Promise.all([
self.User.create({name: 'Matt'}), self.User.create({name: 'Matt'}),
...@@ -1107,17 +1120,24 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1107,17 +1120,24 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
}).spread(function(user, project) { }).spread(function(user, project) {
self.user = user; self.user = user;
self.project = project; self.project = project;
return user.addProject(project).return (user); return user.addProject(project, { logging: spy }).return (user);
}).then(function(user) { }).then(function(user) {
return user.getProjects(); expect(spy.calledTwice).to.be.ok; // Once for SELECT, once for INSERT
spy.reset();
return user.getProjects({
logging: spy
});
}).then(function(projects) { }).then(function(projects) {
var project = projects[0]; var project = projects[0];
expect(spy.calledOnce).to.be.ok;
spy.reset();
expect(project).to.be.ok; expect(project).to.be.ok;
return self.user.removeProject(project).on('sql', function(sql) { return self.user.removeProject(project, {
// TODO: rewrite this to use logging and check the generated sql logging: spy
}).return (project); }).return (project);
}).then(function(project) { }).then(function(project) {
expect(spy.calledTwice).to.be.ok; // Once for SELECT, once for REMOVE
return self.user.setProjects([project]); return self.user.setProjects([project]);
}); });
}); });
...@@ -1552,8 +1572,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1552,8 +1572,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
describe('source belongs to target', function() { describe('source belongs to target', function() {
beforeEach(function() { beforeEach(function() {
this.A.belongsTo(this.B, { as: 'relation1' }); this.A.belongsTo(this.B, { as: 'relation1' });
this.A.belongsToMany(this.B, { as: 'relation2' }); this.A.belongsToMany(this.B, { as: 'relation2', through: 'AB' });
this.B.belongsToMany(this.A, { as: 'relation2' }); this.B.belongsToMany(this.A, { as: 'relation2', through: 'AB' });
return this.sequelize.sync({ force: true }); return this.sequelize.sync({ force: true });
}); });
...@@ -1578,8 +1598,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1578,8 +1598,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
describe('target belongs to source', function() { describe('target belongs to source', function() {
beforeEach(function() { beforeEach(function() {
this.B.belongsTo(this.A, { as: 'relation1' }); this.B.belongsTo(this.A, { as: 'relation1' });
this.A.belongsToMany(this.B, { as: 'relation2' }); this.A.belongsToMany(this.B, { as: 'relation2', through: 'AB' });
this.B.belongsToMany(this.A, { as: 'relation2' }); this.B.belongsToMany(this.A, { as: 'relation2', through: 'AB' });
return this.sequelize.sync({ force: true }); return this.sequelize.sync({ force: true });
}); });
...@@ -1711,8 +1731,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1711,8 +1731,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
it('can cascade deletes both ways by default', function() { it('can cascade deletes both ways by default', function() {
var self = this; var self = this;
this.User.belongsToMany(this.Task); this.User.belongsToMany(this.Task, { through: 'tasksusers' });
this.Task.belongsToMany(this.User); this.Task.belongsToMany(this.User, { through: 'tasksusers' });
return this.sequelize.sync({ force: true }).bind({}).then(function() { return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Promise.all([ return Promise.all([
...@@ -1752,8 +1772,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1752,8 +1772,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var self = this var self = this
, spy = sinon.spy(); , spy = sinon.spy();
this.User.belongsToMany(this.Task, { onDelete: 'RESTRICT'}); this.User.belongsToMany(this.Task, { onDelete: 'RESTRICT', through: 'tasksusers' });
this.Task.belongsToMany(this.User, { onDelete: 'RESTRICT'}); this.Task.belongsToMany(this.User, { onDelete: 'RESTRICT', through: 'tasksusers' });
return this.sequelize.sync({ force: true }).bind({}).then(function() { return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Promise.all([ return Promise.all([
...@@ -1785,8 +1805,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1785,8 +1805,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
var spy = sinon.spy() var spy = sinon.spy()
, self = this; , self = this;
self.User.belongsToMany(self.Task, { onDelete: 'RESTRICT'}); self.User.belongsToMany(self.Task, { onDelete: 'RESTRICT', through: 'tasksusers' });
self.Task.belongsToMany(self.User, { onDelete: 'CASCADE'}); self.Task.belongsToMany(self.User, { onDelete: 'CASCADE', through: 'tasksusers' });
return this.sequelize.sync({ force: true }).bind({}).then(function() { return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Sequelize.Promise.join( return Sequelize.Promise.join(
...@@ -1823,8 +1843,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() { ...@@ -1823,8 +1843,8 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), function() {
it('should be possible to remove all constraints', function() { it('should be possible to remove all constraints', function() {
var self = this; var self = this;
this.User.belongsToMany(this.Task, { constraints: false }); this.User.belongsToMany(this.Task, { constraints: false, through: 'tasksusers' });
this.Task.belongsToMany(this.User, { constraints: false }); this.Task.belongsToMany(this.User, { constraints: false, through: 'tasksusers' });
return this.sequelize.sync({ force: true }).bind({}).then(function() { return this.sequelize.sync({ force: true }).bind({}).then(function() {
return Promise.all([ return Promise.all([
......
...@@ -108,6 +108,7 @@ describe(Support.getTestDialectTeaser('Self'), function() { ...@@ -108,6 +108,7 @@ describe(Support.getTestDialectTeaser('Self'), function() {
expect(foreignIdentifiers).to.have.members(['preexisting_parent', 'preexisting_child']); expect(foreignIdentifiers).to.have.members(['preexisting_parent', 'preexisting_child']);
expect(rawAttributes).to.have.members(['preexisting_parent', 'preexisting_child']); expect(rawAttributes).to.have.members(['preexisting_parent', 'preexisting_child']);
var count = 0;
return this.sequelize.sync({ force: true }).bind(this).then(function() { return this.sequelize.sync({ force: true }).bind(this).then(function() {
return Promise.all([ return Promise.all([
Person.create({ name: 'Mary' }), Person.create({ name: 'Mary' }),
...@@ -118,26 +119,36 @@ describe(Support.getTestDialectTeaser('Self'), function() { ...@@ -118,26 +119,36 @@ describe(Support.getTestDialectTeaser('Self'), function() {
this.mary = mary; this.mary = mary;
this.chris = chris; this.chris = chris;
this.john = john; this.john = john;
return mary.setParents([john]).on('sql', function(sql) { return mary.setParents([john], {
if (sql.match(/INSERT/)) { logging: function(sql) {
expect(sql).to.have.string('preexisting_child'); if (sql.match(/INSERT/)) {
expect(sql).to.have.string('preexisting_parent'); count++;
expect(sql).to.have.string('preexisting_child');
expect(sql).to.have.string('preexisting_parent');
}
} }
}); });
}).then(function() { }).then(function() {
return this.mary.addParent(this.chris).on('sql', function(sql) { return this.mary.addParent(this.chris, {
if (sql.match(/INSERT/)) { logging: function(sql) {
expect(sql).to.have.string('preexisting_child'); if (sql.match(/INSERT/)) {
expect(sql).to.have.string('preexisting_parent'); count++;
expect(sql).to.have.string('preexisting_child');
expect(sql).to.have.string('preexisting_parent');
}
} }
}); });
}).then(function() { }).then(function() {
return this.john.getChildren().on('sql', function(sql) { return this.john.getChildren(undefined, {
var whereClause = sql.split('FROM')[1]; // look only in the whereClause logging: function(sql) {
expect(whereClause).to.have.string('preexisting_child'); count++;
expect(whereClause).to.have.string('preexisting_parent'); var whereClause = sql.split('FROM')[1]; // look only in the whereClause
expect(whereClause).to.have.string('preexisting_child');
expect(whereClause).to.have.string('preexisting_parent');
}
}); });
}).then(function(children) { }).then(function(children) {
expect(count).to.be.equal(3);
expect(_.map(children, 'id')).to.have.members([this.mary.id]); expect(_.map(children, 'id')).to.have.members([this.mary.id]);
}); });
}); });
......
...@@ -55,8 +55,8 @@ if (dialect.match(/^postgres/)) { ...@@ -55,8 +55,8 @@ if (dialect.match(/^postgres/)) {
this.users = null; this.users = null;
this.tasks = null; this.tasks = null;
this.User.hasMany(this.Task, {as: 'Tasks', through: 'usertasks'}); this.User.belongsToMany(this.Task, {as: 'Tasks', through: 'usertasks'});
this.Task.hasMany(this.User, {as: 'Users', through: 'usertasks'}); this.Task.belongsToMany(this.User, {as: 'Users', through: 'usertasks'});
var users = [] var users = []
, tasks = []; , tasks = [];
......
...@@ -39,8 +39,10 @@ if (dialect.match(/^postgres/)) { ...@@ -39,8 +39,10 @@ if (dialect.match(/^postgres/)) {
}); });
it('should be able to search within an array', function() { it('should be able to search within an array', function() {
return this.User.findAll({where: {email: ['hello', 'world']}, attributes: ['id','username','email','settings','document','phones','emergency_contact','friends']}).on('sql', function(sql) { return this.User.findAll({where: {email: ['hello', 'world']}, attributes: ['id','username','email','settings','document','phones','emergency_contact','friends']}, {
expect(sql).to.equal('SELECT "id", "username", "email", "settings", "document", "phones", "emergency_contact", "friends" FROM "Users" AS "User" WHERE "User"."email" = ARRAY[\'hello\',\'world\']::TEXT[];'); logging: function (sql) {
expect(sql).to.equal('Executing (default): SELECT "id", "username", "email", "settings", "document", "phones", "emergency_contact", "friends" FROM "Users" AS "User" WHERE "User"."email" = ARRAY[\'hello\',\'world\']::TEXT[];');
}
}); });
}); });
...@@ -95,10 +97,11 @@ if (dialect.match(/^postgres/)) { ...@@ -95,10 +97,11 @@ if (dialect.match(/^postgres/)) {
username: 'bob', username: 'bob',
emergency_contact: { name: 'joe', phones: [1337, 42] } emergency_contact: { name: 'joe', phones: [1337, 42] }
}, { }, {
fields: ['id', 'username', 'document', 'emergency_contact'] fields: ['id', 'username', 'document', 'emergency_contact'],
}).on('sql', function(sql) { logging: function(sql) {
var expected = '\'{"name":"joe","phones":[1337,42]}\''; var expected = '\'{"name":"joe","phones":[1337,42]}\'';
expect(sql.indexOf(expected)).not.to.equal(-1); expect(sql.indexOf(expected)).not.to.equal(-1);
}
}); });
}); });
...@@ -294,9 +297,11 @@ if (dialect.match(/^postgres/)) { ...@@ -294,9 +297,11 @@ if (dialect.match(/^postgres/)) {
username: 'bob', username: 'bob',
email: ['myemail@email.com'], email: ['myemail@email.com'],
settings: {mailing: false, push: 'facebook', frequency: 3} settings: {mailing: false, push: 'facebook', frequency: 3}
}).on('sql', function(sql) { }, {
var expected = '\'"mailing"=>"false","push"=>"facebook","frequency"=>"3"\',\'"default"=>"\'\'value\'\'"\''; logging: function (sql) {
expect(sql.indexOf(expected)).not.to.equal(-1); var expected = '\'"mailing"=>"false","push"=>"facebook","frequency"=>"3"\',\'"default"=>"\'\'value\'\'"\'';
expect(sql.indexOf(expected)).not.to.equal(-1);
}
}); });
}); });
...@@ -375,25 +380,25 @@ if (dialect.match(/^postgres/)) { ...@@ -375,25 +380,25 @@ if (dialect.match(/^postgres/)) {
mood: DataTypes.ENUM('neutral', 'happy', 'sad', 'ecstatic', 'meh', 'joyful') mood: DataTypes.ENUM('neutral', 'happy', 'sad', 'ecstatic', 'meh', 'joyful')
}); });
return User.sync().then(function() { return User.sync({
expect(User.rawAttributes.mood.values).to.deep.equal(['neutral', 'happy', 'sad', 'ecstatic', 'meh', 'joyful']); logging: function (sql) {
count++; if (sql.indexOf('neutral') > -1) {
}).on('sql', function(sql) { expect(sql.indexOf("ALTER TYPE \"enum_UserEnums_mood\" ADD VALUE 'neutral' BEFORE 'happy'")).to.not.be.equal(-1);
if (sql.indexOf('neutral') > -1) { count++;
expect(sql).to.equal("ALTER TYPE \"enum_UserEnums_mood\" ADD VALUE 'neutral' BEFORE 'happy'"); }
count++; else if (sql.indexOf('ecstatic') > -1) {
} expect(sql.indexOf("ALTER TYPE \"enum_UserEnums_mood\" ADD VALUE 'ecstatic' BEFORE 'meh'")).to.not.be.equal(-1);
else if (sql.indexOf('ecstatic') > -1) { count++;
expect(sql).to.equal("ALTER TYPE \"enum_UserEnums_mood\" ADD VALUE 'ecstatic' BEFORE 'meh'"); }
count++; else if (sql.indexOf('joyful') > -1) {
} expect(sql.indexOf("ALTER TYPE \"enum_UserEnums_mood\" ADD VALUE 'joyful' AFTER 'meh'")).to.not.be.equal(-1);
else if (sql.indexOf('joyful') > -1) { count++;
expect(sql).to.equal("ALTER TYPE \"enum_UserEnums_mood\" ADD VALUE 'joyful' AFTER 'meh'"); }
count++;
} }
}).then(function() {
expect(User.rawAttributes.mood.values).to.deep.equal(['neutral', 'happy', 'sad', 'ecstatic', 'meh', 'joyful']);
expect(count).to.equal(3);
}); });
}).then(function() {
expect(count).to.equal(4);
}); });
}); });
}); });
...@@ -475,8 +480,10 @@ if (dialect.match(/^postgres/)) { ...@@ -475,8 +480,10 @@ if (dialect.match(/^postgres/)) {
it('should use postgres "TIMESTAMP WITH TIME ZONE" instead of "DATETIME"', function() { it('should use postgres "TIMESTAMP WITH TIME ZONE" instead of "DATETIME"', function() {
return this.User.create({ return this.User.create({
dates: [] dates: []
}).on('sql', function(sql) { }, {
expect(sql.indexOf('TIMESTAMP WITH TIME ZONE')).to.be.greaterThan(0); logging: function(sql) {
expect(sql.indexOf('TIMESTAMP WITH TIME ZONE')).to.be.greaterThan(0);
}
}); });
}); });
}); });
......
...@@ -1707,7 +1707,7 @@ describe(Support.getTestDialectTeaser('Instance'), function() { ...@@ -1707,7 +1707,7 @@ describe(Support.getTestDialectTeaser('Instance'), function() {
return User.sync().then(function() { return User.sync().then(function() {
var user = User.build({ username: 'foo' }); var user = User.build({ username: 'foo' });
expect(user.values).to.deep.equal({ username: 'foo', id: null }); expect(user.get({ plain: true })).to.deep.equal({ username: 'foo', id: null });
}); });
}); });
}); });
...@@ -1767,9 +1767,11 @@ describe(Support.getTestDialectTeaser('Instance'), function() { ...@@ -1767,9 +1767,11 @@ describe(Support.getTestDialectTeaser('Instance'), function() {
return UserDelete.create({name: 'hallo', bio: 'welt'}).then(function(u) { return UserDelete.create({name: 'hallo', bio: 'welt'}).then(function(u) {
return UserDelete.findAll().then(function(users) { return UserDelete.findAll().then(function(users) {
expect(users.length).to.equal(1); expect(users.length).to.equal(1);
return u.destroy().on('sql', function(sql) { return u.destroy({
expect(sql).to.exist; logging: function (sql) {
expect(sql.toUpperCase().indexOf('DELETE')).to.be.above(-1); expect(sql).to.exist;
expect(sql.toUpperCase().indexOf('DELETE')).to.be.above(-1);
}
}); });
}); });
}); });
......
...@@ -842,16 +842,22 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -842,16 +842,22 @@ describe(Support.getTestDialectTeaser('Model'), function() {
paranoid: true paranoid: true
}); });
var test = false;
return User.sync({ force: true }).then(function() { return User.sync({ force: true }).then(function() {
return User.create({username: 'Peter', secretValue: '42'}).then(function(user) { return User.create({username: 'Peter', secretValue: '42'}).then(function(user) {
return user.updateAttributes({ secretValue: '43' }, ['secretValue']).on('sql', function(sql) { return user.updateAttributes({ secretValue: '43' }, {
if (dialect === 'mssql') { fields: ['secretValue'], logging: function (sql) {
expect(sql).to.not.contain('createdAt'); test = true;
} else { if (dialect === 'mssql') {
expect(sql).to.match(/UPDATE\s+[`"]+User1s[`"]+\s+SET\s+[`"]+secretValue[`"]='43',[`"]+updatedAt[`"]+='[^`",]+'\s+WHERE [`"]+id[`"]+\s=\s1/); expect(sql).to.not.contain('createdAt');
} else {
expect(sql).to.match(/UPDATE\s+[`"]+User1s[`"]+\s+SET\s+[`"]+secretValue[`"]='43',[`"]+updatedAt[`"]+='[^`",]+'\s+WHERE [`"]+id[`"]+\s=\s1/);
}
} }
}); });
}); });
}).then(function() {
expect(test).to.be.true;
}); });
}); });
...@@ -862,16 +868,20 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -862,16 +868,20 @@ describe(Support.getTestDialectTeaser('Model'), function() {
}, { }, {
paranoid: true paranoid: true
}); });
var test = false;
return User.sync({ force: true }).then(function() { return User.sync({ force: true }).then(function() {
return User.create({ name: 'meg', bio: 'none' }).then(function(u) { return User.create({ name: 'meg', bio: 'none' }).then(function(u) {
expect(u).to.exist; expect(u).to.exist;
expect(u).not.to.be.null; return u.updateAttributes({name: 'brian'}, {
return u.updateAttributes({name: 'brian'}).on('sql', function(sql) { logging: function (sql) {
expect(sql).to.exist; test = true;
expect(sql.toUpperCase().indexOf('UPDATE')).to.be.above(-1); expect(sql).to.exist;
expect(sql.toUpperCase().indexOf('UPDATE')).to.be.above(-1);
}
}); });
}); });
}).then(function() {
expect(test).to.be.true;
}); });
}); });
...@@ -1572,9 +1582,15 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -1572,9 +1582,15 @@ describe(Support.getTestDialectTeaser('Model'), function() {
}); });
it('allows sql logging', function() { it('allows sql logging', function() {
return this.User.count().on('sql', function(sql) { var test = false;
expect(sql).to.exist; return this.User.count({
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1); logging: function (sql) {
test = true;
expect(sql).to.exist;
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1);
}
}).then(function() {
expect(test).to.be.true;
}); });
}); });
...@@ -1659,9 +1675,15 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -1659,9 +1675,15 @@ describe(Support.getTestDialectTeaser('Model'), function() {
}); });
it('allows sql logging', function() { it('allows sql logging', function() {
return this.UserWithAge.min('age').on('sql', function(sql) { var test = false;
expect(sql).to.exist; return this.UserWithAge.min('age', {
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1); logging: function (sql) {
test = true;
expect(sql).to.exist;
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1);
}
}).then(function() {
expect(test).to.be.true;
}); });
}); });
...@@ -1783,9 +1805,15 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -1783,9 +1805,15 @@ describe(Support.getTestDialectTeaser('Model'), function() {
}); });
it('allows sql logging', function() { it('allows sql logging', function() {
return this.UserWithAge.max('age').on('sql', function(sql) { var logged = false;
expect(sql).to.exist; return this.UserWithAge.max('age', {
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1); logging: function (sql) {
expect(sql).to.exist;
logged = true;
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1);
}
}).then(function() {
expect(logged).to.true;
}); });
}); });
}); });
...@@ -1847,9 +1875,15 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -1847,9 +1875,15 @@ describe(Support.getTestDialectTeaser('Model'), function() {
}); });
it('allows sql logging', function() { it('allows sql logging', function() {
return this.UserWithAge.sum('age').on('sql', function(sql) { var logged = false;
expect(sql).to.exist; return this.UserWithAge.sum('age', {
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1); logging: function (sql) {
expect(sql).to.exist;
logged = true;
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1);
}
}).then(function() {
expect(logged).to.true;
}); });
}); });
}); });
...@@ -1897,19 +1931,28 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -1897,19 +1931,28 @@ describe(Support.getTestDialectTeaser('Model'), function() {
if (Support.dialectIsMySQL() || dialect === 'sqlite') { if (Support.dialectIsMySQL() || dialect === 'sqlite') {
it('should take schemaDelimiter into account if applicable', function() { it('should take schemaDelimiter into account if applicable', function() {
var test = 0;
var UserSpecialUnderscore = this.sequelize.define('UserSpecialUnderscore', {age: Sequelize.INTEGER}, {schema: 'hello', schemaDelimiter: '_'}); var UserSpecialUnderscore = this.sequelize.define('UserSpecialUnderscore', {age: Sequelize.INTEGER}, {schema: 'hello', schemaDelimiter: '_'});
var UserSpecialDblUnderscore = this.sequelize.define('UserSpecialDblUnderscore', {age: Sequelize.INTEGER}); var UserSpecialDblUnderscore = this.sequelize.define('UserSpecialDblUnderscore', {age: Sequelize.INTEGER});
return UserSpecialUnderscore.sync({force: true}).then(function(User) { return UserSpecialUnderscore.sync({force: true}).then(function(User) {
return UserSpecialDblUnderscore.schema('hello', '__').sync({force: true}).then(function(DblUser) { return UserSpecialDblUnderscore.schema('hello', '__').sync({force: true}).then(function(DblUser) {
return DblUser.create({age: 3}).on('sql', function(dblSql) { return DblUser.create({age: 3}, {
expect(dblSql).to.exist; logging: function (sql) {
expect(dblSql.indexOf('INSERT INTO `hello__UserSpecialDblUnderscores`')).to.be.above(-1);
}).then(function() {
return User.create({age: 3}).on('sql', function(sql) {
expect(sql).to.exist; expect(sql).to.exist;
expect(sql.indexOf('INSERT INTO `hello_UserSpecialUnderscores`')).to.be.above(-1); test++;
expect(sql.indexOf('INSERT INTO `hello__UserSpecialDblUnderscores`')).to.be.above(-1);
}
}).then(function() {
return User.create({age: 3}, {
logging: function (sql) {
expect(sql).to.exist;
test++;
expect(sql.indexOf('INSERT INTO `hello_UserSpecialUnderscores`')).to.be.above(-1);
}
}); });
}); });
}).then(function() {
expect(test).to.equal(2);
}); });
}); });
}); });
...@@ -1924,27 +1967,27 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -1924,27 +1967,27 @@ describe(Support.getTestDialectTeaser('Model'), function() {
return UserPublic.sync({ force: true }).then(function() { return UserPublic.sync({ force: true }).then(function() {
return UserPublic.schema('special').sync({ force: true }).then(function() { return UserPublic.schema('special').sync({ force: true }).then(function() {
return self.sequelize.queryInterface.describeTable('Publics') return self.sequelize.queryInterface.describeTable('Publics', {
.on('sql', function(sql) { logging: function(sql) {
if (dialect === 'sqlite' || Support.dialectIsMySQL() || dialect === 'mssql') { if (dialect === 'sqlite' || Support.dialectIsMySQL() || dialect === 'mssql') {
expect(sql).to.not.contain('special'); expect(sql).to.not.contain('special');
count++; count++;
}
} }
}) }).then(function(table) {
.then(function(table) {
if (dialect === 'postgres') { if (dialect === 'postgres') {
expect(table.id.defaultValue).to.not.contain('special'); expect(table.id.defaultValue).to.not.contain('special');
count++; count++;
} }
return self.sequelize.queryInterface.describeTable('Publics', {
return self.sequelize.queryInterface.describeTable('Publics', 'special') schema: 'special',
.on('sql', function(sql) { logging: function(sql) {
if (dialect === 'sqlite' || Support.dialectIsMySQL() || dialect === 'mssql') { if (dialect === 'sqlite' || Support.dialectIsMySQL() || dialect === 'mssql') {
expect(sql).to.contain('special'); expect(sql).to.contain('special');
count++; count++;
}
} }
}) }).then(function(table) {
.then(function(table) {
if (dialect === 'postgres') { if (dialect === 'postgres') {
expect(table.id.defaultValue).to.contain('special'); expect(table.id.defaultValue).to.contain('special');
count++; count++;
...@@ -2000,50 +2043,55 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -2000,50 +2043,55 @@ describe(Support.getTestDialectTeaser('Model'), function() {
it('should be able to create and update records under any valid schematic', function() { it('should be able to create and update records under any valid schematic', function() {
var self = this; var self = this;
var logged = 0;
return self.UserPublic.sync({ force: true }).then(function(UserPublicSync) { return self.UserPublic.sync({ force: true }).then(function(UserPublicSync) {
return UserPublicSync.create({age: 3}).on('sql', function(UserPublic) { return UserPublicSync.create({age: 3}, {
expect(UserPublic).to.exist; logging: function(UserPublic) {
if (dialect === 'postgres') { logged++;
expect(self.UserSpecialSync.getTableName().toString()).to.equal('"special"."UserSpecials"');
expect(UserPublic.indexOf('INSERT INTO "UserPublics"')).to.be.above(-1);
} else if (dialect === 'sqlite') {
expect(self.UserSpecialSync.getTableName().toString()).to.equal('`special.UserSpecials`');
expect(UserPublic.indexOf('INSERT INTO `UserPublics`')).to.be.above(-1);
} else if (dialect === 'mssql') {
expect(self.UserSpecialSync.getTableName().toString()).to.equal('[special].[UserSpecials]');
expect(UserPublic.indexOf('INSERT INTO [UserPublics]')).to.be.above(-1);
} else {
expect(self.UserSpecialSync.getTableName().toString()).to.equal('`special.UserSpecials`');
expect(UserPublic.indexOf('INSERT INTO `UserPublics`')).to.be.above(-1);
}
})
.then(function() {
return self.UserSpecialSync.schema('special').create({age: 3})
.on('sql', function(UserSpecial) {
expect(UserSpecial).to.exist;
if (dialect === 'postgres') { if (dialect === 'postgres') {
expect(UserSpecial.indexOf('INSERT INTO "special"."UserSpecials"')).to.be.above(-1); expect(self.UserSpecialSync.getTableName().toString()).to.equal('"special"."UserSpecials"');
expect(UserPublic.indexOf('INSERT INTO "UserPublics"')).to.be.above(-1);
} else if (dialect === 'sqlite') { } else if (dialect === 'sqlite') {
expect(UserSpecial.indexOf('INSERT INTO `special.UserSpecials`')).to.be.above(-1); expect(self.UserSpecialSync.getTableName().toString()).to.equal('`special.UserSpecials`');
expect(UserPublic.indexOf('INSERT INTO `UserPublics`')).to.be.above(-1);
} else if (dialect === 'mssql') { } else if (dialect === 'mssql') {
expect(UserSpecial.indexOf('INSERT INTO [special].[UserSpecials]')).to.be.above(-1); expect(self.UserSpecialSync.getTableName().toString()).to.equal('[special].[UserSpecials]');
expect(UserPublic.indexOf('INSERT INTO [UserPublics]')).to.be.above(-1);
} else { } else {
expect(UserSpecial.indexOf('INSERT INTO `special.UserSpecials`')).to.be.above(-1); expect(self.UserSpecialSync.getTableName().toString()).to.equal('`special.UserSpecials`');
expect(UserPublic.indexOf('INSERT INTO `UserPublics`')).to.be.above(-1);
} }
}) }
.then(function(UserSpecial) { }).then(function(UserPublic) {
return UserSpecial.updateAttributes({age: 5}) return self.UserSpecialSync.schema('special').create({age: 3}, {
.on('sql', function(user) { logging: function(UserSpecial) {
expect(user).to.exist; logged++;
if (dialect === 'postgres') { if (dialect === 'postgres') {
expect(user.indexOf('UPDATE "special"."UserSpecials"')).to.be.above(-1); expect(UserSpecial.indexOf('INSERT INTO "special"."UserSpecials"')).to.be.above(-1);
} else if (dialect === 'sqlite') {
expect(UserSpecial.indexOf('INSERT INTO `special.UserSpecials`')).to.be.above(-1);
} else if (dialect === 'mssql') { } else if (dialect === 'mssql') {
expect(user.indexOf('UPDATE [special].[UserSpecials]')).to.be.above(-1); expect(UserSpecial.indexOf('INSERT INTO [special].[UserSpecials]')).to.be.above(-1);
} else { } else {
expect(user.indexOf('UPDATE `special.UserSpecials`')).to.be.above(-1); expect(UserSpecial.indexOf('INSERT INTO `special.UserSpecials`')).to.be.above(-1);
}
}
}).then(function(UserSpecial) {
return UserSpecial.updateAttributes({age: 5}, {
logging: function(user) {
logged++;
if (dialect === 'postgres') {
expect(user.indexOf('UPDATE "special"."UserSpecials"')).to.be.above(-1);
} else if (dialect === 'mssql') {
expect(user.indexOf('UPDATE [special].[UserSpecials]')).to.be.above(-1);
} else {
expect(user.indexOf('UPDATE `special.UserSpecials`')).to.be.above(-1);
}
} }
}); });
}); });
}).then(function() {
expect(logged).to.equal(3);
}); });
}); });
}); });
......
...@@ -31,11 +31,13 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -31,11 +31,13 @@ describe(Support.getTestDialectTeaser('Model'), function() {
it('can handle plain strings', function() { it('can handle plain strings', function() {
return this.User.find({ return this.User.find({
where: Sequelize[method]('1=1', '2=2') where: Sequelize[method]('1=1', '2=2')
}).on('sql', function(sql) { }, {
if (dialect === 'mssql') { logging: function(sql) {
expect(sql).to.contain('WHERE (1=1 ' + word + ' 2=2)'); if (dialect === 'mssql') {
}else { expect(sql).to.contain('WHERE (1=1 ' + word + ' 2=2)');
expect(sql).to.contain('WHERE (1=1 ' + word + ' 2=2) LIMIT 1'); }else {
expect(sql).to.contain('WHERE (1=1 ' + word + ' 2=2) LIMIT 1');
}
} }
}); });
}); });
...@@ -43,11 +45,13 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -43,11 +45,13 @@ describe(Support.getTestDialectTeaser('Model'), function() {
it('can handle arrays', function() { it('can handle arrays', function() {
return this.User.find({ return this.User.find({
where: Sequelize[method](['1=?', 1], ['2=?', 2]) where: Sequelize[method](['1=?', 1], ['2=?', 2])
}).on('sql', function(sql) { }, {
if (dialect === 'mssql') { logging: function(sql) {
expect(sql).to.contain('WHERE (1=1 ' + word + ' 2=2)'); if (dialect === 'mssql') {
}else { expect(sql).to.contain('WHERE (1=1 ' + word + ' 2=2)');
expect(sql).to.contain('WHERE (1=1 ' + word + ' 2=2) LIMIT 1'); }else {
expect(sql).to.contain('WHERE (1=1 ' + word + ' 2=2) LIMIT 1');
}
} }
}); });
}); });
...@@ -55,42 +59,42 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -55,42 +59,42 @@ describe(Support.getTestDialectTeaser('Model'), function() {
it('can handle objects', function() { it('can handle objects', function() {
return this.User.find({ return this.User.find({
where: Sequelize[method]({ username: 'foo', intVal: 2 }, { secretValue: 'bar' }) where: Sequelize[method]({ username: 'foo', intVal: 2 }, { secretValue: 'bar' })
}).on('sql', function(sql) { }, {
var expectation = ({ logging: function(sql) {
mysql: "WHERE (`User`.`username`='foo' AND `User`.`intVal`=2 " + word + " `User`.`secretValue`='bar')", var expectation = ({
mssql: 'WHERE ([User].[username]=\'foo\' AND [User].[intVal]=2 ' + word + ' [User].[secretValue]=\'bar\')', mysql: "WHERE (`User`.`username`='foo' AND `User`.`intVal`=2 " + word + " `User`.`secretValue`='bar')",
sqlite: "WHERE (`User`.`username`='foo' AND `User`.`intVal`=2 " + word + " `User`.`secretValue`='bar')", mssql: 'WHERE ([User].[username]=\'foo\' AND [User].[intVal]=2 ' + word + ' [User].[secretValue]=\'bar\')',
postgres: 'WHERE ("User"."username"=\'foo\' AND "User"."intVal"=2 ' + word + ' "User"."secretValue"=\'bar\')', sqlite: "WHERE (`User`.`username`='foo' AND `User`.`intVal`=2 " + word + " `User`.`secretValue`='bar')",
mariadb: "WHERE (`User`.`username`='foo' AND `User`.`intVal`=2 " + word + " `User`.`secretValue`='bar')" postgres: 'WHERE ("User"."username"=\'foo\' AND "User"."intVal"=2 ' + word + ' "User"."secretValue"=\'bar\')',
})[Support.getTestDialect()]; mariadb: "WHERE (`User`.`username`='foo' AND `User`.`intVal`=2 " + word + " `User`.`secretValue`='bar')"
})[Support.getTestDialect()];
if (!expectation) { if (!expectation) {
console.log(sql); throw new Error('Undefined expectation for ' + Support.getTestDialect());
throw new Error('Undefined expectation for ' + Support.getTestDialect()); }
expect(sql).to.contain(expectation);
} }
expect(sql).to.contain(expectation);
}); });
}); });
it('can handle numbers', function() { it('can handle numbers', function() {
return this.User.find({ return this.User.find({
where: Sequelize[method](1, 2) where: Sequelize[method](1, 2)
}).on('sql', function(sql) { }, {
var expectation = ({ logging: function(sql) {
mysql: 'WHERE (`User`.`id`=1 ' + word + ' `User`.`id`=2)', var expectation = ({
sqlite: 'WHERE (`User`.`id`=1 ' + word + ' `User`.`id`=2)', mysql: 'WHERE (`User`.`id`=1 ' + word + ' `User`.`id`=2)',
postgres: 'WHERE ("User"."id"=1 ' + word + ' "User"."id"=2)', sqlite: 'WHERE (`User`.`id`=1 ' + word + ' `User`.`id`=2)',
mssql: 'WHERE ([User].[id]=1 ' + word + ' [User].[id]=2)', postgres: 'WHERE ("User"."id"=1 ' + word + ' "User"."id"=2)',
mariadb: 'WHERE (`User`.`id`=1 ' + word + ' `User`.`id`=2)' mssql: 'WHERE ([User].[id]=1 ' + word + ' [User].[id]=2)',
})[Support.getTestDialect()]; mariadb: 'WHERE (`User`.`id`=1 ' + word + ' `User`.`id`=2)'
})[Support.getTestDialect()];
if (!expectation) { if (!expectation) {
console.log(sql); throw new Error('Undefined expectation for ' + Support.getTestDialect());
throw new Error('Undefined expectation for ' + Support.getTestDialect()); }
expect(sql).to.contain(expectation);
} }
expect(sql).to.contain(expectation);
}); });
}); });
}); });
...@@ -100,11 +104,13 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -100,11 +104,13 @@ describe(Support.getTestDialectTeaser('Model'), function() {
it('allows nesting of Sequelize.or', function() { it('allows nesting of Sequelize.or', function() {
return this.User.find({ return this.User.find({
where: Sequelize.and(Sequelize.or('1=1', '2=2'), Sequelize.or('3=3', '4=4')) where: Sequelize.and(Sequelize.or('1=1', '2=2'), Sequelize.or('3=3', '4=4'))
}).on('sql', function(sql) { }, {
if (dialect === 'mssql') { logging: function(sql) {
expect(sql).to.contain('WHERE ((1=1 OR 2=2) AND (3=3 OR 4=4))'); if (dialect === 'mssql') {
}else { expect(sql).to.contain('WHERE ((1=1 OR 2=2) AND (3=3 OR 4=4))');
expect(sql).to.contain('WHERE ((1=1 OR 2=2) AND (3=3 OR 4=4)) LIMIT 1'); }else {
expect(sql).to.contain('WHERE ((1=1 OR 2=2) AND (3=3 OR 4=4)) LIMIT 1');
}
} }
}); });
}); });
...@@ -113,32 +119,35 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -113,32 +119,35 @@ describe(Support.getTestDialectTeaser('Model'), function() {
return this.User.find({ return this.User.find({
where: Sequelize.and(Sequelize.or({username: {eq: 'foo'}}, {username: {eq: 'bar'}}), where: Sequelize.and(Sequelize.or({username: {eq: 'foo'}}, {username: {eq: 'bar'}}),
Sequelize.or({id: {eq: 1}}, {id: {eq: 4}})) Sequelize.or({id: {eq: 1}}, {id: {eq: 4}}))
}).on('sql', function(sql) { }, {
var expectation = ({ logging: function(sql) {
mysql: "WHERE ((`User`.`username` = 'foo' OR `User`.`username` = 'bar') AND (`User`.`id` = 1 OR `User`.`id` = 4)) LIMIT 1", var expectation = ({
sqlite: "WHERE ((`User`.`username` = 'foo' OR `User`.`username` = 'bar') AND (`User`.`id` = 1 OR `User`.`id` = 4)) LIMIT 1", mysql: "WHERE ((`User`.`username` = 'foo' OR `User`.`username` = 'bar') AND (`User`.`id` = 1 OR `User`.`id` = 4)) LIMIT 1",
postgres: 'WHERE (("User"."username" = \'foo\' OR "User"."username" = \'bar\') AND ("User"."id" = 1 OR "User"."id" = 4)) LIMIT 1', sqlite: "WHERE ((`User`.`username` = 'foo' OR `User`.`username` = 'bar') AND (`User`.`id` = 1 OR `User`.`id` = 4)) LIMIT 1",
mssql: 'WHERE (([User].[username] = \'foo\' OR [User].[username] = \'bar\') AND ([User].[id] = 1 OR [User].[id] = 4))', postgres: 'WHERE (("User"."username" = \'foo\' OR "User"."username" = \'bar\') AND ("User"."id" = 1 OR "User"."id" = 4)) LIMIT 1',
mariadb: "WHERE ((`User`.`username` = 'foo' OR `User`.`username` = 'bar') AND (`User`.`id` = 1 OR `User`.`id` = 4)) LIMIT 1" mssql: 'WHERE (([User].[username] = \'foo\' OR [User].[username] = \'bar\') AND ([User].[id] = 1 OR [User].[id] = 4))',
})[Support.getTestDialect()]; mariadb: "WHERE ((`User`.`username` = 'foo' OR `User`.`username` = 'bar') AND (`User`.`id` = 1 OR `User`.`id` = 4)) LIMIT 1"
})[Support.getTestDialect()];
if (!expectation) {
console.log(sql); if (!expectation) {
throw new Error('Undefined expectation for ' + Support.getTestDialect()); throw new Error('Undefined expectation for ' + Support.getTestDialect());
} }
expect(sql).to.contain(expectation); expect(sql).to.contain(expectation);
}
}); });
}); });
it('allows nesting of Sequelize.and', function() { it('allows nesting of Sequelize.and', function() {
return this.User.find({ return this.User.find({
where: Sequelize.or(Sequelize.and('1=1', '2=2'), Sequelize.and('3=3', '4=4')) where: Sequelize.or(Sequelize.and('1=1', '2=2'), Sequelize.and('3=3', '4=4'))
}).on('sql', function(sql) { }, {
if (dialect === 'mssql') { logging: function(sql) {
expect(sql).to.contain('WHERE ((1=1 AND 2=2) OR (3=3 AND 4=4))'); if (dialect === 'mssql') {
}else { expect(sql).to.contain('WHERE ((1=1 AND 2=2) OR (3=3 AND 4=4))');
expect(sql).to.contain('WHERE ((1=1 AND 2=2) OR (3=3 AND 4=4)) LIMIT 1'); }else {
expect(sql).to.contain('WHERE ((1=1 AND 2=2) OR (3=3 AND 4=4)) LIMIT 1');
}
} }
}); });
}); });
...@@ -147,21 +156,22 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -147,21 +156,22 @@ describe(Support.getTestDialectTeaser('Model'), function() {
return this.User.find({ return this.User.find({
where: Sequelize.or(Sequelize.and({username: {eq: 'foo'}}, {username: {eq: 'bar'}}), where: Sequelize.or(Sequelize.and({username: {eq: 'foo'}}, {username: {eq: 'bar'}}),
Sequelize.and({id: {eq: 1}}, {id: {eq: 4}})) Sequelize.and({id: {eq: 1}}, {id: {eq: 4}}))
}).on('sql', function(sql) { }, {
var expectation = ({ logging: function(sql) {
mysql: "WHERE ((`User`.`username` = 'foo' AND `User`.`username` = 'bar') OR (`User`.`id` = 1 AND `User`.`id` = 4)) LIMIT 1", var expectation = ({
sqlite: "WHERE ((`User`.`username` = 'foo' AND `User`.`username` = 'bar') OR (`User`.`id` = 1 AND `User`.`id` = 4)) LIMIT 1", mysql: "WHERE ((`User`.`username` = 'foo' AND `User`.`username` = 'bar') OR (`User`.`id` = 1 AND `User`.`id` = 4)) LIMIT 1",
postgres: 'WHERE (("User"."username" = \'foo\' AND "User"."username" = \'bar\') OR ("User"."id" = 1 AND "User"."id" = 4)) LIMIT 1', sqlite: "WHERE ((`User`.`username` = 'foo' AND `User`.`username` = 'bar') OR (`User`.`id` = 1 AND `User`.`id` = 4)) LIMIT 1",
mssql: 'WHERE (([User].[username] = \'foo\' AND [User].[username] = \'bar\') OR ([User].[id] = 1 AND [User].[id] = 4))', postgres: 'WHERE (("User"."username" = \'foo\' AND "User"."username" = \'bar\') OR ("User"."id" = 1 AND "User"."id" = 4)) LIMIT 1',
mariadb: "WHERE ((`User`.`username` = 'foo' AND `User`.`username` = 'bar') OR (`User`.`id` = 1 AND `User`.`id` = 4)) LIMIT 1" mssql: 'WHERE (([User].[username] = \'foo\' AND [User].[username] = \'bar\') OR ([User].[id] = 1 AND [User].[id] = 4))',
})[Support.getTestDialect()]; mariadb: "WHERE ((`User`.`username` = 'foo' AND `User`.`username` = 'bar') OR (`User`.`id` = 1 AND `User`.`id` = 4)) LIMIT 1"
})[Support.getTestDialect()];
if (!expectation) {
console.log(sql); if (!expectation) {
throw new Error('Undefined expectation for ' + Support.getTestDialect()); throw new Error('Undefined expectation for ' + Support.getTestDialect());
} }
expect(sql).to.contain(expectation); expect(sql).to.contain(expectation);
}
}); });
}); });
...@@ -169,8 +179,10 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -169,8 +179,10 @@ describe(Support.getTestDialectTeaser('Model'), function() {
it('still allows simple arrays lookups', function() { it('still allows simple arrays lookups', function() {
return this.User.find({ return this.User.find({
where: ['id IN (?) OR id IN (?)', [1, 2], [3, 4]] where: ['id IN (?) OR id IN (?)', [1, 2], [3, 4]]
}).on('sql', function(sql) { }, {
expect(sql).to.contain('id IN (1, 2) OR id IN (3, 4)'); logging: function(sql) {
expect(sql).to.contain('id IN (1, 2) OR id IN (3, 4)');
}
}); });
}); });
} }
...@@ -191,58 +203,60 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -191,58 +203,60 @@ describe(Support.getTestDialectTeaser('Model'), function() {
Sequelize.and(42, '2=2', ['1=?', 1], { username: 'foo' }) Sequelize.and(42, '2=2', ['1=?', 1], { username: 'foo' })
) )
] ]
}).on('sql', function(sql) { }, {
if (dialect === 'postgres') { logging: function(sql) {
expect(sql).to.contain( if (dialect === 'postgres') {
'WHERE (' + [ expect(sql).to.contain(
'"User"."id"=42 AND 2=2 AND 1=1 AND "User"."username"=\'foo\' AND ', 'WHERE (' + [
'(', '"User"."id"=42 AND 2=2 AND 1=1 AND "User"."username"=\'foo\' AND ',
'"User"."id"=42 OR 2=2 OR 1=1 OR "User"."username"=\'foo\' OR ', '(',
'("User"."id"=42 AND 2=2 AND 1=1 AND "User"."username"=\'foo\') OR ', '"User"."id"=42 OR 2=2 OR 1=1 OR "User"."username"=\'foo\' OR ',
'("User"."id"=42 OR 2=2 OR 1=1 OR "User"."username"=\'foo\')', '("User"."id"=42 AND 2=2 AND 1=1 AND "User"."username"=\'foo\') OR ',
') AND ', '("User"."id"=42 OR 2=2 OR 1=1 OR "User"."username"=\'foo\')',
'(', ') AND ',
'"User"."id"=42 AND 2=2 AND 1=1 AND "User"."username"=\'foo\' AND ', '(',
'("User"."id"=42 OR 2=2 OR 1=1 OR "User"."username"=\'foo\') AND ', '"User"."id"=42 AND 2=2 AND 1=1 AND "User"."username"=\'foo\' AND ',
'("User"."id"=42 AND 2=2 AND 1=1 AND "User"."username"=\'foo\')', '("User"."id"=42 OR 2=2 OR 1=1 OR "User"."username"=\'foo\') AND ',
')' '("User"."id"=42 AND 2=2 AND 1=1 AND "User"."username"=\'foo\')',
].join('') + ')'
')' ].join('') +
); ')'
} else if (dialect === 'mssql') { );
expect(sql).to.contain( } else if (dialect === 'mssql') {
'WHERE (' + [ expect(sql).to.contain(
'[User].[id]=42 AND 2=2 AND 1=1 AND [User].[username]=\'foo\' AND ', 'WHERE (' + [
'(', '[User].[id]=42 AND 2=2 AND 1=1 AND [User].[username]=\'foo\' AND ',
'[User].[id]=42 OR 2=2 OR 1=1 OR [User].[username]=\'foo\' OR ', '(',
'([User].[id]=42 AND 2=2 AND 1=1 AND [User].[username]=\'foo\') OR ', '[User].[id]=42 OR 2=2 OR 1=1 OR [User].[username]=\'foo\' OR ',
'([User].[id]=42 OR 2=2 OR 1=1 OR [User].[username]=\'foo\')', '([User].[id]=42 AND 2=2 AND 1=1 AND [User].[username]=\'foo\') OR ',
') AND ', '([User].[id]=42 OR 2=2 OR 1=1 OR [User].[username]=\'foo\')',
'(', ') AND ',
'[User].[id]=42 AND 2=2 AND 1=1 AND [User].[username]=\'foo\' AND ', '(',
'([User].[id]=42 OR 2=2 OR 1=1 OR [User].[username]=\'foo\') AND ', '[User].[id]=42 AND 2=2 AND 1=1 AND [User].[username]=\'foo\' AND ',
'([User].[id]=42 AND 2=2 AND 1=1 AND [User].[username]=\'foo\')', '([User].[id]=42 OR 2=2 OR 1=1 OR [User].[username]=\'foo\') AND ',
')' '([User].[id]=42 AND 2=2 AND 1=1 AND [User].[username]=\'foo\')',
].join('') + ')'
')' ].join('') +
); ')'
} else { );
expect(sql).to.contain( } else {
'WHERE (' + [ expect(sql).to.contain(
"`User`.`id`=42 AND 2=2 AND 1=1 AND `User`.`username`='foo' AND ", 'WHERE (' + [
'(', "`User`.`id`=42 AND 2=2 AND 1=1 AND `User`.`username`='foo' AND ",
"`User`.`id`=42 OR 2=2 OR 1=1 OR `User`.`username`='foo' OR ", '(',
"(`User`.`id`=42 AND 2=2 AND 1=1 AND `User`.`username`='foo') OR ", "`User`.`id`=42 OR 2=2 OR 1=1 OR `User`.`username`='foo' OR ",
"(`User`.`id`=42 OR 2=2 OR 1=1 OR `User`.`username`='foo')", "(`User`.`id`=42 AND 2=2 AND 1=1 AND `User`.`username`='foo') OR ",
') AND ', "(`User`.`id`=42 OR 2=2 OR 1=1 OR `User`.`username`='foo')",
'(', ') AND ',
"`User`.`id`=42 AND 2=2 AND 1=1 AND `User`.`username`='foo' AND ", '(',
"(`User`.`id`=42 OR 2=2 OR 1=1 OR `User`.`username`='foo') AND ", "`User`.`id`=42 AND 2=2 AND 1=1 AND `User`.`username`='foo' AND ",
"(`User`.`id`=42 AND 2=2 AND 1=1 AND `User`.`username`='foo')", "(`User`.`id`=42 OR 2=2 OR 1=1 OR `User`.`username`='foo') AND ",
')' "(`User`.`id`=42 AND 2=2 AND 1=1 AND `User`.`username`='foo')",
].join('') + ')'
')' ].join('') +
); ')'
);
}
} }
}); });
}); });
......
...@@ -71,18 +71,26 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -71,18 +71,26 @@ describe(Support.getTestDialectTeaser('Model'), function() {
it('should be ignored in find, findAll and includes', function() { it('should be ignored in find, findAll and includes', function() {
return Promise.all([ return Promise.all([
this.User.find().on('sql', this.sqlAssert), this.User.find(null, {
this.User.findAll().on('sql', this.sqlAssert), logging: this.sqlAssert
}),
this.User.findAll(null, {
logging: this.sqlAssert
}),
this.Task.findAll({ this.Task.findAll({
include: [ include: [
this.User this.User
] ]
}).on('sql', this.sqlAssert), }, {
logging: this.sqlAssert
}),
this.Project.findAll({ this.Project.findAll({
include: [ include: [
this.User this.User
] ]
}).on('sql', this.sqlAssert) }, {
logging: this.sqlAssert
})
]); ]);
}); });
...@@ -132,7 +140,9 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -132,7 +140,9 @@ describe(Support.getTestDialectTeaser('Model'), function() {
var self = this; var self = this;
return this.User.bulkCreate([{ return this.User.bulkCreate([{
field1: 'something' field1: 'something'
}]).on('sql', this.sqlAssert).then(function() { }], {
logging: this.sqlAssert
}).then(function() {
return self.User.findAll(); return self.User.findAll();
}).then(function(users) { }).then(function(users) {
expect(users[0].storage).to.equal('something'); expect(users[0].storage).to.equal('something');
......
...@@ -675,11 +675,12 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -675,11 +675,12 @@ describe(Support.getTestDialectTeaser('Model'), function() {
return this.User.create({ return this.User.create({
intVal: this.sequelize.cast('1', type) intVal: this.sequelize.cast('1', type)
}).on('sql', function(sql) { }, {
expect(sql).to.match(new RegExp("CAST\\('1' AS " + type.toUpperCase() + '\\)')); logging: function(sql) {
match = true; expect(sql).to.match(new RegExp("CAST\\('1' AS " + type.toUpperCase() + '\\)'));
}) match = true;
.then(function(user) { }
}).then(function(user) {
return self.User.find(user.id).then(function(user) { return self.User.find(user.id).then(function(user) {
expect(user.intVal).to.equal(1); expect(user.intVal).to.equal(1);
expect(match).to.equal(true); expect(match).to.equal(true);
...@@ -698,14 +699,15 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -698,14 +699,15 @@ describe(Support.getTestDialectTeaser('Model'), function() {
return this.User.create({ return this.User.create({
intVal: type intVal: type
}).on('sql', function(sql) { }, {
if (Support.dialectIsMySQL()) { logging: function(sql) {
expect(sql).to.contain('CAST(CAST(1-2 AS UNSIGNED) AS SIGNED)'); if (Support.dialectIsMySQL()) {
} else { expect(sql).to.contain('CAST(CAST(1-2 AS UNSIGNED) AS SIGNED)');
expect(sql).to.contain('CAST(CAST(1-2 AS INTEGER) AS INTEGER)'); } else {
expect(sql).to.contain('CAST(CAST(1-2 AS INTEGER) AS INTEGER)');
}
match = true;
} }
match = true;
}).then(function(user) { }).then(function(user) {
return self.User.find(user.id).then(function(user) { return self.User.find(user.id).then(function(user) {
expect(user.intVal).to.equal(-1); expect(user.intVal).to.equal(-1);
...@@ -811,11 +813,17 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -811,11 +813,17 @@ describe(Support.getTestDialectTeaser('Model'), function() {
mystr: { type: Sequelize.ARRAY(Sequelize.STRING) } mystr: { type: Sequelize.ARRAY(Sequelize.STRING) }
}); });
var test = false;
return User.sync({force: true}).then(function() { return User.sync({force: true}).then(function() {
return User.create({myvals: [], mystr: []}).on('sql', function(sql) { return User.create({myvals: [], mystr: []}, {
expect(sql.indexOf('ARRAY[]::INTEGER[]')).to.be.above(-1); logging: function(sql) {
expect(sql.indexOf('ARRAY[]::VARCHAR[]')).to.be.above(-1); test = true;
expect(sql.indexOf('ARRAY[]::INTEGER[]')).to.be.above(-1);
expect(sql.indexOf('ARRAY[]::VARCHAR[]')).to.be.above(-1);
}
}); });
}).then(function() {
expect(test).to.be.true;
}); });
}); });
...@@ -829,16 +837,22 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -829,16 +837,22 @@ describe(Support.getTestDialectTeaser('Model'), function() {
myvals: { type: Sequelize.ARRAY(Sequelize.INTEGER) }, myvals: { type: Sequelize.ARRAY(Sequelize.INTEGER) },
mystr: { type: Sequelize.ARRAY(Sequelize.STRING) } mystr: { type: Sequelize.ARRAY(Sequelize.STRING) }
}); });
var test = false;
return User.sync({force: true}).then(function() { return User.sync({force: true}).then(function() {
return User.create({myvals: [1, 2, 3, 4], mystr: ['One', 'Two', 'Three', 'Four']}).then(function(user) { return User.create({myvals: [1, 2, 3, 4], mystr: ['One', 'Two', 'Three', 'Four']}).then(function(user) {
user.myvals = []; user.myvals = [];
user.mystr = []; user.mystr = [];
return user.save().on('sql', function(sql) { return user.save(undefined, {
expect(sql.indexOf('ARRAY[]::INTEGER[]')).to.be.above(-1); logging: function(sql) {
expect(sql.indexOf('ARRAY[]::VARCHAR[]')).to.be.above(-1); test = true;
expect(sql.indexOf('ARRAY[]::INTEGER[]')).to.be.above(-1);
expect(sql.indexOf('ARRAY[]::VARCHAR[]')).to.be.above(-1);
}
}); });
}); });
}).then(function() {
expect(test).to.be.true;
}); });
}); });
...@@ -986,13 +1000,18 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -986,13 +1000,18 @@ describe(Support.getTestDialectTeaser('Model'), function() {
smth: {type: Sequelize.STRING, allowNull: false} smth: {type: Sequelize.STRING, allowNull: false}
}); });
var test = false;
return User.sync({ force: true }).then(function() { return User.sync({ force: true }).then(function() {
return User return User
.create({ name: 'Fluffy Bunny', smth: 'else' }) .create({ name: 'Fluffy Bunny', smth: 'else' }, {
.on('sql', function(sql) { logging: function(sql) {
expect(sql).to.exist; expect(sql).to.exist;
expect(sql.toUpperCase().indexOf('INSERT')).to.be.above(-1); test = true;
expect(sql.toUpperCase().indexOf('INSERT')).to.be.above(-1);
}
}); });
}).then(function() {
expect(test).to.be.true;
}); });
}); });
...@@ -1601,9 +1620,7 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -1601,9 +1620,7 @@ describe(Support.getTestDialectTeaser('Model'), function() {
data.push({ uniqueName: 'Michael', secretValue: '26' }); data.push({ uniqueName: 'Michael', secretValue: '26' });
return self.User.bulkCreate(data, { fields: ['uniqueName', 'secretValue'], ignoreDuplicates: true }).catch(function(err) { return self.User.bulkCreate(data, { fields: ['uniqueName', 'secretValue'], ignoreDuplicates: true }).catch(function(err) {
expect(err).to.exist;
if (dialect === 'mssql') { if (dialect === 'mssql') {
console.log(err.message);
expect(err.message).to.match(/mssql does not support the \'ignoreDuplicates\' option./); expect(err.message).to.match(/mssql does not support the \'ignoreDuplicates\' option./);
} else { } else {
expect(err.message).to.match(/postgres does not support the \'ignoreDuplicates\' option./); expect(err.message).to.match(/postgres does not support the \'ignoreDuplicates\' option./);
......
...@@ -117,10 +117,16 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -117,10 +117,16 @@ describe(Support.getTestDialectTeaser('Model'), function() {
}); });
it('treats questionmarks in an array', function() { it('treats questionmarks in an array', function() {
var test = false;
return this.UserPrimary.find({ return this.UserPrimary.find({
where: ['specialkey = ?', 'awesome'] where: ['specialkey = ?', 'awesome']
}).on('sql', function(sql) { }, {
expect(sql).to.contain("WHERE specialkey = 'awesome'"); logging: function(sql) {
test = true;
expect(sql).to.contain("WHERE specialkey = 'awesome'");
}
}).then(function() {
expect(test).to.be.true;
}); });
}); });
...@@ -190,9 +196,15 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -190,9 +196,15 @@ describe(Support.getTestDialectTeaser('Model'), function() {
}); });
it('allows sql logging', function() { it('allows sql logging', function() {
return this.User.find({ where: { username: 'foo' } }).on('sql', function(sql) { var test = false;
expect(sql).to.exist; return this.User.find({ where: { username: 'foo' } }, {
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1); logging: function(sql) {
test = true;
expect(sql).to.exist;
expect(sql.toUpperCase().indexOf('SELECT')).to.be.above(-1);
}
}).then(function() {
expect(test).to.be.true;
}); });
}); });
...@@ -257,16 +269,17 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -257,16 +269,17 @@ describe(Support.getTestDialectTeaser('Model'), function() {
return this.User.bulkCreate([{username: 'jack'}, {username: 'jack'}]).then(function() { return this.User.bulkCreate([{username: 'jack'}, {username: 'jack'}]).then(function() {
return self.sequelize.Promise.map(permutations, function(perm) { return self.sequelize.Promise.map(permutations, function(perm) {
return self.User.find(perm).then(function(user) { return self.User.find(perm, {
logging: function(s) {
expect(s.indexOf(0)).not.to.equal(-1);
count++;
}
}).then(function(user) {
expect(user).to.be.null; expect(user).to.be.null;
count++;
}).on('sql', function(s) {
expect(s.indexOf(0)).not.to.equal(-1);
count++;
}); });
}); });
}).then(function() { }).then(function() {
expect(count).to.be.equal(2 * permutations.length); expect(count).to.be.equal(permutations.length);
}); });
}); });
......
...@@ -397,22 +397,6 @@ describe(Support.getTestDialectTeaser('Promise'), function() { ...@@ -397,22 +397,6 @@ describe(Support.getTestDialectTeaser('Promise'), function() {
}); });
}); });
it('should still work with .success() when emitting', function(done) {
var spy = sinon.spy()
, promise = new SequelizePromise(function(resolve, reject) {
// no-op
});
promise.success(spy);
promise.then(function() {
expect(spy.calledOnce).to.be.true;
expect(spy.firstCall.args).to.deep.equal(['yay']);
done();
});
promise.emit('success', 'yay');
});
it('should still work with .done() when rejecting', function(done) { it('should still work with .done() when rejecting', function(done) {
var spy = sinon.spy() var spy = sinon.spy()
, promise = new SequelizePromise(function(resolve, reject) { , promise = new SequelizePromise(function(resolve, reject) {
...@@ -440,110 +424,5 @@ describe(Support.getTestDialectTeaser('Promise'), function() { ...@@ -440,110 +424,5 @@ describe(Support.getTestDialectTeaser('Promise'), function() {
done(); done();
}); });
}); });
it('should still work with .on(\'error\') when throwing', function(done) {
var spy = sinon.spy()
, promise = new SequelizePromise(function(resolve, reject) {
throw new Error('noway');
});
promise.on('error', spy);
promise.catch(function() {
expect(spy.calledOnce).to.be.true;
expect(spy.firstCall.args[0]).to.be.an.instanceof(Error);
done();
});
});
it('should still work with .error() when emitting', function(done) {
var spy = sinon.spy()
, promise = new SequelizePromise(function(resolve, reject) {
// no-op
});
promise.on('error', spy);
promise.catch(function() {
expect(spy.calledOnce).to.be.true;
expect(spy.firstCall.args[0]).to.be.an.instanceof(Error);
done();
});
promise.emit('error', new Error('noway'));
});
it('should still support sql events', function() {
var spy = sinon.spy()
, promise = new SequelizePromise(function(resolve, reject) {
resolve('yay');
});
promise.on('sql', spy);
promise.emit('sql', 'SQL STATEMENT 1');
promise.emit('sql', 'SQL STATEMENT 2');
return promise.then(function() {
expect(spy.calledTwice).to.be.true;
});
});
describe('proxy', function() {
it('should correctly work with success listeners', function(done) {
var emitter = new SequelizePromise(function() {})
, proxy = new SequelizePromise(function() {})
, success = sinon.spy();
emitter.success(success);
proxy.success(function() {
process.nextTick(function() {
expect(success.called).to.be.true;
done();
});
});
proxy.proxy(emitter);
proxy.emit('success');
});
it('should correctly work with complete/done listeners', function(done) {
var promise = new SequelizePromise(function() {})
, proxy = new SequelizePromise(function() {})
, complete = sinon.spy();
promise.complete(complete);
proxy.complete(function() {
process.nextTick(function() {
expect(complete.called).to.be.true;
done();
});
});
proxy.proxy(promise);
proxy.emit('success');
});
});
describe('when emitting an error event with an array of errors', function() {
describe('if an error handler is given', function() {
it('should return the whole array', function(done) {
var emitter = new SequelizePromise(function() {});
var errors = [
[
new Error('First error'),
new Error('Second error')
], [
new Error('Third error')
]
];
emitter.error(function(err) {
expect(err).to.equal(errors);
done();
});
emitter.emit('error', errors);
});
});
});
}); });
}); });
...@@ -5,11 +5,16 @@ var chai = require('chai') ...@@ -5,11 +5,16 @@ var chai = require('chai')
, expect = chai.expect , expect = chai.expect
, Support = require(__dirname + '/support') , Support = require(__dirname + '/support')
, QueryChainer = require('../../lib/query-chainer') , QueryChainer = require('../../lib/query-chainer')
, CustomEventEmitter = require('../../lib/emitters/custom-event-emitter'); , CustomEventEmitter;
chai.config.includeStack = true; chai.config.includeStack = true;
describe(Support.getTestDialectTeaser('QueryChainer'), function() { describe(Support.getTestDialectTeaser('QueryChainer'), function() {
before(function() {
CustomEventEmitter = require('../../lib/emitters/custom-event-emitter');
});
beforeEach(function() { beforeEach(function() {
this.queryChainer = new QueryChainer(); this.queryChainer = new QueryChainer();
}); });
...@@ -40,7 +45,7 @@ describe(Support.getTestDialectTeaser('QueryChainer'), function() { ...@@ -40,7 +45,7 @@ describe(Support.getTestDialectTeaser('QueryChainer'), function() {
expect(true).to.be.true; expect(true).to.be.true;
done(); done();
}).error(function(err) { }).error(function(err) {
console.log(err); done(err);
}); });
emitter1.run(); emitter1.run();
......
...@@ -6,7 +6,14 @@ var chai = require('chai') ...@@ -6,7 +6,14 @@ var chai = require('chai')
, Support = require(__dirname + '/support') , Support = require(__dirname + '/support')
, DataTypes = require(__dirname + '/../../lib/data-types') , DataTypes = require(__dirname + '/../../lib/data-types')
, dialect = Support.getTestDialect() , dialect = Support.getTestDialect()
, _ = require('lodash'); , _ = require('lodash')
, count = 0
, log = function (sql) {
// sqlite fires a lot more querys than the other dbs. this is just a simple hack, since i'm lazy
if (dialect !== 'sqlite' || count === 0) {
count++;
}
};
chai.config.includeStack = true; chai.config.includeStack = true;
...@@ -20,12 +27,22 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -20,12 +27,22 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
it('should drop all tables', function() { it('should drop all tables', function() {
var self = this; var self = this;
return this.queryInterface.dropAllTables().then(function() { return this.queryInterface.dropAllTables().then(function() {
return self.queryInterface.showAllTables().then(function(tableNames) { return self.queryInterface.showAllTables({logging: log}).then(function(tableNames) {
expect(count).to.be.equal(1);
count = 0;
expect(tableNames).to.be.empty; expect(tableNames).to.be.empty;
return self.queryInterface.createTable('table', { name: DataTypes.STRING }).then(function() { return self.queryInterface.createTable('table', { name: DataTypes.STRING }, {
return self.queryInterface.showAllTables().then(function(tableNames) { logging: log
}).then(function() {
expect(count).to.be.equal(1);
count = 0;
return self.queryInterface.showAllTables({logging: log}).then(function(tableNames) {
expect(count).to.be.equal(1);
count = 0;
expect(tableNames).to.have.length(1); expect(tableNames).to.have.length(1);
return self.queryInterface.dropAllTables().then(function() { return self.queryInterface.dropAllTables({logging: log}).then(function() {
expect(count).to.be.equal(1);
count = 0;
return self.queryInterface.showAllTables().then(function(tableNames) { return self.queryInterface.showAllTables().then(function(tableNames) {
expect(tableNames).to.be.empty; expect(tableNames).to.be.empty;
}); });
...@@ -56,7 +73,9 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -56,7 +73,9 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
describe('indexes', function() { describe('indexes', function() {
beforeEach(function() { beforeEach(function() {
var self = this; var self = this;
return this.queryInterface.dropTable('Group').then(function() { return this.queryInterface.dropTable('Group', {logging: log}).then(function() {
expect(count).to.be.equal(1);
count = 0;
return self.queryInterface.createTable('Group', { return self.queryInterface.createTable('Group', {
username: DataTypes.STRING, username: DataTypes.STRING,
isAdmin: DataTypes.BOOLEAN, isAdmin: DataTypes.BOOLEAN,
...@@ -67,11 +86,20 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -67,11 +86,20 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
it('adds, reads and removes an index to the table', function() { it('adds, reads and removes an index to the table', function() {
var self = this; var self = this;
return this.queryInterface.addIndex('Group', ['username', 'isAdmin']).then(function() { return this.queryInterface.addIndex('Group', ['username', 'isAdmin'], {
return self.queryInterface.showIndex('Group').then(function(indexes) { logging: log
}).then(function() {
expect(count).to.be.equal(1);
count = 0;
return self.queryInterface.showIndex('Group', {logging: log}).then(function(indexes) {
expect(count).to.be.equal(1);
count = 0;
var indexColumns = _.uniq(indexes.map(function(index) { return index.name; })); var indexColumns = _.uniq(indexes.map(function(index) { return index.name; }));
expect(indexColumns).to.include('group_username_is_admin'); expect(indexColumns).to.include('group_username_is_admin');
return self.queryInterface.removeIndex('Group', ['username', 'isAdmin']).then(function() { return self.queryInterface.removeIndex('Group', ['username', 'isAdmin'], {logging: log}).then(function() {
expect(count).to.be.equal(1);
count = 0;
return self.queryInterface.showIndex('Group').then(function(indexes) { return self.queryInterface.showIndex('Group').then(function(indexes) {
indexColumns = _.uniq(indexes.map(function(index) { return index.name; })); indexColumns = _.uniq(indexes.map(function(index) { return index.name; }));
expect(indexColumns).to.be.empty; expect(indexColumns).to.be.empty;
...@@ -96,7 +124,10 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -96,7 +124,10 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
}, { freezeTableName: true }); }, { freezeTableName: true });
return Users.sync({ force: true }).then(function() { return Users.sync({ force: true }).then(function() {
return self.queryInterface.describeTable('_Users').then(function(metadata) { return self.queryInterface.describeTable('_Users', {logging: log}).then(function(metadata) {
expect(count).to.be.equal(1);
count = 0;
var username = metadata.username; var username = metadata.username;
var isAdmin = metadata.isAdmin; var isAdmin = metadata.isAdmin;
var enumVals = metadata.enumVals; var enumVals = metadata.enumVals;
...@@ -179,9 +210,16 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -179,9 +210,16 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
it('should work with schemas', function() { it('should work with schemas', function() {
var self = this; var self = this;
return self.sequelize.dropAllSchemas().then(function() { return self.sequelize.dropAllSchemas({logging: log}).then(function() {
return self.sequelize.createSchema('hero'); // TODO: FIXME: somehow these do not fire the logging function
if (dialect !== 'mysql' && dialect !== 'sqlite' && dialect !== 'mariadb') {
expect(count).to.be.above(0);
}
count = 0;
return self.sequelize.createSchema('hero', {logging: log});
}).then(function() { }).then(function() {
expect(count).to.be.equal(1);
count = 0;
return self.queryInterface.createTable('User', { return self.queryInterface.createTable('User', {
name: { name: {
type: DataTypes.STRING type: DataTypes.STRING
...@@ -191,8 +229,12 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -191,8 +229,12 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
}); });
}).then(function() { }).then(function() {
return self.queryInterface.rawSelect('User', { return self.queryInterface.rawSelect('User', {
schema: 'hero' schema: 'hero',
logging: log
}, 'name'); }, 'name');
}).then(function() {
expect(count).to.be.equal(1);
count = 0;
}); });
}); });
}); });
...@@ -205,7 +247,12 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -205,7 +247,12 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
}, { freezeTableName: true }); }, { freezeTableName: true });
return Users.sync({ force: true }).then(function() { return Users.sync({ force: true }).then(function() {
return self.queryInterface.renameColumn('_Users', 'username', 'pseudo'); return self.queryInterface.renameColumn('_Users', 'username', 'pseudo', {logging: log}).then(function() {
if (dialect === 'sqlite')
count++;
expect(count).to.be.equal(2);
count = 0;
});
}); });
}); });
...@@ -297,6 +344,11 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -297,6 +344,11 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
schema: 'archive' schema: 'archive'
}, 'currency', { }, 'currency', {
type: DataTypes.FLOAT type: DataTypes.FLOAT
}, {
logging: log
}).then(function() {
expect(count).to.be.equal(1);
count = 0;
}); });
}); });
}); });
...@@ -328,7 +380,10 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -328,7 +380,10 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
referenceKey: 'id', referenceKey: 'id',
onUpdate: 'cascade', onUpdate: 'cascade',
onDelete: 'set null' onDelete: 'set null'
}); }, {logging: log});
}).then(function() {
expect(count).to.be.equal(1);
count = 0;
}); });
}); });
...@@ -404,8 +459,10 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() { ...@@ -404,8 +459,10 @@ describe(Support.getTestDialectTeaser('QueryInterface'), function() {
it('should get a list of foreign keys for the table', function() { it('should get a list of foreign keys for the table', function() {
var sql = this.queryInterface.QueryGenerator.getForeignKeysQuery('hosts', this.sequelize.config.database); var sql = this.queryInterface.QueryGenerator.getForeignKeysQuery('hosts', this.sequelize.config.database);
return this.sequelize.query(sql, {type: this.sequelize.QueryTypes.FOREIGNKEYS}).then(function(fks) { return this.sequelize.query(sql, {type: this.sequelize.QueryTypes.FOREIGNKEYS, logging: log}).then(function(fks) {
expect(count).to.be.equal(1);
expect(fks).to.have.length(3); expect(fks).to.have.length(3);
count = 0;
var keys = Object.keys(fks[0]), var keys = Object.keys(fks[0]),
keys2 = Object.keys(fks[1]), keys2 = Object.keys(fks[1]),
keys3 = Object.keys(fks[2]); keys3 = Object.keys(fks[2]);
......
...@@ -113,7 +113,6 @@ describe(Support.getTestDialectTeaser('Sequelize'), function() { ...@@ -113,7 +113,6 @@ describe(Support.getTestDialectTeaser('Sequelize'), function() {
.sequelizeWithInvalidConnection .sequelizeWithInvalidConnection
.authenticate() .authenticate()
.catch(function(err) { .catch(function(err) {
console.log(err.message);
expect( expect(
err.message.match(/connect ECONNREFUSED/) || err.message.match(/connect ECONNREFUSED/) ||
err.message.match(/invalid port number/) || err.message.match(/invalid port number/) ||
...@@ -397,7 +396,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), function() { ...@@ -397,7 +396,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), function() {
if (Support.getTestDialect() === 'postgres') { if (Support.getTestDialect() === 'postgres') {
it('replaces named parameters with the passed object and ignores casts', function() { it('replaces named parameters with the passed object and ignores casts', function() {
return expect(this.sequelize.query('select :one as foo, :two as bar, \'1000\'::integer as baz', null, { raw: true }, { one: 1, two: 2 }).get(0)) return expect(this.sequelize.query('select :one as foo, :two as bar, \'1000\'::integer as baz', null, { raw: true, replacements: { one: 1, two: 2 } }).get(0))
.to.eventually.deep.equal([{ foo: 1, bar: 2, baz: 1000 }]); .to.eventually.deep.equal([{ foo: 1, bar: 2, baz: 1000 }]);
}); });
......
...@@ -20,8 +20,6 @@ describe(Support.getTestDialectTeaser('Vectors'), function() { ...@@ -20,8 +20,6 @@ describe(Support.getTestDialectTeaser('Vectors'), function() {
return Student.sync({force: true}).then(function () { return Student.sync({force: true}).then(function () {
return Student.create({ return Student.create({
name: 'Robert\\\'); DROP TABLE "students"; --' name: 'Robert\\\'); DROP TABLE "students"; --'
}, {
logging: console.log
}).then(function(result) { }).then(function(result) {
expect(result.get('name')).to.equal('Robert\\\'); DROP TABLE "students"; --'); expect(result.get('name')).to.equal('Robert\\\'); DROP TABLE "students"; --');
return Student.findAll(); return Student.findAll();
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!