sequelize: Wrong SQL generated when two level associations are required with limit.

Assocations:

User hasMany Jobs
Job hasMany Shares
Share hasOne Block

Code in User Model

let jobs = await this.getJobs({
  attributes: ['id'],
  include: [{
    attributes: ['id'],
    association: 'shares',
    required: true,
    include: [{
      required: true,
      association: 'block'
    }]
  }],
  offset: 0,
  limit: 10
})

SQL Generated

 SELECT `Job`.*, 
       `shares`.`id` AS `shares.id` 
FROM   (SELECT `Job`.`id`, 
               `shares->block`.`id`                  AS `shares.block.id`, 
               `shares->block`.`shareId`             AS `shares.block.shareId`, 
               `shares->block`.`rewardTypeId`        AS 
               `shares.block.rewardTypeId`, 
               `shares->block`.`height`              AS `shares.block.height`, 
               `shares->block`.`hash`                AS `shares.block.hash`, 
               `shares->block`.`confirmationCount`   AS 
                      `shares.block.confirmationCount`, 
               `shares->block`.`rewardAmount`        AS 
               `shares.block.rewardAmount`, 
               `shares->block`.`difficulty`          AS 
               `shares.block.difficulty`, 
               `shares->block`.`createdAt`           AS `shares.block.createdAt` 
               , 
               `shares->block`.`settleStatus`        AS 
               `shares.block.settleStatus`, 
               `shares->block`.`settledAt`           AS `shares.block.settledAt` 
               , 
               `shares->block`.`status`              AS 
               `shares.block.status`, 
               `shares->block`.`expectedShareAmount` AS 
                      `shares.block.expectedShareAmount`, 
               `shares->block`.`totalShareAmount`    AS 
               `shares.block.totalShareAmount` 
        FROM   `Job` AS `Job` 
               INNER JOIN `Block` AS `shares->block` 
                       ON `shares`.`id` = `shares->block`.`shareId` 
        WHERE  `Job`.`userId` = 1
               AND (SELECT `jobId` 
                    FROM   `Share` AS `shares` 
                    WHERE  ( `shares`.`jobId` = `Job`.`id` ) 
                    LIMIT  1) IS NOT NULL 
        LIMIT  0, 10) AS `Job` 
       INNER JOIN `Share` AS `shares` 
               ON `Job`.`id` = `shares`.`jobId`; 

Result:

Unknown column 'shares.id' in 'on clause'

Reason:

Due to the limit, the join table statment misses the second level join in the subquery. The proper sql should be:

SELECT `Job`.*, 
       `shares`.`id` AS `shares.id` 
FROM   (SELECT `Job`.`id`, 
               `shares->block`.`id`                  AS `shares.block.id`, 
               `shares->block`.`shareId`             AS `shares.block.shareId`, 
               `shares->block`.`rewardTypeId`        AS 
               `shares.block.rewardTypeId`, 
               `shares->block`.`height`              AS `shares.block.height`, 
               `shares->block`.`hash`                AS `shares.block.hash`, 
               `shares->block`.`confirmationCount`   AS 
                      `shares.block.confirmationCount`, 
               `shares->block`.`rewardAmount`        AS 
               `shares.block.rewardAmount`, 
               `shares->block`.`difficulty`          AS 
               `shares.block.difficulty`, 
               `shares->block`.`createdAt`           AS `shares.block.createdAt` 
               , 
               `shares->block`.`settleStatus`        AS 
               `shares.block.settleStatus`, 
               `shares->block`.`settledAt`           AS `shares.block.settledAt` 
               , 
               `shares->block`.`status`              AS 
               `shares.block.status`, 
               `shares->block`.`expectedShareAmount` AS 
                      `shares.block.expectedShareAmount`, 
               `shares->block`.`totalShareAmount`    AS 
               `shares.block.totalShareAmount` 
        FROM   `Job` AS `Job` 
##### Missed this join
               INNER JOIN `Share` AS `shares` 
                       ON `Job`.`id` = `shares`.`jobId` 
#####
               INNER JOIN `Block` AS `shares->block` 
                       ON `shares`.`id` = `shares->block`.`shareId` 
        WHERE  `Job`.`userId` = 1
               AND (SELECT `jobId` 
                    FROM   `Share` AS `shares` 
                    WHERE  ( `shares`.`jobId` = `Job`.`id` ) 
                    LIMIT  1) IS NOT NULL 
        LIMIT  0, 10) AS `Job` 
       INNER JOIN `Share` AS `shares` 
               ON `Job`.`id` = `shares`.`jobId` 

or much simplier one:

SELECT `Job`.`id`, 
  `shares`.`id`                         AS `shares.id`, 
  `shares->block`.`id`                  AS `shares.block.id`, 
  `shares->block`.`shareId`             AS `shares.block.shareId`, 
  `shares->block`.`rewardTypeId`        AS `shares.block.rewardTypeId`, 
  `shares->block`.`height`              AS `shares.block.height`, 
  `shares->block`.`hash`                AS `shares.block.hash`, 
  `shares->block`.`confirmationCount`   AS `shares.block.confirmationCount`, 
  `shares->block`.`rewardAmount`        AS `shares.block.rewardAmount`, 
  `shares->block`.`difficulty`          AS `shares.block.difficulty`, 
  `shares->block`.`createdAt`           AS `shares.block.createdAt`, 
  `shares->block`.`settleStatus`        AS `shares.block.settleStatus`, 
  `shares->block`.`settledAt`           AS `shares.block.settledAt`, 
  `shares->block`.`status`              AS `shares.block.status`, 
  `shares->block`.`expectedShareAmount` AS `shares.block.expectedShareAmount`, 
  `shares->block`.`totalShareAmount`    AS `shares.block.totalShareAmount` 
FROM   `Job` AS `Job` 
  INNER JOIN `Share` AS `shares` 
    ON `Job`.`id` = `shares`.`jobId` 
  INNER JOIN `Block` AS `shares->block` 
    ON `shares`.`id` = `shares->block`.`shareId` 
WHERE  `Job`.`userId` = 1
LIMIT  0, 10

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 15 (1 by maintainers)

Most upvoted comments

I need this. Do not close. @shtse8