-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Get formatted query from Pool.query() method #991
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
base: master
Are you sure you want to change the base?
Conversation
Address issue mysqljs#984 var p=Pool.query( sql, vdata, function() {}); console.log(p.sql); // unformatted This commit changes the behavior and returns the formatted sql statement immediately. Also prevents side effect of Connection.query() re-formatting the SQL statement so as not to corrupt the SQL statement. A new connection config variable, isFormatted, keeps track of query formatting. The Pool.prototype.format method added. Similar to Connection.prototype.format, except adapted to use config.connectionConfig. The format() method uses mysql.format() so as not to require SqlString module.
### Addresses issue mysqljs#984 ```javascript var p= Pool.query(sql,data, function (){}); console.log(p.sql); // un-formatted sql statement ``` This commit changes the behavior of `Pool.query()` method so as to return the **formatted SQL statement** as expected, as in `Connection.query()`. #### Preventing side effects Since `Pool.query()` method uses `Connection.query()` internally, `Connection.query()` needs to know if the SQL statement has already been formatted so as to prevent double formatting and corrupting the query. A new connection config variable `isFormatted` keeps track of formatting status. #### Additional method The `Pool.prototype.format` method added to Pool module. Similar to `Connection.prototype.format` method and modified to work inside Pool class.
redundant assignment operation moved inside a conditional
lib/Pool.js
Outdated
@@ -171,6 +171,8 @@ Pool.prototype.end = function (cb) { | |||
Pool.prototype.query = function (sql, values, cb) { | |||
var query = Connection.createQuery(sql, values, cb); | |||
|
|||
query.isFormatted = false; |
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.
Move this so it always exists, otherwise we are altering the hidden class and fracturing it.
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.e. it should be set within createQuery
Thanks for this! I won't be able to merge it until there are tests, though. If I have time, I can add some tests, but if you can first, that would be great :) |
@dougwilson I will have to rewrite my tests to make them easily replicable. I used real tables and data for my test so will need to make self sufficient queries with no table dependency. Do you have some recommendation for the kind of tests you'd like to see? |
The minimum is a test for the issue you referenced that fails without this and passes with this. For patterns, there are lots and lots of tests to look at in the tests folder :) If you were wondering, the reason I cannot put things in without tests is because if they don't go in at the same time, they get forgotten and eventually something regresses the fix. |
Use 2 Pool instances to test if formatted SQL query is returned from the pool.query() method. pool1 uses default transformation and pool2 applies a custom queryFormat.
Moved default Query property isFormatted from Pool module to Query module. When a Query object is first instantiated, isFormatted is false by default.
@dougwilson I've included a unit test file: Also I moved the |
I'm not sure if I'm missing something but it looks like one could just move formatting to |
Yep, I agree with @sidorares if it's possible :) Also, if you're going to introduce a new |
@sidorares and @dougwilson if so shouldn't the call to One problem seems to be that What do you think? |
I think |
@sidorares The problem with making
Any suggestion? |
In the end, it's really impossible to make this solution look good without it not being backwards-compatible :) |
@@ -255,6 +259,13 @@ Pool.prototype.escapeId = function escapeId(value) { | |||
return mysql.escapeId(value, false); | |||
}; | |||
|
|||
Pool.prototype.format = function(sql, values) { | |||
if (typeof this.config.connectionConfig.queryFormat == "function") { | |||
return this.config.connectionConfig.queryFormat.call(this, sql, values, this.config.connectionConfig.timezone); |
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 have to think about if it's acceptable that the context of the queryFormat
call is not going to be a Connection
object in these cases and if this is going to be an 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.
I did find a solution to keep createQuery
as a static method of Connection
and provide the right context for instance config, which keeps things backward compatible. I'll commit the changes later from another machine.
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.
Does it take care of this context issue, though?
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.
Otherwise there is no need to add a new commit, really. I've already adjusted your commit to make it an instance method (still under your name). The problem right now is backwards compatibility with this function context.
5847ec8
to
be37e88
Compare
65c4c0c
to
fa96a75
Compare
638d79d
to
88bade0
Compare
946727b
to
37fbbdd
Compare
Solution to resolve #984
This commit changes the behavior of
Pool.query()
method so as to return the formatted SQL statement as expected, as inConnection.query()
.Preventing side effects
Since
Pool.query()
method usesConnection.query()
internally,Connection.query()
needs to know if the SQL statement has already been formatted so as to prevent double formatting and corrupting the query.A new Query object property
isFormatted
keeps track of formatting status.Additional method
The
Pool.prototype.format
method was added to Pool module. Similar toConnection.prototype.format
method and modified to work inside the Pool class.Testing with error inducing query
Using the
Pool.query
method this query could be passed this wayIn the absence of the
isFormatted
property, if we allow thePool.query()
method to format (escape and replace placeholders) a query before it is passed to theConnection.query
method, the latter will try to reformat the query a second time by replacing the?
inside'John ? J ?'
with another copy of the same string, resulting in an SQL error.The addition of the
isFormatted
property to the Query object is crucial for this fix to work. It isundefined
by default and evaluates tofalse
in a boolean operation. Therefore no change was made to thelib/protocol/sequences/Query.js
file. The property is set afterConnection.createQuery()
method returns a Query object.