2009-01-01 22 views
8

Estoy trabajando en el desarrollo de una API C++ que utiliza complementos diseñados a medida para interactuar con diferentes motores de base de datos utilizando sus API y su sintaxis específica de SQL .SQLite3: Inserte BLOB con caracteres NULL en C++

Actualmente, estoy tratando de encontrar una forma de manchas inserción, pero desde NULL es el carácter de terminación en C/C++, el BLOB se va a truncar cuando se construye la INSERT INTO cadena de consulta. Hasta ahora, he trabajado 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); 
//... 

espero que, si es del todo posible hacerlo en la consola interactiva SQLite3, debería ser posible construir la cadena de consulta con escapado adecuadamente NULL caracteres. ¿Tal vez hay una forma de hacer esto con SQL estándar que también es compatible con la sintaxis SQLite SQL?

Seguramente alguien debe haber enfrentado la misma situación antes. Busqué en Google y encontré algunas respuestas, pero estuve en otros lenguajes de programación (Python).

Gracias de antemano por sus comentarios.

+0

[Este] (http://www.sqlite.org/c3ref/bind_blob.html) página parece enumerar todas las funciones que necesita. – zvrba

Respuesta

8

Querrá utilizar esta función con una declaración preparada.

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

En C/C++, la forma habitual de tratar con nulos en las cadenas es o bien almacenar el principio de la cadena y una longitud, o almacenar un puntero al comienzo de una cadena y otra al final de la cuerda.

1

Desea precompilar la instrucción sqlite_prepare_v2() y luego vincula el blob usando sqlite3_bind_blob(). Tenga en cuenta que la instrucción que enlaza será INSERT INTO table VALUES (?).

+0

No estoy seguro de esto pero ¿tiene un solo "?" placemarker funciona? ¿O es necesario tener tantos como el número de campos de tabla? – jbatista

+1

Sí, deberá hacer coincidir el conteo de campo si lo hace de esta manera. –

9

Gracias a todos nuevamente por sus comentarios. Esta vez estoy informando cómo resolví el problema con la ayuda de las indicaciones proporcionadas aquí. Espero que esto ayude a otros en el futuro.

Según lo sugerido por los primeros tres carteles, utilicé las declaraciones preparadas — adicionalmente porque también estaba interesado en obtener los tipos de datos de las columnas, y un simple sqlite3_get_table() no funcionaría.

Después de preparar la instrucción SQL en la forma de la siguiente cadena constante:

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

sigue siendo el unión de los valores correspondientes. Esto se hace publicando tantas llamadas sqlite3_bind_blob() como columnas. (También recurrí al sqlite3_bind_text() para otros tipos de datos "simples" porque la API en la que estoy trabajando puede traducir enteros/dobles/etc en una cadena). Por lo tanto:

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

Tenga en cuenta también que algunas funciones (sqlite3_open_v2(), sqlite3_prepare_v2()) aparecen en las versiones posteriores de SQLite (supongo 3.5.x y posteriores).

+1

Missing slqite3_close (db) – kibab

+0

@kibab Gracias, se arregló. (Por cierto, hubieras sido bienvenido a haberlo mejorado). – jbatista

+0

No sabía que podía editar otras publicaciones :) Gracias, es bueno saberlo. – kibab

Cuestiones relacionadas