Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

newbie: sqlite3 programm

41 views
Skip to first unread message

tok...@gmail.com

unread,
Jul 26, 2018, 10:39:47 AM7/26/18
to
Hi there,

here is my prog:

#include <iostream>
using std::cout;

#include <string>
using std::string;

#include <stdlib.h>
#include <sqlite3.h>

static int callback(void *NotUsed, int argc, char **argv, char **azColName) {

int i;
for(i = 0; i<argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}

cout << "\n";
return EXIT_SUCCESS;
}

void openDb(const string &fn, sqlite3 *db) {

// Open database
int rc = sqlite3_open(fn.c_str(), &db); // ???

if( rc ) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "Opened database successfully\n");
}
}

//--- main --------------------------------------------------------------------

int main(int argc, char* argv[]) {

sqlite3 *db; // ???
char *zErrMsg = 0;
int rc;
const char *sql;

openDb("tester.db", db); // ???

// Create SQL statement
sql = "SELECT * FROM COMPANY;";

// Execute SQL statement
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);

if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Records created successfully\n");
}

sqlite3_close(db);

return EXIT_SUCCESS;
}

--------------------------------------------------

It does not work correctly. When I compile my prog there is a warning:

sqlite3.cpp: In function ‘int main(int, char**)’:
sqlite3.cpp:43:25: warning: ‘db’ is used uninitialized in this function [-Wuninitialized]
openDb("tester.db", db); // ???

I have comment out critical parts with // ???
Can anyone help me please? Thanx a lot.

Here is the result when I call the prog:


Opened database successfully
SQL error: (null)

o-o

Thomas





Barry Schwarz

unread,
Jul 26, 2018, 1:02:46 PM7/26/18
to
You define db in main but do not set its value (initialization or
assignment). Since db is passed to openDb by value, the compiler
correctly notifies you that this is invalid. This indeterminate value
is then copied to the local variable db in openDb. You pass the
address of this local variable to sqlite3_open which will replace the
current value by dereferencing this address. The local variable db
now contains the result of sqlite3_open. Unfortunately, this local
variable is destroyed when openDb returns. The end result is the
variable db in main still has the original indeterminate value (which
happened to be NULL on your system).

You apparently wanted openDb to change the value of db in main. The
way to do this is:
Call openDb with &db as the second argument. (Since you are not
passing the value of db, the fact that its value has not been set is
irrelevant. The address of db is a valid address regardless of the
value it points to.)
Change the signature of openDb to receive sqlite** instead of
sqlite*. (Since db in main has type sqlite*, &db has type sqlite**.)
Change the call to sqlite3_open from &db to db. (db in openDb has
the correct type, sqlite**. Its value is the address of db in main.
sqlite3_open will dereference the value it receives and update the
variable pointed to, which happens to be db in main. At this point,
db in main will contain the value (address) you need it to.)

It would be easier to understand these concepts if you used different
names for the variable in main and the parameter in openDb. Using db
for both variables led to wrong conclusion that when sqlite3_open
updated db in openDb it would somehow affect the value of db in main.

--
Remove del for email

Thomas Kaufmann

unread,
Jul 27, 2018, 7:04:49 AM7/27/18
to
Thanks. I'll try it.

Jorgen Grahn

unread,
Jul 27, 2018, 8:07:34 AM7/27/18
to
On Thu, 2018-07-26, tok...@gmail.com wrote:
> Hi there,
>
> here is my prog:
>
> #include <iostream>
> using std::cout;
>
> #include <string>
> using std::string;
>
> #include <stdlib.h>
> #include <sqlite3.h>
>
> static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
...

Perhaps you should look for a C++ API to sqlite3. Callbacks is one of
those things that C++ (especially C++11 with lambdas and
std::function) are better at than C, and a C++ API would surely let
you use those (or avoid callbacks entirely).

The C API lets you pass a context as a void*, but you're not using it.
I find that I almost always end up using it, because otherwise I must
use global variables to communicate with the callback's
implementation. (In your case you use stdout and cout.)

> int i;
> for(i = 0; i<argc; i++) {
> printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
> }
>
> cout << "\n";

Mixing printf()/stdout output with std::cout output is supported, but
it's confusing and can hurt performance. Stick to one of them.

> return EXIT_SUCCESS;

EXIT_SUCCESS is normally used with the return from main(), or in exit().
If the sqlite3 docs don't explicitly tell you to use it, don't.

...

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Thomas Kaufmann

unread,
Jul 28, 2018, 8:46:07 AM7/28/18
to
Thanx al lot.

o-o

Thomas

Thomas Kaufmann

unread,
Jul 29, 2018, 10:26:52 AM7/29/18
to
Barry: it works. THANK YOU!
0 new messages