So I'm having some trouble with parameter binding with SQLite in C. I am using sqlite3_bind_* functions to insert BLOBs and strings into a database. After an insertion however, I inspect the database with SQLiteBrowser and find to my surprise that the types are all jumbled up! Here is some sample code that should reproduce the effect.
This chunk creates the table.
const char *TABLE_NAME = "PASSWORD_ENTRY"; const char *USER_ID_COLUMN_NAME = "USER_ID"; const char *INDEX_COLUMN_NAME = "INDEX_VALUE"; const char *SERVICE_COLUMN_NAME = "SERVICE"; const char *SYM_ENC_KEY_COLUMN_NAME = "SYM_ENC_KEY"; const char *ASYM_ENC_KEY_COLUMN_NAME = "ASYM_ENC_KEY"; const char *TIMESTAMP_COLUMN_NAME = "TIMESTAMP"; /* CREATE TABLE IF NOT EXISTS TABLE_NAME ( USER_ID_COLUMN_NAME INTEGER, INDEX_COLUMN_NAME INTEGER, SERVICE_COLUMN_NAME TEXT, SYM_ENC_KEY_COLUMN_NAME BLOB, ASYM_ENC_KEY_COLUMN_NAME BLOB, TIME_STAMP_COLUMN_NAME BLOB, PRIMARY KEY (USER_ID_COLUMN_NAME, INDEX_COLUMN_NAME)); */ char *f = "CREATE TABLE IF NOT EXISTS %s (%s INTEGER, %s INTEGER, %s TEXT, %s BLOB, %s BLOB, %s BLOB, PRIMARY KEY (%s, %s));"; char *s = malloc(snprintf(NULL, 0, f, TABLE_NAME, USER_ID_COLUMN_NAME, INDEX_COLUMN_NAME, SERVICE_COLUMN_NAME, SYM_ENC_KEY_COLUMN_NAME, ASYM_ENC_KEY_COLUMN_NAME, TIMESTAMP_COLUMN_NAME, USER_ID_COLUMN_NAME, INDEX_COLUMN_NAME) + 1); sprintf(s, f, TABLE_NAME, USER_ID_COLUMN_NAME, INDEX_COLUMN_NAME, SERVICE_COLUMN_NAME, SYM_ENC_KEY_COLUMN_NAME, ASYM_ENC_KEY_COLUMN_NAME, TIMESTAMP_COLUMN_NAME, USER_ID_COLUMN_NAME, INDEX_COLUMN_NAME); const char *DB_NAME = "passwordmanager.db"; sqlite3* db; int r = 0; // Get the database r = sqlite3_open(DB_NAME, &db); if (r) { printf("Error opening database: %s\n", sqlite3_errmsg(db)); return NULL; } printf("Database opened.\n"); r = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL); if (r) { printf("Error preparing create table statement: %s\n", sqlite3_errmsg(db)); return 1; } r = sqlite3_step(stmt); if (r != 101 && r) { printf("Error executing create table statement: %s\n", sqlite3_errmsg(db)); return 1; } printf("Password entry table ready.\n"); sqlite3_finalize(stmt);Now that that's done, I'll give you a sample insertion.
sqlite3_stmt *stmt2; long userId = 50l; short index = 2; long timestamp = 100l; char *service = "stackoverflow.com"; const int SYM_ENC_KEY_LEN = 10; const int ASYM_ENC_KEY_LEN = 11; char *symEncKey = "symEncKey"; char *asymEncKey = "asymEncKey"; char *f = "INSERT INTO PASSWORD_ENTRY (USER_ID, INDEX_VALUE, SERVICE, TIMESTAMP, SYM_ENC_KEY, ASYM_ENC_KEY) VALUES (?, ?, ?, ?, ?, ?);"; printf("SQL ready.\n"); r = sqlite3_prepare_v2(db, f, strlen(f), &stmt2, NULL); if (r != 0) { printf("Error preparing addition statement: %s\n", sqlite3_errmsg(db)); sqlite3_finalize(stmt2); sqlite3_close(db); return; } printf("Prepared the addition statement, binding...\n"); sqlite3_bind_int64(stmt2, 1, (sqlite3_int64) userId); sqlite3_bind_int(stmt2, 2, (int) index); sqlite3_bind_text(stmt2, 3, service, strlen(service) + 1, 0); sqlite3_bind_int64(stmt2, 4, (sqlite_int64) timestamp); sqlite3_bind_blob(stmt2, 5, (void *) symEncKey, SYM_ENC_KEY_LEN, 0); sqlite3_bind_blob(stmt2, 6, (void *) asymEncKey, ASYM_ENC_KEY_LEN, 0); // Execute the statement r = sqlite3_step(stmt2); if (r != 101) { printf("Error executing addition statement: %s\n", sqlite3_errmsg(db)); sqlite3_finalize(stmt2); sqlite3_close(db); return; } printf("Executed the addition statement.\n"); sqlite3_finalize(stmt2); sqlite3_close(db);
Now, if you'd care to view the database with SQLiteBrowser or any similar tool you may have, provided you have the same luck as me, you'll see that column SERVICE contains a BLOB and the SYM_ENC_KEY column contains a string, regardless of the fact that I used the opposite sqlite3_bind_* functions. Does anyone have any idea as to how this could be happening? If you need more information, please ask. I am a new poster.