Email list hosting service & mailing list manager

Named vs numbered SQL parameters Lassi Kortela (18 Sep 2019 08:48 UTC)
Re: Named vs numbered SQL parameters Peter Bex (18 Sep 2019 09:13 UTC)
Re: Named vs numbered SQL parameters Lassi Kortela (18 Sep 2019 09:35 UTC)
Re: Named vs numbered SQL parameters Peter Bex (18 Sep 2019 09:49 UTC)
Re: Named vs numbered SQL parameters Lassi Kortela (18 Sep 2019 10:10 UTC)
Re: Named vs numbered SQL parameters Peter Bex (18 Sep 2019 10:16 UTC)
Re: Named vs numbered SQL parameters Lassi Kortela (18 Sep 2019 10:30 UTC)
Re: Named vs numbered SQL parameters Peter Bex (18 Sep 2019 10:38 UTC)
Re: Named vs numbered SQL parameters Lassi Kortela (18 Sep 2019 10:50 UTC)
Re: Named vs numbered SQL parameters Alaric Snell-Pym (18 Sep 2019 10:39 UTC)
Re: Named vs numbered SQL parameters Lassi Kortela (19 Sep 2019 14:20 UTC)
Re: Named vs numbered SQL parameters Peter Bex (19 Sep 2019 14:53 UTC)
Re: Named vs numbered SQL parameters Alaric Snell-Pym (19 Sep 2019 16:05 UTC)
Re: Named vs numbered SQL parameters John Cowan (18 Sep 2019 22:36 UTC)
Re: Named vs numbered SQL parameters Peter Bex (19 Sep 2019 07:20 UTC)
Re: Named vs numbered SQL parameters John Cowan (19 Sep 2019 13:54 UTC)
Re: Named vs numbered SQL parameters Peter Bex (19 Sep 2019 14:04 UTC)
Re: Named vs numbered SQL parameters Lassi Kortela (19 Sep 2019 14:07 UTC)
Re: Named vs numbered SQL parameters Peter Bex (19 Sep 2019 14:19 UTC)
Re: Named vs numbered SQL parameters Lassi Kortela (19 Sep 2019 14:28 UTC)
Re: Named vs numbered SQL parameters Alaric Snell-Pym (19 Sep 2019 16:00 UTC)

Re: Named vs numbered SQL parameters Lassi Kortela 18 Sep 2019 09:34 UTC

> The real issue with any common syntax we want to support is translation.
> There must be a way to escape them.  And I'm not sure how that works
> with quoted arguments like SELECT 'Que pasa?'; should not be converted
> to SELECT 'Que pasa$1' in Postgres.  So in order to do this correctly,
> you need some sort of rudimental SQL parser?!  I don't know how other
> languages do this.
>
> Apparently PHP's PDO totally botches this (no surprise there):
> https://stackoverflow.com/questions/16311939/how-to-prevent-pdo-from-interpreting-a-question-mark-as-a-placeholder
>
> We could use a really really stupid approach and simply replace any
> placeholder with its exact string.
>
> So for example
>
> (sql-execute "INSERT INTO foo VALUES (:myval1, :myval2)"
>               '((:myval1 . 1) (:myval2 . 2)))
>
> If the query gets messed up the user should simply choose better
> placeholders.
>
> If we want to do it the way some language drivers do, you end up with
> issues because the colon is used for casting in Postgres.  So:
>
> (sql-execute "INSERT INTO foo VALUES (:myval1::int, :myval2::int)"
>               '((myval1 . 1) (myval2 . 2)))
>
> might result in an error because ":int" is not bound to a value.  A simple
> solution would be to only replace the variables in the alist, but then
> you can't give an error when some variables are forgotten to be bound.
> Of course, the SQL engine will give an error in such a case...
>
> I see PDO actually includes an SQL parser in order to be able to replace
> their questionmark-based parameter handling:
> https://github.com/php/php-src/blob/master/ext/pdo/pdo_sql_parser.re#L51
>
> I don't really want to go down this route, it is too complicated for a
> straightforward database abstraction.  And as the Stack Overflow post
> showed, it's too brittle to get right (SQL is a pain to parse, especially
> with all the extensions that various dialects throw onto it).
>
> If you search the web for "postgresql question mark placeholders", you
> see several posts on the Postgres mailing list of people struggling with
> various language bindings which try to do this question mark
> normalisation, which fails.  It's even so that Postgres manual includes
> a note in the documentation that you must escape bare question marks in
> SQL statements in the JDBC driver:
> https://jdbc.postgresql.org/documentation/head/statement.html

Oh my god :D Thanks for taking the time to write up all those cases.
Should have learned to expect something like this by now :)

I like your idea of doing dumb replacements of the named placeholders.
We can't possibly parse SQL right (with all the extensions and all the
quoting and escaping styles).

So that problematic query on Stack Overflow would just work as-is:

     (sql-execute "SELECT * FROM tbl WHERE hst ? 'foo'")

Then there's the question of how paranoid we want to be :D I mean, we
could use a generic syntax like this:

     (sql-execute
      "INSERT INTO foo VALUES ({{myval1}}::int, {{myval2}}::int)"
      '((myval1 . 1) (myval2 . 2)))

Or maybe too much of a good thing is wonderful:

     (sql-execute
      "INSERT INTO foo VALUES ({{{myval1}}}::int, {{{myval2}}}::int)"
      '((myval1 . 1) (myval2 . 2)))

In expansion syntax, I've learned from experience to prefer some kind of
brackets around the identifier being expanded, instead of only having a
prefix (dollar sign, colon, etc.) When you use many languages you tend
to forget what characters are valid in the identifier; the explicit
closing bracket makes it obvious where the identifier ends. Templating
languages also tend to use braces around identifiers, and they have to
operate in some of the most hostile syntactic environments around :p

Maybe even one pair of braces would be enough since the user can choose
their own placeholder names to avoid any conflicts:

     (sql-execute
      "INSERT INTO foo VALUES ({myval1}::int, {myval2}::int)"
      '((myval1 . 1) (myval2 . 2)))