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

Commit 930cb9a5 by Jan Aagaard Meier

Fixed a bug where plain objects in combination with sequelize.where were not con…

…verted properly to SQL. Closes #2077
1 parent cde11b7f
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
- [BUG] Copy the options object in association getters. [#2311](https://github.com/sequelize/sequelize/issues/2311) - [BUG] Copy the options object in association getters. [#2311](https://github.com/sequelize/sequelize/issues/2311)
- [BUG] `Model#destroy()` now supports `field`, this also fixes an issue with `N:M#removeAssociation` and `field` - [BUG] `Model#destroy()` now supports `field`, this also fixes an issue with `N:M#removeAssociation` and `field`
- [BUG] Customized error message can now be set for unique constraint that was created manually (not with sync, but e.g. with migrations) or that has fields with underscore naming. This was problem at least with postgres before. - [BUG] Customized error message can now be set for unique constraint that was created manually (not with sync, but e.g. with migrations) or that has fields with underscore naming. This was problem at least with postgres before.
- [BUG] Fixed a bug where plain objects like `{ in: [...] }` were not properly converted to SQL when combined with a sequelize method (`fn`, `where` etc.). Closes [#2077](https://github.com/sequelize/sequelize/issues/2077)
- [INTERNALS] Update `inflection` dependency to v1.5.2 - [INTERNALS] Update `inflection` dependency to v1.5.2
#### Backwards compatability changes #### Backwards compatability changes
......
...@@ -1367,17 +1367,8 @@ module.exports = (function() { ...@@ -1367,17 +1367,8 @@ module.exports = (function() {
value = this.getWhereConditions(value, tableName, factory, options, prepend); value = this.getWhereConditions(value, tableName, factory, options, prepend);
result = (value === 'NULL') ? key + ' IS NULL' : [key, value].join(smth.comparator); result = (value === 'NULL') ? key + ' IS NULL' : [key, value].join(smth.comparator);
} else if (_.isObject(value)) { } else if (_.isPlainObject(value)) {
if (value.join) { result = this.plainObjectToWhere(value, key, key, factory).join(' AND ');
//using as sentinel for join column => value
result = [key, value.join].join('=');
} else {
for (logic in value) {
_result.push([key, this.escape(value[logic])].join(' ' + Utils.getWhereLogic(logic, value[logic]) + ' '));
}
result = _result.join(' AND ');
}
} else { } else {
if (typeof value === 'boolean') { if (typeof value === 'boolean') {
value = this.booleanValue(value); value = this.booleanValue(value);
...@@ -1664,29 +1655,8 @@ module.exports = (function() { ...@@ -1664,29 +1655,8 @@ module.exports = (function() {
if (Array.isArray(value)) { if (Array.isArray(value)) {
result.push(this.arrayValue(value, key, _key, dao, 'IN')); result.push(this.arrayValue(value, key, _key, dao, 'IN'));
} else if ((value) && (typeof value === 'object') && !(value instanceof Date) && !Buffer.isBuffer(value)) { } else if (value && Utils._.isPlainObject(value)) {
if (!!value.join) { result = result.concat(this.plainObjectToWhere(value, key, _key, dao));
//using as sentinel for join column => value
_value = this.quoteIdentifiers(value.join);
result.push([_key, _value].join('='));
} else {
for (var logic in value) {
var logicResult = Utils.getWhereLogic(logic, hash[key][logic]);
if (logicResult === 'IN' || logicResult === 'NOT IN') {
var values = Array.isArray(value[logic]) ? value[logic] : [value[logic]];
result.push(this.arrayValue(values, key, _key, dao, logicResult));
}
else if (logicResult === 'BETWEEN' || logicResult === 'NOT BETWEEN') {
_value = this.escape(value[logic][0]);
var _value2 = this.escape(value[logic][1]);
result.push(' (' + _key + ' ' + logicResult + ' ' + _value + ' AND ' + _value2 + ') ');
} else {
_value = this.escape(value[logic]);
result.push([_key, _value].join(' ' + logicResult + ' '));
}
}
}
} else { } else {
if (typeof value === 'boolean') { if (typeof value === 'boolean') {
_value = this.booleanValue(value); _value = this.booleanValue(value);
...@@ -1701,6 +1671,36 @@ module.exports = (function() { ...@@ -1701,6 +1671,36 @@ module.exports = (function() {
return result.join(' AND '); return result.join(' AND ');
}, },
plainObjectToWhere: function (value, key, _key, dao) {
var _value
, result = [];
if (!!value.join) {
//using as sentinel for join column => value
_value = this.quoteIdentifiers(value.join);
result.push([_key, _value].join('='));
} else {
for (var logic in value) {
var logicResult = Utils.getWhereLogic(logic, value[logic]);
if (logicResult === 'IN' || logicResult === 'NOT IN') {
var values = Array.isArray(value[logic]) ? value[logic] : [value[logic]];
result.push(this.arrayValue(values, key, _key, dao, logicResult));
}
else if (logicResult === 'BETWEEN' || logicResult === 'NOT BETWEEN') {
_value = this.escape(value[logic][0]);
var _value2 = this.escape(value[logic][1]);
result.push(' (' + _key + ' ' + logicResult + ' ' + _value + ' AND ' + _value2 + ') ');
} else {
_value = this.escape(value[logic]);
result.push([_key, _value].join(' ' + logicResult + ' '));
}
}
}
return result;
},
booleanValue: function(value) { booleanValue: function(value) {
return value; return value;
} }
......
...@@ -279,6 +279,19 @@ if (Support.dialectIsMySQL()) { ...@@ -279,6 +279,19 @@ if (Support.dialectIsMySQL()) {
context: QueryGenerator, context: QueryGenerator,
needsSequelize: true needsSequelize: true
}, { }, {
title: 'Combination of sequelize.fn, sequelize.col and { in: ... }',
arguments: ['myTable', function (sequelize) {
return {
where: sequelize.and(
{ archived: null},
sequelize.where(sequelize.fn('COALESCE', sequelize.col('place_type_codename'), sequelize.col('announcement_type_codename')), { in: ['Lost', 'Found'] })
)
};
}],
expectation: "SELECT * FROM `myTable` WHERE (`myTable`.`archived` IS NULL AND COALESCE(`place_type_codename`, `announcement_type_codename`) IN ('Lost','Found'));",
context: QueryGenerator,
needsSequelize: true
}, {
arguments: ['myTable', {limit: 10}], arguments: ['myTable', {limit: 10}],
expectation: "SELECT * FROM `myTable` LIMIT 10;", expectation: "SELECT * FROM `myTable` LIMIT 10;",
context: QueryGenerator context: QueryGenerator
......
...@@ -308,6 +308,19 @@ if (dialect.match(/^postgres/)) { ...@@ -308,6 +308,19 @@ if (dialect.match(/^postgres/)) {
context: QueryGenerator, context: QueryGenerator,
needsSequelize: true needsSequelize: true
}, { }, {
title: 'Combination of sequelize.fn, sequelize.col and { in: ... }',
arguments: ['myTable', function (sequelize) {
return {
where: sequelize.and(
{ archived: null},
sequelize.where(sequelize.fn('COALESCE', sequelize.col('place_type_codename'), sequelize.col('announcement_type_codename')), { in: ['Lost', 'Found'] })
)
};
}],
expectation: 'SELECT * FROM "myTable" WHERE ("myTable"."archived" IS NULL AND COALESCE("place_type_codename", "announcement_type_codename") IN (\'Lost\',\'Found\'));',
context: QueryGenerator,
needsSequelize: true
}, {
title: 'single string argument is not quoted', title: 'single string argument is not quoted',
arguments: ['myTable', {group: "name"}], arguments: ['myTable', {group: "name"}],
expectation: "SELECT * FROM \"myTable\" GROUP BY name;" expectation: "SELECT * FROM \"myTable\" GROUP BY name;"
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!