Most active commenters
  • masklinn(3)

←back to thread

620 points tambourine_man | 12 comments | | HN request time: 0.928s | source | bottom
Show context
serbuvlad ◴[] No.43750075[source]
All things considered, this is pretty cool. Basically, this replaces

    db.execute("QUERY WHERE name = ?", (name,))
with

    db.execute(t"QUERY WHERE name = {name}")
Does the benefit from this syntactic sugar outweigh the added complexity of a new language feature? I think it does in this case for two reasons:

1. Allowing library developers to do whatever they want with {} expansions is a good thing, and will probably spawn some good uses.

2. Generalizing template syntax across a language, so that all libraries solve this problem in the same way, is probably a good thing.

replies(12): >>43750226 #>>43750250 #>>43750260 #>>43750279 #>>43750513 #>>43750750 #>>43752117 #>>43752173 #>>43752293 #>>43754738 #>>43756560 #>>43763190 #
benwilber0 ◴[] No.43752173[source]
Aren't there other benefits to server-side parameter binding besides just SQL-injection safety? For instance, using PG's extended protocol (binary) instead of just raw SQL strings. Caching parameterized prepared statements, etc.

Also:

    db.execute(t"QUERY WHERE name = {name}")
Is dangerously close to:

    db.execute(f"QUERY WHERE name = {name}")

A single character difference and now you've just made yourself trivially injectible.

I don't think this new format specifier is in any way applicable to SQL queries.

replies(12): >>43752236 #>>43752283 #>>43752331 #>>43752336 #>>43752358 #>>43752859 #>>43753280 #>>43753699 #>>43754372 #>>43754646 #>>43755330 #>>43756720 #
1. masklinn ◴[] No.43752331[source]
> Aren't there other benefits to server-side parameter binding besides just SQL-injection safety? For instance, using PG's extended protocol (binary) instead of just raw SQL strings. Caching parameterized prepared statements, etc.

All of which can be implemented on top of template strings.

> A single character difference and now you've just made yourself trivially injectible.

It's not just a one character difference, it's a different type. So `db.execute` can reject strings both statically and dynamically.

> I don't think

Definitely true.

> this new format specifier is in any way applicable to SQL queries.

It's literally one of PEP 750's motivations.

replies(7): >>43752391 #>>43752395 #>>43752558 #>>43752752 #>>43754441 #>>43755649 #>>43755673 #
2. VWWHFSfQ ◴[] No.43752391[source]
> It's literally one of PEP 750's motivations.

Python is notorious for misguided motivations. We're not "appealing to authority" here. We're free to point out when things are goofy.

3. willcipriano ◴[] No.43752395[source]

    from string.templatelib import Template

    def execute(query: Template)
Should allow for static analysis to prevent this issue if you run mypy as part of your pr process.

That would be in addition to doing any runtime checks.

replies(1): >>43752563 #
4. woodrowbarlow ◴[] No.43752558[source]
nitpicking:

> It's not just a one character difference, it's a different type. So `db.execute` can reject strings both statically and dynamically.

in this case, that's not actually helpful because SQL statements don't need to have parameters, so db.execute will always need to accept a string.

replies(2): >>43753027 #>>43754776 #
5. benwilber0 ◴[] No.43752563[source]
The first mistake we're going to see a library developer make is:

    def execute(query: Union[str, Template]):

Maybe because they want their execute function to be backwards compatible, or just because they really do want to allow either raw strings are a template string.
replies(1): >>43754807 #
6. tczMUFlmoNk ◴[] No.43752752[source]
> > I don't think

> Definitely true.

The rest of your comment is valuable, but this is just mean-spirited and unnecessary.

7. anamexis ◴[] No.43753027[source]
You can just pass it a template with no substitutions.
8. rangerelf ◴[] No.43754441[source]
>> I don't think >Definitely true.

I thought we left middle-school playground tactics behind.

9. masklinn ◴[] No.43754776[source]
> db.execute will always need to accept a string.

No. A t-string with no placeholders is perfectly fine. You can use that even if you have no parameters.

10. masklinn ◴[] No.43754807{3}[source]
> they really do want to allow either raw strings are a template string.

I’d consider that an invalid use case:

1. You can create a template string without placeholders.

2. Even if the caller does need to pass in a string (because they’re executing from a file, or t-strings don’t support e.g. facetting) then they can just… wrap the string in a template explicitly.

11. ◴[] No.43755649[source]
12. davepeck ◴[] No.43755673[source]
> Caching parameterized prepared statements, etc.

I didn’t explicitly mention this in my post but, yes, the Template type is designed with caching in mind. In particular, the .strings tuple is likely to be useful as a cache key in many cases.