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. > 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 _______________________________________________ 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/6LEZYLI6KJ2WXWZM2C6PVD3STD5LF2QU/ Code of Conduct: http://python.org/psf/codeofconduct/