Seite 1 von 1
psycopg2 verhält sich nicht wie erwartet
Verfasst: Montag 5. Dezember 2016, 16:37
von Judge
Hallo zusammen,
evtl. bin ich zu blöd Dokus zu lesen; ich versichere aber, dass ich das heute schon gefühlte 100x getan habe und trotzdem nicht dahinter komme
Im
psycopg - Usage Guide steht:
Psycopg can automatically convert Python objects to and from SQL literals: using this feature your code will be more robust and reliable.
>>> SQL = "INSERT INTO authors (name) VALUES (%s);"
>>> data = ("O'Reilly", )
>>> cur.execute(SQL, data)
Ich habe mir jetzt ein stupid-as-f**k Beispiel gebaut:
Code: Alles auswählen
#!/usr/bin/python2
import psycopg2
# Create connection and cursor objects
con = psycopg2.connect(database="postgres", user="postgres", host="127.0.0.1", password="postgres")
con.set_isolation_level(0)
cur = con.cursor()
# http://initd.org/psycopg/docs/usage.htm ... ql-queries
SQL = "CREATE DATABASE %s;"
data = ("testdb", )
cur.execute(SQL, data)
con.close
Muss man nicht viel zu sagen: Soll auf die PostgreSQL DB auf localhost verbinden und die Datenbank "testdb" anlegen. Syntax eigentlich doch 1:1 wie im Beispiel.
So, jetzt führe ich das aus und erhalte:
judge@judge-nb:~$ ./test.py
Traceback (most recent call last):
File "./test.py", line 12, in <module>
cur.execute(SQL, data)
psycopg2.ProgrammingError: syntax error at or near "'testdb'"
LINE 1: CREATE DATABASE 'testdb';
Kopiere ich das und gebe das 1:1 in psql ein, sagt der auch:
postgres=# CREATE DATABASE 'testdb';
ERROR: syntax error at or near "'testdb'"
LINE 1: CREATE DATABASE 'testdb';
postgres=#
Gebe ich es ohne die Anführungsstriche in psql ein, klappt es:
postgres=# CREATE DATABASE testdb;
CREATE DATABASE
postgres=#
Wenig überraschend: Wenn ich das stumpf als unparameterisierte Operation ausführen lasse, klappt es auch mit psycopg2:
Aber das ist ja nicht Sinn der Sache.
Was macht psycopg2 da? Die zitierte Doku liest sich für mich so, als wenn er mit genau so einer Syntaxunterscheidung umgehen kann.
Oder mache ich was falsch?
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Montag 5. Dezember 2016, 16:55
von BlackJack
@Judge: Ein Tabellenname ist kein Wert. Platzhalter in SQL sind nur für Werte. Denn die ändern sich bei den Abfragen, nicht so etwas wie Tabellennamen. Wenn man ”variable” Tabellennamen hat, dann stimmt in der Regel etwas mit dem Datenbankentwurf nicht.
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Montag 5. Dezember 2016, 18:18
von Judge
Hi BlackJack,
leider verstehe ich Deine Antwort nicht.
Ich lege da ja keine Tabelle an, sondern eine Datenbank. "Diese sollten nicht variabel sein" - ich münze das mal noch diesem Missverständnis zu.
Denn denke ich z.B. an die Übergabe eines DB namens in einer durch den Anwender editierten Configdatei ergibt es sich hierbei ja durchaus das der CREATE code dazu sinnvoll mit solchen Variablen arbeitet.
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Montag 5. Dezember 2016, 18:23
von DasIch
Werte sind alles was du in eine Spalte packen kannst. Alles andere als Datenbank Namen, Tabellen Namen, Spalten Namen, usw. sind keine Werte und sollten nicht Variabel sein. Selbst wenn du diese Namen irgendwie generierst, sollte dies nicht vom User beeinflusst sein. Also sowas wie Usern über Konfigurationsdateien solche Namen festlegen lassen ist überhaupt keine gute Idee.
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Montag 5. Dezember 2016, 20:31
von Judge
Bitte nicht in den falschen Hals kriegen, aber ich möchte nicht über (Un-/)Sinn von Scripten oder gutem und schlechtem Design/Stil philosophieren, sondern die technischen Gründe für ein fehlschlagen der gezeigten Anweisungen verstehen und wie ich technisch das Ziel erreiche.
Das etwas eine gute oder schlechte Idee ist, führt sicher nicht zu Fehlermeldungen eines Computerprogrammes.
Frage 1: Ich habe also einen variablen String und möchte eine PostgreSQL Datenbank anlegen, die so heißt: Wie mache ich das?
Frage 2: Ich verstehe, das das von mir gewählte Konstrukt davon ausgeht, das der resultierende Query in einem anderen (PostgreSQL-)Kontext verwendet wird, bei dem andere Regeln bezüglich der Quotation gelten als beim anlegen von Datenbanken. Da ich diese Einschränkung auf einen Anwendungsfall jedoch auch nach vielfachem lesen der Psycopg2 Doku nicht finden kann, stellt sich mir die Frage: Fehlt diese Info? Oder überlese ich das immer und immer wieder?
Ich würde mich freuen, wenn mich mal jemand mit der Nase drauf stubsen würde.
Vielen Dank für Eure Hilfe!
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Montag 5. Dezember 2016, 20:36
von BlackJack
@Judge: Frage 1: Selbst eine Zeichenkette zusammenbauen und hoffen das dabei nichts böses passiert.
Frage 2 verstehe ich nicht‽
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Montag 5. Dezember 2016, 20:45
von DasIch
Der technische Grund dafür dass das nicht geht, ist dass die Entwickler das für schlechtes Design halten und dementsprechend sowas nicht unterstützen. Wenn jemand über die Brücke springen will, hilft man üblicherweise nicht dabei. Du musst halt in diesem Fall String Formatting betreiben.
Zu 2:
Ein Name ist kein Literal.
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Dienstag 6. Dezember 2016, 12:09
von Judge
@BlackJack:
Zu Frage 2: Ich würde solche Dokus gerne in Zukunft auch alleine lesen können und wollte wissen, wo dieser Punkt beschrieben steht, den ich erst jetzt mit Hilfe von erfahrenen Programmierern verstehe.
So wie DasIch es mit seiner Antwort versucht hat: Pointing auf einen relevanten Doku-Teil, der mir gezeigt hätte das der Codeansatz Quark ist, ehe ich es durch Trial & Fail bemerkt habe.
@DasIch:
Ich bin kein gelernter Programmierer; "nur" Systemintegrator und Programmier-Autodidakt. Daher sieh es mir bitte nach, falls die folgende Frage allzu blöd sein sollte:
Was genau ist ein "Literal" in diesem Kontext? Ein "SQL Literal" / String literal scheint laut meiner Recherche einfach nur ein "Typ" von Daten zu sein, der nicht durch einen Identifier (/Variable?) repräsentiert wird. Also z.B.:
Ein String - Literal = 'Hallo Welt'
Numerischer Literal = 78
In diesem Zusammenhang verstehe ich die Aussage "Ein Name ist kein Literal" nicht.
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Dienstag 6. Dezember 2016, 12:51
von Sirius3
@Judge: ungefähr das ist die Definition von Literal. Genauer steht das z.B. auf
Wikipedia.
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Dienstag 6. Dezember 2016, 13:53
von BlackJack
@Judge: Ich habe Frage 2 komplett nicht verstanden, also nicht verstanden was Du da überhaupt fragst.
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Dienstag 6. Dezember 2016, 15:38
von Judge
Sirius3 hat geschrieben:@Judge: ungefähr das ist die Definition von Literal. Genauer steht das z.B. auf
Wikipedia.
OK, also schonmal die Bezeichnung korrekt verstanden.
Jetzt bringe ich das aber dennoch nicht mit dem Satz "Ein Name ist kein Literal" übereinander. Wenn ein Schemaname z.B. "SchweineToast" ist, kann man doch gleichzeitig die korrekte Aussage treffen " 'SchweineToast' ist ein Zeichenkettenliteral" - richtig? Also was bedeutet "Ein Name ist kein Literal" nun - wie ist diese Aussage zu verstehen?
BlackJack hat geschrieben:@Judge: Ich habe Frage 2 komplett nicht verstanden, also nicht verstanden was Du da überhaupt fragst.
Dann formuliere ich die Frage mal anders:
Wo steht es in der psycopg Doku, das das "automatic Python object to SQL literals conversion" - Feature nicht bei Namen von Datenbanken verwendet werden darf?
Re: psycopg2 verhält sich nicht wie erwartet
Verfasst: Dienstag 6. Dezember 2016, 15:45
von BlackJack
@Judge: Wenn Du "Ein Name ist kein Literal" nicht mit Deinem Verständnis von Literal übereinander bringst, dann hast Du die Bezeichnung doch nicht verstanden. Ein Literal ist Syntax die direkt einen ganz konkreten Wert erzeugt. Ein Name steht indirekt für einen Wert. Der Name SchweineToast kann für alles mögliche stehen. Das Zeichenkettenliteral 'SchweineToast' steht direkt für den Wert der Zeichenkette die das Wort SchweineToast enthält und nichts anderes.
Edit: Das man das nicht für Namen verwenden kann ist in "automatic Python object to SQL literals conversion" implizit enthalten weil die Konverierung zu SQL-Literalen gemacht wird und Namen sind ja eben keine Literale. Per Definition was ein Literal ist.