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

Commit 58c1b859 by Thaddeus Quintin

Merge branch 'master' into pass-options-to-getTableName

Conflicts:
	lib/model.js
2 parents a4b15fe7 0e53c4b7
...@@ -398,7 +398,13 @@ module.exports = { ...@@ -398,7 +398,13 @@ module.exports = {
UUIDV4: 'UUIDV4', UUIDV4: 'UUIDV4',
/** /**
* A virtual value that is not stored in the DB. This could for example be useful if you want to provide a default value in your model * A key / value column. Only available in postgres.
* @property HSTORE
*/
HSTORE: 'HSTORE',
/**
* A virtual value that is not stored in the DB. This could for example be useful if you want to provide a default value in your model
* that is returned to the user but not stored in the DB. * that is returned to the user but not stored in the DB.
* *
* You could also use it to validate a value before permuting and storing it. Checking password length before hashing it for example: * You could also use it to validate a value before permuting and storing it. Checking password length before hashing it for example:
...@@ -453,22 +459,5 @@ module.exports = { ...@@ -453,22 +459,5 @@ module.exports = {
* An array of `type`, e.g. `DataTypes.ARRAY(DataTypes.DECIMAL)`. Only available in postgres. * An array of `type`, e.g. `DataTypes.ARRAY(DataTypes.DECIMAL)`. Only available in postgres.
* @property ARRAY * @property ARRAY
*/ */
ARRAY: function(type) { return type + '[]'; }, ARRAY: function(type) { return type + '[]'; }
/**
* A key / value column. Only available in postgres.
* @property HSTORE
*/
get HSTORE() {
var result = function() {
return {
type: 'HSTORE'
};
};
result.type = 'HSTORE';
result.toString = result.valueOf = function() { return 'HSTORE'; };
return result;
}
}; };
...@@ -143,7 +143,9 @@ module.exports = (function() { ...@@ -143,7 +143,9 @@ module.exports = (function() {
/* /*
Returns an insert into command. Parameters: table name + hash of attribute-value-pairs. Returns an insert into command. Parameters: table name + hash of attribute-value-pairs.
*/ */
insertQuery: function(table, valueHash, modelAttributes) { insertQuery: function(table, valueHash, modelAttributes, options) {
options = options || {};
var query var query
, valueQuery = 'INSERT INTO <%= table %> (<%= attributes %>) VALUES (<%= values %>)' , valueQuery = 'INSERT INTO <%= table %> (<%= attributes %>) VALUES (<%= values %>)'
, emptyQuery = 'INSERT INTO <%= table %>' , emptyQuery = 'INSERT INTO <%= table %>'
...@@ -168,7 +170,7 @@ module.exports = (function() { ...@@ -168,7 +170,7 @@ module.exports = (function() {
emptyQuery += ' VALUES ()'; emptyQuery += ' VALUES ()';
} }
if (this._dialect.supports['RETURNING']) { if (this._dialect.supports['RETURNING'] && options.returning) {
valueQuery += ' RETURNING *'; valueQuery += ' RETURNING *';
emptyQuery += ' RETURNING *'; emptyQuery += ' RETURNING *';
} }
...@@ -235,7 +237,7 @@ module.exports = (function() { ...@@ -235,7 +237,7 @@ module.exports = (function() {
query += ' LIMIT ' + this.escape(options.limit) + ' '; query += ' LIMIT ' + this.escape(options.limit) + ' ';
} }
if (this._dialect.supports['RETURNING'] && (options.returning || options.returning === undefined)) { if (this._dialect.supports['RETURNING'] && options.returning) {
query += ' RETURNING *'; query += ' RETURNING *';
} }
...@@ -789,7 +791,7 @@ module.exports = (function() { ...@@ -789,7 +791,7 @@ module.exports = (function() {
if (include.where) { if (include.where) {
targetWhere = self.getWhereConditions(include.where, self.sequelize.literal(self.quoteIdentifier(as)), include.model, whereOptions); targetWhere = self.getWhereConditions(include.where, self.sequelize.literal(self.quoteIdentifier(as)), include.model, whereOptions);
joinQueryItem += ' AND ' + targetWhere; joinQueryItem += ' AND ' + targetWhere;
if (subQuery) { if (subQuery && include.required) {
if (!options.where) options.where = {}; if (!options.where) options.where = {};
// Creating the as-is where for the subQuery, checks that the required association exists // Creating the as-is where for the subQuery, checks that the required association exists
...@@ -875,11 +877,14 @@ module.exports = (function() { ...@@ -875,11 +877,14 @@ module.exports = (function() {
if (childInclude.subQuery && subQuery) { if (childInclude.subQuery && subQuery) {
joinQueries.subQuery = joinQueries.subQuery.concat(childJoinQueries.subQuery); joinQueries.subQuery = joinQueries.subQuery.concat(childJoinQueries.subQuery);
} else { }
if (childJoinQueries.mainQuery) {
joinQueries.mainQuery = joinQueries.mainQuery.concat(childJoinQueries.mainQuery); joinQueries.mainQuery = joinQueries.mainQuery.concat(childJoinQueries.mainQuery);
} }
}.bind(this)); }.bind(this));
} }
return joinQueries; return joinQueries;
}; };
...@@ -889,6 +894,7 @@ module.exports = (function() { ...@@ -889,6 +894,7 @@ module.exports = (function() {
subJoinQueries = subJoinQueries.concat(joinQueries.subQuery); subJoinQueries = subJoinQueries.concat(joinQueries.subQuery);
mainJoinQueries = mainJoinQueries.concat(joinQueries.mainQuery); mainJoinQueries = mainJoinQueries.concat(joinQueries.mainQuery);
}.bind(this)); }.bind(this));
} }
......
...@@ -258,15 +258,15 @@ module.exports = (function() { ...@@ -258,15 +258,15 @@ module.exports = (function() {
return Utils._.compact([ return Utils._.compact([
'CREATE', options.indicesType, 'INDEX', options.indexName, 'CREATE', options.indicesType, 'INDEX', options.indexName,
(options.indexType ? ('USING ' + options.indexType) : undefined), (options.indexType ? ('USING ' + options.indexType) : undefined),
'ON', tableName, '(' + transformedAttributes.join(', ') + ')', 'ON', this.quoteIdentifiers(tableName), '(' + transformedAttributes.join(', ') + ')',
(options.parser ? 'WITH PARSER ' + options.parser : undefined) (options.parser ? 'WITH PARSER ' + options.parser : undefined)
]).join(' '); ]).join(' ');
}, },
showIndexQuery: function(tableName, options) { showIndexQuery: function(tableName, options) {
var sql = 'SHOW INDEX FROM `<%= tableName %>`<%= options %>'; var sql = 'SHOW INDEX FROM <%= tableName %><%= options %>';
return Utils._.template(sql)({ return Utils._.template(sql)({
tableName: tableName, tableName: this.quoteIdentifiers(tableName),
options: (options || {}).database ? ' FROM `' + options.database + '`' : '' options: (options || {}).database ? ' FROM `' + options.database + '`' : ''
}); });
}, },
...@@ -279,7 +279,7 @@ module.exports = (function() { ...@@ -279,7 +279,7 @@ module.exports = (function() {
indexName = Utils._.underscored(tableName + '_' + indexNameOrAttributes.join('_')); indexName = Utils._.underscored(tableName + '_' + indexNameOrAttributes.join('_'));
} }
return Utils._.template(sql)({ tableName: tableName, indexName: indexName }); return Utils._.template(sql)({ tableName: this.quoteIdentifiers(tableName), indexName: indexName });
}, },
attributesToSQL: function(attributes) { attributesToSQL: function(attributes) {
......
...@@ -255,11 +255,17 @@ module.exports = (function() { ...@@ -255,11 +255,17 @@ module.exports = (function() {
}, },
bulkInsertQuery: function(tableName, attrValueHashes, options, modelAttributes) { bulkInsertQuery: function(tableName, attrValueHashes, options, modelAttributes) {
var query = 'INSERT INTO <%= table %> (<%= attributes %>) VALUES <%= tuples %> RETURNING *;' options = options || {};
var query = 'INSERT INTO <%= table %> (<%= attributes %>) VALUES <%= tuples %>'
, tuples = [] , tuples = []
, serials = [] , serials = []
, allAttributes = []; , allAttributes = [];
if (this._dialect.supports['RETURNING'] && options.returning) {
query += ' RETURNING *';
}
Utils._.forEach(attrValueHashes, function(attrValueHash) { Utils._.forEach(attrValueHashes, function(attrValueHash) {
Utils._.forOwn(attrValueHash, function(value, key) { Utils._.forOwn(attrValueHash, function(value, key) {
if (allAttributes.indexOf(key) === -1) { if (allAttributes.indexOf(key) === -1) {
...@@ -291,6 +297,8 @@ module.exports = (function() { ...@@ -291,6 +297,8 @@ module.exports = (function() {
, tuples: tuples.join(',') , tuples: tuples.join(',')
}; };
query = query + ';';
return Utils._.template(query)(replacements); return Utils._.template(query)(replacements);
}, },
...@@ -590,7 +598,7 @@ module.exports = (function() { ...@@ -590,7 +598,7 @@ module.exports = (function() {
}, },
databaseConnectionUri: function(config) { databaseConnectionUri: function(config) {
var template = '<%= protocol %>://<%= user %>:<%= password %>@<%= host %><% if(port) { %>:<%= port %><% } %>/<%= database %>'; var template = '<%= protocol %>://<%= user %>:<%= password %>@<%= host %><% if(port) { %>:<%= port %><% } %>/<%= database %><% if(ssl) { %>?ssl=<%= ssl %><% } %>';
return Utils._.template(template)({ return Utils._.template(template)({
user: config.username, user: config.username,
...@@ -598,7 +606,8 @@ module.exports = (function() { ...@@ -598,7 +606,8 @@ module.exports = (function() {
database: config.database, database: config.database,
host: config.host, host: config.host,
port: config.port, port: config.port,
protocol: config.protocol protocol: config.protocol,
ssl: config.ssl
}); });
}, },
...@@ -814,7 +823,7 @@ module.exports = (function() { ...@@ -814,7 +823,7 @@ module.exports = (function() {
if (value && value._isSequelizeMethod) { if (value && value._isSequelizeMethod) {
return value.toString(this); return value.toString(this);
} else { } else {
if (field && field.type && field.type.toString() === DataTypes.HSTORE.type && Utils._.isObject(value)) { if (Utils._.isObject(value) && field && (field === DataTypes.HSTORE || field.type === DataTypes.HSTORE)) {
value = hstore.stringify(value); value = hstore.stringify(value);
} }
......
...@@ -7,6 +7,16 @@ var Utils = require('../../utils') ...@@ -7,6 +7,16 @@ var Utils = require('../../utils')
, QueryTypes = require('../../query-types') , QueryTypes = require('../../query-types')
, Promise = require('../../promise'); , Promise = require('../../promise');
// Parses hstore fields if the model has any hstore fields.
// This cannot be done in the 'pg' lib because hstore is a UDT.
var parseHstoreFields = function(model, row) {
Utils._.keys(row).forEach(function(key) {
if (model._isHstoreAttribute(key)) {
row[key] = hstore.parse(row[key]);
}
});
};
module.exports = (function() { module.exports = (function() {
var Query = function(client, sequelize, callee, options) { var Query = function(client, sequelize, callee, options) {
this.client = client; this.client = client;
...@@ -125,15 +135,9 @@ module.exports = (function() { ...@@ -125,15 +135,9 @@ module.exports = (function() {
}); });
} }
// Parse hstore fields if the model has any hstore fields.
// This cannot be done in the 'pg' lib because hstore is a UDT.
if (!!self.callee && !!self.callee._hasHstoreAttributes) { if (!!self.callee && !!self.callee._hasHstoreAttributes) {
rows.forEach(function(row) { rows.forEach(function(row) {
Utils._.keys(row).forEach(function(key) { parseHstoreFields(self.callee, row);
if (self.callee._isHstoreAttribute(key)) {
row[key] = hstore.parse(row[key]);
}
});
}); });
} }
...@@ -141,20 +145,34 @@ module.exports = (function() { ...@@ -141,20 +145,34 @@ module.exports = (function() {
} }
} else if (self.send('isShowOrDescribeQuery')) { } else if (self.send('isShowOrDescribeQuery')) {
return results; return results;
} else if ([QueryTypes.BULKUPDATE, QueryTypes.BULKDELETE].indexOf(self.options.type) !== -1) { } else if (QueryTypes.BULKUPDATE === self.options.type) {
if (!self.options.returning) {
return result.rowCount;
}
if (!!self.callee && !!self.callee._hasHstoreAttributes) {
rows.forEach(function(row) {
parseHstoreFields(self.callee, row);
});
}
return self.send('handleSelectQuery', rows);
} else if (QueryTypes.BULKDELETE === self.options.type) {
return result.rowCount; return result.rowCount;
} else if (self.send('isInsertQuery') || self.send('isUpdateQuery')) { } else if (self.send('isInsertQuery') || self.send('isUpdateQuery')) {
if (self.callee !== null) { // may happen for bulk inserts or bulk updates if (!!self.callee && self.callee.dataValues) {
if (!!self.callee.Model && !!self.callee.Model._hasHstoreAttributes) {
parseHstoreFields(self.callee.Model, rows[0]);
}
for (var key in rows[0]) { for (var key in rows[0]) {
if (rows[0].hasOwnProperty(key)) { if (rows[0].hasOwnProperty(key)) {
var record = rows[0][key]; var record = rows[0][key];
if (!!self.callee.Model && !!self.callee.Model.rawAttributes && !!self.callee.Model.rawAttributes[key] && !!self.callee.Model.rawAttributes[key].type && self.callee.Model.rawAttributes[key].type.toString() === DataTypes.HSTORE.toString()) {
record = hstore.parse(record);
}
var attr = Utils._.find(self.callee.Model.rawAttributes, function (attribute) { var attr = Utils._.find(self.callee.Model.rawAttributes, function (attribute) {
return attribute.fieldName === key || attribute.field === key; return attribute.fieldName === key || attribute.field === key;
}); });
self.callee.dataValues[attr && attr.fieldName || key] = record; self.callee.dataValues[attr && attr.fieldName || key] = record;
} }
} }
......
...@@ -307,7 +307,7 @@ module.exports = (function() { ...@@ -307,7 +307,7 @@ module.exports = (function() {
showIndexQuery: function(tableName) { showIndexQuery: function(tableName) {
var sql = "PRAGMA INDEX_LIST(<%= tableName %>)"; var sql = "PRAGMA INDEX_LIST(<%= tableName %>)";
return Utils._.template(sql, { tableName: tableName }); return Utils._.template(sql, { tableName: this.quoteIdentifiers(tableName) });
}, },
removeIndexQuery: function(tableName, indexNameOrAttributes) { removeIndexQuery: function(tableName, indexNameOrAttributes) {
...@@ -318,7 +318,7 @@ module.exports = (function() { ...@@ -318,7 +318,7 @@ module.exports = (function() {
indexName = Utils._.underscored(tableName + '_' + indexNameOrAttributes.join('_')); indexName = Utils._.underscored(tableName + '_' + indexNameOrAttributes.join('_'));
} }
return Utils._.template(sql, { tableName: tableName, indexName: indexName }); return Utils._.template(sql, { tableName: this.quoteIdentifiers(tableName), indexName: indexName });
}, },
describeTableQuery: function(tableName, schema, schemaDelimiter) { describeTableQuery: function(tableName, schema, schemaDelimiter) {
...@@ -328,7 +328,7 @@ module.exports = (function() { ...@@ -328,7 +328,7 @@ module.exports = (function() {
options.quoted = false; options.quoted = false;
var sql = "PRAGMA TABLE_INFO(<%= tableName %>);"; var sql = "PRAGMA TABLE_INFO(<%= tableName %>);";
return Utils._.template(sql, { tableName: this.addSchema({tableName: tableName, options: options})}); return Utils._.template(sql, { tableName: this.addSchema({tableName: this.quoteIdentifiers(tableName), options: options})});
}, },
removeColumnQuery: function(tableName, attributes) { removeColumnQuery: function(tableName, attributes) {
......
...@@ -81,7 +81,7 @@ module.exports = (function() { ...@@ -81,7 +81,7 @@ module.exports = (function() {
} else { } else {
dataType = attribute; dataType = attribute;
} }
if (dataType === undefined) { if (dataType === undefined) {
throw new Error('Unrecognized data type for field ' + name); throw new Error('Unrecognized data type for field ' + name);
} }
...@@ -262,12 +262,13 @@ module.exports = (function() { ...@@ -262,12 +262,13 @@ module.exports = (function() {
this.Instance.prototype.validators = {}; this.Instance.prototype.validators = {};
Utils._.each(this.rawAttributes, function(definition, name) { Utils._.each(this.rawAttributes, function(definition, name) {
var type = definition.originalType || definition.type || definition; var type = definition.originalType || definition.type || definition;
if (type === DataTypes.BOOLEAN) { if (type === DataTypes.BOOLEAN) {
self._booleanAttributes.push(name); self._booleanAttributes.push(name);
} else if (type === DataTypes.DATE) { } else if (type === DataTypes.DATE) {
self._dateAttributes.push(name); self._dateAttributes.push(name);
} else if (type === DataTypes.HSTORE.type) { } else if (type === DataTypes.HSTORE) {
self._hstoreAttributes.push(name); self._hstoreAttributes.push(name);
} else if (type === DataTypes.VIRTUAL) { } else if (type === DataTypes.VIRTUAL) {
self._virtualAttributes.push(name); self._virtualAttributes.push(name);
...@@ -1342,6 +1343,7 @@ module.exports = (function() { ...@@ -1342,6 +1343,7 @@ module.exports = (function() {
* @param {Boolean} [options.validate=true] Should each row be subject to validation before it is inserted. The whole insert will fail if one row fails validation * @param {Boolean} [options.validate=true] Should each row be subject to validation before it is inserted. The whole insert will fail if one row fails validation
* @param {Boolean} [options.hooks=true] Run before / after bulk update hooks? * @param {Boolean} [options.hooks=true] Run before / after bulk update hooks?
* @param {Boolean} [options.individualHooks=false] Run before / after update hooks? * @param {Boolean} [options.individualHooks=false] Run before / after update hooks?
* @param {Boolean} [options.returning=false] Return the affected rows (only for postgres)
* @param {Number} [options.limit] How many rows to update (only for mysql and mariadb) * @param {Number} [options.limit] How many rows to update (only for mysql and mariadb)
* @deprecated The syntax is due for change, in order to make `where` more consistent with the rest of the API * @deprecated The syntax is due for change, in order to make `where` more consistent with the rest of the API
* *
...@@ -1354,6 +1356,7 @@ module.exports = (function() { ...@@ -1354,6 +1356,7 @@ module.exports = (function() {
validate: true, validate: true,
hooks: true, hooks: true,
individualHooks: false, individualHooks: false,
returning: false,
force: false force: false
}, options || {}); }, options || {});
...@@ -1458,7 +1461,11 @@ module.exports = (function() { ...@@ -1458,7 +1461,11 @@ module.exports = (function() {
} }
// Run query to update all rows // Run query to update all rows
return self.QueryInterface.bulkUpdate(self.getTableName(options), attrValueHashUse, where, options, self.tableAttributes).then(function(affectedRows) { return self.QueryInterface.bulkUpdate(self.getTableName(), attrValueHashUse, where, options, self.tableAttributes).then(function(affectedRows) {
if (options.returning) {
return [affectedRows.length, affectedRows];
}
return [affectedRows]; return [affectedRows];
}); });
}).tap(function(result) { }).tap(function(result) {
......
...@@ -414,7 +414,7 @@ module.exports = (function() { ...@@ -414,7 +414,7 @@ module.exports = (function() {
}; };
QueryInterface.prototype.insert = function(dao, tableName, values, options) { QueryInterface.prototype.insert = function(dao, tableName, values, options) {
var sql = this.QueryGenerator.insertQuery(tableName, values, dao.Model.rawAttributes); var sql = this.QueryGenerator.insertQuery(tableName, values, dao.Model.rawAttributes, options);
return this.sequelize.query(sql, dao, options).then(function(result) { return this.sequelize.query(sql, dao, options).then(function(result) {
result.isNewRecord = false; result.isNewRecord = false;
...@@ -448,9 +448,11 @@ module.exports = (function() { ...@@ -448,9 +448,11 @@ module.exports = (function() {
}; };
QueryInterface.prototype.bulkUpdate = function(tableName, values, identifier, options, attributes) { QueryInterface.prototype.bulkUpdate = function(tableName, values, identifier, options, attributes) {
var sql = this.QueryGenerator.updateQuery(tableName, values, identifier, options, attributes); var sql = this.QueryGenerator.updateQuery(tableName, values, identifier, options, attributes)
, table = Utils._.isObject(tableName) ? tableName : { tableName: tableName }
, daoTable = Utils._.find(this.sequelize.daoFactoryManager.daos, { tableName: table.tableName });
return this.sequelize.query(sql, null, options); return this.sequelize.query(sql, daoTable, options);
}; };
QueryInterface.prototype.delete = function(dao, tableName, identifier, options) { QueryInterface.prototype.delete = function(dao, tableName, identifier, options) {
......
...@@ -805,6 +805,32 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () { ...@@ -805,6 +805,32 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
}) })
}) })
if (dialect === "postgres") {
it('returns the affected rows if `options.returning` is true', function(_done) {
var self = this
, data = [{ username: 'Peter', secretValue: '42' },
{ username: 'Paul', secretValue: '42' },
{ username: 'Bob', secretValue: '43' }]
, done = _.after(2, _done)
this.User.bulkCreate(data).success(function() {
self.User.update({ username: 'Bill' }, { secretValue: '42' }, { returning: true }).spread(function(count, rows) {
expect(count).to.equal(2)
expect(rows).to.have.length(2)
done()
})
self.User.update({ username: 'Bill'}, { secretValue: '44' }, { returning: true }).spread(function(count, rows) {
expect(count).to.equal(0)
expect(rows).to.have.length(0)
done()
})
})
})
}
if(Support.dialectIsMySQL()) { if(Support.dialectIsMySQL()) {
it('supports limit clause', function (done) { it('supports limit clause', function (done) {
var self = this var self = this
......
...@@ -5,39 +5,36 @@ var chai = require('chai') ...@@ -5,39 +5,36 @@ var chai = require('chai')
, Support = require(__dirname + '/../support') , Support = require(__dirname + '/../support')
, DataTypes = require(__dirname + "/../../lib/data-types") , DataTypes = require(__dirname + "/../../lib/data-types")
, datetime = require('chai-datetime') , datetime = require('chai-datetime')
, async = require('async');
chai.use(datetime) chai.use(datetime)
chai.config.includeStack = true chai.config.includeStack = true
describe(Support.getTestDialectTeaser("Include"), function () { describe(Support.getTestDialectTeaser("Include"), function () {
describe('find', function () { describe('find', function () {
it('should include a non required model, with conditions and two includes N:M 1:M', function ( done ) {
it( 'Try to include a non required model, with conditions and two includes N:M 1:M', function ( done ) { var A = this.sequelize.define('A', { name: DataTypes.STRING(40) }, { paranoid: true })
var DT = DataTypes, , B = this.sequelize.define('B', { name: DataTypes.STRING(40) }, { paranoid: true })
S = this.sequelize, , C = this.sequelize.define('C', { name: DataTypes.STRING(40) }, { paranoid: true })
A = S.define('A', { name: DT.STRING(40) }, { paranoid: true }), , D = this.sequelize.define('D', { name: DataTypes.STRING(40) }, { paranoid: true });
B = S.define('B', { name: DT.STRING(40) }, { paranoid: true }),
C = S.define('C', { name: DT.STRING(40) }, { paranoid: true }),
D = S.define('D', { name: DT.STRING(40) }, { paranoid: true })
// Associations // Associations
A.hasMany( B ) A.hasMany(B);
B.belongsTo( B ) B.belongsTo(B);
B.belongsTo( D ) B.belongsTo(D);
B.hasMany( C, { B.hasMany(C, {
through: 'BC', through: 'BC',
}) });
C C.hasMany(B, {
.hasMany( B, { through: 'BC',
through: 'BC', });
})
D D.hasMany(B);
.hasMany( B )
S.sync({ force: true }).done( function ( err ) { expect( err ).not.to.be.ok this.sequelize.sync({ force: true }).done(function ( err ) {
expect( err ).not.to.be.ok;
A.find({ A.find({
include: [ include: [
...@@ -47,13 +44,134 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -47,13 +44,134 @@ describe(Support.getTestDialectTeaser("Include"), function () {
]} ]}
] ]
}).done( function ( err ) { }).done( function ( err ) {
expect( err ).not.to.be.ok expect( err ).not.to.be.ok;
done() done();
});
});
});
it("should still pull the main record when an included model is not required and has where restrictions without matches", function () {
var A = this.sequelize.define('A', {
name: DataTypes.STRING(40)
})
, B = this.sequelize.define('B', {
name: DataTypes.STRING(40)
});
A.hasMany(B);
B.hasMany(A);
return this.sequelize
.sync({force: true})
.then(function () {
return A.create({
name: 'Foobar'
});
})
.then(function () {
return A.find({
where: {name: 'Foobar'},
include: [
{model: B, where: {name: 'idontexist'}, required: false}
]
});
})
.then(function (a) {
expect(a).to.not.equal(null);
expect(a.get('bs')).to.deep.equal([]);
});
});
it('should support many levels of belongsTo (with a lower level having a where)', function (done) {
var A = this.sequelize.define('A', {})
, B = this.sequelize.define('B', {})
, C = this.sequelize.define('C', {})
, D = this.sequelize.define('D', {})
, E = this.sequelize.define('E', {})
, F = this.sequelize.define('F', {})
, G = this.sequelize.define('G', {
name: DataTypes.STRING
}) })
, H = this.sequelize.define('H', {
name: DataTypes.STRING
});
A.belongsTo(B);
B.belongsTo(C);
C.belongsTo(D);
D.belongsTo(E);
E.belongsTo(F);
F.belongsTo(G);
G.belongsTo(H);
var b, singles = [
B,
C,
D,
E,
F,
G,
H
];
this.sequelize.sync().done(function () {
async.auto({
a: function (callback) {
A.create({}).done(callback);
},
singleChain: function (callback) {
var previousInstance;
}) async.eachSeries(singles, function (model, callback) {
var values = {};
}) if (model.name === 'G') {
values.name = 'yolo';
}
model.create(values).done(function (err, instance) {
if (previousInstance) {
previousInstance["set"+model.name](instance).done(function () {
previousInstance = instance;
callback();
});
} else {
previousInstance = b = instance;
callback();
}
});
}, callback);
},
ab: ['a', 'singleChain', function (callback, results) {
results.a.setB(b).done(callback);
}]
}, function () {
}) A.find({
}) include: [
\ No newline at end of file {model: B, include: [
{model: C, include: [
{model: D, include: [
{model: E, include: [
{model: F, include: [
{model: G, where: {
name: 'yolo'
}, include: [
{model: H}
]}
]}
]}
]}
]}
]}
]
}).done(function (err, a) {
expect(err).not.to.be.ok;
expect(a.b.c.d.e.f.g.h).to.be.ok;
done();
});
});
});
});
});
});
\ No newline at end of file
...@@ -523,6 +523,118 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -523,6 +523,118 @@ describe(Support.getTestDialectTeaser("Include"), function () {
}) })
}) })
it('should support many levels of belongsTo (with a lower level having a where)', function (done) {
var A = this.sequelize.define('A', {})
, B = this.sequelize.define('B', {})
, C = this.sequelize.define('C', {})
, D = this.sequelize.define('D', {})
, E = this.sequelize.define('E', {})
, F = this.sequelize.define('F', {})
, G = this.sequelize.define('G', {
name: DataTypes.STRING
})
, H = this.sequelize.define('H', {
name: DataTypes.STRING
})
A.belongsTo(B)
B.belongsTo(C)
C.belongsTo(D)
D.belongsTo(E)
E.belongsTo(F)
F.belongsTo(G)
G.belongsTo(H)
var b, singles = [
B,
C,
D,
E,
F,
G,
H
]
this.sequelize.sync().done(function () {
async.auto({
as: function (callback) {
A.bulkCreate([
{},
{},
{},
{},
{},
{},
{},
{}
]).done(function () {
A.findAll().done(callback)
})
},
singleChain: function (callback) {
var previousInstance
async.eachSeries(singles, function (model, callback) {
var values = {};
if (model.name === 'G') {
values.name = 'yolo';
}
model.create(values).done(function (err, instance) {
if (previousInstance) {
previousInstance["set"+model.name](instance).done(function () {
previousInstance = instance
callback()
})
} else {
previousInstance = b = instance
callback()
}
})
}, callback)
},
abs: ['as', 'singleChain', function (callback, results) {
var chainer = new Sequelize.Utils.QueryChainer()
results.as.forEach(function (a) {
chainer.add(a.setB(b))
})
chainer.run().done(callback)
}]
}, function () {
A.findAll({
include: [
{model: B, include: [
{model: C, include: [
{model: D, include: [
{model: E, include: [
{model: F, include: [
{model: G, where: {
name: 'yolo'
}, include: [
{model: H}
]}
]}
]}
]}
]}
]}
]
}).done(function (err, as) {
expect(err).not.to.be.ok
expect(as.length).to.be.ok
as.forEach(function (a) {
expect(a.b.c.d.e.f.g.h).to.be.ok
})
done()
})
})
})
})
it('should support ordering with only belongsTo includes', function(done) { it('should support ordering with only belongsTo includes', function(done) {
var User = this.sequelize.define('User', {}) var User = this.sequelize.define('User', {})
, Item = this.sequelize.define('Item', {'test': DataTypes.STRING}) , Item = this.sequelize.define('Item', {'test': DataTypes.STRING})
...@@ -1679,5 +1791,37 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -1679,5 +1791,37 @@ describe(Support.getTestDialectTeaser("Include"), function () {
}) })
}) })
}) })
it("should still pull the main record(s) when an included model is not required and has where restrictions without matches", function () {
var self = this
, A = this.sequelize.define( 'A', {name: DataTypes.STRING(40)} )
, B = this.sequelize.define( 'B', {name: DataTypes.STRING(40)} );
A.hasMany(B);
B.hasMany(A);
return this.sequelize
.sync({force: true})
.then(function () {
return A.create({
name: 'Foobar'
});
})
.then(function () {
return A.findAll({
where: {name: 'Foobar'},
include: [
{model: B, where: {name: 'idontexist'}, required: false}
]
});
})
.then(function (as) {
expect(as.length).to.equal(1);
expect(as[0].get('bs')).deep.equal([]);
});
});
}) })
}) })
\ No newline at end of file
...@@ -474,7 +474,7 @@ if (Support.dialectIsMySQL()) { ...@@ -474,7 +474,7 @@ if (Support.dialectIsMySQL()) {
addIndexQuery: [ addIndexQuery: [
{ {
arguments: ['User', ['username', 'isAdmin']], arguments: ['User', ['username', 'isAdmin']],
expectation: 'CREATE INDEX user_username_is_admin ON User (`username`, `isAdmin`)' expectation: 'CREATE INDEX user_username_is_admin ON `User` (`username`, `isAdmin`)'
}, { }, {
arguments: [ arguments: [
'User', [ 'User', [
...@@ -482,17 +482,17 @@ if (Support.dialectIsMySQL()) { ...@@ -482,17 +482,17 @@ if (Support.dialectIsMySQL()) {
'isAdmin' 'isAdmin'
] ]
], ],
expectation: "CREATE INDEX user_username_is_admin ON User (`username`(10) ASC, `isAdmin`)" expectation: "CREATE INDEX user_username_is_admin ON `User` (`username`(10) ASC, `isAdmin`)"
}, { }, {
arguments: [ arguments: [
'User', ['username', 'isAdmin'], { parser: 'foo', indicesType: 'FULLTEXT', indexName: 'bar'} 'User', ['username', 'isAdmin'], { parser: 'foo', indicesType: 'FULLTEXT', indexName: 'bar'}
], ],
expectation: "CREATE FULLTEXT INDEX bar ON User (`username`, `isAdmin`) WITH PARSER foo" expectation: "CREATE FULLTEXT INDEX bar ON `User` (`username`, `isAdmin`) WITH PARSER foo"
}, { }, {
arguments: [ arguments: [
'User', ['username', 'isAdmin'], { indicesType: 'UNIQUE'} 'User', ['username', 'isAdmin'], { indicesType: 'UNIQUE'}
], ],
expectation: "CREATE UNIQUE INDEX user_username_is_admin ON User (`username`, `isAdmin`)" expectation: "CREATE UNIQUE INDEX user_username_is_admin ON `User` (`username`, `isAdmin`)"
} }
], ],
...@@ -509,10 +509,10 @@ if (Support.dialectIsMySQL()) { ...@@ -509,10 +509,10 @@ if (Support.dialectIsMySQL()) {
removeIndexQuery: [ removeIndexQuery: [
{ {
arguments: ['User', 'user_foo_bar'], arguments: ['User', 'user_foo_bar'],
expectation: "DROP INDEX user_foo_bar ON User" expectation: "DROP INDEX user_foo_bar ON `User`"
}, { }, {
arguments: ['User', ['foo', 'bar']], arguments: ['User', ['foo', 'bar']],
expectation: "DROP INDEX user_foo_bar ON User" expectation: "DROP INDEX user_foo_bar ON `User`"
} }
], ],
......
...@@ -260,7 +260,7 @@ if (dialect.match(/^postgres/)) { ...@@ -260,7 +260,7 @@ if (dialect.match(/^postgres/)) {
.create({ username: 'user', email: ['foo@bar.com'], settings: { created: { test: '"value"' }}}) .create({ username: 'user', email: ['foo@bar.com'], settings: { created: { test: '"value"' }}})
.success(function(newUser) { .success(function(newUser) {
// Check to see if the default value for an hstore field works // Check to see if the default value for an hstore field works
expect(newUser.document).to.deep.equal({default: 'value'}) expect(newUser.document).to.deep.equal({ default: 'value' })
expect(newUser.settings).to.deep.equal({ created: { test: '"value"' }}) expect(newUser.settings).to.deep.equal({ created: { test: '"value"' }})
// Check to see if updating an hstore field works // Check to see if updating an hstore field works
...@@ -295,6 +295,22 @@ if (dialect.match(/^postgres/)) { ...@@ -295,6 +295,22 @@ if (dialect.match(/^postgres/)) {
.error(console.log) .error(console.log)
}) })
it("should update hstore correctly and return the affected rows", function(done) {
var self = this
this.User
.create({ username: 'user', email: ['foo@bar.com'], settings: { created: { test: '"value"' }}})
.success(function(oldUser) {
// Update the user and check that the returned object's fields have been parsed by the hstore library
self.User.update({settings: {should: 'update', to: 'this', first: 'place'}}, oldUser.identifiers, { returning: true }).spread(function(count, users) {
expect(count).to.equal(1);
expect(users[0].settings).to.deep.equal({should: 'update', to: 'this', first: 'place'})
done()
})
})
.error(console.log)
})
it("should read hstore correctly", function(done) { it("should read hstore correctly", function(done) {
var self = this var self = this
var data = { username: 'user', email: ['foo@bar.com'], settings: { created: { test: '"value"' }}} var data = { username: 'user', email: ['foo@bar.com'], settings: { created: { test: '"value"' }}}
......
...@@ -454,108 +454,111 @@ if (dialect.match(/^postgres/)) { ...@@ -454,108 +454,111 @@ if (dialect.match(/^postgres/)) {
insertQuery: [ insertQuery: [
{ {
arguments: ['myTable', {}], arguments: ['myTable', {}],
expectation: "INSERT INTO \"myTable\" DEFAULT VALUES RETURNING *;" expectation: "INSERT INTO \"myTable\" DEFAULT VALUES;"
}, },
{ {
arguments: ['myTable', {name: 'foo'}], arguments: ['myTable', {name: 'foo'}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo');"
}, {
arguments: ['myTable', {name: 'foo'}, {}, { returning: true }],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;",
}, { }, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}], arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;');"
}, { }, {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}], arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00');"
}, { }, {
arguments: ['myTable', {data: new Buffer('Sequelize') }], arguments: ['myTable', {data: new Buffer('Sequelize') }],
expectation: "INSERT INTO \"myTable\" (\"data\") VALUES (E'\\\\x53657175656c697a65') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"data\") VALUES (E'\\\\x53657175656c697a65');"
}, { }, {
arguments: ['myTable', {name: 'foo', numbers: new Uint8Array([1,2,3])}], arguments: ['myTable', {name: 'foo', numbers: new Uint8Array([1,2,3])}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"numbers\") VALUES ('foo',ARRAY[1,2,3]) RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"numbers\") VALUES ('foo',ARRAY[1,2,3]);"
}, { }, {
arguments: ['myTable', {name: 'foo', foo: 1}], arguments: ['myTable', {name: 'foo', foo: 1}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1) RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1);"
}, { }, {
arguments: ['myTable', {name: 'foo', nullValue: null}], arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL) RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL);"
}, { }, {
arguments: ['myTable', {name: 'foo', nullValue: null}], arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL) RETURNING *;", expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL);",
context: {options: {omitNull: false}} context: {options: {omitNull: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', nullValue: null}], arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;", expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo');",
context: {options: {omitNull: true}} context: {options: {omitNull: true}}
}, { }, {
arguments: ['myTable', {name: 'foo', nullValue: undefined}], arguments: ['myTable', {name: 'foo', nullValue: undefined}],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo') RETURNING *;", expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo');",
context: {options: {omitNull: true}} context: {options: {omitNull: true}}
}, { }, {
arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: 'foo'}], arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: 'foo'}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo') RETURNING *;" expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo');"
}, { }, {
arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: JSON.stringify({info: 'Look ma a " quote'})}], arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: JSON.stringify({info: 'Look ma a " quote'})}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('{\"info\":\"Look ma a \\\" quote\"}') RETURNING *;" expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('{\"info\":\"Look ma a \\\" quote\"}');"
}, { }, {
arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: "foo';DROP TABLE mySchema.myTable;"}], arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: "foo';DROP TABLE mySchema.myTable;"}],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'';DROP TABLE mySchema.myTable;') RETURNING *;" expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'';DROP TABLE mySchema.myTable;');"
}, { }, {
arguments: ['myTable', function (sequelize) { arguments: ['myTable', function (sequelize) {
return { return {
foo: sequelize.fn('NOW') foo: sequelize.fn('NOW')
} }
}], }],
expectation: "INSERT INTO \"myTable\" (\"foo\") VALUES (NOW()) RETURNING *;", expectation: "INSERT INTO \"myTable\" (\"foo\") VALUES (NOW());",
needsSequelize: true needsSequelize: true
}, },
// Variants when quoteIdentifiers is false // Variants when quoteIdentifiers is false
{ {
arguments: ['myTable', {name: 'foo'}], arguments: ['myTable', {name: 'foo'}],
expectation: "INSERT INTO myTable (name) VALUES ('foo') RETURNING *;", expectation: "INSERT INTO myTable (name) VALUES ('foo');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}], arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}],
expectation: "INSERT INTO myTable (name) VALUES ('foo'';DROP TABLE myTable;') RETURNING *;", expectation: "INSERT INTO myTable (name) VALUES ('foo'';DROP TABLE myTable;');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}], arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}],
expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00') RETURNING *;", expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', numbers: new Uint8Array([1,2,3])}], arguments: ['myTable', {name: 'foo', numbers: new Uint8Array([1,2,3])}],
expectation: "INSERT INTO myTable (name,numbers) VALUES ('foo',ARRAY[1,2,3]) RETURNING *;", expectation: "INSERT INTO myTable (name,numbers) VALUES ('foo',ARRAY[1,2,3]);",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', foo: 1}], arguments: ['myTable', {name: 'foo', foo: 1}],
expectation: "INSERT INTO myTable (name,foo) VALUES ('foo',1) RETURNING *;", expectation: "INSERT INTO myTable (name,foo) VALUES ('foo',1);",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', nullValue: null}], arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL) RETURNING *;", expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL);",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', nullValue: null}], arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL) RETURNING *;", expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL);",
context: {options: {omitNull: false, quoteIdentifiers: false}} context: {options: {omitNull: false, quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', nullValue: null}], arguments: ['myTable', {name: 'foo', nullValue: null}],
expectation: "INSERT INTO myTable (name) VALUES ('foo') RETURNING *;", expectation: "INSERT INTO myTable (name) VALUES ('foo');",
context: {options: {omitNull: true, quoteIdentifiers: false}} context: {options: {omitNull: true, quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', nullValue: undefined}], arguments: ['myTable', {name: 'foo', nullValue: undefined}],
expectation: "INSERT INTO myTable (name) VALUES ('foo') RETURNING *;", expectation: "INSERT INTO myTable (name) VALUES ('foo');",
context: {options: {omitNull: true, quoteIdentifiers: false}} context: {options: {omitNull: true, quoteIdentifiers: false}}
}, { }, {
arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: 'foo'}], arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: 'foo'}],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo') RETURNING *;", expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: JSON.stringify({info: 'Look ma a " quote'})}], arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: JSON.stringify({info: 'Look ma a " quote'})}],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('{\"info\":\"Look ma a \\\" quote\"}') RETURNING *;", expectation: "INSERT INTO mySchema.myTable (name) VALUES ('{\"info\":\"Look ma a \\\" quote\"}');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: "foo';DROP TABLE mySchema.myTable;"}], arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: "foo';DROP TABLE mySchema.myTable;"}],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'';DROP TABLE mySchema.myTable;') RETURNING *;", expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'';DROP TABLE mySchema.myTable;');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
} }
...@@ -564,86 +567,89 @@ if (dialect.match(/^postgres/)) { ...@@ -564,86 +567,89 @@ if (dialect.match(/^postgres/)) {
bulkInsertQuery: [ bulkInsertQuery: [
{ {
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]], arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar');"
}, {
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}], { returning: true }],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING *;",
}, { }, {
arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]], arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;'),('bar') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\") VALUES ('foo'';DROP TABLE myTable;'),('bar');"
}, { }, {
arguments: ['myTable', [{name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {name: 'bar', birthday: moment("2012-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}]], arguments: ['myTable', [{name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {name: 'bar', birthday: moment("2012-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00') RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"birthday\") VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00');"
}, { }, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]], arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1),('bar',2) RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"foo\") VALUES ('foo',1),('bar',2);"
}, { }, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]], arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;" expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL);"
}, { }, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]], arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;", expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL);",
context: {options: {omitNull: false}} context: {options: {omitNull: false}}
}, { }, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]], arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;", expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL);",
context: {options: {omitNull: true}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not context: {options: {omitNull: true}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, { }, {
arguments: ['myTable', [{name: 'foo', nullValue: undefined}, {name: 'bar', nullValue: undefined}]], arguments: ['myTable', [{name: 'foo', nullValue: undefined}, {name: 'bar', nullValue: undefined}]],
expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL) RETURNING *;", expectation: "INSERT INTO \"myTable\" (\"name\",\"nullValue\") VALUES ('foo',NULL),('bar',NULL);",
context: {options: {omitNull: true}} // Note: As above context: {options: {omitNull: true}} // Note: As above
}, { }, {
arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: 'foo'}, {name: 'bar'}]], arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'),('bar') RETURNING *;" expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'),('bar');"
}, { }, {
arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: JSON.stringify({info: 'Look ma a " quote'})}, {name: JSON.stringify({info: 'Look ma another " quote'})}]], arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: JSON.stringify({info: 'Look ma a " quote'})}, {name: JSON.stringify({info: 'Look ma another " quote'})}]],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('{\"info\":\"Look ma a \\\" quote\"}'),('{\"info\":\"Look ma another \\\" quote\"}') RETURNING *;" expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('{\"info\":\"Look ma a \\\" quote\"}'),('{\"info\":\"Look ma another \\\" quote\"}');"
}, { }, {
arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'bar'}]], arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'';DROP TABLE mySchema.myTable;'),('bar') RETURNING *;" expectation: "INSERT INTO \"mySchema\".\"myTable\" (\"name\") VALUES ('foo'';DROP TABLE mySchema.myTable;'),('bar');"
}, },
// Variants when quoteIdentifiers is false // Variants when quoteIdentifiers is false
{ {
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]], arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO myTable (name) VALUES ('foo'),('bar') RETURNING *;", expectation: "INSERT INTO myTable (name) VALUES ('foo'),('bar');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]], arguments: ['myTable', [{name: "foo';DROP TABLE myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO myTable (name) VALUES ('foo'';DROP TABLE myTable;'),('bar') RETURNING *;", expectation: "INSERT INTO myTable (name) VALUES ('foo'';DROP TABLE myTable;'),('bar');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', [{name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {name: 'bar', birthday: moment("2012-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}]], arguments: ['myTable', [{name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {name: 'bar', birthday: moment("2012-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}]],
expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00') RETURNING *;", expectation: "INSERT INTO myTable (name,birthday) VALUES ('foo','2011-03-27 10:01:55.000 +00:00'),('bar','2012-03-27 10:01:55.000 +00:00');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]], arguments: ['myTable', [{name: 'foo', foo: 1}, {name: 'bar', foo: 2}]],
expectation: "INSERT INTO myTable (name,foo) VALUES ('foo',1),('bar',2) RETURNING *;", expectation: "INSERT INTO myTable (name,foo) VALUES ('foo',1),('bar',2);",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]], arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;", expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL);",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]], arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;", expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL);",
context: {options: {quoteIdentifiers: false, omitNull: false}}, context: {options: {quoteIdentifiers: false, omitNull: false}},
}, { }, {
arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]], arguments: ['myTable', [{name: 'foo', nullValue: null}, {name: 'bar', nullValue: null}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;", expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL);",
context: {options: {omitNull: true, quoteIdentifiers: false}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not context: {options: {omitNull: true, quoteIdentifiers: false}} // Note: We don't honour this because it makes little sense when some rows may have nulls and others not
}, { }, {
arguments: ['myTable', [{name: 'foo', nullValue: undefined}, {name: 'bar', nullValue: undefined}]], arguments: ['myTable', [{name: 'foo', nullValue: undefined}, {name: 'bar', nullValue: undefined}]],
expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL) RETURNING *;", expectation: "INSERT INTO myTable (name,nullValue) VALUES ('foo',NULL),('bar',NULL);",
context: {options: {omitNull: true, quoteIdentifiers: false}} // Note: As above context: {options: {omitNull: true, quoteIdentifiers: false}} // Note: As above
}, { }, {
arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: 'foo'}, {name: 'bar'}]], arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: 'foo'}, {name: 'bar'}]],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'),('bar') RETURNING *;", expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'),('bar');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: JSON.stringify({info: 'Look ma a " quote'})}, {name: JSON.stringify({info: 'Look ma another " quote'})}]], arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: JSON.stringify({info: 'Look ma a " quote'})}, {name: JSON.stringify({info: 'Look ma another " quote'})}]],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('{\"info\":\"Look ma a \\\" quote\"}'),('{\"info\":\"Look ma another \\\" quote\"}') RETURNING *;", expectation: "INSERT INTO mySchema.myTable (name) VALUES ('{\"info\":\"Look ma a \\\" quote\"}'),('{\"info\":\"Look ma another \\\" quote\"}');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'bar'}]], arguments: [{schema: 'mySchema', tableName: 'myTable'}, [{name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'bar'}]],
expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'';DROP TABLE mySchema.myTable;'),('bar') RETURNING *;", expectation: "INSERT INTO mySchema.myTable (name) VALUES ('foo'';DROP TABLE mySchema.myTable;'),('bar');",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
} }
], ],
...@@ -651,47 +657,50 @@ if (dialect.match(/^postgres/)) { ...@@ -651,47 +657,50 @@ if (dialect.match(/^postgres/)) {
updateQuery: [ updateQuery: [
{ {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}], arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}],
expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *" expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2"
}, { }, {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, 2], arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, 2],
expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *" expectation: "UPDATE \"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2"
}, { }, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}], arguments: ['myTable', {bar: 2}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *" expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo'"
}, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}, { returning: true }],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *",
}, { }, {
arguments: ['myTable', {numbers: new Uint8Array([1,2,3])}, {name: 'foo'}], arguments: ['myTable', {numbers: new Uint8Array([1,2,3])}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"numbers\"=ARRAY[1,2,3] WHERE \"name\"='foo' RETURNING *" expectation: "UPDATE \"myTable\" SET \"numbers\"=ARRAY[1,2,3] WHERE \"name\"='foo'"
}, { }, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}], arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"name\"='foo'';DROP TABLE myTable;' WHERE \"name\"='foo' RETURNING *" expectation: "UPDATE \"myTable\" SET \"name\"='foo'';DROP TABLE myTable;' WHERE \"name\"='foo'"
}, { }, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}], arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2,\"nullValue\"=NULL WHERE \"name\"='foo' RETURNING *" expectation: "UPDATE \"myTable\" SET \"bar\"=2,\"nullValue\"=NULL WHERE \"name\"='foo'"
}, { }, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}], arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2,\"nullValue\"=NULL WHERE \"name\"='foo' RETURNING *", expectation: "UPDATE \"myTable\" SET \"bar\"=2,\"nullValue\"=NULL WHERE \"name\"='foo'",
context: {options: {omitNull: false}} context: {options: {omitNull: false}}
}, { }, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}], arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *", expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo'",
context: {options: {omitNull: true}} context: {options: {omitNull: true}}
}, { }, {
arguments: ['myTable', {bar: 2, nullValue: undefined}, {name: 'foo'}], arguments: ['myTable', {bar: 2, nullValue: undefined}, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo' RETURNING *", expectation: "UPDATE \"myTable\" SET \"bar\"=2 WHERE \"name\"='foo'",
context: {options: {omitNull: true}} context: {options: {omitNull: true}}
}, { }, {
arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}], arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}],
expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2 RETURNING *" expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo',\"birthday\"='2011-03-27 10:01:55.000 +00:00' WHERE \"id\"=2"
}, { }, {
arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}], arguments: [{tableName: 'myTable', schema: 'mySchema'}, {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}],
expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo'';DROP TABLE mySchema.myTable;' WHERE \"name\"='foo' RETURNING *" expectation: "UPDATE \"mySchema\".\"myTable\" SET \"name\"='foo'';DROP TABLE mySchema.myTable;' WHERE \"name\"='foo'"
}, { }, {
arguments: ['myTable', function (sequelize) { arguments: ['myTable', function (sequelize) {
return { return {
bar: sequelize.fn('NOW') bar: sequelize.fn('NOW')
} }
}, {name: 'foo'}], }, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=NOW() WHERE \"name\"='foo' RETURNING *", expectation: "UPDATE \"myTable\" SET \"bar\"=NOW() WHERE \"name\"='foo'",
needsSequelize: true needsSequelize: true
}, { }, {
arguments: ['myTable', function (sequelize) { arguments: ['myTable', function (sequelize) {
...@@ -699,54 +708,54 @@ if (dialect.match(/^postgres/)) { ...@@ -699,54 +708,54 @@ if (dialect.match(/^postgres/)) {
bar: sequelize.col('foo') bar: sequelize.col('foo')
} }
}, {name: 'foo'}], }, {name: 'foo'}],
expectation: "UPDATE \"myTable\" SET \"bar\"=\"foo\" WHERE \"name\"='foo' RETURNING *", expectation: "UPDATE \"myTable\" SET \"bar\"=\"foo\" WHERE \"name\"='foo'",
needsSequelize: true needsSequelize: true
}, },
// Variants when quoteIdentifiers is false // Variants when quoteIdentifiers is false
{ {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}], arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}],
expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *", expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, 2], arguments: ['myTable', {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, 2],
expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *", expectation: "UPDATE myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {bar: 2}, {name: 'foo'}], arguments: ['myTable', {bar: 2}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2 WHERE name='foo' RETURNING *", expectation: "UPDATE myTable SET bar=2 WHERE name='foo'",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {numbers: new Uint8Array([1,2,3])}, {name: 'foo'}], arguments: ['myTable', {numbers: new Uint8Array([1,2,3])}, {name: 'foo'}],
expectation: "UPDATE myTable SET numbers=ARRAY[1,2,3] WHERE name='foo' RETURNING *", expectation: "UPDATE myTable SET numbers=ARRAY[1,2,3] WHERE name='foo'",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}], arguments: ['myTable', {name: "foo';DROP TABLE myTable;"}, {name: 'foo'}],
expectation: "UPDATE myTable SET name='foo'';DROP TABLE myTable;' WHERE name='foo' RETURNING *", expectation: "UPDATE myTable SET name='foo'';DROP TABLE myTable;' WHERE name='foo'",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}], arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2,nullValue=NULL WHERE name='foo' RETURNING *", expectation: "UPDATE myTable SET bar=2,nullValue=NULL WHERE name='foo'",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}], arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2,nullValue=NULL WHERE name='foo' RETURNING *", expectation: "UPDATE myTable SET bar=2,nullValue=NULL WHERE name='foo'",
context: {options: {omitNull: false, quoteIdentifiers: false}}, context: {options: {omitNull: false, quoteIdentifiers: false}},
}, { }, {
arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}], arguments: ['myTable', {bar: 2, nullValue: null}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2 WHERE name='foo' RETURNING *", expectation: "UPDATE myTable SET bar=2 WHERE name='foo'",
context: {options: {omitNull: true, quoteIdentifiers: false}}, context: {options: {omitNull: true, quoteIdentifiers: false}},
}, { }, {
arguments: ['myTable', {bar: 2, nullValue: undefined}, {name: 'foo'}], arguments: ['myTable', {bar: 2, nullValue: undefined}, {name: 'foo'}],
expectation: "UPDATE myTable SET bar=2 WHERE name='foo' RETURNING *", expectation: "UPDATE myTable SET bar=2 WHERE name='foo'",
context: {options: {omitNull: true, quoteIdentifiers: false}}, context: {options: {omitNull: true, quoteIdentifiers: false}},
}, { }, {
arguments: [{schema: 'mySchema', tableName: 'myTable'}, {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}], arguments: [{schema: 'mySchema', tableName: 'myTable'}, {name: 'foo', birthday: moment("2011-03-27 10:01:55 +0000", "YYYY-MM-DD HH:mm:ss Z").toDate()}, {id: 2}],
expectation: "UPDATE mySchema.myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2 RETURNING *", expectation: "UPDATE mySchema.myTable SET name='foo',birthday='2011-03-27 10:01:55.000 +00:00' WHERE id=2",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
}, { }, {
arguments: [{schema: 'mySchema', tableName: 'myTable'}, {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}], arguments: [{schema: 'mySchema', tableName: 'myTable'}, {name: "foo';DROP TABLE mySchema.myTable;"}, {name: 'foo'}],
expectation: "UPDATE mySchema.myTable SET name='foo'';DROP TABLE mySchema.myTable;' WHERE name='foo' RETURNING *", expectation: "UPDATE mySchema.myTable SET name='foo'';DROP TABLE mySchema.myTable;' WHERE name='foo'",
context: {options: {quoteIdentifiers: false}} context: {options: {quoteIdentifiers: false}}
} }
], ],
......
...@@ -68,8 +68,8 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () { ...@@ -68,8 +68,8 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () {
describe('indexes', function() { describe('indexes', function() {
beforeEach(function(done) { beforeEach(function(done) {
var self = this var self = this
this.queryInterface.dropTable('Users').success(function() { this.queryInterface.dropTable('Group').success(function() {
self.queryInterface.createTable('Users', { self.queryInterface.createTable('Group', {
username: DataTypes.STRING, username: DataTypes.STRING,
isAdmin: DataTypes.BOOLEAN, isAdmin: DataTypes.BOOLEAN,
from: DataTypes.STRING from: DataTypes.STRING
...@@ -82,19 +82,19 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () { ...@@ -82,19 +82,19 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () {
it('adds, reads and removes an index to the table', function(done) { it('adds, reads and removes an index to the table', function(done) {
var self = this var self = this
this.queryInterface.addIndex('Users', ['username', 'isAdmin']).complete(function(err) { this.queryInterface.addIndex('Group', ['username', 'isAdmin']).complete(function(err) {
expect(err).to.be.null expect(err).to.be.null
self.queryInterface.showIndex('Users').complete(function(err, indexes) { self.queryInterface.showIndex('Group').complete(function(err, indexes) {
expect(err).to.be.null expect(err).to.be.null
var indexColumns = _.uniq(indexes.map(function(index) { return index.name })) var indexColumns = _.uniq(indexes.map(function(index) { return index.name }))
expect(indexColumns).to.include('users_username_is_admin') expect(indexColumns).to.include('group_username_is_admin')
self.queryInterface.removeIndex('Users', ['username', 'isAdmin']).complete(function(err) { self.queryInterface.removeIndex('Group', ['username', 'isAdmin']).complete(function(err) {
expect(err).to.be.null expect(err).to.be.null
self.queryInterface.showIndex('Users').complete(function(err, indexes) { self.queryInterface.showIndex('Group').complete(function(err, indexes) {
expect(err).to.be.null expect(err).to.be.null
indexColumns = _.uniq(indexes.map(function(index) { return index.name })) indexColumns = _.uniq(indexes.map(function(index) { return index.name }))
...@@ -107,14 +107,10 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () { ...@@ -107,14 +107,10 @@ describe(Support.getTestDialectTeaser("QueryInterface"), function () {
}) })
}) })
it('does not fail on reserved keywords', function (done) { it('does not fail on reserved keywords', function () {
this.queryInterface.addIndex('Users', ['from']).done(function(err) { return this.queryInterface.addIndex('Group', ['from']);
expect(err).to.be.null });;
});
done()
})
})
})
describe('describeTable', function() { describe('describeTable', function() {
it('reads the metadata of the table', function(done) { it('reads the metadata of the table', function(done) {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!