How to quote a string value explicitly (Python DB API/Psycopg2)

34,695

Solution 1

Ok, so I was curious and went and looked at the source of psycopg2. Turns out I didn't have to go further than the examples folder :)

And yes, this is psycopg2-specific. Basically, if you just want to quote a string you'd do this:

from psycopg2.extensions import adapt

print adapt("Hello World'; DROP DATABASE World;")

But what you probably want to do is to write and register your own adapter;

In the examples folder of psycopg2 you find the file 'myfirstrecipe.py' there is an example of how to cast and quote a specific type in a special way.

If you have objects for the stuff you want to do, you can just create an adapter that conforms to the 'IPsycopgSQLQuote' protocol (see pydocs for the myfirstrecipe.py-example...actually that's the only reference I can find to that name) that quotes your object and then registering it like so:

from psycopg2.extensions import register_adapter

register_adapter(mytype, myadapter)

Also, the other examples are interesting; esp. 'dialtone.py' and 'simple.py'.

Solution 2

I guess you're looking for the mogrify function.

Example:

>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT INTO test (num, data) VALUES (42, E'bar')"

Solution 3

You should try to avoid doing your own quoting. Not only will it be DB-specific as people have pointed out, but flaws in quoting are the source of SQL injection bugs.

If you don't want to pass around queries and values separately, then pass around a list of the parameters:

def make_my_query():
    # ...
    return sql, (value1, value2)

def do_it():
    query = make_my_query()
    cursor.execute(*query)

(I probably have the syntax of cursor.execute wrong) The point here is that just because cursor.execute takes a number of arguments, that doesn't mean you have to handle them all separately. You can deal with them as one list.

Solution 4

This'll be database dependent (iirc, mysql allows \ as an escape character, while something like oracle expects quotes to be doubled: 'my '' quoted string').

Someone correct me if i'm wrong, but the double-quoting method is the standard method.

It may be worth looking at what other db abstraction libraries do (sqlalchemy, cx_Oracle, sqlite, etc).

I've got to ask - why do you want to inline the values instead of bind them?

Share:
34,695
Dariusz Walczak
Author by

Dariusz Walczak

Updated on July 09, 2022

Comments

  • Dariusz Walczak
    Dariusz Walczak almost 2 years

    For some reasons, I would like to do an explicit quoting of a string value (becoming a part of constructed SQL query) instead of waiting for implicit quotation performed by cursor.execute method on contents of its second parameter.

    By "implicit quotation" I mean:

    value = "Unsafe string"
    query = "SELECT * FROM some_table WHERE some_char_field = %s;"
    cursor.execute( query, (value,) ) # value will be correctly quoted
    

    I would prefer something like that:

    value = "Unsafe string"
    query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
        READY_TO_USE_QUOTING_FUNCTION(value)
    cursor.execute( query ) # value will be correctly quoted, too
    

    Is such low level READY_TO_USE_QUOTING_FUNCTION expected by Python DB API specification (I couldn't find such functionality in PEP 249 document). If not, maybe Psycopg2 provides such function? If not, maybe Django provides such function? I would prefer not to write such function myself...