:- module(sqlite3, [ sqlite3_query/4, sqlite_flag/2 ]). :- use_foreign_module('libsqlite3.so', [ sqlite3_open([cstr,-ptr], sint), sqlite3_exec([ptr,cstr,ptr,ptr,-ptr], sint), sqlite3_prepare_v2([ptr,cstr,ptr,-ptr,-ccstr], sint), sqlite3_step([ptr], sint), sqlite3_finalize([ptr], sint), sqlite3_column_count([ptr], sint), sqlite3_column_name([ptr,sint], ccstr), sqlite3_column_type([ptr,sint], sint), sqlite3_column_int64([ptr,sint], sint), sqlite3_column_double([ptr,sint], double), sqlite3_column_text([ptr,sint], ccstr), sqlite3_close([ptr], sint) ]). :- help(sqlite3_open(+atom,--stream,-integer),[iso(false),desc('Open an Sqlite3 database returning a connection (as a stream).')]). :- help(sqlite3_exec(+stream,+atom,+integer,+integer,-integer,-integer),[iso(false),desc('Execute an SQL statement on an Sqlite3 database connection')]). :- help(sqlite3_prepare_v2(+stream,+atom,+integer,-integer,-integer,-integer),[iso(false)]). :- help(sqlite3_step(+stream,-integer),[iso(false)]). :- help(sqlite3_finalize(+stream,-integer),[iso(false)]). :- help(sqlite3_column_count(+stream,-integer),[iso(false)]). :- help(sqlite3_column_name(+stream,+integer,-atom),[iso(false)]). :- help(sqlite3_column_type(+stream,+integer,-integer),[iso(false)]). :- help(sqlite3_column_int64(+stream,+integer,-integer),[iso(false)]). :- help(sqlite3_column_double(+stream,+integer,-float),[iso(false)]). :- help(sqlite3_column_text(+stream,+integer,-string),[iso(false)]). :- help(sqlite3_close(+stream,-integer),[iso(false),desc('Close an Sqlite3 database connection.')]). sqlite_flag('SQLITE_OK', 0). sqlite_flag('SQLITE_ERROR', 1). sqlite_flag('SQLITE_ABORT', 4). sqlite_flag('SQLITE_BUSY', 5). sqlite_flag('SQLITE_LOCKED', 6). sqlite_flag('SQLITE_READONLY', 8). sqlite_flag('SQLITE_FULL', 13). sqlite_flag('SQLITE_ROW', 100). sqlite_flag('SQLITE_DONE', 101). sqlite_flag('SQLITE_INTEGER', 1). sqlite_flag('SQLITE_FLOAT', 2). sqlite_flag('SQLITE_TEXT', 3). sqlite_flag('SQLITE_BLOB', 4). sqlite_flag('SQLITE_NULL', 5). :- help(sqlite_flag(+atom,-integer),[iso(false)]). % WARNING: This is experimental! sqlite3_query(Conn, Sql, Cols, Names) :- sqlite_flag('SQLITE_OK', SQLITE_OK), sqlite_flag('SQLITE_ROW', SQLITE_ROW), sqlite3_prepare_v2(Conn, Sql, -1, Statement, _, Ret), Ret =:= SQLITE_OK, repeat, ( ( sqlite3_step(Statement, Ret2), Ret2 =:= SQLITE_ROW ) -> get_row(Statement, Cols, Names) ; ( !, sqlite3_finalize(Statement, _Ret), fail ) ). :- help(sqlite3_query(+stream,+string,-list,-list),[iso(false),desc('Query an Sqlite3 database connection and return a row as a list of column values and a list of column names. Bactracking may return more rows.')]). get_col(_, 0, Cols, Cols, Names, Names) :- !. get_col(Statement, Count, Col, Cols, Name, Names) :- sqlite_flag('SQLITE_INTEGER', SQLITE_INTEGER), sqlite_flag('SQLITE_FLOAT', SQLITE_FLOAT), sqlite_flag('SQLITE_TEXT', SQLITE_TEXT), sqlite_flag('SQLITE_BLOB', SQLITE_BLOB), Count1 is Count - 1, sqlite3_column_name(Statement, Count1, NewName), sqlite3_column_type(Statement, Count1, Type), ( Type =:= SQLITE_INTEGER -> sqlite3_column_int64(Statement, Count1, Value) ; Type =:= SQLITE_FLOAT -> sqlite3_column_double(Statement, Count1, Value) ; Type =:= SQLITE_TEXT -> sqlite3_column_text(Statement, Count1, Value) ; Type =:= SQLITE_BLOB -> sqlite3_column_text(Statement, Count1, Value) ; Value = '(void)' ), get_col(Statement, Count1, [Value|Col], Cols, [NewName|Name], Names). get_row(Statement, Cols, Names) :- sqlite3_column_count(Statement, Count), get_col(Statement, Count, [], Cols, [], Names).