2009-01-01 24 views
8

Sto lavorando allo sviluppo di un'API C++ che utilizza plug-in personalizzati per interfacciare con diversi motori di database utilizzando le loro API e la specifica sintassi SQL .SQLite3: Inserisci BLOB con caratteri NULL in C++

Attualmente, sto cercando di trovare un modo di BLOB inserimento, ma dal momento che è NULL il carattere di terminazione in C/C++, il BLOB viene troncato quando si costruisce la INSERT INTO stringa di query. Finora, ho lavorato con

//... 
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); 
//... 

Mi aspetto che, se è a tutto il possibile per farlo nella console interattiva SQLite3, dovrebbe essere possibile costruire la stringa di query con correttamente sfuggito NULL caratteri. Forse c'è un modo per farlo con SQL standard che è anche supportato dalla sintassi SQLite SQL?

Sicuramente qualcuno deve aver affrontato la stessa situazione prima. Ho cercato su Google e trovato alcune risposte, ma in altri linguaggi di programmazione (Python).

Grazie in anticipo per il vostro feedback.

+0

[Questa] (http://www.sqlite.org/c3ref/bind_blob.html) pagina sembra elencare tutte le funzioni necessarie. – zvrba

risposta

8

Si vorrà utilizzare questa funzione con una dichiarazione preparata.

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

In C/C++, il modo standard di trattare con i NULL in stringhe è o memorizzare l'inizio della stringa, lunghezza, o memorizzare un puntatore all'inizio di una stringa e uno alla fine la stringa.

1

Si desidera precompilare la dichiarazione sqlite_prepare_v2() e quindi associare il BLOB all'utilizzo di sqlite3_bind_blob(). Tieni presente che l'affermazione vincolante sarà INSERISCI NELLA VALUTAZIONE della tabella (?).

+0

Non ne sono sicuro, ma ha un singolo "?" il segnaposto funziona? O è necessario avere il numero di campi della tabella? – jbatista

+1

Sì, è necessario abbinare il conteggio dei campi se lo si fa in questo modo. –

9

Grazie ancora a tutti per il vostro feedback. Questa volta sto segnalando come ho risolto il problema con l'aiuto delle indicazioni fornite qui. Speriamo che questo aiuti gli altri in futuro.

Come suggerito dai primi tre poster, ho utilizzato le dichiarazioni preparate — in aggiunta perché ero interessato anche a ottenere i tipi di dati delle colonne e non sarebbe stato necessario un semplice sqlite3_get_table().

Dopo aver preparato l'istruzione SQL nella forma del seguente stringa costante:

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

rimane la legame dei corrispondenti valori. Questo viene fatto emettendo altrettante chiamate sqlite3_bind_blob() come colonne. (Ho anche fatto ricorso a sqlite3_bind_text() per altri tipi di dati "semplici" perché l'API su cui sto lavorando può tradurre interi/doppi/etc in una stringa). Quindi:

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); 

Si noti inoltre che alcune funzioni (sqlite3_open_v2(), sqlite3_prepare_v2()) compaiono sulle versioni successive SQLite (suppongo 3.5.x e versioni successive).

+1

Manca slqite3_close (db) – kibab

+0

@kibab Grazie, risolto. (A proposito, sarebbe stato il benvenuto per averlo migliorato da solo.) – jbatista

+0

Non sapevo di poter modificare altri post :) Grazie, buono a sapersi. – kibab