reading junk out of a blob in sqlite - c

I have a snippet of code which is somehow messing up the reading of bytes of a sqlite database. I've experienced this multiple times: first with a PNG where the last three bytes would differ, second with the king james bible and thirdly with a very simple test case. I'm stumped as to where I'm messing up. In all these cases, the command line sqlite tool can see the data inside the database correctly (both when viewed manually and when using writefile).
So the insertion is definitely working correctly, it's just that somehow my extraction is erroneous somehow. I am quite a novice at C so I expect I may have misallocated memory in someway, I just don't understand how.
#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
static char const dummy_content[] =
"hello world more \n\n\n hello worlds \nlalalala";
int
main(int argc, char **argv) {
sqlite3 *db;
sqlite3_stmt *stmt;
int rc, file_len, sqlite_len;
const char *file_contents;
const char *sqlite_contents;
rc = sqlite3_open("blah.db", &db);
if ( rc ) {
fprintf(stderr, "couldn't open db\n");
return 1;
}
/* initialise the schema */
rc = sqlite3_exec(db,
"BEGIN TRANSACTION;"
"DROP TABLE IF EXISTS blobs;"
"CREATE TABLE blobs(id TEXT NOT NULL, value BLOB, PRIMARY KEY(id));"
"COMMIT;",
NULL, NULL, NULL);
if ( rc ) {
fprintf(stderr, "couldn't initialise schema");
return 1;
}
file_contents = dummy_content;
file_len = sizeof(dummy_content);
/* insert the bytes */
rc = sqlite3_prepare_v2(db,
"INSERT INTO blobs VALUES(?, ?);",
-1,
&stmt, NULL);
if ( rc ) {
fprintf(stderr, "error preparing stmt: %s", sqlite3_errmsg(db));
return 1;
}
printf("prepared stmt\n");
rc = sqlite3_bind_text(stmt, 1, "boring", -1, NULL);
rc = rc | sqlite3_bind_blob(stmt, 2, file_contents, file_len, NULL);
if ( rc ) {
fprintf(stderr, "error binding to sql stmt");
return 1;
}
if ( (rc = sqlite3_step(stmt)) != SQLITE_DONE) {
fprintf(stderr, "something went wrong with execution");
}
sqlite3_finalize(stmt);
if ( rc != SQLITE_DONE ) return 1;
printf("loaded db\n");
/* load the bytes */
rc = sqlite3_prepare_v2(db,
"SELECT value FROM blobs WHERE id = ?;",
-1, &stmt, NULL);
if ( rc ) {
fprintf(stderr, "error preparing stmt: %s", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_bind_text(stmt, 1, "boring", -1, NULL);
if ( rc ) { fprintf(stderr, "error binding"); return 1; }
sqlite_len = -1;
while ( (rc = sqlite3_step(stmt)) != SQLITE_DONE ) {
if ( rc == SQLITE_ERROR ) {
fprintf(stderr, "error executing sql");
sqlite3_finalize(stmt);
return 1;
} else if ( rc == SQLITE_ROW ) {
sqlite_contents = sqlite3_column_blob(stmt, 0);
sqlite_len = sqlite3_column_bytes(stmt, 0);
}
}
if ( sqlite_len < 0 ) {
fprintf(stderr, "no value found in db");
sqlite3_finalize(stmt);
return 1;
}
printf("sqlite_len: %i file_len: %i\n", sqlite_len, file_len);
printf("from file string: %s\n", file_contents);
printf("from sqlite string: %s\n", sqlite_contents);
/* this frees the memory for the sqlite_contents */
sqlite3_finalize(stmt);
return 0;
}

You can only use the value returned by sqlite3_column_blob() until the next time you call sqlite3_step(). Your code isn't obeying that restriction (You're trying to print out the blob after another call to sqlite3_step() returns SQLITE_DONE)
From the documentation:
The pointers returned are valid until a type conversion occurs as described above, or until sqlite3_step() or sqlite3_reset() or sqlite3_finalize() is called.

Related

sqlite3_bind_text() not binding placeholders

I am trying to use placeholder parameters as described in the sqlite documentation.
Below is the code I'm running.
No matter how I position the ? in the sql command, sqlite3_bind_text() doesn't work. I have also tried #table, :table, and ?1 as
placeholders. I even tried replacing the first two exec the calls with explicit prepare
and step calls.
What's interesting is that sqlite3_bind_int() works if I have a clause like:
sql = "SELECT * FROM test WHERE rowid = ?;";
Using sprintf() also works:
sprintf(sql, "SELECT %s FROM test;", "message");
/* gcc -l sqlite3 retrieve.c -o retrieve */
#include <stdio.h>
#include <sqlite3.h>
int main()
{
sqlite3 *db;
sqlite3_stmt *stmt;
int result;
const char *sql;
char *err_msg;
err_msg = 0;
result = sqlite3_open("test.db", &db);
if (result)
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
sql = "CREATE TABLE IF NOT EXISTS test ("
"id INTEGER PRIMARY KEY,"
"message TEXT NOT NULL );";
result = sqlite3_exec(db, sql, NULL, 0, &err_msg);
if (result != SQLITE_OK)
{
fprintf(stderr, "SQL exec error: %s\n", err_msg);
sqlite3_free(err_msg);
}
sql = "INSERT INTO test (message) VALUES ('hi how ya doin');";
result = sqlite3_exec(db, sql, NULL, 0, &err_msg);
if (result != SQLITE_OK)
{
fprintf(stderr, "SQL exec error: %s\n", err_msg);
sqlite3_free(err_msg);
}
sql = "SELECT message FROM ?;"; /* doesn't work */
/* sql = "SELECT ? FROM test;"; /\* doesn't work *\/ */
result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
result = sqlite3_bind_text(stmt, 1, "test", -1, SQLITE_STATIC); /* doesn't work */
/* result = sqlite3_bind_text(stmt, 1, "message", -1, SQLITE_STATIC); /\* doesn't work *\/ */
if (result != SQLITE_OK)
{
fprintf(stderr, "Could not bind string\n");
}
else
{
printf("SQLITE_OK\n");
}
while (sqlite3_step(stmt) == SQLITE_ROW) /* checking for done leaves room for error */
{
printf("%s\n", sqlite3_column_text(stmt, 0));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}

Check whether a sqlite3 table column is filled or not

Requirement :
Check whether a sqlite3 table column is filled or not and if it is not filled, fill up with a value.
I assume that if data is not filled to a field that field will show as NULL.
Following commands I have tried, but the commands are not working for me.
UPDATE SET = 1 WHERE = NULL --> Not working
UPDATE SET = 1 WHERE IS NULL --> Not working
UPDATE SET = 1 WHERE = 0 --> Not working
UPDATE SET = 1 WHERE = '' --> Not working
Below is the c code I am using :
#include <stdio.h> /* needed for vsnprintf */
#include <stdarg.h> /* needed for va_list */
#include <stdlib.h> /* needed for malloc-free */
#include <string.h>
#include <sqlite3.h>
int main(int argc, char* argv[])
{
sqlite3 *db;
sqlite3_stmt *stmt;
char *query = NULL, *zErrMsg = 0, *sql = NULL;
char name[20] = "SAM";
int rc, i = 100;
/* Open database */
rc = sqlite3_open("test.db", &db);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
while (1);
return(0);
}
else {
fprintf(stderr, "Opened database successfully..NEW\n");
}
/* Create a table */
rc = sqlite3_exec(db, "create table demo (name text, age integer);", NULL, NULL, &zErrMsg);
if (rc != SQLITE_OK)
{
printf("Error: %s:Unable to create the table\n", zErrMsg);
while (1);
}
asprintf(&query, "insert into demo (name) values ('%s');", name);
/* Insert into table */
sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); /* 2 */
if (sqlite3_step(stmt) == SQLITE_ROW)
{
printf("Inserted successfully\n");
}
if(stmt)
{
sqlite3_finalize(stmt);
stmt = NULL;
}
if(query)
{
free(query);
query = NULL;
}
asprintf(&query, "insert into demo (name, age) values ('%s',%d);", name, i);
/* Insert into table */
sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); /* 2 */
if (sqlite3_step(stmt) == SQLITE_ROW)
{
printf("Inserted successfully\n");
}
if(stmt)
{
sqlite3_finalize(stmt);
stmt = NULL;
}
if(query)
{
free(query);
query = NULL;
}
asprintf(&query, "insert into demo (name) values ('%s');", name);
/* Insert into table */
sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); /* 3 */
if (sqlite3_step(stmt) == SQLITE_ROW)
{
printf("Inserted successfully\n");
}
if(stmt)
{
sqlite3_finalize(stmt);
stmt = NULL;
}
if(query)
{
free(query);
query = NULL;
}
asprintf(&query, "UPDATE demo SET age = 1 WHERE age = NULL");
stmt = NULL;
rc = sqlite3_prepare_v2(db, query, -1, &stmt, 0);
if (rc == SQLITE_OK)
{
printf("sqlite3_prepare_v2:Executed successfully\n");
}
rc = sqlite3_step(stmt); /* 3 */
if (rc != SQLITE_DONE)
{
printf("ERROR inserting data: %s\n", sqlite3_errmsg(db));
}
if(stmt)
{
sqlite3_finalize(stmt);
stmt = NULL;
}
if(query)
{
free(query);
query = NULL;
}
sqlite3_close(db);
return 0;
}
Thanks in advance

