Creating an sqlite3 table with c++ - c++

I know their is another question with this exact title but it doesn't solve my problem, so here goes.
I am following a tutorial on using SQLite with c++, but when I run my program to create the database table, I get an error;
static int create_database(const char *s);
static int create_table(const char *s);
int main(){
const char *file = "Mafia.sqlite";
sqlite3 *db;
create_database(file);
create_table(file);
}
static int create_database(const char* s){
sqlite3 *db = NULL;
int query = 0;
query = sqlite3_open_v2(s, &db, SQLITE_OPEN_CREATE, NULL);
cout << "Database created successfully!\n";
sqlite3_close(db);
return 0;
}
static int create_table(const char* s){
sqlite3 *db;
string sql = "CREATE TABLE IF NOT EXISTS USERS("
"ID INTEGER PRIMARY KEY AUTOINCREMENT,"
"USERNAME TEXT NOT NULL,"
"PASSWORD TEXT NOT NULL);";
try{
int query = 0;
query = sqlite3_open_v2(s, &db, SQLITE_OPEN_READWRITE, NULL);
char *error_message;
query = sqlite3_exec(db, sql.c_str(), NULL, 0, &error_message);
if(query != SQLITE_OK){
cerr << "Error occurred creating table!\n";
sqlite3_errmsg(db);
sqlite3_free(error_message);
}else
cout << "Table created successfully\n";
sqlite3_close(db);
}
catch(const exception &e){
cerr << e.what() << '\n';
}
}
My terminal returns the following:
Database created successfully!
Error occurred creating table!
test(13698,0x109148dc0) malloc: Non-aligned pointer 0x102bd9641 being freed
test(13698,0x109148dc0) malloc: *** set a breakpoint in malloc_error_break to debug
Edit
I corrected the sql error and I still have the same problem
Thanks.

There are couple of things,
First you need to initialize error_message to nullptr. Otherwise sqlite3_free will cause a crash since error_message is having some garbage value.
Secondly, according to the SQLITE documentation, you need to use atleast one of the three options while opening an SQLITE connection,
SQLITE_OPEN_READONLY
SQLITE_OPEN_READWRITE
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
You are not supposed to use SQLITE_OPEN_CREATE as a standalone option.
If you change these two, it should work fine.

Related

SQLite3 Insert statement error, but error message blank?

I'm working on a basic program to learn how to use SQLite3; a user gives input on a song they'd like to add to a SQLite database, and it is inserted. As far as I can seen, the insert statement I'm generating- while not pretty- is a valid statement, but once it reaches my queryDatabase() function it enters the error clause. It prints "Error in execution: ", but when it moves on to errmsg, it seems to enter into a state where nothing happens/no actual error message is printed until I enter .quit. I've tried altering the print line like cout << "ERROR EXECUTING SQL: " << errmsg << "End";, and "End" never prints.
Here is the section of code that calls the queryDatabase() function/passes the command string. args refers to a vector that contains the user input:
string sqlq;
sqlq = "INSERT INTO songs (sid, title, composer) VALUES(";
sqlq.append(args[2]); sqlq.append(", "); sqlq.append("\'"); sqlq.append(args[3]); sqlq.append("\'"); sqlq.append(", "); sqlq.append("\'"); sqlq.append(args[4]); sqlq.append("\'"); sqlq.append(");");
data.queryDatabase(sqlq);
and here is the queryDatabase() function:
sqlite3 *db;
char * errmsg = 0;
int rc;
void Data::queryDatabase(string queryString){
if(queryString.empty()) return;
const char * sqlQuery = queryString.c_str();
rc = sqlite3_exec(db, sqlQuery, callback, (void *) data, &errmsg);
if( rc != SQLITE_OK) {
cout << "Error in execution: " << errmsg;
} else {
cout << "\nSQL QUERY SUCCEEDED\n";
}
}
Both queryString and sqlQuery print INSERT INTO songs (sid, title, composer) VALUES(1905, 'Anti-rage', 'Emperor X'); which as far as I know is a valid command, as copy and pasting this when working direct in the database from terminal results in the song being added. Why might this not be inserting correctly, and why am I not being given an error message?
MODIFIED FOR MORE INFO:
Here's the callback
static int callback(
void * data, //pass through data provided to sqlite3_exec() [4th argument]
int argc, //# of cols in table row
char ** argv, //array of strings representing table row values
char ** azColName //array of strings representing column names
){
for (int i=0; i<argc; i++){
cout << argv[i] << ", ";
}
cout << "\n";
return 0;
}

SQLite errorcode: sqlite_step() returns 5 (SQLITE_BUSY)

I am working on a school project which involves SQLite3.
I've created a bunch of functions for my DatabaseManager class which all work quite good.
Now, after adding a function with a DELETE statement, sqlite3_step() returns SQLITE_BUSY and the sqlite3_errmsg() says "Database is locked".
Before opening this function I have already called sqlite3_finalize() and sqlite3_close().
int errorcode;
sqlite3 *db;
//sql statement
std::string statement = "DELETE FROM tbl_follower WHERE flw_ID = " + std::to_string(row);
sqlite3_stmt *binStatement;
errorcode = sqlite3_open(m_filePath.c_str(), &db);
if (errorcode != SQLITE_OK)
std::cerr << sqlite3_errmsg(db) << std::endl;
errorcode = sqlite3_prepare_v2(db, statement.c_str(), statement.size(), &binStatement, NULL);
if(errorcode != SQLITE_OK)
std::cerr << sqlite3_errmsg(db) << std::endl;
errorcode = sqlite3_step(binStatement);
if (errorcode == SQLITE_DONE)
{
sqlite3_finalize(binStatement);
sqlite3_close(db);
}
else
{
//error
std::cerr << sqlite3_errmsg(db) << std::endl;
sqlite3_finalize(binStatement);
sqlite3_close(db);
}
I am pretty sure the issue is somewhere in this code because I have already checked all of my other functions for mistakes (which all work without giving an error). My SQL statement is also correct.
"Database is locked" means that there is some other active transaction.
You probably forgot to finalize a statement in some other part of the program.

