it-swarm.com.de

So zitieren Sie einen Zeichenfolgenwert explizit (Python DB API/Psycopg2)

Aus bestimmten Gründen möchte ich einen String-Wert explizit in Anführungszeichen setzen (Teil einer konstruierten SQL-Abfrage werden), anstatt auf implizite Anführungszeichen zu warten, die von der cursor.execute-Methode für den Inhalt des zweiten Parameters ausgeführt werden.

Mit "implizites Zitat" meine ich:

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

Ich würde so etwas vorziehen:

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

Wird von der Python-DB-API-Spezifikation ein so niedriger READY_TO_USE_QUOTING_FUNCTION erwartet (ich konnte eine solche Funktionalität in PEP 249 document nicht finden)? Wenn nicht, bietet Psycopg2 vielleicht eine solche Funktion? Wenn nicht, bietet Django vielleicht eine solche Funktion? Ich würde es vorziehen, solche Funktion nicht selbst zu schreiben ...

27
Dariusz Walczak

Ok, also war ich neugierig und habe mir die Quelle von psycopg2 angesehen. Es stellte sich heraus, dass ich nicht weiter als bis zum Beispielordner gehen musste :)

Und ja, das ist psycopg2-spezifisch. Wenn Sie nur eine Zeichenfolge zitieren möchten, gehen Sie folgendermaßen vor:

from psycopg2.extensions import adapt

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

Aber was Sie wahrscheinlich tun möchten, ist, Ihren eigenen Adapter zu schreiben und zu registrieren.

Im Beispielordner von psycopg2 finden Sie die Datei 'myfirstrecipe.py' . Dort finden Sie ein Beispiel, wie Sie einen bestimmten Typ auf besondere Weise umsetzen und zitieren können.

Wenn Sie Objekte für die Dinge haben, die Sie tun möchten, können Sie einfach einen Adapter erstellen, der dem 'IPsycopgSQLQuote'-Protokoll entspricht (siehe pydocs für das myfirstrecipe.py-Beispiel ... das ist eigentlich die einzige Referenz, die ich zu diesem Namen finden kann ), die Ihr Objekt zitiert und dann wie folgt registriert:

from psycopg2.extensions import register_adapter

register_adapter(mytype, myadapter)

Auch die anderen Beispiele sind interessant; esp. 'dialtone.py' und 'simple.py' .

29

Ich vermute, Sie suchen nach der Funktion mogrify .

Beispiel:

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

Sie sollten versuchen, nicht selbst zu zitieren. Es wird nicht nur DB-spezifisch sein, wie die Leute betont haben, sondern auch Zitatfehler sind die Ursache für SQL-Injection-Fehler.

Wenn Sie Abfragen und Werte nicht separat weitergeben möchten, geben Sie eine Liste der Parameter weiter:

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

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

(Ich habe wahrscheinlich die Syntax von cursor.execute falsch) Der Punkt hier ist, dass nur, weil cursor.execute eine Reihe von Argumenten akzeptiert, das nicht bedeutet, dass Sie sie alle separat behandeln müssen. Sie können sie als eine Liste behandeln.

2
Ned Batchelder

Ich denke nicht, dass Sie genügend Gründe für Ihre Vermeidung angeben, um dies auf die richtige Weise zu tun. Bitte verwenden Sie die APi, wie sie entworfen wurde, und versuchen Sie nicht, Ihren Code für den nächsten Benutzer weniger lesbar und anfälliger zu machen.

1
ironfroggy

PyPika in einer anderen guten Option zum Erstellen von SQL-Anweisungen. Anwendungsbeispiel (basierend auf einem Beispiel auf der Homepage des Projekts):

>>> from pypika import Order, Query
>>> Query.from_('customers').select('id', 'fname', 'lname', 'phone').orderby('id', order=Order.desc)
SELECT "id","fname","lname","phone" FROM "customers" ORDER BY "id" DESC
0
asherbar

Dies ist datenbankabhängig (iirc, mysql erlaubt \ als Escape-Zeichen, während Oracle erwartet, dass die Anführungszeichen verdoppelt werden: 'my '' quoted string').

Jemand korrigiert mich, wenn ich falsch liege, aber die Methode der doppelten Anführungszeichen ist die Standardmethode.

Es kann sich lohnen, sich andere DB-Abstraktionsbibliotheken anzusehen (sqlalchemy, cx_Oracle, sqlite usw.).

Ich muss fragen: Warum möchten Sie die Werte einbinden, anstatt sie zu binden?

0

Ihr Code-Snippet würde laut psycopg extension docs genau so aussehen

from psycopg2.extensions import adapt

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

Die Funktion getquoted gibt die value als Zeichenfolge in Anführungszeichen und mit Escapezeichen zurück. Sie können also auch folgendermaßen vorgehen: "SELECT * FROM some_table WHERE some_char_field = " + adapt(value).getquoted().

0
Roberto

Dies wird DB-abhängig sein. Im Fall von MySQLdb verfügt die Klasse connection beispielsweise über eine Methode literal, die den Wert in die korrekte Darstellung mit Escapezeichen für die Übergabe an MySQL konvertiert (dies wird von cursor.execute verwendet).

Ich stelle mir vor, dass Postgres etwas Ähnliches hat, aber ich glaube nicht, dass es eine Funktion gibt, mit der Werte als Teil der DB API 2.0-Spezifikation maskiert werden können.

0
davidavr