Reputation: 2859
I am misunderstandng something likley fundamental concerning pointers in C.
In the code below, if db_open( "name.db", dbP )
is invoked from within another function, the database is opened/created but dbP
is not recognized afterward in build_schema
but is NULL
. If db_open
is changed to not have an argument sqlite3 *db
and references the gloabal dbP
, then dbP
is recognized in build_schema
and is not NULL
.
The objective is to have db_open
accept any database name and sqlite db handle.
Would you please explain what I am doing wrong and misunderstanding?
Thank you.
I added more code as requested. The database is created successfully and build_schema
is invoked but the sqlite prepare statement returns an error code of 21 because dbP
is null
in that function if print it out. However, if alter db_open
to not have the second argument and reference dbP
in all functions, build_schema
succeeds, the SQL statements are processed, the database has tables in it, and printing out dbP
shows something like AL
.
// function prototype
int db_open( char [], sqlite3 *db );
// Global variables.
sqlite3 *dbP; // The primary database.
int main( void )
{
int rc;
switch( rc = db_open( "path/db_name.db", dbP ) )
{
case 'c' :
build_schema( &J[ i ] );
break;
case 'o' :
get_base( &J[ i ] );
break;
default: ...;
}
}
int db_open( char db_name[], sqlite3 *db )
{
int rc;
// Attempt to open the database as if already existed; will fail if does not exist.
rc = sqlite3_open_v2( db_name, &db, SQLITE_OPEN_READWRITE, NULL );
if ( rc == 14 )
{
// Error code of 14 is a generic "unable to open database."
// First, assume failed to open because database doesn't exist; and modify flags to attempt to create it anew.
rc = sqlite3_open_v2( db_name, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL );
// If rc > 0 then failed to create a database; otherwise, return "c" indicating successful creation of database.
return rc ? 'e' : 'c';
}
else if ( rc )
// Correction of error codes other than 14 is not attempted, and user is informed.
return 'e';
else
// Existing database opened successfully.
return 'o';
} // close db_open
void build_schema( char *j )
{
sqlite3_stmt *stmt;
char *sql;
const char *tail;
int rc;
sql = "SQL statement_1 to create a table;"
"SQL statement_2 to create a table;"
"SQL statement_3; to create a table";
while ( sqlite3_complete( sql ) )
{
rc = sqlite3_prepare_v2( dbP, sql, -1, &stmt, &tail );
sqlite3_step( stmt );
sql = tail;
}
sqlite3_finalize( stmt );
}
Upvotes: 0
Views: 169
Reputation: 74655
The problem I see is that you are passing the value of dbP
rather than the location of dbP
to your helper function which then takes the location of its argument so when the sqlite3_open_v2
function writes. It is writing to the location of the argument of the db_open
function db
rather than the location of the global dbP
.
int sqlite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
const char *zVfs /* Name of VFS module to use */
);
db_open
should take a sqlite3 **
and then it should just pass it along. This then puts the & in the right place. So see have a &dbP
.
switch( rc = db_open( "path/db_name.db", &dbP ) )
int db_open( char db_name[], sqlite3 **db )
rc = sqlite3_open_v2( db_name, db, SQLITE_OPEN_READWRITE, NULL );
Upvotes: 1