On Wednesday, 18 September 2013 at 21:31:00 UTC, Charles Hixson
wrote:
I'm trying to use SQLite3 in D, but am getting a segmentation
fault when I attempt to replace the exec statement with a
prepare statement. What am I doing wrong?
If the prepare statement is commented out, and the exec
statement is uncommented, the program runs successfully.
(There's no data yet in the database file.)
The test program is:
pragma (lib, "sqlite3");
import etc.c.sqlite3;
import std.exception;
import std.stdio;
import std.string;
/** int function(void*, int, char**, char**) callback */
extern(C)
int callback (void* notUsed, int argc, char** argv,
char** azColName)
{
for (int i = 0; i < argc; i++)
{ printf ("%s = %s\n", azColName[i], argv[i] ? argv[i] :
"null"); }
printf ("\n");
return 0;
}
void main()
{ sqlite3* db;
int rc;
char* zErrMsg = null;
sqlite3_stmt** stmt;
rc = sqlite3_open (toStringz("data/sqlitetest.db"),
&db);
if (SQLITE_OK != rc)
{ printf ("DB create error: %s\n", sqlite3_errmsg(db) );
}
string sql =
"create table if not exists wrds (name text primary
key, id int)\0";
rc = sqlite3_exec(db, sql.ptr, &callback,
cast(void*)0, &zErrMsg);
if (SQLITE_OK != rc)
{ printf ("DB create table error: %s\n",
sqlite3_errmsg(db) );
printf ("sql = <<%s>>\n", sql);
}
sql = "select * from wrds\0";
rc = sqlite3_prepare(db, toStringz(sql),
cast(int)sql.length, stmt, null);
// if (SQLITE_OK != rc)
// { printf ("DB prepare statement error: %s\n",
sqlite3_errmsg(db) );
// printf ("sql = <<%s>>\n", sql);
// }
// rc = sqlite3_step(*stmt);
// if (SQLITE_OK != rc)
// { printf ("DB statement step error: %s\n",
sqlite3_errmsg(db) );
// printf ("sql = <<%s>>\n", sql);
// }
//
// rc = sqlite3_exec(db, sql.ptr, &callback,
cast(void*)0, &zErrMsg);
// if (SQLITE_OK != rc)
// { printf ("DB select error: %s\n", sqlite3_errmsg(db)
);
// printf ("sql = <<%s>>\n", sql);
// }
//
rc = sqlite3_close (db);
enforce (rc == SQLITE_OK);
}
Sorry I'm not a sqlite3 expert, nor do I have access to DMD at
the moment so cannot fully test but that sqlite3_stmt** looks
wrong, try this:
change:
---
sqlite3_stmt** stmt;
...
rc= sqlite3_prepare(db, toStringz(sql), cast(int)sql.length,
stmt, null);
...
rc= sqlite3_step(*stmt);
---
to:
---
sqlite3_stmt* stmt;
...
rc= sqlite3_prepare(db, toStringz(sql), cast(int)sql.length,
&stmt, null);
...
rc= sqlite3_step(stmt);
---
I think (from ancient memory) that you also need to clean up the
statement with something like:
sqlite_finalize(stmt);
but don't quote me on that :D