question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Nested include with limit and order on column with "field" value generates broken SQL

See original GitHub issue

What 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:closed
  • Created 6 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
keyiiscommented, Sep 8, 2019

+1

1reaction
maciejrybczonekcommented, Sep 8, 2019

+1

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found