2010-02-08 10 views
7

Es ist unmöglich zu sqlite3_bind_text ein Tabellenname, weil sqlite3_prepare_v2 eine Anweisung wie vorzubereiten versagt:Gibt es eine C SQLite-API zum Angeben/Entkommenlassen des Namens einer Tabelle?

SELECT * FROM ? ; 

ich den Namen Tabelle vermuten benötigt, um die Anweisung zu analysieren, so dass die zitierte Bedürfnisse vor sqlite3_prepare_v2 geschehen sein.

Gibt es so etwas wie ein ? Vielleicht existiert es bereits unter einem Namen, den ich nicht erkennen kann, aber in der Funktionsliste kann ich nichts finden.

+1

Ihre vorgeschlagene sqlite3_quote_tablename-Funktion könnte die Eingabe bereinigen, um SQL-Injection-Angriffe zu verhindern. Dazu könnte es die Eingabe analysieren, um sicherzustellen, dass es sich um ein Zeichenfolgenliteral handelt. http://www.sqlite.org/lang_expr.html#litvalue – momeara

+0

Eine sehr späte Antwort: Danke, das war die Route, die ich genommen habe. Mein ehemaliger Arbeitgeber besitzt diesen Code jetzt aber. Wenn du das als Antwort posten willst, werde ich es akzeptieren :) – gavinbeatty

Antwort

1

Ihre vorgeschlagenen sqlite3_quote_tablename Funktion könnte die Eingabe sanieren SQL-Injection-Angriffe zu verhindern. Dazu könnte es die Eingabe analysieren, um sicherzustellen, dass es sich um ein Zeichenfolgenliteral handelt. http://sqlite.org/lang_expr.html#litvalue

+0

T er antwortet, dass meine vorgeschlagene Funktion nicht existiert, und der Link ist ein nützlicher Leitfaden, um ihn zu implementieren;) – gavinbeatty

2

Wenn ein Tabellenname ungültige Zeichen enthält, können Sie den Tabellennamen in doppelte Anführungszeichen setzen, so.

sqlite> create table "test table" (id); 
sqlite> insert into "test table" values (1); 
sqlite> select * from "test table"; 
id 
---------- 
1 

Natürlich sollten Sie möglichst keine ungültigen Zeichen verwenden. Es macht die Entwicklung komplizierter und ist fast immer unnötig (IMO, das einzige Mal, wenn es notwendig ist, wenn Sie ein Projekt erben, das bereits auf diese Weise fertig ist und es zu groß ist, um es zu ändern).

+0

Das Problem besteht darin, dies programmgesteuert zu tun. Gibt es eine offizielle Methode? – gavinbeatty

+0

+1 für die erste Quelle, die ich finden konnte, erzählte mir das Escape-Zeichen für Tabellen und Spalten. Anscheinend ist mein google-fu heute schwach ... –

+0

@Charlie Kilian, danke, sql ist von einer Datenbank zur anderen ziemlich beständig, der schwierige Teil ist, alle kleinen Uneinheitlichkeiten zu finden. Einige andere Datenbanken, wie SQL-Server und Zugriff, verwenden '[' und ']', um ungültige Objektnamen zu umgehen. sqlite ustes '" ', was interessanterweise auch für Strings verwendet werden kann, obwohl ''' mehr Standard ist und in sqlite und den meisten Datenbanken unterstützt wird. –

0

Wenn SQLite nicht Tabellennamen als Parameter akzeptieren, ich glaube nicht, gibt es eine Lösung für Ihr Problem ...

berücksichtigen, dass:

Parameter, die nicht zugeordnet sind, Werte, die sqlite3_bind() verwenden, werden als NULL behandelt.

Also im Falle Ihrer Abfrage wäre der Tabellenname NULL, was natürlich ungültig ist.

+0

Es gibt keine Aussage zu 'sqlite3_step', wenn 'sqlite3_prepare_v2' fehlschlägt. I ' Ich frage, ob es eine andere API gibt, um etwas wie einen Tabellennamen zu binden. Etwas wie 'printf% q" 'in bash. edit: Formatierung – gavinbeatty

+1

Was ich meine ist, dass Sie keine Aussage vorbereiten können, die führen könnte zu einer falschen Bindung von Parametern –

1

Wenn SQLite mit Prepared Statements mit Parametern die Parameter: „gibt einen Platzhalter in dem Ausdruck für einen Literalwert, die bei Laufzeit ausgefüllt ist“

Bevor jede SQL-Anweisung ausführt, SQLite „kompiliert“ die SQL-Zeichenfolge in eine Reihe von opcodes, die von einer internen virtuellen Maschine ausgeführt werden. Die Tabellennamen und Spaltennamen, auf denen die SQL-Anweisung ausgeführt wird, sind ein notwendiger Teil des Kompilierungsprozesses.

Sie können die Parameter „Werte“ zu Prepared Statements wie diese binden:

SELECT * FROM FOO WHERE name=?; 

Und dann sqlite3_bind_text() rufen Sie die Zeichenfolge gavinbeatty auf die bereits kompilierten Anweisung zu binden. Dies bedeutet jedoch, Architektur, dass Sie nicht Verwendung Parameter wie folgt aus:

SELECT * FROM ? WHERE name=?; // Can't bind table name as a parameter 
SELECT * FROM FOO WHERE ?=10; // Can't bind column name as a parameter 
+1

Ich weiß, dass der Tabellenname nicht gebunden werden kann, da die parse/compile-Stufe den Tabellenname benötigt Ich suche nach einer etablierten Möglichkeit, entweder zu testen, dass ein Tabellenname gültig ist, oder a zu kanonisieren Tabellenname – gavinbeatty

0

Ich war auf der Suche nach so etwas und konnte es auch nicht finden. In meinem Fall befanden sich die erwarteten Tabellennamen immer in einem festen Satz von Tabellen (diese waren also leicht zu validieren).Die Feldnamen auf der anderen Seite waren nicht so, also habe ich die Zeichenfolge gefiltert, ziemlich alles entfernt, was kein Buchstabe, Nummer oder Unterstrich war (ich wusste, dass meine Felder zu diesen Parametern passen würden). Das hat den Trick gemacht.