Benutzung des Escape-Syntax in prepared statements

Moin,

ich benutze für das automatische Einspielen von Daten in eine Postgres-DB prepared statements. Sonderzeichen maskieren ich mit \, dies führt jedoch zu der bekannten Fehlermeldung: Please use E’’ syntax… blabla :slight_smile:.
Es funktioniert zwar alles, aber ich würde die Meldungen trotzdem gerne loswerden. Dabei bin ich auf ein Problem gestoßen:
Ein prepared statement sieht wie folgt aus:

INSERT INTO foo_table (foo, bar, baz, foobar, barfoo) VALUES($1::int,(SELECT timestamptz 'epoch' + $2::int * interval '1 second'),$3::int,$4::text,$5::text)

Wie schon zu sehen, kommt die Meldung, wenn in einer der letzten beiden Spalten ein \ auftaucht.
Ich habe probiert, das statement folgendermaßen abzuändern:

INSERT INTO foo_table (foo, bar, baz, foobar, barfoo) VALUES($1::int,(SELECT timestamptz 'epoch' + $2::int * interval '1 second'),$3::int,E'$4::text',E'$5::text')

Das funktioniert jedoch nicht. Hat jemand eine Idee?

Lass mal das Casten der Datentypen ganz weg. Du brauchst das nicht, weil die Datenbank schon weiß, dass dort ein ::text ankommt. Außerdem müssten die ::text außerhalb der ‘’ stehen.

Ok, ich probiere es mal mit E’$4’.

Danke,

jan0sch, der jetzt auf den Cronjob wartet. :wink:

Wenn ich es mit E’$4’, E’$5’ probiere, gibt es die Fehlermeldung:

An error occured : ERROR:  bind message supplies 5 parameters, but prepared statement "foo" requires 3

Vermutlich verhindert das Anführungszeichen das ordnungsgemäße Behandeln der $-Parameter?

Hmm, jetzt war ich verwirrt und hatte ursprünglich angenommen, das $1 steht für das Ergebnis eines Regexp.

Du nutzt Prepared Statements? Da drin brauchst du keine Escapes. Damit musst du (und darfst du) deine Daten nicht escapen. Du schickst die beim Ausführen des Prepared Statements einfach so an die Datenbank, wie sie ankommen.

Ok, dann werde ich mit den Warnhinweisen wohl leben müssen.

Du hast mich nicht verstanden.

Wenn du Prepared Statements verwendest, brauchst du kein Escaping.


Das Escaping ist notwendig, wenn du die Anfrage als String zusammensetzt und direkt ausführst. Also so etwas:

select ... from tabelle where id = '1'

Dann müsstest du die 1 escapen. Wenn statt der 1 dir jemand ein ’ als Wert übermittelt, sieht die Anfrage nämlich sonst so aus:

select ... from tabelle where id = '''

Wenn du Prepared Statements verwendest, wird die Anfrage in der Datenbank geparst und vorbereitet und erst später beim Ausführen kommen die Daten hinzu. Beim Ausführen findet aber kein Parsen mehr statt, demzufolge kann niemand aus der SQL-Anfrage ausbrechen und demzufolge muss man die Daten bei einem Prepared Statement nicht escapen.



Hinweis in eigener Sache: das ist Thema in meiner Schulung, siehe Signatur.

Achso. :slight_smile:

Nochmal zur Verinnerlichung:

Wenn ich also ein Skript laufen habe, das via prepared statement Daten in die DB schauffelt, muß ich diese Daten nicht escapen.

Wenn ich eine Funktion (z.B. Trigger) habe, in der ich mir eine SQL-Anweisung zusammenbaue, die ich via EXECUTE ausführe, dann muß ich escapen.

Habe ich das so richtig verstanden?

Zu letzterem Punkt hätte ich noch eine Frage: Kann man das E auch davorschreiben, wenn es nichts zu escapen gibt?

Danke für Deine Antworten.

Ja, ja, ja :wink:

Speziell zu deiner letzten Frage: woher weisst du, ob es nichts zu escapen gibt? Kontrollierst du die Inhalte, sprich, kommen die aus einer vertrauenswürdigen Quelle?

Eine vertrauenswürdige Quelle wäre zum Beispiel der Integer, den du vorher aus einer Tabelle ausgelesen hast und von dem du demzufolge weißt, das sich da drin kein Text sondern nur eine Zahl befinden kann.

Als jemand, dessen Wurzeln in der Systemprogrammierung liegen, vertraue ich sowieso keiner Eingabe von draußen. :wink:

Meine Frage war anders gemeint, aber mir ist das gerade auch selbst klargeworden. Man kann also prinzipiell das E davorsetzen. :slight_smile:

Danke nochmal für Deine Hilfe.