Rethinking parameterized SQL queries John Cowan (27 Feb 2021 01:18 UTC)
Re: Rethinking parameterized SQL queries Lassi Kortela (27 Feb 2021 09:13 UTC)
Re: Rethinking parameterized SQL queries Lassi Kortela (27 Feb 2021 09:17 UTC)
Re: Rethinking parameterized SQL queries Lassi Kortela (27 Feb 2021 09:30 UTC)
Re: Rethinking parameterized SQL queries John Cowan (27 Feb 2021 20:08 UTC)
Re: Rethinking parameterized SQL queries Lassi Kortela (27 Feb 2021 20:36 UTC)
Re: Rethinking parameterized SQL queries John Cowan (27 Feb 2021 22:14 UTC)
Re: Rethinking parameterized SQL queries Peter Bex (28 Feb 2021 10:21 UTC)
Re: Rethinking parameterized SQL queries John Cowan (01 Mar 2021 03:29 UTC)
Re: Rethinking parameterized SQL queries Florian Weimer (27 Feb 2021 12:32 UTC)
Re: Rethinking parameterized SQL queries Lassi Kortela (27 Feb 2021 12:39 UTC)

Re: Rethinking parameterized SQL queries Lassi Kortela 27 Feb 2021 09:13 UTC

Thanks for getting back to the topic with a detailed writeup.

I continue to believe that string handling is an anti-pattern to be
avoided unless absolutely necessary, especially with something like SQL
that can read sensitive data and do destructive writes. I also continue
to believe that prepared statements are mandatory from a security and
performance point of view.

Psycopg, the PostgreSQL interface for Python, is probably one of the
most mature SQL interfaces (it's now going on version 3) and this is the
kind of escaping they did in v2: <https://www.psycopg.org/docs/sql.html.
That page doesn't inspire confidence that they know what they're doing.

The quote_ident() function for escaping identifiers such as table and
column names is a good idea though.

If a complete SQL grammar covering the major DB engines is too hard,
could we at least assume that we can represent a complete tokenization
of the grammar as S-expressions? Something like this:

(let ((foo <...>) (bar <...>))
   `(insert into ($table-name ,foo) values (col1 |,| ($column-name ,bar))))

That syntax isn't very good, but the general idea is that the SQL

insert into foo values (bar, baz)

is tokenized as the S-expression

(insert into foo values (bar |,| baz))

which is literal, except that ($type value) escapes that can poke holes
in it and inject variables. You could have many categories:

($view-name "x")
($table-name "x)
($column-name "x")
($parameter 1)
($parameter "foo")
...

as needed.