Reread my comment. It’s about noticing you have an “f” or a “t” and both are very similar characters.
db.execute("SELECT foo FROM bar;")
db.execute(f"SELECT foo FROM bar WHERE id = {foo_id};")
db.execute(t"SELECT foo FROM bar WHERE id = {foo_id};")
The first and second look identical to execute() because all it sees is a string. But the second one is wrong, a hard-to-see typo of the third.If f-strings didn't exist there'd be no issue because it could distinguish by type as you say. But we have an incorrect SQL-injection-prone usage here that can't be distinguished by type from the correct plain string usage.
db.execute(t"SELECT foo FROM bar;")
See? No reason to accept strings, it's absolutely fine to always error if a string is passed.There's also simply no hard requirement to overload an `execute` function. We have options beyond "no templates at all" and "execute takes templates and strings", for example by introducing a separate function. Why does perfect have to be the enemy of good here?