SQLite3: Inserir BLOB com caracteres NULL em C ++
Pergunta
Eu estou trabalhando no desenvolvimento de API de C ++ que usa plugins customizados a interface com diferentes bancos de dados usando suas APIs e SQL específica sintaxe.
Atualmente, estou tentando encontrar uma maneira de inserir BLOBs, mas desde NULL
é
o caráter de terminação em C / C ++, o BLOB fica truncado ao construir
INSERT INTO string de consulta. Até agora, eu tenho trabalhado com
//...
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, se for de todo possível fazê-lo no console interativo SQLite3, deve ser possível construir a string de consulta com personagens NULL
adequadamente escaparam. Talvez haja uma maneira de fazer isso com o SQL padrão, que também é suportado pelo SQLite SQL sintaxe?
Certamente alguém deve ter enfrentado a mesma situação antes. Eu pesquisei e encontrei algumas respostas, mas estavam em outras linguagens de programação (Python).
Agradecemos antecipadamente para o seu feedback.
Solução
Você vai querer usar esta função com uma declaração preparada.
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
C / C ++, a maneira padrão de lidar com nulos em cadeias, quer seja para armazenar o início da cadeia e um comprimento, ou armazenar um apontador para o início de uma cadeia e um para o final da cadeia.
Outras dicas
Obrigado a todos novamente por seu feedback. Desta vez eu estou relatando como eu resolvi o problema com a ajuda das indicações fornecidas aqui. Esperemos que isto irá ajudar os outros no futuro.
Como sugerido pelos três primeiros cartazes, fiz uso elaborou demonstrações -. Além disso, porque eu também estava interessado na obtenção de tipos de dados das colunas, e uma sqlite3_get_table()
simples não faria
Depois de preparar a instrução SQL na forma do seguinte string constante:
INSERT INTO table VALUES(?,?,?,?);
permanece o de ligação dos valores correspondentes. Isto é feito através da emissão de tantas chamadas sqlite3_bind_blob()
como as colunas. (Eu também recorreu a sqlite3_bind_text()
para outros tipos de dados "simples" porque a API que estou trabalhando pode traduzir números inteiros / duplos / etc para uma string). Assim:
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);
Note também que algumas funções (sqlite3_open_v2()
, sqlite3_prepare_v2()
) aparecem nas versões mais tarde SQLite (suponho 3.5.x e posterior).
Você quer pré-compilar o sqlite_prepare_v2()
declaração, e depois ligar o blob em usar sqlite3_bind_blob()
. Note-se que a declaração que ligam in será inserir valores da tabela (?) .