Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Bindings are not in the correct order when joining a subquery in a delete operation #6277

@glejune

Description

@glejune

When joining a subquery in a delete operation, the bindings for the "where" come before the bindings for the "join", causing the resulting query not to be what is expected. This could be dangerous because it could cause the wrong data to be deleted.

Knex version: 3.1.0

Here is the sample code

import Knex from "knex"

const knex = Knex({ client: 'mysql' })

async function main() {
    const subQuery = knex.from('tableA').where('fieldA', 'valueForFieldA').as('subQuery')
    const knexQuery = knex.delete()
        .from(knex.raw('tableB'))
        .innerJoin(subQuery, "subQuery.id", "=", "tableB.relatedId")
        .where('tableA.fieldB', 'valueForFieldB')
    console.log(knexQuery.toSQL())

}

main()
    .then(() => knex.destroy())
    .catch(err => {
        console.error(err);
        return knex.destroy();
    });

And the resulting query generated (we would expect valueForFieldA to come first in the bindings):

{
  method: 'del',
  options: {},
  timeout: false,
  cancelOnTimeout: false,
  bindings: [ 'valueForFieldB', 'valueForFieldA' ],
  __knexQueryUid: 'IwfHyZEac_9o2mnqZFVJQ',
  sql: 'delete tableB from tableB inner join (select * from `tableA` where `fieldA` = ?) as `subQuery` on `subQuery`.`id` = `tableB`.`relatedId` where `tableA`.`fieldB` = ?'
}

We can see in the code that the this.where() call is before the this.join() call, this explains why the bindings for the "where" come first in the resulting query.

I think this is related to #873

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions