4

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?

6
  • Why don't you do the join in SQL? Commented Apr 5, 2013 at 14:26
  • I don't actually understand you? Commented Apr 5, 2013 at 14:27
  • With what other data do you want to join the addresses data? Commented Apr 5, 2013 at 14:30
  • I have string that will be passed as an argument on program call like this: ./program string And also i want to compare data from database if they fulfill some conditions in relation to other fields which is not possible by sql. Commented Apr 5, 2013 at 15:50
  • 1
    I think that it's very clear what i need. I NEED TO GET DATA OUT, and that has nothing to be done with comparing!!! Commented Apr 5, 2013 at 23:06

1 Answer 1

10

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);
Sign up to request clarification or add additional context in comments.

1 Comment

Great, thank you. I did it with: "vector<vector<string> > &ptr = (vector<vector<string> >)table;"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.