Knex version: 2.5.1 and later
Database + version: Postgres 15.5
OS: Mac & Alpine linux
Bug
db // Knex instance
// Basic query that includes a join with literal join value
const qb = db('table_a').innerJoin('table_b', join => {
join.onVal('table_b.id', '123')
})
// Executing select on this query results in proper formatting of literal value
// SQL: select "table_a"."id" from "table_a" inner join "table_b" on "table_b"."id" = '123'
console.log(qb.select('table_a.id').toQuery())
// Executing delete on this query results in literal value being formatted as if it were a column name
// SQL: delete from "table_a" using "table_b" where "table_b"."id" = "123"
console.log(qb.delete().toQuery())
In select queries, onVal, andOnVal etc. work as expected and documented. The supplied second value is treated as a literal value and, in the case of strings, is quoted with ' single quotes. If the same query syntax is used in a delete() query, the value is suddenly treated as a column name and not a value and is formatted with " double quotes. This obviously breaks the execution because no column exists with that name.
It should be noted that this issue only seems to affect string values. Using the value 123 instead of '123' works OK. However this is no use if your database is using UUID identifiers.
Feature discussion / request
Use case:
We like to reuse filtering logic in our repository layer so that common filters can be applied to multiple different queries without repeating the implementation. This means sometimes onVal is used in select OR delete statements.
We'd like and expect onVal to behave the same in all query contexts, since it shouldn't care about if it is a delete or select
Workaround
We can work around this by wrapping the value in raw('?', '123') but that defeats the point of the onVal interface. For now we are just doing join.on('table_a.id', db.raw('?', '123'))
Environment
Knex version: 2.5.1 and later Database + version: Postgres 15.5 OS: Mac & Alpine linux
Bug
In select queries,
onVal
,andOnVal
etc. work as expected and documented. The supplied second value is treated as a literal value and, in the case of strings, is quoted with'
single quotes. If the same query syntax is used in adelete()
query, the value is suddenly treated as a column name and not a value and is formatted with"
double quotes. This obviously breaks the execution because no column exists with that name.It should be noted that this issue only seems to affect string values. Using the value
123
instead of'123'
works OK. However this is no use if your database is using UUID identifiers.Feature discussion / request
Use case:
onVal
is used in select OR delete statements.onVal
to behave the same in all query contexts, since it shouldn't care about if it is a delete or selectWorkaround
We can work around this by wrapping the value in
raw('?', '123')
but that defeats the point of theonVal
interface. For now we are just doingjoin.on('table_a.id', db.raw('?', '123'))
Missing / erroneus documentation
In case it helps, this was the PR that introduced these methods: https://github.com/knex/knex/pull/2746