On 8/29/19 11:14 AM, Chris Angelico wrote:
> On Fri, Aug 30, 2019 at 3:51 AM Pasha Stetsenko <stpa...@gmail.com> wrote:
>> My understanding is that for a sql prefix the most valuable part is to be 
>> able
>> to know that it was created from a literal. No other magic, definitely not
>> auto-executing. Then it would be legal to write
>>
>>     result = conn.execute(sql"SELECT * FROM people WHERE id=?",
>>                           user_id)
>>
>> but not
>>
>>     result = conn.execute(f"SELECT * FROM people WHERE id={user_id}")
>>
>> In order to achieve this, the `execute()` method only has to look at
>> the type of its argument, and throw an error if it's a plain string.
> There's no such thing, though, any more than there's such a thing as a
> "raw string". There are only two types of string in Python - text and
> bytes. You can't behave differently based on whether you were given a
> triple-quoted, raw, or other string literal.

But isn't the idea of the sql" (or other) prefix was that the 'plain
string' was put through a special function that processes it, and that
function could return an object of some other type, so it could detect
the difference.

>
>> Perhaps with some more imagination we can make
>>
>>     result = conn.execute(sql"SELECT * FROM people WHERE id={user_id}")
>>
>> work too, but in this case the `sql"..."` token would only create an
>> `UnpreparedStatement` object, which expects a variable named "user_id",
>> and then the `conn.execute()` method would pass locals()/globals() into
>> the `.prepare()` method of that statement, binding those values to
>> the placeholders. Crucially, the `.prepare()` method shouldn't modify the
>> object, but return a new PreparedStatement, which then gets executed
>> by the `conn.execute()`.
> One way to handle this particular case would be to do it as a variant
> of f-string that doesn't join its arguments, but passes the list to
> some other function. Just replace the final step BUILD_STRING step
> with BUILD_LIST, then call the function. There'd need to be some way
> to recognize which sections were in the literal and which came from
> interpolations (one option is to simply include empty strings where
> necessary such that it always starts with a literal and then
> alternates), but otherwise, the "sql" manager could do all the
> escaping it wants. However, this wouldn't be enough to truly
> parameterize a query; it would only do escaping into the string
> itself.
>
> Another option would be to have a single variant of f-string that,
> instead of creating a string, creates a "string with formatted
> values". That would then be a single object that can be passed around
> as normal, and if conn.execute() received such a string, it could do
> the proper parameterization.
>
> Not sure either of them would be worth the hassle, though.
>
> ChrisA
=

-- 
Richard Damon
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JNVP4DU6S3NXQ3MAXOF6XXY3E6VGKVSL/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to