sqlite3_bind_text() not binding placeholders - c

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

Related

SQLite3 is not writing table creations to the database

I am currently struggling with a problem that looks to me like it's a regression since I have not previously experienced it before.
The following program is supported to create a SQLite3 database, a new table called sample, and populate it with a single row.
#include <sqlite3.h>
#include <stdio.h>
int main() {
int rc;
sqlite3_stmt* stmt;
sqlite3* db;
rc = sqlite3_open("/tmp/test_second.db", &db);
if (rc) {
printf("Failed to open sqlite3 database: %s\n", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_prepare_v2(db, "CREATE TABLE sample (anum INTEGER PRIMARY KEY); ", -1, &stmt, NULL);
if (rc != SQLITE_OK) {
printf("Failed to create table: %s\n", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
rc = sqlite3_prepare_v2(db, "INSERT INTO sample (anum) VALUES (0); ", -1, &stmt, NULL);
if (rc != SQLITE_OK) {
printf("Failed to insert row: %s\n", sqlite3_errmsg(db));
return 1;
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
I have compiled this on two different environments: CentOS 7.9 with GCC 4.8.5 and SQLite 3.7.17, and Ubuntu 20.04.5 LTS with GCC 9.4.0 and SQLite 3.31.1.
On both environments, compiling and running the program gives the following error:
Failed to insert row: no such table: sample
And the database is a zero-length file with no tables inside. However, pasting these SQL statements directly into an sqlite3 shell works flawlessly. What is wrong with the code?
You're just preparing statements to be run, but you're not running them using the sqlite3_step() function.
The flow is written out in the intro to the SQLite C interface document.
For your two static SQL statements, the convenience wrapper sqlite3_exec() would work out fine:
#include <sqlite3.h>
#include <stdio.h>
int main() {
int rc = 0;
sqlite3 *db;
rc = sqlite3_open("/tmp/test_second.db", &db);
if (rc) {
printf("Failed to open sqlite3 database: %s\n", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_exec(db, "CREATE TABLE sample (anum INTEGER PRIMARY KEY); ", NULL, NULL, NULL);
if (rc != SQLITE_OK) {
printf("Failed to create table: %s\n", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_exec(db, "INSERT INTO sample (anum) VALUES (0); ", NULL, NULL, NULL);
if (rc != SQLITE_OK) {
printf("Failed to insert row: %s\n", sqlite3_errmsg(db));
return 1;
}
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

reading junk out of a blob in sqlite

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.

How to check if record is present in sqlite in C

I am just starting with sqlite, need some quick help. I have following code which is working. In the last query i.e "Select * from company where id = 2". I just want to check if there exists a row having id = 2. That's it. But I am not able to do that. The call back method is common to all the queries so, can't modify it, and don't want to write a specific call back for last query.
Can I get just 0/1 or False/True for the last query?
What I have tried is to use, count rows but again with callback it prints the result but not 0/1.
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main()
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
/* Open database */
rc = sqlite3_open("test.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
fprintf(stderr, "Opened database successfully\n");
}
sql = "CREATE TABLE COMPANY(" \
"ID INT PRIMARY KEY NOT NULL," \
"NAME TEXT NOT NULL," \
"AGE INT NOT NULL," \
"ADDRESS CHAR(50)," \
"SALARY REAL );";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "Table created successfully\n");
}
/* Create SQL statement */
sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
"VALUES (1, 'Paul', 32, 'California', 20000.00 ); " \
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
"VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); " \
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
"VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" \
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
"VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "Records created successfully\n");
}
sql = "Select * from COMPANY where id = 2";
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "Records created successfully\n");
}
sqlite3_close(db);
return 0;
}
You can exec your query differently
sql = "Select * from COMPANY where id = 2";
struct sqlite3_stmt *selectstmt;
int result = sqlite3_prepare_v2(db, sql, -1, &selectstmt, NULL);
if(result == SQLITE_OK)
{
if (sqlite3_step(selectstmt) == SQLITE_ROW)
{
// record found
}
else
{
// no record found
}
}
sqlite3_finalize(selectstmt);

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.

Resources