C++ SQLite return some values? - c++

I am coding a serverside program that uses SQLite. When a client logs in, I want to get its informations from a Userinfo table.
Its columns are
Userno(int),
money(int),
bankmoney(int),
gender(string),
name,
surname
I want to write these informations to a user structure
struct userstruct
{
int userno;
int money;
int bankmoney
....
}
When a user logs in I want to create a new struct and set infos of user from this table via SQLite.

The following:
static int callback(void *data, int argc, char **argv, char **azColName)
void *data - can be used to give pointer to an object - aka this, or anything else, can be null
int argc - column count - number of selected records
char **argv - ARRAY of column values.
char **azColName - ARRAY of column names
btw: better use prepare - bind - step, like the following sample, this way it works without a callback:
sqlite3_prepare_v2(db, "select distinct name, age from demo where age > ? order by 2,1;", -1, &stmt, NULL);
sqlite3_bind_int(stmt, 1, 16); /* 1 */
while ( (rc = sqlite3_step(stmt)) == SQLITE_ROW) { /* 2 */
printf("%s is %d years old\n", sqlite3_column_text(stmt, 0), sqlite3_column_int(stmt, 1)); /* 3 */
}

Related

Need help storing a value I get from a sqlite3 DB in a C++ variable

I'm having a 'Data.db' with 3 tables in it that store some kind of 'football data'.
One table is for 'teams' and another one is for 'players'. What I want to do now is to get the 'highest' ID from 'Teams' so I can assign newly generated players to that team.
(Every player has a _teamId)
I am able to print the ID I want by using this query and a callback_id that prints just the value I need.
Query:
string query = "SELECT COUNT(ID) FROM TEAMS;";
highest_id = (sqlite3_exec(db, query.c_str(), callback_id, 0, &messageError));
Callback:
int Team::callback_id(void* data, int count, char** values, char** columns) {
int id = atoi(values[1]);
std::cout << "callback_id says: " << id << endl;
return 0;
}
What do I have to do to store this id from my callback function in a variable that I can use later in my program? It seems like I can't just return it and I can't just assign the id value to my Team::_id as it gives me an error:
'invalid use of member ‘Team::_id’ in static member function'
Help would be much appreciated. I'm still trying to learn more about sqlite3 and the callback function in particular but I've wasted so much time on this problem that I don't know what else I could try.
You have a void* argument in sqlite3_exec which you currently set to 0. Instead, pass a pointer to an object there. This makes it possible to store what you like in that object in the callback.
One often passes a pointer to an object and call a non-static member function in that object to deal with the callback.
Example:
class Team {
public:
void func() {
std::string query = "SELECT COUNT(ID) FROM TEAMS;";
sqlite3_exec(db, query.c_str(), &Team::callback_id_proxy, this, &messageError);
// ^^^^
}
// a static callback proxy, casting `data` to a `Team*`
static int callback_id_proxy(void* data, int count, char** values, char** columns) {
return static_cast<Team*>(data)->callback_id(count, values, columns);
}
int callback_id(int count, char** values, char** columns) {
// here you can store what you like in your `Team` object
if(count > 0) highest_id = atoi(values[0]);
else highest_id = 0;
return 0;
}
int highest_id;
};
Note: You may want to use SELECT MAX(ID) FROM TEAMS; instead. Otherwise, you may get duplicates if you delete a team and then add a new team.
Another option is to make func and highest_id static too. I've renamed highest_id into number_of_teams here, because that's what it really is.
class Team {
public:
static int get_number_of_teams() {
std::string query = "SELECT COUNT(ID) FROM TEAMS;";
if(sqlite3_exec(db, query.c_str(),
&Team::callback_count,
nullptr, // static function, no "this" available
&messageError) == SQLITE_ABORT)
throw std::runtime_error("callback_id returned non-zero");
return number_of_teams;
}
static int callback_count(void* data, int count, char** values, char** columns) {
if(count > 0) {
number_of_teams = atoi(values[0]);
return 0;
}
return 1; // indicate error
}
private:
inline static int number_of_teams = -1;
};

SQLite3 in c++ outputing empty list on SELECT

