C++ populate vector from sqlite3 callback function?

c++, sqlite

Solution

The fourth parameter of `sqlite3_exec` can be used to pass information to the callback. In your case, a pointer to the `table` would be useful:

typedef vector<vector<string> > table_type;
static int callbackDB(void *ptr, int argc, char* argv[], char* cols[])
{
    table_type* table = static_cast<table_type*>(ptr);
    vector<string> row;
    for (int i = 0; i < argc; i++)
        row.push_back(argv[i] ? argv[i] : "(NULL)");
    table->push_back(row);
    return 0;
}
...
    rc = sqlite3_exec(db, query, callbackDB, &table, &errmsg);

However, using callbacks like this is not very useful because you get just a bunch of naked strings. You should rather use the prepare/step/finalize interface directly so that you can use proper data types:

class Address {
public:
    Address(int id, const string& name, const string& number);
    ...
}

    ...
    vector<Address> addresses;
    sqlite3_stmt *stmt;
    rc = sqlite3_prepare_v2(db, "SELECT id, name, number FROM addresses",
                            -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        cerr << "SELECT failed: " << sqlite3_errmsg(db) << endl;
        return ...; // or throw
    }
    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
        int id = sqlite3_column_int(stmt, 0);
        const char* name = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
        const char* number = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
        // let's assume number can be NULL:
        addresses.push_back(Address(id, name, number ? number : ""));
    }
    if (rc != SQLITE_DONE) {
        cerr << "SELECT failed: " << sqlite3_errmsg(db) << endl;
        // if you return/throw here, don't forget the finalize
    }
    sqlite3_finalize(stmt);

Problem

I have a sqlite3 table "addresses" like this: ``` +----+------+--------+ | ID | name | number | +----+------+--------+ | 1 | John | 413434 | +----+------+--------+ ``` And i want to populate global vector, which i would be able to use somewhere else and join it with some other data. So far, i have this: ``` ... #include <sqlite3.h> using namespace std; static int callbackDB(void *NotUsed, int argc, char **argv, char **szColName) { for(int i = 0; i < argc; i++) cout << szColName[i] << " = " << argv[i] << endl; return 0; } int main(int argc, char* argv[]) { vector<vector<string> > table; for( int i = 0; i < 2; i++ ) table.push_back(std::vector< std::string >()); sqlite3 *db; char *szErrMsg = 0; // open database int rc = sqlite3_open("database.db", &db); const char *query; query = "SELECT * FROM addresses"; rc = sqlite3_exec(db, query, callbackDB, 0, &szErrMsg); return 0; } ``` How could i get results in vector or in some other way so that i'll be able to use it easier?

Original source