-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Open
Labels
Description
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