I am currently working on c++ with SQLite3, everything works fine, i can add stuff in the table, but when i do a SELECT * FROM myTable; is returns me (null)...
the variable rc of
sqlite3 *db;
char *zErrMsg;
int rc;
std::string sql = "SELECT * FROM users;";
char csql[sql.size()+1];
strcpy(csql, csql.c_str()); // String to char*
rc = sqlite3_exec(db, csql, callback, 0, &zErrMsg); // rc = 21 Error
...
is 21.. According to https://www.sqlite.org/c3ref/c_abort.html it means that I "Used the library incorrectly".. I then checked with python and online sql on the same .db file and it outputs me what is good..
If anyone could help me and explain me what I did wrong and how to correct it?
Thank you very much !
ps:
here is my function addUser in case the problem is in the add..
bool addUser(std::string username, std::string password){
char cpassword[password.size()+1];
strcpy(cpassword, password.c_str());
std::string shashedP = hashPass(cpassword); // hashPass returns std::string
std::string sql = "INSERT INTO users (username, passw) VALUES ('" + username + "', " + shashedP + ");";
char csql[sql.size()+1];
strcpy(csql, sql.c_str());
rc = sqlite3_exec(db, csql, callback, 0, &zErrMsg); // rc = SQLITE3_OK = 0 everytime
...
That's... strange... code (Plus as was already mentioned, not really valid C++, though some compilers do support C style VLAs as an extension). The normal workflow is to use a prepared statement for anything returning rows, or taking user-supplied arguments in the form of placeholders. sqlite3_exec() is mostly only good for creating tables and such where there's no results and no runtime defined arguments to pass to the query.
For example:
std::string query = "SELECT foo FROM bar WHERE name = ?";
std::string name = "Bob";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, query.c_str(), query.size(), &stmt, nullptr) != SQLITE_OK) {
// Error reporting and handling
}
sqlite3_bind_text(stmt, 1, name.c_str(), name.size(), SQLITE_STATIC);
while (sqlite3_step(stmt) == SQLITE_ROW) {
int foo = sqlite3_column_int(stmt, 0);
// Do stuff with the current row's foo
}
sqlite3_finalize(stmt);
More reading.

sqlite3_exec() Callback function clarification

