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/