I am using SQLite3 header files in my C++ program and trying to create a table and insert data onto it, it works fine on a regular input.
It shows error when I use it in a C++ loop with changing variables.
I am using the database to insert my reading from RS-232.
Here is my code:
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
std::string sql_str;
std::ostringstream temp;
std::string command;
/* Open database */
rc = sqlite3_open("test_1.db", &db);
if (rc){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}
else{
fprintf(stderr, "Opened database successfully\n");
}
std::string str;
std::ostringstream oss;
oss << id_count; // stornig the primary id int values into a string
str = "INSERT INTO M_DATA (ID, DETAILS) VALUES(";
str += oss.str(); //copying the int primary id
str += ", '";
std::string str_t1(szBuffer); //Copying character aray to a string
str += str_t1; //concatening the string
str += "');";
//printing what the database takes
//output_file << std::endl << str << std::endl;
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0'; // don't forget the terminating 0
sql = writable;
output_file << std::endl << "## SQL COMMAND : " << sql << "#" << std::endl;
// don't forget to free the string after finished using it
delete[] writable;
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
output_file << std::endl << "** SQL ERROR : " << zErrMsg << "*" << std::endl;
sqlite3_free(zErrMsg);
}
else{
fprintf(stdout, "Records created successfully\n");
}
// _sleep(3000);
sqlite3_close(db);
My issue is I have a szBuffer which changes everytime, and I have to insert it as a new entry into the table.
Is there a way to increment the Primary Key and store my string into it?
The sz buffer at a single line will give data like: For Ex:
szBuffer : ersion = 1 [SPI]: MinorVersion = 2 [SPI]: Real Time
= 1434260351 [SPI]: SR # = SBB-ST1000090
The SQL command in the string I pass is like this:
SQL COMMAND : INSERT INTO M_DATA (ID, DETAILS) VALUES(9,
'ersion = 1 [SPI]: MinorVersion = 2 [SPI]: Real Time = 1434260351
[SPI]: SR # = SBB-ST1000090');
The Error which I get is like:
SQL ERROR : near "¸”_": syntax error
I am not sure if I am doing this right or wrong.
Can we use the insert statement in a loop? Am I passing the string the right way? (It looks correct to me when I print it out.)
But why do I get an error?
Is there any better way to enter my data?
I am very new to this so I tried search the internet, but no one is doing it the way I did it.
Please help.
Many Thanks.
(Almost) never build a SQL statement via string concatenation. Use a prepared statement and bind the parameter values.
// Prepare the statement
sqlite3_stmt* stmt;
int result = sqlite3_prepare_v2(db, "INSERT INTO M_DATA (ID, DETAILS) VALUES(?, ?);", -1, &stmt, nullptr);
// TODO: Handle when result != SQLITE_OK
while(/* whatever you wanted to loop on */)
{
// Bind in the parameter values
result = sqlite3_bind_int(stmt, 1, id_count);
// TODO: Handle when result != SQLITE_OK
result = sqlite3_bind_text(stmt, 2, szBuffer, -1, SQLITE_STATIC);
// TODO: Handle when result != SQLITE_OK
// Invoke the statement
result = sqlite3_step(stmt);
// TODO: Handle when result != SQLITE_OK
// Reset the statement to allow binding variables on the next iteration
result = sqlite3_reset(stmt);
}
// Release the statement
sqlite3_finalize(stmt);
Related
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;
}
while(in) {
memset(str, 0,1024);
in.getline(str, 1024); // delim defaults to '\n'
string output = modifyString(str);
if (output != ""){
cout << output << endl;
string output1 = "INSERT INTO DATA_SRC "\
"VALUES (" + output + ");";
cout << output1 << endl;
const char * command = output1.c_str();
cout << output << endl;
rc = sqlite3_exec(db, command, callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
return 1;
}
}
for here, I + two string together.
And the out put intially is:
'D3318','D.A. Kline','Quantitative determination of sugars in fruits by GLC separation of TMS derivatives',1970,'Journal of AOAC International',53,6,1198,1202
which is good. But after I combine it to others.
Expected:
INSERT INTO DATA_SRC VALUES ('D3318','D.A. Kline','Quantitative determination of sugars in fruits by GLC separation of TMS derivatives',1970,'Journal of AOAC International',53,6,1198,1202);
Reality:
INSERT INTO DATA_SRC VALUES ('D3318','D.A. Kline','Quantitative determination of sugars in fruits by GLC separation of TMS derivatives',1970,'Journal of AOAC In);rnational',53,6,1198,1202
I do not now why.
Your modifyString function (which you didn't show) is copying a null byte to the end of the string. The string output functions will stop on a null byte, in order to be compatible with C-strings.
i have a sqlite3 database and i need to query on it using visual c++ 2013?
i am using sqlite3.h for creating connection an manipulate database;
i am using this code to retraive data :
sqlite3_stmt *stmt;
sqlite3_prepare_v2(db, "SELECT * FROM response where list_id =?", -1, &stmt, NULL);
sqlite3_bind_int(stmt, 1, *2*);
tree<SensorState>::iterator itr = sensorTree.begin();
for (;;)
{
int rc = sqlite3_step(stmt);
if (rc == SQLITE_DONE){
break;
}
else if (rc != SQLITE_ROW){
cout << "error in reading sensore with error No: " << rc;
break;
}
const char* name = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2));
int value = sqlite3_column_int(stmt, 3);
cout << name<< "->" << value <<endl;
}
now in terminal i am getting this outbut:
but it must show this output:
s1->5
s2->2
s4->2
how can i rea string correctly from sqlite3 using c++?
I want to read data from txt file and insert it into SQlite database table with C++. I prepared a code but it doesn't work.
Example line from my txt file is follows;
',1417392060.000000','1.245430','1.2456','1.24469','1.245000'
And code;
sqlite3 *db;
char *zErrMsgt = 0;
int rct;
int rch;
int rchi;
rct = sqlite3_open("final.db", &db);
if( rct ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
fprintf(stdout, "Opened database successfully\n");
}
string resline;
ifstream res("Res.txt");
while(getline(res,resline)){
string sqlli = "INSERT into FOREXNEW(DATE,OPEN,HIGH,LOW,CLOSE) VALUES ("getline(res,resline)");";
rchi = sqlite3_exec(db, sqlli.c_str(), callback, 0, &zErrMsgt);
if( rchi != SQLITE_OK ){
cout << "SQL error:" << zErrMsgt;
sqlite3_free(zErrMsgt);
}}
sqlite3_close(db);
Any alternate suggestions and solutions will be appreciated as well:) Thank you.
Getline doesn't return a string; it copies it to the variable passed in the second parameter. Change the erroneous line:
string sqlli = "INSERT into FOREXNEW(DATE,OPEN,HIGH,LOW,CLOSE) VALUES ("getline(res,resline)");";
to:
string sqlli = "INSERT into FOREXNEW(DATE,OPEN,HIGH,LOW,CLOSE) VALUES ("+resline+");";
And check if it works.
I am trying to save the contents of the key and value of a map into a database table. The .dbo file is created, but nothing goes into the table. It doesn't create table but it doesn't exit. I wonder what is wrong with my code.
void names_table( std::map<std::string, unsigned int> &names ){
std::string sql;
std::string str1;
std::string str2;
std::string str3;
sqlite3_stmt *stmt;
const char *file_names = create_db_file( ); /* default to temp db */
sqlite3 *db;
sqlite3_initialize( );
int rc = sqlite3_open_v2( file_names, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if ( rc != SQLITE_OK) {
sqlite3_close( db );
cout << "Error: Database cannot open!" << endl;
exit( EXIT_FAILURE);
}
sql = "CREATE TABLE IF NOT EXISTS names_table (offset INTEGER PRIMARY KEY, stname TEXT);";
sqlite3_prepare_v2(db, sql.c_str(), sql.size(), &stmt, NULL);
if (sqlite3_step(stmt) != SQLITE_DONE) cout << "Didn't Create Table!" << endl;
for (auto pm = names.begin(); pm != names.end(); pm++) {
str2 = "'" + pm->first + "'";
char tmp[15];
sprintf(tmp,"%u",pm->second);
str3 = tmp;
str1 = (((("INSERT INTO names_table VALUES(" + str3) + ", ") + str2) + ");");
std::cout << str1 << std::endl;
sql = (char *)str1.c_str();
// stmt = NULL;
rc = sqlite3_prepare_v2(db, sql.c_str(), sql.size(), &stmt, NULL);
if ( rc != SQLITE_OK) {
sqlite3_close(db);
cout << "Error: Data cannot be inserted!" << endl;
exit ( EXIT_FAILURE);
}
}
sqlite3_close( db );
}
INSERT INTO names_table VALUES(ramsar, 8329) - I hope you're aware that string literals in SQL need to be enclosed in quotes. Try this: INSERT INTO names_table VALUES('ramsar', 8329).
EDIT: Actually, your code will never do what you want, because you're not even calling sqlite3_step after sqlite3_prepare_v2, which means that you're only compiling your SQL statement, but never evaluating it. Where did you find this bad example? See here and here decent examples on how to use the SQLite C++ interface properly.
PS: Stop messing around with sprintf in C++. You have std::stringstream for it.