You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Error: syntax error at or near "$1" with super simple query #539
any query using .query(string, [value...], fn) gives me this error, even with the appropriate number of values, did the api change or something? Even simple stuff like:
client.query('create user $1 with password \'Something1\'',['tobi'],function(err){if(err)throwerr;console.log('created');});
@visionmedia I don't think prepared statements can be used with the create user command (or similar). I'll see if I can find documentation to back this up.
Using .query with arguments string, [value...], fn will generate a prepared statement if I'm not mistaken.
prepared statements have several benefits include performance enhancements - via cached query planning and also security - injection escaping. So the way you used the query method was just fine :) Unfortunately it seems prepared statements can't be used with the create command. :/
So you'll want to do some injection escaping on your own, build the query string, and then just pass string, fn as the arguments to query.
@visionmedia It's always fun the first time you realize PostgreSQL server doesn't accept parameters in certain places where you'd love to have them be used. Most commands don't accept parameters and a few places in queries you think it would be nice to use them they aren't accepted. 😦
The good news is there are manual escaping helpers already built into node-postgres as well for the times when you want to insert user created or untrusted content into a part of a query or command where parameters aren't accepted.
If you're using the native bindings they actually use the escape written into libpq. If you're using the pure JavaScript client the escape is as close to a direct port of the libpq escape functions as possible.
Reacted by Ian Langworth ☠ and cosmicsands
Reacted by Ian Langworth ☠, jimmy, dr-alberto and Shishir Kaji Shrestha
Haha yeah :D I've only used mysql/sqlite, I actually thought it was a feature of this lib. Would you be interested in some sort of method that allows escaping for cases like this? Not sure off hand what a decent method name would be
Yeah, I think it would be handy for sure. I have a few thoughts...
However it ends up it should be pretty clear about being intended for when you cannot add parameters to a query in a normal way. I think having to manually escape your inputs with hand-rolled string concatenation when they cannot be parameterized is a pain and error prone, but I don't want it to be confused as a general purpose substitute for parameterized queries.
So I'm wondering if, like you said, it could be it's own module. Something like pg-escape and you could use it like...
varescape=require('pg-escape')client.query(escape('create user ? with password \Something\`, ['my_username']))
I used the ? placeholder from mysql there instead of the PostgreSQL $n placeholder because that might advertise it more as something that's not happening within the PostgreSQL server itself? Not sure...maybe that's ugly? Another advantage of it being it's own module is it could contain a lovely readme file that explained something like "Generally you wanna use parameterized SQL, but sometimes commands don't take parameters where you want. You can use this to safely escape those commands" or something.
Of course it could also just be added onto the query or client object as another method. My only hesitation with that is this module already has a lot of functionality, as you've probably noticed. I'm actually working right now in spinning parts of it out into other modules for better reuse and to hopefully lower the barrier of entry for collaboration. It it were stuck onto the client object it could look like this maybe...
vartext=client.escape('create user $1 with password \Something\', ['my_username'])client.query(text,function(err,rows){})
or if the client-side escaping used the question mark placeholder you could get crazy:
vartext=client.escape('select ? from my_table where id = $1',['my_column_name'])client.query(text,['some_id'],function(err,rows){});
I'd like to see a module like pg-escape ... the client could depend on it and export it again like client.escape(...).
About ? vs $n: I think, both are not sufficient. What should ? or $1 stand for? An identifier? A literal? I think it should be handled more like by the format function, so i propose the same "type system":
@visionmedia that function also escapes single quotes, which along with backslashes are the only things you need to escape in postgres string literals. Single quotes are escaped with a preceding single quote, and backslashes are escaped with a preceding backslash. The c-style backslash escaping is non-standard and will produce a warning unless the literal is prefixed with E as you can see in that function when hasBackslash is true.
Another restriction on parameter symbols is that they only work in SELECT, INSERT, UPDATE, and DELETE commands. In other statement types (generically called utility statements), you must insert values textually even if they are just data values.
Activity
lalitkapoor commentedon Mar 14, 2014
@visionmedia I don't think prepared statements can be used with the
create usercommand (or similar). I'll see if I can find documentation to back this up.lalitkapoor commentedon Mar 14, 2014
I can't find anything specifically to back that up from docs -- so maybe I'm wrong 😦. I do see some people who've tried to do that and have had experienced the same error (in java):
http://www.postgresql.org/message-id/[email protected]
On another note if you want to do a quick check to see if
queryis work like you'd expect you could try the following (from the readme):lalitkapoor commentedon Mar 14, 2014
Looks like I'm not able to prepare the statement using the prepare command in the psql shell (9.3):
tj commentedon Mar 14, 2014
Ah I see, I thought the injection escaping was done by this library for .query()
lalitkapoor commentedon Mar 15, 2014
Using .query with arguments
string, [value...], fnwill generate a prepared statement if I'm not mistaken.prepared statements have several benefits include performance enhancements - via cached query planning and also security - injection escaping. So the way you used the query method was just fine :) Unfortunately it seems prepared statements can't be used with the create command. :/
So you'll want to do some injection escaping on your own, build the query string, and then just pass
string, fnas the arguments toquery.Hope that helps clarify things :)
lalitkapoor commentedon Mar 15, 2014
More details on how sql injection is handled in this lib: https://github.com/brianc/node-postgres/wiki/FAQ#8-does-node-postgres-handle-sql-injection
tj commentedon Mar 15, 2014
Cool thanks! Maybe we can add an alternative method so people don't have to re-implement escaping outside of the library
brianc commentedon Mar 15, 2014
@visionmedia It's always fun the first time you realize PostgreSQL server doesn't accept parameters in certain places where you'd love to have them be used. Most commands don't accept parameters and a few places in queries you think it would be nice to use them they aren't accepted. 😦
The good news is there are manual escaping helpers already built into node-postgres as well for the times when you want to insert user created or untrusted content into a part of a query or command where parameters aren't accepted.
https://github.com/brianc/node-postgres/blob/master/lib/client.js#L228
https://github.com/brianc/node-postgres/blob/master/lib/client.js#L247
I apologize these aren't better documented.
If you're using the native bindings they actually use the escape written into
libpq. If you're using the pure JavaScript client the escape is as close to a direct port of thelibpqescape functions as possible.tj commentedon Mar 15, 2014
Haha yeah :D I've only used mysql/sqlite, I actually thought it was a feature of this lib. Would you be interested in some sort of method that allows escaping for cases like this? Not sure off hand what a decent method name would be
brianc commentedon Mar 15, 2014
Yeah, I think it would be handy for sure. I have a few thoughts...
However it ends up it should be pretty clear about being intended for when you cannot add parameters to a query in a normal way. I think having to manually escape your inputs with hand-rolled string concatenation when they cannot be parameterized is a pain and error prone, but I don't want it to be confused as a general purpose substitute for parameterized queries.
So I'm wondering if, like you said, it could be it's own module. Something like
pg-escapeand you could use it like...I used the
?placeholder from mysql there instead of the PostgreSQL$nplaceholder because that might advertise it more as something that's not happening within the PostgreSQL server itself? Not sure...maybe that's ugly? Another advantage of it being it's own module is it could contain a lovely readme file that explained something like "Generally you wanna use parameterized SQL, but sometimes commands don't take parameters where you want. You can use this to safely escape those commands" or something.Of course it could also just be added onto the query or client object as another method. My only hesitation with that is this module already has a lot of functionality, as you've probably noticed. I'm actually working right now in spinning parts of it out into other modules for better reuse and to hopefully lower the barrier of entry for collaboration. It it were stuck onto the client object it could look like this maybe...
or if the client-side escaping used the question mark placeholder you could get crazy:
What do you think?
hoegaarden commentedon Mar 17, 2014
I'd like to see a module like
pg-escape... the client could depend on it and export it again likeclient.escape(...).About
?vs$n: I think, both are not sufficient. What should?or$1stand for? An identifier? A literal? I think it should be handled more like by the format function, so i propose the same "type system":%sfor a simple string%Ifor an identifier%Lfor a literalGood? Bad? Ugly?
tj commentedon Mar 17, 2014
@hoegaarden sounds good to me, I'll whip something up
tj commentedon Mar 17, 2014
quick question, what's the reasoning behind using the escaped mode for https://github.com/brianc/node-postgres/blob/master/lib/client.js#L247? I'm not too familiar, but if all it does is escape slashes couldn't a normal string constant be used?
benighted commentedon Mar 17, 2014
@visionmedia that function also escapes single quotes, which along with backslashes are the only things you need to escape in postgres string literals. Single quotes are escaped with a preceding single quote, and backslashes are escaped with a preceding backslash. The c-style backslash escaping is non-standard and will produce a warning unless the literal is prefixed with
Eas you can see in that function whenhasBackslashis true.tj commentedon Mar 17, 2014
https://github.com/segmentio/pg-escape should be sufficient :D
hoegaarden commentedon Mar 18, 2014
👍
brianc commentedon Mar 18, 2014
ah nice! 😄
gajus commentedon Nov 7, 2021
Is there somewhere Postgres documentation that identifies all contexts in which prepared statements cannot be used?
gajus commentedon Nov 7, 2021
Found it:
https://www.postgresql.org/docs/9.1/plpgsql-statements.html