I am having trouble understanding the use of the callback function in a SQLite3 database.
I understand it is used to traverse SELECT statements with multiple records. But I do not understand how it does that or how to make my own useful callback. I have read through this tutorial several times to try to understand, but that is just not doing it for me.
When I use their example and debug in Visual Studio to see how the argument arrays are populated and traversed i get lost. Also VS only shows the current slot in the array, not the entire array itself.
If you need any clarification please let me know as I am here to learn!
I am asking for someone to explain how the callback is used. Maybe some examples of how others have used it. Just an explanation of what this one is doing even:
static int callback(void *data, int argc, char **argv, char **azColName){
int i;
fprintf(stderr, "%s: ", (const char*)data);
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
Let's assume you have a very simple table called User that looks something like this:
╔════╦══════════╗
║ ID ║ Name ║
╟────╫──────────╢
║ 1 ║ Slvrfn ║
║ 2 ║ Sean ║
║ 3 ║ Drew ║
║ 4 ║ mah ║
╚════╩══════════╝
And you call sqlite3_exec like this (the arguments are described in detail in the documentation):
/* Error handling omitted for brevity */
sqlite3_exec(db, "SELECT * FROM User", my_special_callback, NULL, NULL);
SQLite will execute the passed SQL statement and for every result row that it finds it will call my_special_callback. So with our example User table, my_special_callback will be called 4 times. So let's create my_special_callback:
/*
* Arguments:
*
* unused - Ignored in this case, see the documentation for sqlite3_exec
* count - The number of columns in the result set
* data - The row's data
* columns - The column names
*/
static int my_special_callback(void *unused, int count, char **data, char **columns)
{
int idx;
printf("There are %d column(s)\n", count);
for (idx = 0; idx < count; idx++) {
printf("The data in column \"%s\" is: %s\n", columns[idx], data[idx]);
}
printf("\n");
return 0;
}
Given our example table and data, the output will look like this:
There are 2 column(s)
The data in column "ID" is: 1
The data in column "Name" is: Slvrfn
There are 2 column(s)
The data in column "ID" is: 2
The data in column "Name" is: Sean
There are 2 column(s)
The data in column "ID" is: 3
The data in column "Name" is: Drew
There are 2 column(s)
The data in column "ID" is: 4
The data in column "Name" is: mah
Now to how to make this useful, that is where the 4th argument to sqlite3_exec comes in. From the documentation:
The 4th argument to sqlite3_exec() is relayed through to the 1st
argument of each callback invocation.
So let's say that we want to run our SQL and build a linked list of the names of all of our users. The first thing we need to do is change how we are calling sqlite3_exec:
/* Create my fictional linked list */
struct my_linked_list *head = my_linked_list_alloc();
/*
* Pass a pointer to my list as the 4th argument to sqlite3_exec. Error
* handling omitted for brevity
*/
sqlite3_exec(db, "SELECT * FROM User", my_special_callback, head, NULL);
/* My list is now built, I can do stuff with it... */
my_linked_list_traverse(head, /* ... Stuff ... */);
And modify my_special_callback to use it
/*
* Arguments:
*
* list - Pointer to a linked list of names
* count - The number of columns in the result set
* data - The row's data
* columns - The column names
*/
static int my_special_callback(void *list, int count, char **data, char **columns)
{
struct my_linked_list *head = list;
/*
* We know that the value from the Name column is in the second slot
* of the data array.
*/
my_linked_list_append(head, data[1]);
return 0;
}
Now, if you were to use the callback you included in your question, you would call it like this:
/*
* Pass the table name as the 4th argument to sqlite3_exec. Error
* handling omitted for brevity
*/
sqlite3_exec(db, "SELECT * FROM User", callback, "User", NULL);
The output would be:
User:
ID = 1
Name = Slvrfn
User:
ID = 2
Name = Sean
... etc ...
(Except the User: part would be printed to stderr instead of stdout)
Hopefully this helps clear things up for you. Let me know if there is still something that you don't understand.
That tutorial is horrible, because it does not use anything but sqlite3_exec().
In the general case, the only useful way to use sqlite3_exec() is to replace it with sqlite3_prepare_v2()/sqlite3_step()/sqlite3_column_*()/sqlite3_finalize() calls so that you can read the data in the same place where you actually need to handle it:
sqlite3_stmt *stmt;
const char *sql = "SELECT ID, Name FROM User";
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
print("error: ", sqlite3_errmsg(db));
return;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
int id = sqlite3_column_int (stmt, 0);
const char *name = sqlite3_column_text(stmt, 1);
// ...
}
if (rc != SQLITE_DONE) {
print("error: ", sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);

Sqlite C++ Image to Blob wont store nothing

I googled a lot and couldn't find any solution. I'm currently writing myself an
app in Codegear 2007 C++. I'm writing this app for my little kittens, its kinda' a dairy
but I call it KittyBook.
So i have two tables(sorry didn't understand how to CodeBlock) :
Kitten Info
Kitten Data.
KittenInfo Stores their names and their ID ( primary key ), their gender and their birth. This one works.
The other one should store a Blob. So after trying so many ways. It won't be stored in the table, not even the other data if I do the Query with normal insert but excluding the blob table.
So, I dunno what I'm doing wrong BUT I love SQLite so far. No turning back then eh?
The function is :
void CDatabase::InsertKittenData(int Kitten_ID, int kittenDay, bool DayOrWeek,
char * kitten_weight, char * Kitten_Comment, string PhotoFile) {
unsigned char * blob;
ifstream::pos_type size;
int size2 = 0;
if (FileExists(PhotoFile.c_str())) {
ifstream file(PhotoFile.c_str(), ios::in | ios::binary | ios::ate);
if (file.is_open()) {
size = file.tellg();
blob = new char[size];
file.seekg(0, ios::beg);
file.read(blob, size);
file.close();
}
}
else {
blob = NULL;
}
sqlite3 *dbp;
sqlite3_stmt *ppStmt;
// NULL = primary key autoinc.
char * Sql = "INSERT INTO KittenData VALUES ( NULL, ? , ? ,? , ? , ? , ?);";
int rc = sqlite3_open("KittyBook.db", &dbp);
if (rc)
return;
if (sqlite3_prepare_v2(dbp, Sql, -1, &ppStmt, NULL) != SQLITE_OK) {
return;
}
if (ppStmt) {
if (sqlite3_bind_int(ppStmt, 1, Kitten_ID) != SQLITE_OK)
return;
if (sqlite3_bind_int(ppStmt, 2, kittenDay) != SQLITE_OK)
return;
if (sqlite3_bind_int(ppStmt, 3, DayOrWeek) != SQLITE_OK)
return;
if (sqlite3_bind_text(ppStmt, 4, // Index of wildcard
kitten_weight, strlen(kitten_weight), // length of text
SQLITE_STATIC) != SQLITE_OK)
return;
if (sqlite3_bind_text(ppStmt, 5, // Index of wildcard
Kitten_Comment, strlen(Kitten_Comment), // length of text
SQLITE_STATIC) != SQLITE_OK)
return;
if (sqlite3_bind_blob(ppStmt, 6, blob, size2, SQLITE_TRANSIENT)
!= SQLITE_OK)
return;
if (sqlite3_step(ppStmt) != SQLITE_DONE)
return;
}
sqlite3_finalize(ppStmt);
sqlite3_exec(dbp, "COMMIT", NULL, NULL, NULL);
sqlite3_close(dbp);
}
You declare and initialize size2 as zero:
int size2 = 0;
then the next use of size2 is when you bind the blob:
sqlite3_bind_blob(ppStmt, 6, blob, size2, SQLITE_TRANSIENT)
From the fine manual:
In those routines that have a fourth argument, its value is the number of bytes in the parameter. To be clear: the value is the number of bytes in the value, not the number of characters.
and the fourth argument in this case is size2 and that's zero. The result is that you're telling SQLite to bind a zero-length blob and then you're wondering why nothing gets stored. Well, nothing gets stored because you're asking SQLite to store zero bytes and it is only doing what it is told.
Perhaps you want to use size instead of size2.
mu is too short, gave me the idea to do the Function step by step and increasing column
by column. Dunno what i did wrong, but its working now.
Cheers mu is too short :)

SQLite multi insert from C++ just adding the first one

I have the following code for SQLite:
std::vector<std::vector<std::string> > InternalDatabaseManager::query(std::string query)
{
sqlite3_stmt *statement;
std::vector<std::vector<std::string> > results;
if(sqlite3_prepare_v2(internalDbManager, query.c_str(), -1, &statement, 0) == SQLITE_OK)
{
int cols = sqlite3_column_count(statement);
int result = 0;
while(true)
{
result = sqlite3_step(statement);
std::vector<std::string> values;
if(result == SQLITE_ROW)
{
for(int col = 0; col < cols; col++)
{
std::string s;
char *ptr = (char*)sqlite3_column_text(statement, col);
if(ptr) s = ptr;
values.push_back(s);
}
results.push_back(values);
} else
{
break;
}
}
sqlite3_finalize(statement);
}
std::string error = sqlite3_errmsg(internalDbManager);
if(error != "not an error") std::cout << query << " " << error << std::endl;
return results;
}
When I try to pass a query string like:
INSERT INTO CpuUsage (NODE_ID, TIME_ID, CORE_ID, USER, NICE, SYSMODE, IDLE, IOWAIT, IRQ, SOFTIRQ, STEAL, GUEST) VALUES (1, 1, -1, 1014711, 117915, 175551, 5908257, 112996, 2613, 4359, 0, 0); INSERT INTO CpuUsage (NODE_ID, TIME_ID, CORE_ID, USER, NICE, SYSMODE, IDLE, IOWAIT, IRQ, SOFTIRQ, STEAL, GUEST) VALUES (1, 1, 0, 1014711, 117915, 175551, 5908257, 112996, 2613, 4359, 0, 0); INSERT INTO CpuUsage (NODE_ID, TIME_ID, CORE_ID, USER, NICE, SYSMODE, IDLE, IOWAIT, IRQ, SOFTIRQ, STEAL, GUEST) VALUES (1, 1, 1, 1014711, 117915, 175551, 5908257, 112996, 2613, 4359, 0, 0);
It results just inserting the first insert. Using some other tool lite SQLiteStudio it performs ok.
Any ideas to help me, please?
Thanks,
Pedro
EDIT
My query is a std::string.
const char** pzTail;
const char* q = query.c_str();
int result = -1;
do {
result = sqlite3_prepare_v2(internalDbManager, q, -1, &statement, pzTail);
q = *pzTail;
}
while(result == SQLITE_OK);
This gives me Description: cannot convert ‘const char*’ to ‘const char**’ for argument ‘5’ to ‘int sqlite3_prepare_v2(sqlite3*, const char*, int, sqlite3_stmt*, const char*)’
SQLite's prepare_v2 will only create a statement from the first insert in your string. You can think of it as a "pop front" mechanism.
int sqlite3_prepare_v2(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
From http://www.sqlite.org/c3ref/prepare.html
If pzTail is not NULL then *pzTail is made to point to the first byte
past the end of the first SQL statement in zSql. These routines only
compile the first statement in zSql, so *pzTail is left pointing to
what remains uncompiled.
The pzTail parameter will point to the rest of the inserts, so you can loop through them all until they have all been prepared.
The other option is to only do one insert at a time, which makes the rest of your handling code a little bit simpler usually.
Typically I have seen people do this sort of thing under the impression that they will be evaluated under the same transaction. This is not the case, though. The second one may fail and the first and third will still succeed.