MySQL in C++ Seg Fault

I'm implementing mySQL in C++ and ran into an issue. I'm getting a seg fault. And I'm not sure why.
Was hoping someone would know what is going on.
The seg fault seems to be happening somewhere after the MYSQL_ROW productList; line, I haven't been able to pin point where though.
void Receiving::getProduct(const string productToReturn) {
MYSQL *connect, mysql; //Pointers to MySQL
connect = mysql_init(&mysql); // Initialize the connections
int totalRows = 0;
connect = mysql_real_connect(connect,SERVER,USER,PASSWORD,DATABASE,0,NULL,0); //Connect to database
if(connect) { //If connection successful
string sqlQuery; //will hold query
MYSQL_RES *resSetProduct; //define product result set
MYSQL_ROW productList; //define row for product
sqlQuery = "SELECT * FROM Inventory WHERE item_id = \' "; //Create query with desired product id
sqlQuery += productToReturn;
sqlQuery += " \'";
mysql_query(connect, sqlQuery.c_str()); // Send query to the database
resSetProduct = mysql_store_result(connect); // Receive the result and store it in resSetProduct
totalRows = mysql_num_rows(resSetProduct); // count of stored rows
if(totalRows == 0){ //nothing found
cout << "Sorry! No inventory found for that product!" << endl;
}
else {
cout << "Product Id In Stock" << endl;
while( (productList = mysql_fetch_row(resSetProduct)) != NULL ) { //printout the products
cout << productList[0] << " " << productList[1] << endl;
}
}
mysql_free_result(resSetProduct);
}
else //Failed to connect
cerr << "Failed To Connect!";
mysql_close(connect);
}
You should check if mysql_query returns zero. If it does not, mysql_store_result will return NULL and mysql_num_rows might fail with a segfault.
If mysql_query returns non-zero you can check the error codes according to the mysql documentation, eg. here: MySQL mysql_query
As soon as those errors are cleared, mysql_num_rows should not segfault anymore.

Sqlite c++ ATTACH memory database

I try to attach in memory db to an existing db connection via c++ api like this:
void InMemoryDbtest(){
sqlite3 *db;
int rc = sqlite3_open("E:/VS_workspace/ConsoleSQLITE/Debug/TPCH.sqlite", &db);
if (rc){
cout << "nie moge otworzyc bazy danych ";}
else{
cout << "otwarcie bazy ---- udalo sie\n";}
char *err;
sqlite3_exec(db, "ATTACH DATABASE 'file::memory:?cache=shared' as pom",0,0,&err);
cout << "error" << err << endl;
string q = "create table pom.bla as select n_name from NATION ";
sqlite3_exec(db, q.c_str(), 0, 0, &err);
cout << "error" << err << endl;
}
I get 2 error messages"
unable to open database: file:memory
and
unknown database pom
Any ideas? When i try to attach db in sqlite console everything works just fine
Thank you for your suggestions the solution is:
first : set SQLITE_USE_URI flag in sqlite3.c to 1 instead of 0 (just using SQLITE_OPEN_URI flag with sqlite3_open_v2() wsn't enough)
#ifndef SQLITE_USE_URI
# define SQLITE_USE_URI 1
#endif
then you can use uri's with all sqlite3 functions.
proper uri for windows is:
int rc2 = sqlite3_open("file:///E:/VS_workspace/ConsoleSQLITE/Debug/TPCH.sqlite", &db);

C++ MySQL Sql syntax error while syntax is correct

my C++ program reads a file with sql query and tries to execute it. When I execute the query using phpmyadmin, it works, but when executed in my program, it ends up with the following error:
Code:
ifstream create_file ("create.sql");
if (create_file.is_open())
{
char * create;
int length;
create_file.seekg (0, ios::end);
length = create_file.tellg();
create_file.seekg (0, ios::beg);
create = new char [length];
create_file.read (create,length);
create_file.close();
cout << "Executing query: " << endl;
cout.write (create,length);
cout << "EOF query" << endl;
if(mysql_query(mysql, "CREATE DATABASE grant_db")) {
fprintf(stderr, "Failed to create database: Error: %s\n",
mysql_error(mysql));
}
if(mysql_select_db(mysql, "grant_db")) {
fprintf(stderr, "Failed to select database: Error: %s\n",
mysql_error(mysql));
}
if(mysql_query(mysql, create)) {
fprintf(stderr, "Failed to create table: Error: %s\n",
mysql_error(mysql));
mysql_query(mysql, "DROP DATABASE grant_db");
}
delete[] create;
} else cout << "Unable to open file 'create.sql'.";
Thanks for your help!
You can't put multiple statements in a single mysql_query call. You need to execute them one at a time, by default at least. See the mysql_query docs.
My bet would be that it doesn't handle the /* ... */ comments. Try using -- comments instead.