tags:

views:

101

answers:

4

I have a string, specifically a SQL query, that goes through multiple formatting passes before it is passed to the backend to be executed, at which point Django performs yet another string format. How can I preserve the placeholders that need to make it to the database throughout all of this? Something like the following is the best I've come up with, but is definitely not as flexible as I need it to be. I am running Python 2.5

from django.db import connection
cursor = connection.cursor()    
cursor.execute("SELECT DATE_FORMAT('2010-01-01 12:00:00', '%%%%H:%%%%i:%%%%s') as %s" % 'foo')
A: 

Well, for string values you should be able to use something like this:

cursor.execute("SELECT DATE_FORMAT('2010-01-01 12:00:00', %%s) as %s" % 'foo', ('%H:%i:%s',))

This of course doesn't help for actual placeholders in the query, like you can see on %%s.

Lukáš Lalinský
The date format string actually gets introduced at the very beginning of the process, this relies on it being the last addition.
tcdent
This just makes it parametrized. If you are passing the query around before you execute it, you would need to pass the query plus its arguments.
Lukáš Lalinský
A simplified version of my query would be more like: cursor.execute("SELECT %s", ("DATE_FORMAT('2010-01-01 12:00:00', '%H:%i:%s')", )) which doesn't work because Django treats the format substitution as a string and wraps it in quotes. Basically, the entire DATE_FORMAT call needs to stay in one piece.
tcdent
No, that would be a non-working version. There is a reason why I said to parametrize only the formatting string.
Lukáš Lalinský
A: 

If you're running Python 2.6+ you can use str.format() in order to shed one level of percent signs.

Ignacio Vazquez-Abrams
Sorry, should have specified. Still on 2.5
tcdent
A: 

I think you should also use ? placeholders in SQL syntax instead of string formatting, e.g. change @Lukás' answer to:

cursor.execute("SELECT DATE_FORMAT('2010-01-01 12:00:00', '?') as ?",('%H:%i:%s',"foo"))
Kimvais
You don't always get a choice. Some DB-API adapters only support the %s syntax.
Ignacio Vazquez-Abrams
MySQL seems to fall under those that don't support it; getting a TypeError when I substitute them.
tcdent
A: 
" ".join([r"SELECT DATE_FORMAT('2010-01-01 12:00:00', '%H:%i:%s') as", "foo"])
Dyno Fu