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

Commit f387f3c7 by Mick Hansen

Merge pull request #2496 from overlookmotel/table-name-in-quote

Fix for ambiguous column names in ORDER BY
2 parents 05426e62 ce64c7be
......@@ -4,6 +4,7 @@
#### Backwards compatability changes
- When eager-loading a many-to-many association, the attributes of the through table are now accessible through an attribute named after the through model rather than the through table name singularized. i.e. `Task.find({include: Worker})` where the table name for through model `TaskWorker` is `TableTaskWorkers` used to produce `{ Worker: { ..., TableTaskWorker: {...} } }`. It now produces `{ Worker: { ..., TaskWorker: {...} } }`. Does not affect models where table name is auto-defined by Sequelize, or where table name is model name pluralized.
- When using `Model#find()` with an `order` clause, the table name is prepended to the `ORDER BY` SQL. e.g. `ORDER BY Task.id` rather than `ORDER BY id`. The change is to avoid ambiguous column names where there are eager-loaded associations with the same column names. A side effect is that code like `Task.findAll( { include: [ User ], order: [ [ 'Users.id', 'ASC' ] ] } )` will now throw an error. This should be achieved with `Task.findAll( { include: [ User ], order: [ [ User, 'id', 'ASC' ] ] } )` instead.
# 2.0.0-rc2
- [FEATURE] Added to posibility of using a sequelize object as key in `sequelize.where`. Also added the option of specifying a comparator
......
......@@ -574,7 +574,7 @@ module.exports = (function() {
}
// add 1st string as quoted, 2nd as unquoted raw
var sql = (i > 0 ? this.quoteIdentifier(tableNames.join('.')) + '.' : '') + this.quote(obj[i], parent, force);
var sql = (i > 0 ? this.quoteIdentifier(tableNames.join('.')) + '.' : (Utils._.isString(obj[0]) ? this.quoteIdentifier(parent.name) + '.' : '')) + this.quote(obj[i], parent, force);
if (i < len - 1) {
sql += ' ' + obj[i + 1];
}
......
......@@ -389,7 +389,7 @@ describe(Support.getTestDialectTeaser("Include"), function () {
]}
],
order: [
['User.id', 'ASC']
['id', 'ASC']
]
}).done(function (err, users) {
expect(err).not.to.be.ok
......@@ -780,8 +780,8 @@ describe(Support.getTestDialectTeaser("Include"), function () {
{model: Tag}
],
order: [
['Product.id', 'ASC'],
['Tags.id', 'ASC']
['id', 'ASC'],
[Tag, 'id', 'ASC']
]
}).done(function (err, products) {
expect(err).not.to.be.ok
......@@ -1460,7 +1460,7 @@ describe(Support.getTestDialectTeaser("Include"), function () {
]}
],
order: [
['User.id', 'ASC']
['id', 'ASC']
]
}).done(function (err, users) {
expect(err).not.to.be.ok
......@@ -1709,7 +1709,7 @@ describe(Support.getTestDialectTeaser("Include"), function () {
],
limit: 6,
order: [
['Product.id', 'ASC']
['id', 'ASC']
]
}).done(function (err, products) {
expect(err).not.to.be.ok
......@@ -1739,7 +1739,7 @@ describe(Support.getTestDialectTeaser("Include"), function () {
],
limit: 10,
order: [
['Product.id', 'ASC']
['id', 'ASC']
]
}).done(function (err, products) {
expect(err).not.to.be.ok
......
......@@ -680,8 +680,8 @@ describe(Support.getTestDialectTeaser("Includes with schemas"), function () {
{model: Tag}
],
order: [
['Product.id', 'ASC'],
['Tags.id', 'ASC']
['id', 'ASC'],
[Tag, 'id', 'ASC']
]
}).done(function (err, products) {
expect(err).not.to.be.ok
......@@ -1316,7 +1316,7 @@ describe(Support.getTestDialectTeaser("Includes with schemas"), function () {
]}
],
order: [
['User.id', 'ASC']
['id', 'ASC']
]
}).done(function (err, users) {
expect(err).not.to.be.ok
......@@ -1401,7 +1401,7 @@ describe(Support.getTestDialectTeaser("Includes with schemas"), function () {
],
limit: 3,
order: [
[self.models.Product.name+'.id', 'ASC']
['id', 'ASC']
]
}).done(function (err, products) {
expect(err).not.to.be.ok
......@@ -1430,7 +1430,7 @@ describe(Support.getTestDialectTeaser("Includes with schemas"), function () {
],
limit: 6,
order: [
['Product.id', 'ASC']
['id', 'ASC']
]
}).done(function (err, products) {
expect(err).not.to.be.ok
......@@ -1460,7 +1460,7 @@ describe(Support.getTestDialectTeaser("Includes with schemas"), function () {
],
limit: 10,
order: [
['Product.id', 'ASC']
['id', 'ASC']
]
}).done(function (err, products) {
expect(err).not.to.be.ok
......
......@@ -163,9 +163,10 @@ if (Support.dialectIsMySQL()) {
expectation: "SELECT * FROM `myTable` ORDER BY `myTable`.`id`;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: [["id", 'DESC']]}],
expectation: "SELECT * FROM `myTable` ORDER BY `id` DESC;",
context: QueryGenerator
arguments: ['myTable', {order: [["id", 'DESC']]}, function(sequelize) {return sequelize.define('myTable', {});}],
expectation: "SELECT * FROM `myTable` AS `myTable` ORDER BY `myTable`.`id` DESC;",
context: QueryGenerator,
needsSequelize: true
}, {
title: 'raw arguments are neither quoted nor escaped',
arguments: ['myTable', {order: [[{raw: 'f1(f2(id))'}, 'DESC']]}],
......@@ -588,7 +589,8 @@ if (Support.dialectIsMySQL()) {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}};
if (test.needsSequelize) {
test.arguments[1] = test.arguments[1](this.sequelize);
if (_.isFunction(test.arguments[1])) test.arguments[1] = test.arguments[1](this.sequelize);
if (_.isFunction(test.arguments[2])) test.arguments[2] = test.arguments[2](this.sequelize);
}
QueryGenerator.options = context.options;
QueryGenerator._dialect = this.sequelize.dialect;
......
......@@ -249,9 +249,10 @@ if (dialect.match(/^postgres/)) {
expectation: 'SELECT * FROM "myTable" ORDER BY "myTable"."id";',
context: QueryGenerator
}, {
arguments: ['myTable', {order: [["id", 'DESC']]}],
expectation: 'SELECT * FROM "myTable" ORDER BY "id" DESC;',
context: QueryGenerator
arguments: ['myTable', {order: [["id", 'DESC']]}, function(sequelize) {return sequelize.define('myTable', {});}],
expectation: 'SELECT * FROM "myTable" AS "myTable" ORDER BY "myTable"."id" DESC;',
context: QueryGenerator,
needsSequelize: true
}, {
title: 'raw arguments are neither quoted nor escaped',
arguments: ['myTable', {order: [[{raw: 'f1(f2(id))'},'DESC']]}],
......@@ -984,7 +985,8 @@ if (dialect.match(/^postgres/)) {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}};
if (test.needsSequelize) {
test.arguments[1] = test.arguments[1](this.sequelize);
if (_.isFunction(test.arguments[1])) test.arguments[1] = test.arguments[1](this.sequelize);
if (_.isFunction(test.arguments[2])) test.arguments[2] = test.arguments[2](this.sequelize);
}
QueryGenerator.options = context.options;
QueryGenerator._dialect = this.sequelize.dialect;
......
......@@ -154,9 +154,10 @@ if (dialect === 'sqlite') {
expectation: "SELECT * FROM `myTable` ORDER BY `myTable`.`id`;",
context: QueryGenerator
}, {
arguments: ['myTable', {order: [["id", 'DESC']]}],
expectation: "SELECT * FROM `myTable` ORDER BY `id` DESC;",
context: QueryGenerator
arguments: ['myTable', {order: [["id", 'DESC']]}, function(sequelize) {return sequelize.define('myTable', {});}],
expectation: "SELECT * FROM `myTable` AS `myTable` ORDER BY `myTable`.`id` DESC;",
context: QueryGenerator,
needsSequelize: true
}, {
title: 'raw arguments are neither quoted nor escaped',
arguments: ['myTable', {order: [[{raw: 'f1(f2(id))'}, 'DESC']]}],
......@@ -536,7 +537,8 @@ if (dialect === 'sqlite') {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}};
if (test.needsSequelize) {
test.arguments[1] = test.arguments[1](this.sequelize);
if (_.isFunction(test.arguments[1])) test.arguments[1] = test.arguments[1](this.sequelize);
if (_.isFunction(test.arguments[2])) test.arguments[2] = test.arguments[2](this.sequelize);
}
QueryGenerator.options = context.options;
QueryGenerator._dialect = this.sequelize.dialect;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!