Nested include with limit and order on column with "field" value generates broken SQL
See original GitHub issueWhat you are doing?
It is a minimal code snippet I could create that reproduces the bug. You could copy->paste->execute it, just set your DB credentials
'use strict'
const Sequelize = require('sequelize')
const dbConfig = {
type: 'mysql', user: 'root', password: 'root',
database: 'db', host: 'localhost'
}
;(async () => {
const sequelize = new Sequelize(
dbConfig.database, dbConfig.user, dbConfig.password, {
host: dbConfig.host,
dialect: dbConfig.type,
pool: {max: 100, min: 0, idle: 10000},
dialectOptions: {
charset: 'utf8_general_ci',
}
}
)
await sequelize.authenticate()
// I have removed the timestamps to simplify the generated SQL
const A = sequelize.define('A', {
id: {type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true},
bId: {type: Sequelize.INTEGER, field: 'b_id'} // <- defined with field. It is important part
}, {timestamps: false})
const B = sequelize.define('B', {
id: {type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true},
}, {timestamps: false})
const C = sequelize.define('C', {
id: {type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true},
bId: {type: Sequelize.INTEGER}
}, {timestamps: false})
A.belongsTo(B, {as: 'B', foreignKey: 'bId'})
B.hasMany(C, {as: 'Cs', foreignKey: 'bId'})
await sequelize.sync({force: true})
await A.create({
B: {
Cs: {
}
}
}, {
include: [{
model: B,
as: 'B',
include: [{
model: C,
as: 'Cs'
}]
}]
})
const result = await A.findAll({
order: [['bId', 'ASC']], // <- this parameter is the source of broken SQL
limit: 1, // <- required for broken SQL to be generated
include: [{
model: B,
as: 'B',
include: [{ // <- required nested include of 1-n relation
model: C,
as: 'Cs'
}]
}]
})
console.dir(result[0].toJSON(), {depth: null})
sequelize.close()
})()
What do you expect to happen?
.findAll
should be executed with no errors and in log should be (formatted):
{
id: 1,
bId: 1,
B: {
id: 1,
Cs: [{
id: 1,
bId: 1
}]
}
}
SQL should be
SELECT
`A`.*, `B`.`id` AS `B.id`,
`B->Cs`.`id` AS `B.Cs.id`,
`B->Cs`.`bId` AS `B.Cs.bId`
FROM (
SELECT
`A`.`id`, `A`.`b_id` AS `bId`
FROM
`As` AS `A`
ORDER BY
`A`.`b_id` ASC LIMIT 1
) AS `A`
LEFT OUTER JOIN
`Bs` AS `B`
ON
`A`.`bId` = `B`.`id`
LEFT OUTER JOIN
`Cs` AS `B->Cs`
ON
`B`.`id` = `B->Cs`.`bId`
ORDER BY `A`.`bId` ASC; -- <- this is the difference: "bId" instead of "b_id"
What is actually happening?
Error SequelizeDatabaseError: Unknown column 'A.b_id' in 'order clause'
is rising
This SQL is generated (formatted):
SELECT
`A`.*, `B`.`id` AS `B.id`,
`B->Cs`.`id` AS `B.Cs.id`,
`B->Cs`.`bId` AS `B.Cs.bId`
FROM (
SELECT
`A`.`id`, `A`.`b_id` AS `bId`
FROM
`As` AS `A`
ORDER BY
`A`.`b_id` ASC LIMIT 1
) AS `A`
LEFT OUTER JOIN
`Bs` AS `B`
ON
`A`.`bId` = `B`.`id`
LEFT OUTER JOIN
`Cs` AS `B->Cs`
ON
`B`.`id` = `B->Cs`.`bId`
ORDER BY `A`.`b_id` ASC; -- <- should be "bId", not "b_id"
The problem is definitely is about A
has the property bId
with field b_id
. And in SQL statement (in the last line) it is trying to use it’s field value b_id
, but because it’s property name is bId
it has been renamed in the inner query to bId
(sixth line) it ques an error
Dialect: mysql Database version: 5.7.17 Sequelize version: 4.8.2
Issue Analytics
- State:
- Created 6 years ago
- Comments:7 (3 by maintainers)
Top Results From Across the Web
Sequelize - Adding a limit to a query with an include, fails to ...
If I copy/paste the SQL Query generated by Sequelize and insert it directly into Workbench, it retrieves the proper amount of rows.
Read more >Writing Subqueries in SQL | Advanced SQL - Mode Analytics
This lesson of the SQL tutorial for data analysis covers using subqueries in SQL with aggregate functions, conditional logic, and joins.
Read more >Reference to RECURSIVE table column apparently ... - SQLite Forum
The following statement works as expected. WITH RECURSIVE cnt ( x , list , done , Pagelist ) AS ( VALUES ( 1...
Read more >Solve common issues with JSON in SQL Server
I want to produce complex JSON with several arrays on the same level. FOR JSON PATH can create nested objects using paths, and...
Read more >Chapter 4. Query Performance Optimization - O'Reilly
The most important part of the MySQL query optimizer is the join optimizer, which decides the best order of execution for multitable queries....
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
+1
+1