Last active
August 5, 2016 18:26
-
-
Save StrumentiResistenti/58943f64c7e702dc4f77c15a120619ea to your computer and use it in GitHub Desktop.
libDBI sqlite3 sequence number test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.