2009-01-01 6 views
8

Ich arbeite an der Entwicklung einer C++ API, die benutzerdefinierte Plugins verwendet, um mit verschiedenen Datenbank-Engines mit ihren APIs und spezifische SQL-Syntax zu verbinden.SQLite3: Einfügen von BLOB mit Nullzeichen in C++

Derzeit bin ich versucht, eine Art und Weise des Einsetzens BLOBs zu finden, aber da NULL ist das Abschlusszeichen in C/C++, die BLOB abgeschnitten wird, wenn die INSERT INTO Query-String-Konstruktion. Bisher habe ich gearbeitet habe

//... 
char* sql; 
void* blob; 
int len; 
//... 
blob = some_blob_already_in_memory; 
len = length_of_blob_already_known; 
sql = sqlite3_malloc(2*len+1); 
sql = sqlite3_mprintf("INSERT INTO table VALUES (%Q)", (char*)blob); 
//... 

Ich gehe davon aus, dass, wenn es überhaupt möglich ist, es in der SQLite3 interaktive Konsole zu tun, sollte es möglich sein, die Query-String zu konstruieren, mit richtig NULL Zeichen entkommen. Vielleicht gibt es eine Möglichkeit, dies mit Standard-SQL zu tun, das auch von SQLite SQL-Syntax unterstützt wird?

Sicher muss jemand die gleiche Situation vorher gehabt haben. Ich habe gegoogelt und einige Antworten gefunden, war aber in anderen Programmiersprachen (Python).

Vielen Dank im Voraus für Ihr Feedback.

+0

[This] (http://www.sqlite.org/c3ref/bind_blob.html) Seite scheint alle Funktionen aufzulisten, die Sie brauchen. – zvrba

Antwort

8

Sie möchten diese Funktion mit einer vorbereiteten Anweisung verwenden.

int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); 

in C/C++, die Standardweise mit NULL-Werten in Strings Umgang entweder den Anfang der Zeichenfolge zu speichern, und eine Länge oder speichern einen Zeiger auf den Anfang einer Zeichenfolge und einen zum Ende die Saite.

1

Sie möchten die Anweisung vorkompilieren und dann den Blob mithilfe von sqlite3_bind_blob() binden. Beachten Sie, dass die Anweisung, an die Sie binden, INSERT INTO VALUES (?) ist.

+0

Ich bin mir nicht sicher, aber hat ein einziges "?" Ortsmarker funktioniert? Oder ist es notwendig, so viele wie die Anzahl der Tabellenfelder zu haben? – jbatista

+1

Ja, Sie müssen die Anzahl der Felder anpassen, wenn Sie dies auf diese Weise tun. –

9

Vielen Dank noch einmal für Ihr Feedback. Diesmal berichte ich, wie ich das Problem mit Hilfe der hier angegebenen Hinweise gelöst habe. Hoffentlich hilft das anderen in der Zukunft.

Wie von den ersten drei Plakaten vorgeschlagen, habe ich vorbereitete Anweisungen — zusätzlich verwendet, weil ich auch interessiert war, die Datentypen der Spalten zu bekommen, und eine einfache sqlite3_get_table() würde nicht tun.

Nachdem die SQL-Anweisung in der Form des folgenden konstanten String vorbereiten:

INSERT INTO table VALUES(?,?,?,?); 

es die Reste des entsprechenden Wertes zu binden. Dies geschieht, indem so viele Aufrufe wie die Spalten sqlite3_bind_blob() ausgegeben werden. (Ich habe auch auf sqlite3_bind_text() für andere "einfache" Datentypen zurückgegriffen, weil die API, an der ich arbeite, ganze Zahlen/doubles/etc in einen String übersetzen kann). Also:

void* blobvalue[4]; 
int blobsize[4]; 
char *tail, *sql="INSERT INTO table VALUES(?,?,?,?)"; 
sqlite3_stmt *stmt=0; 
sqlite3 *db; 
/* ... */ 
db=sqlite3_open("sqlite.db"); 
sqlite3_prepare_v2(db, 
        sql, strlen(sql)+1, 
        &stmt, &tail); 
for(int i=0; i<4; i++) 
    sqlite3_ bind_ blob(stmt, 
         i+1, blobvalue[i], blobsize[i], 
         SQLITE_TRANSIENT); 
if(sqlite3_step(stmt)!=SQLITE_DONE) 
    printf("Error message: %s\n", sqlite3_errmsg(db)); 
sqlite3_finalize(stmt); 
sqlite3_close(db); 

Beachten Sie auch, dass einige Funktionen (sqlite3_open_v2(), sqlite3_prepare_v2()) erscheinen auf den späteren SQLite-Versionen (ich nehme an 3.5.x und höher).

+1

Missing slqite3_close (db) – kibab

+0

@ kibab Danke, behoben. (Übrigens wärst du willkommen gewesen, es selbst verbessert zu haben.) – jbatista

+0

Ich wusste nicht, dass ich andere Beiträge bearbeiten kann :) Danke, gut zu wissen. – kibab

Verwandte Themen