Null string retrieve in prepared/bound parameter query SQLite on C

Iam trying to step a simple SELECT query using C and SQLite3, I make it before, but for any strange reason now isn't working the database is very simple:
CREATE TABLE service(
id integer primary key autoincrement,
name text,
url text);
the C code is that:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sqlite3.h>
int error(char *message, sqlite3 *db) {
fprintf(stderr, "[ %s ] Error: %s\n", message, sqlite3_errmsg(db));
return SQLITE_ERROR;
}
void usage(char *appname) {
printf("Usage: %s <service-name>\n", appname);
exit(EXIT_FAILURE);
}
int main(int argc, char * argv[]){
if (argc < 2) {
usage(argv[0]);
}
sqlite3_stmt *stmt = NULL;
sqlite3 *db = NULL;
int rc;
const char *service_name = NULL;
int idx = -1;
char *sql = "select * from service where name is :name";
int sql_len = strlen(sql);
sqlite3_initialize();
rc = sqlite3_open_v2("getip.db", &db, SQLITE_OPEN_READWRITE, NULL);
if (rc != SQLITE_OK)
error("Connecting to database", db);
rc = sqlite3_prepare_v2(db, sql, sql_len, &stmt, NULL);
if (rc != SQLITE_OK)
error("Preparing statement", db);
char *service_search = argv[1];
idx = sqlite3_bind_parameter_index(stmt, ":name");
rc = sqlite3_bind_text(stmt, idx, service_search, strlen(service_search),
SQLITE_STATIC);
rc = sqlite3_step(stmt);
service_name = sqlite3_column_text(stmt, 2);
printf("[debug] Last code: %d\n", rc);
printf("[debug] SQL: %s\n", sqlite3_sql(stmt));
printf("Name: %s\n", service_name);
sqlite3_finalize(stmt);
return EXIT_SUCCESS;
}
that must be returned the value of column 'url' but return null, and another little doubt is that, the documentation from SQLite3.org mention a function for getting SQL from a statement 'expanded' (char
*sqlite3_expanded_sql(sqlite3_stmt *pStmt);), but at compile i obtain:
undefined reference to `sqlite3_expanded_sql'
the last doubt is not important, the really headache is the first one.

In C can a called function make the caller function return?

I'd like to find a way to make a function return (with a specific value) the function that called it. Is it possible in C? Maybe by checking the call stack?
Abstract example: suppose we have two functions
int called() {
if (some_check_fails()) {
/* here make caller() return -1 so "Hello world!\n" is not printed */
}
}
int caller() {
called();
printf("Hello world!\n");
return 0;
}
I'm searching for something to put in the /* ... */ part.
Real-life example: the code I'm working one is a function that exports data in a SQLite file. This means a lot of calls to the SQLite API that need their return values checked each time. The result is an awfully looking and far too long function like this where the if (resp_code != SQLITE_OK) part repeats on and on:
sqlite3 *db;
char *err_msg;
/* Open the database in read-write mode, create it if not exists yet */
int resp_code = sqlite3_open_v2(filename, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
NULL);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: cannot open database %s, %s\n", filename,
sqlite3_errmsg(db));
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* Create table */
char *query_table = "DROP TABLE IF EXISTS sometable; "
"CREATE TABLE sometable "
"(value int, data TEXT);";
resp_code = sqlite3_exec(db, query_table, 0, 0, &err_msg);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* Prepare statement */
char *query = "INSERT INTO sometable VALUES (#i, #s);";
sqlite3_stmt *stmt;
resp_code = sqlite3_prepare_v2(db, query, 150, &stmt, NULL);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* Start transaction */
resp_code = sqlite3_exec(db, "BEGIN TRANSACTION", 0, 0, &err_msg);
if (resp_code != SQLITE_OK) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
return OMG_ERROR_HERE;
}
/* AND SO ON */
What I'd like is something like:
sqlite3 *db;
char *err_msg;
/* Open the database in read-write mode, create it if not exists yet */
int resp_code = sqlite3_open_v2(filename, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
NULL);
return_this_function_if_not_ok(resp_code);
/* Create table */
char *query_table = "DROP TABLE IF EXISTS sometable; "
"CREATE TABLE sometable "
"(value int, data TEXT);";
resp_code = sqlite3_exec(db, query_table, 0, 0, &err_msg);
return_this_function_if_not_ok(resp_code);
/* Prepare statement */
char *query = "INSERT INTO sometable VALUES (#i, #s);";
sqlite3_stmt *stmt;
resp_code = sqlite3_prepare_v2(db, query, 150, &stmt, NULL);
return_this_function_if_not_ok(resp_code);
/* Start transaction */
resp_code = sqlite3_exec(db, "BEGIN TRANSACTION", 0, 0, &err_msg);
return_this_function_if_not_ok(resp_code);
/* AND SO ON */
EDIT 2015-12-21: I chose FUZxxl's answer as best because it's the only one actually answering my question about returning the caller function. On the other hand chux's answer (based on Rowland Shaw's and Ziffusion's) is solving my SQLite problem the way I prefer.
Big big big thanks to all of you!!
Such a thing is not possible in C, but you can get close.
The identifier __func__ is implicitly declared at the beginning of each function as
static const char __func__[];
It's value is the name of the current function as a string. You can write a function-like macro that implicitly passes the name of the caller to the callee. If the function that should receive the name of the caller is something like:
void error_check_fun(const char *function, int code, int result);
you can write a macro like this:
#define error_check(code, result) error_check_fun(__func__, code, result);
Similarly, __FILE__ and __LINE__ are macros that expand to the current source file and line respectively.
You can try something like this.
#define return_this_function_if_not_ok(db, sql_code, sql_msg, code) \
if ((sql_code) != SQLITE_OK) { \
fprintf(stderr, "SQLite error: %s\n", (*sql_msg)); \
sqlite3_free(sql_msg); \
sqlite3_close(db); \
return (code); \
}
sqlite3 *db;
char *err_msg;
/* Open the database in read-write mode, create it if not exists yet */
int resp_code = sqlite3_open_v2(filename, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
&err_msg);
return_this_function_if_not_ok(db, resp_code, err_msg, OMG_ERROR_HERE);
Recommend something like Rowland Shaw and #Ziffusion
Call a function that packs in the data and handles common house-keeping.
int foo(char *err_msg, int code) {
if (msg) {
fprintf(stderr, "SQLite error: %s\n", err_msg);
sqlite3_free(err_msg);
} else {
fprintf(stderr, "SQLite error: %s\n", "Default error message");
}
sqlite3_close(db);
return code;
}
resp_code = sqlite3_exec(...);
if (resp_code != SQLITE_OK) return foo(err_msg, OMG_ERROR_HERE);
...
resp_code = sqlite3_prepare_v2(db, query, 150, &stmt, NULL);
if (resp_code != SQLITE_OK) return foo(NULL, OMG_ERROR_HERE);
Suggest further, include file and line number. This is something I found very useful.
int bar(char *err_msg, int code, const char *file, int line) {
fprintf(stderr, "SQLite error:%s, Code:%d, File:%s, Line%d\n",
err_msg ? err_msg : "Default error message", code, file, line);
}
sqlite3_free(err_msg);
sqlite3_close(db);
return code;
}
#define foo(err_msg, code, file, line) bar((err_msg), (code), __FILE__, __LINE__)
You can use setjmp()/longjmp() to get this effect, although not exactly like how you are wanting:
#include <setjmp.h>
#include <stdio.h>
int check_result;
int some_check_fails() {
return check_result;
}
int called(jmp_buf buf) {
if (some_check_fails()) {
longjmp(buf,1);
}
}
int caller() {
jmp_buf buf;
if (setjmp(buf)==0) {
called(buf);
printf("Hello world!\n");
return 0;
}
else {
printf("Failure\n");
return -1;
}
}
int main() {
check_result = 0;
caller();
check_result = 1;
caller();
}
Output:
Hello world!
Failure
This technique does avoid putting checks in multiple places, effectively implementing a type of exception handling mechanism. However, there are other ways to clean up the code without resorting to this.

sqlite c api insert binding

I'm trying to use the sqlite3_bind_* function calls to insert values in sqlite DB.
Here's the code I'm using:
#include <stdio.h>
#include "sqlite3.h"
#include <stdlib.h>
#include <string.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
int i;
printf("\n callback");
for (i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main() {
int rc;
char *pStrSql,*zErrMsg;
sqlite3 *db;
sqlite3_stmt *pInsertStmt;
int iAge;
char *pStrName;
const char *pStrInsSql;
const char **pzTail;
rc = sqlite3_open("test.db", &db);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
} else {
fprintf(stdout, "Opened database successfully\n");
}
pStrSql = "DROP TABLE employee";
rc = sqlite3_exec(db, pStrSql, callback, 0, &zErrMsg);
pStrSql = "CREATE TABLE employee (name text,age int);";
rc = sqlite3_exec(db, pStrSql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
printf("Table created successfully\n");
}
pStrInsSql = "INSERT INTO employee VALUES (?,?)";
rc = sqlite3_prepare_v2(db,pStrInsSql,-1,&pInsertStmt,NULL);
if( rc != SQLITE_OK) {
printf("\n Cant prepare Error %s :",sqlite3_errmsg(db));
exit(0);
}
pStrName = "prakash";
rc = sqlite3_bind_text(pInsertStmt,1,pStrName,-1,SQLITE_TRANSIENT);
if( rc != SQLITE_OK) {
printf("\n Cant bind text Error %s :",sqlite3_errmsg(db));
exit(0);
}
iAge = 23;
rc = sqlite3_bind_int(pInsertStmt,2,iAge);
if( rc != SQLITE_OK) {
printf("\n Cant bind int Error %s :",sqlite3_errmsg(db));
exit(0);
}
rc = sqlite3_step(pInsertStmt);
if( rc != SQLITE_OK) {
printf("\n Cant execute insert Error %s :",sqlite3_errmsg(db));
exit(0);
}
sqlite3_clear_bindings(pInsertStmt);
sqlite3_reset(pInsertStmt);
sqlite3_finalize(pInsertStmt);
pStrSql = "select * from employee";
rc = sqlite3_exec(db, pStrSql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return 0;
}
The program fails after the call to sqlite3_step().
The error message being "unknown error".
Can you kindly help me resolve this ?
Thanks
Prakash
sqlite3_step() does not return SQLITE_OK on success; you have to check for SQLITE_DONE (and SQLITE_ROW for queries).

Resources