Skip to content

Instantly share code, notes, and snippets.

@StrumentiResistenti
Last active August 5, 2016 18:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StrumentiResistenti/58943f64c7e702dc4f77c15a120619ea to your computer and use it in GitHub Desktop.
Save StrumentiResistenti/58943f64c7e702dc4f77c15a120619ea to your computer and use it in GitHub Desktop.
libDBI sqlite3 sequence number test
/*
* Compile as:
*
* gcc -o check_sqlite3_seq check_sqlite3_seq.c -ldbi
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#include <dbi/dbi.h>
#define DBNAME "debug.sql"
#define DBDIR "/tmp/"
#define FULLPATH DBDIR DBNAME
/**
* query callback type
*/
typedef int (*callback)(void *, dbi_result);
/**
* wrapper for query execution
*/
void query(dbi_conn dbi, char *query, callback cb, void *cb_arg, int exit_code) {
/*
* connect
*/
if (!dbi_conn_ping(dbi) && dbi_conn_connect(dbi) < 0) {
int error = dbi_conn_error(dbi, NULL);
fprintf(stderr, "Could not connect to DB: error %d\n", error);
exit(1);
}
fprintf(stderr, " ---> QUERY: [%s]\n", query);
dbi_result result = dbi_conn_query(dbi, query);
if (!result) {
const char *errmsg = NULL;
dbi_conn_error(dbi, &errmsg);
fprintf(stderr, "Error with query [%s]: %s\n", query, errmsg);
exit(exit_code);
}
if (cb) { while (dbi_result_next_row(result)) { cb(cb_arg, result); } }
}
/**
* callback called to return integer values
*/
int return_integer(void *return_integer, dbi_result result) {
uint32_t *buffer = (uint32_t *) return_integer;
*buffer = 0;
unsigned int type = dbi_result_get_field_type_idx(result, 1);
if (type == DBI_TYPE_INTEGER) {
unsigned int size = dbi_result_get_field_attribs_idx(result, 1);
unsigned int is_unsigned = size & DBI_INTEGER_UNSIGNED;
size = size & DBI_INTEGER_SIZEMASK;
switch (size) {
case DBI_INTEGER_SIZE8:
if (is_unsigned)
*buffer = dbi_result_get_ulonglong_idx(result, 1);
else
*buffer = dbi_result_get_longlong_idx(result, 1);
break;
case DBI_INTEGER_SIZE4:
case DBI_INTEGER_SIZE3:
if (is_unsigned)
*buffer = dbi_result_get_uint_idx(result, 1);
else
*buffer = dbi_result_get_int_idx(result, 1);
break;
case DBI_INTEGER_SIZE2:
if (is_unsigned)
*buffer = dbi_result_get_ushort_idx(result, 1);
else
*buffer = dbi_result_get_short_idx(result, 1);
break;
case DBI_INTEGER_SIZE1:
if (is_unsigned)
*buffer = dbi_result_get_uchar_idx(result, 1);
else
*buffer = dbi_result_get_char_idx(result, 1);
break;
}
fprintf(stderr, " <--- callback got a integer field [%d]\n", *buffer);
} else if (type == DBI_TYPE_DECIMAL) {
fprintf(stderr, " <--- callback got a decimal field\n");
return (0);
} else if (type == DBI_TYPE_STRING) {
const char *int_string = dbi_result_get_string_idx(result, 1);
*buffer = atoi(int_string);
fprintf(stderr, " <--- callback got a ___STRING___ field: \"%s\"\n", int_string);
} else {
fprintf(stderr, " <--- callback got an unknown type");
exit(255);
}
// fprintf(stdout, "Returning integer: [%d]\n", *buffer);
return (0);
}
int main(int argc, char *argv[]) {
/*
* delete previous instance of the DB
*/
unlink(FULLPATH);
/*
* initialize
*/
dbi_inst instance;
if (dbi_initialize_r(NULL, &instance) == -1) {
fprintf(stderr, "Error: no driver loaded!\n");
exit(1);
}
/*
* create a new connection object and set the DB name and location
*/
dbi_conn dbi = dbi_conn_new_r("sqlite3", instance);
dbi_conn_set_option(dbi, "dbname", "debug.sql");
dbi_conn_set_option(dbi, "sqlite3_dbdir", "/tmp/");
/*
* create the DB schema
*/
query(dbi,
"create table if not exists objects (\n"
"\tinode integer primary key autoincrement not null, \n"
"\tobjectname text(255) not null, \n"
"\tlast_autotag timestamp not null default current_timestamp, \n"
"\tchecksum text(40) not null default '', \n"
"\tsymlink text(1024) not null default '')",
NULL, NULL, 2);
/*
* insert a row
*/
query(dbi, "insert into objects (objectname) values ('testname1'), ('testname2'), ('testname3')", NULL, NULL, 3);
/*
* fetch the last sequence number
*/
int rowid = 0;
query(dbi, "select last_insert_rowid()", return_integer, &rowid, 4);
assert(rowid == 3);
/*
* fetch the last sequence number as integer
*/
rowid = 0;
query(dbi, "select cast(last_insert_rowid() as int)", return_integer, &rowid, 5);
assert(rowid == 3);
fprintf(stdout, "Last inserted sequence number is %d\n", rowid);
return (0);
}
@StrumentiResistenti
Copy link
Author

StrumentiResistenti commented Aug 5, 2016

The returned value 3 is right, but the callback function receives it as a string, which is wrong even in the first case, but explicitly in the second one, where last_insert_rowid() is cast to int.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment