Pregunta

Estoy trabajando en el desarrollo de una API de C ++ que utiliza complementos personalizados para interactuar con diferentes motores de base de datos utilizando sus API y SQL específicos sintaxis.

Actualmente, estoy intentando encontrar una manera de insertar BLOB, pero como NULL es el carácter de terminación en C / C ++, el BLOB se trunca al construir la cadena de consulta INSERT INTO . 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 posible hacerlo en la consola interactiva SQLite3, debería ser posible construir la cadena de consulta con caracteres de NULL escapados correctamente. Tal vez hay una manera 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 estaban en otros lenguajes de programación (Python).

Gracias de antemano por sus comentarios.

¿Fue útil?

Solución

Querrá usar 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 estándar de tratar los NULL en cadenas es almacenar el principio de la cadena y una longitud, o almacenar un puntero al principio de una cadena y uno al final de la cadena. / p>

Otros consejos

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

Como sugirieron los primeros tres carteles, utilicé declaraciones preparadas, además 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 declaración SQL en la forma de la siguiente cadena constante:

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

sigue siendo el enlace de los valores correspondientes. Esto se hace emitiendo tantas llamadas sqlite3_bind_blob () como columnas. (También recurrí a 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). Entonces:

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 que 3.5.xy posteriores).

Desea precompilar la declaración sqlite_prepare_v2 () , y luego vincular el blob usando sqlite3_bind_blob () . Tenga en cuenta que la declaración que vincule será INSERT INTO table VALUES (?) .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top