Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1227: add assertion for basic where clause values #5417
1227: add assertion for basic where clause values #5417
Changes from 2 commits
a228f32
56dcbb3
97a4f57
d0a73d2
8324a41
0a5efcc
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#1227 still applies if
value
is0
the integer.Adding
value.toString()
instead ofvalue
when pushing onto the where statement stack should solve the issue.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
boolean value
false
, if not passed as a string, yields the same result (talking about MySQL here, don't know whether it applies to #1227 ) https://www.db-fiddle.com/f/w8CJ5SAYEKwJqAXyoYPSwC/2There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of "= 1", it should be "= `1`" because for mysql, if
= 0
is used, it may match other values. I'm not sure if it should be this way for other databases though, can someone versed in the other databases comment on this?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this on db-fiddle, postgre does not allow comparisons between types with
=
operator and expectedly returns an error, so that should be fine.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is scary but it is rather a MySQL issue than a library concern. Or at least this is a separate case with the type coercion in MySQL while this pr handles the invalid usage of the where clause with objects as plain values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree that this is not a library concern. The purpose of knex is to abstract away database-specific quirks to allow safe query-building. Since mysql has the quirk of "= 0" matching all values, knex is responsible for escaping it to "= `0`" to represent the developer's intent.
Should adding backticks around values for mysql be added in a different pr then? Two prs addressing the fundamental issue of knex not expecting non-strings through assertions and escaping seems unnecessarily complex, error-prone, and time-consuming compared to calling
.toString()
on inputs.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@r2dev2 there are some issues with this.
1 - backticks for values is invalid syntax in MySQL, backticks should only be used for identifiers.
2 - when we consider quotes instead of backticks, even this is a bit contentious, I thought it would break with integers, but MySQL is full of surprises.
= 0
is perfectly valid in case of integers, and for reasonable types, probably should be used.Here are the related tests: https://www.db-fiddle.com/f/vytxD1kFa3xBiPf7TBADxq/4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, it appears I got a bit confused with previous experiments. It is the quote that should be used for values, not backtick. I added a quote escaping test to your fiddle (so it does
= '0'
instead of= 0
for secret column) and that works properly.Fiddle: https://www.db-fiddle.com/f/vytxD1kFa3xBiPf7TBADxq/5
Edit: I added db-fiddle tests demonstrating quote-escaping works for postgress and sqlite as well below
Postgres: https://www.db-fiddle.com/f/w8CJ5SAYEKwJqAXyoYPSwC/3
Sqlite: https://www.db-fiddle.com/f/w8CJ5SAYEKwJqAXyoYPSwC/4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change is not simple toString. In raw queries you need to convert bindings to string as well, while the collection of bindings could be either array or object (named bindings)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I tried calling
.toString()
at various places in the codebase and it seems like calling.toString()
on all the bindings is not a solution as a binding could map to many different situations such aslimit = ?
Perhaps only calling
.toString()
forwhere =
clauses and other operators where the value can be quoted is a solution? One dirty way I did this was by addingto
lib/dialects/mysql/query/mysql-querycompiler.js
However, I'm sure there is a better way of doing this which someone more familiar with the knex codebase than me can think of.