www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - SQLite3 segmentation at prepare statement

reply Charles Hixson <charleshixsn earthlink.net> writes:
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);
}

-- 
Charles Hixson
Sep 18 2013
parent reply "growler" <growlercab gmail.com> writes:
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
Sep 18 2013
parent Charles Hixson <charleshixsn earthlink.net> writes:
You're right about the finalize, but changing the line to:
rc    =    sqlite3_prepare(db, toStringz(sql), cast(int)sql.length + 
1000, &stmt, null);
results in the compile time error:
sqlitetest.d(39): Error: function etc.c.sqlite3.sqlite3_prepare 
(sqlite3* db, const(char)* zSql, int nByte, sqlite3_stmt** ppStmt, 
const(char*)* pzTail) is not callable using argument types (sqlite3*, 
immutable(char)*, int, sqlite3_stmt***, typeof(null))

On 09/18/2013 09:29 PM, growler wrote:
 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
-- Charles Hixson
Sep 19 2013