Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#9 SQLite3 binding has different semantics for Exec than C API

open
nobody
None
5
2006-11-08
2006-11-08
Michael Houston
No

The SQLite3 API documentation for sqlite3_exec states that:

"Zero or more SQL statements specified in the second
parameter are compiled and executed."

In the binding provided in GNADE for SQLite3, only the
first statement is executed. This is due to the
implementation of Exec, which calls Prepare once, and
throws away the 'tail' of the SQL parameter.

I've implemented a prepare procedure, which provides
the index into the sql string at which the tail starts:

procedure prepare
(self : Handle;
sql : string;
stmt : Statement_Reference;
tail : out Integer;
rv : out Return_Value)
is

function sqlite3_prepare
(db : DB_Access;
zSql : C.char_array;
nBytes : C.int;
ppStmt : access Stmt_Access;
pzTail : System.Address)
return C.int;
pragma Import(C, sqlite3_prepare, "sqlite3_prepare");
-- sqlite3.h:581
-- int sqlite3_prepare(
-- sqlite3 *db, /* Database handle */
-- const char *zSql, /* SQL statement,
UTF-8 encoded */
-- int nBytes, /* Length of zSql in
bytes. */
-- sqlite3_stmt **ppStmt, /* OUT: Statement
handle */
-- const char **pzTail /* OUT: Pointer to
unused portion of zSql */
-- );

cstring : C.char_array := C.To_C(sql);
tail_sql : System.Address;
begin

rv := int_to_ret_val(sqlite3_prepare(Self.db,
cstring,
C.int(-1),

stmt.stmt'Access,

tail_sql'Address)
);

tail := Integer(To_Integer(tail_sql) -
To_Integer(cstring'Address)) + 1;
end prepare;

This can then be used in the Generic_Exec package by
replacing the original Prepare function call with a
call to the new procedure, and inserting the following
recursive call before the final return:

-- Process the tail of the SQL string
if (sql'first + tail < sql'last and then rc =
SQLITE_OK) then
rc := Exec(Self, sql(sql'first + tail ..
sql'last), cb, arg);
end if;

I'm sure there's a better way of doing this, but it
seems to work. I've attached a patch for the relevant
files.

Discussion

  • Patch to provide zero or more statement execution for Exec