While using SQLite in C++98, how to convert stringstream to Unicode and pass it to sqlite3_exec()? I constantly have this error:
error C2440: 'initializing' : cannot convert from 'std::basic_string<_Elem,_Traits,_Ax>' to 'std::basic_string<_Elem,_Traits,_Ax>'
1> with"
Code:
int main(int argc, char* argv[]) {
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
const char* data = "Callback function called";
tstringstream tstrsSQL;
tstrsSQL.imbue(std::locale("C"));
std::string s = tstrsSQL.str(); // converting stringstream to char?
const char* p = s.c_str();
/* Open database */
rc = sqlite3_open("db.db3", &db);
if( rc ) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return(0);
} else {
fprintf(stderr, "Opened database successfully\n");
}
/* Create SQL statement */
tstrsSQL << _T("SELECT") something ("FROM") << table;
/* Execute SQL statement */
rc = sqlite3_exec(db, p, callback, (void*)data, &zErrMsg); // p needs to be unicode
You are using tstringstream, which I guess uses std::wstringstream if UNICODE is defined, so its str() gives a std::basic_string<wchar_t>.
But you get the result into a std::string, which is std::basic_string<char>. So the assignment fails.
Anyway, you take the result and use it in sqlite3_exec(), which takes a const char* as input.
That's why you shouldn't use tstringstream, you should use std::stringstream, and remove the _T from all of the string literals.
Minimal, complete, working code:
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
stringstream strstream;
strstream << "Hello World";
string str = strstream.str();
cout << str << endl;
return 0;
}
Related
Hello how would I go about formatting the result of
sql = "SELECT * from COMPANY ORDER BY ID";
rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
I read there are console commands for it on here https://www.tutorialspoint.com/sqlite/sqlite_commands.htm
so I tried
std::string c3 = "sqlite>.header on";
std::string c1 = "sqlite>.mode column";
cout << system(c3.c_str()) << endl;
cout << system(c1.c_str()) << endl;
but that didn't work to get a table format like result
How would I do this? I've been googling for 3 hours and still didn't get anywhere
You can't control the formatting from the sqlite3 user program, so using system() to call it will not control the C API.
You should do this using the callback function. From the same tutorialpoint site:
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;
}
I copied this code
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
int i;
for (i = 0; i<argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char* argv[]) {
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
/* Open database */
rc = sqlite3_open("test.db", &db);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return(0);
}
else {
fprintf(stdout, "Opened database successfully\n");
}
/* Create SQL statement */
sql = "CREATE TABLE COMPANY(" \
"ID INT PRIMARY KEY NOT NULL," \
"NAME TEXT NOT NULL," \
"AGE INT NOT NULL," \
"ADDRESS CHAR(50)," \
"SALARY REAL );";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
else {
fprintf(stdout, "Table created successfully\n");
}
sqlite3_close(db);
return 0;
}
from official documentation sqlite here: https://www.tutorialspoint.com/sqlite/sqlite_c_cpp.htm
and I got error like this:
Error C2440 '=': cannot convert from 'const char [164]' to 'char *'
I'm using visual studio 2017 and compile file .cpp. I guess something can be wrong with connection between .c and .cpp files, because sqlite is written in .c
The issue is that you are using old C-style variable declaration (all at the beginning) in C++ with the wrong types.
Use this instead:
const char* sql = "CREATE TABLE COMPANY(" \
"ID INT PRIMARY KEY NOT NULL," \
"NAME TEXT NOT NULL," \
"AGE INT NOT NULL," \
"ADDRESS CHAR(50)," \
"SALARY REAL );";
Literal char* are const in C++11.
FindFirstFile function somehow doesn't accept my wstring (nor string) to be passed as a parameter.
I get a compiler error
Cannot convert const char[9] to std::basic_string
#include "stdafx.h"
#include <string>
#include <iostream>
#include <stdio.h>
#include <Windows.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
wstring path = "C:\\*.dmp";
WIN32_FIND_DATA dataFile;
HANDLE hFind;
hFind = FindFirstFile (path.c_str(), &dataFile);
cout << "The name of the first found file is %s \n" dataFile.cFileName << endl;
FindClose hFind;
getchar();
return 0;
}
I get a compiler error
Cannot convert const char[9] to std::basic_string
You need a wide char literal to initialize a std::wstring properly:
wstring path = L"C:\\*.dmp";
// ^
Also you have missed to put another <<
cout << "The name of the first found file is " << dataFile.cFileName << endl;`
// ^^
Also note that output formatting with std::ostream is different from printf() format string styles. Note I removed the %s from the above sample.
Change
const char path[] = "C:\\*.dmp"; // C-style string
hFind = FindFirstFile(path, &dataFile); // Pass the string directly
I have a table(Item) with attribute of id,item
id|itemName
1|noodle
2|burger
Basically I would like to ask is there anyway that I can compare a input results against my database
record?
e.g if I input noodle and there's is a matching record "noodle" in my in my database it will return found;
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <string>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char* argv[])
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
const char *sql;
std::string itemName;
rc = sqlite3_open("test.db", &db);
if( rc ) {
// failed
fprintf(stderr, "Can't open database: %s\n",
sqlite3_errmsg(db));
}
else
{
// success
fprintf(stderr, "Open database successfully\n");
}
std::cout << "Enter a Item" << std::endl;
std::cin >> itemName;
sql = "select * from Item";
rc = sqlite3_exec(db,sql, callback, 0, &zErrMsg);
if(//how do I compare the itemName from my database against the user input)
{
}
sqlite3_close(db);
return 0;
}
Instead of a callback you can use a parameter to specify just the record you need:
std::cin >> itemName;
sql = "select id from Item where itemName = ?";
sqlite3_stmt *stmt;
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
// set the ? parameter to the itemname you are looking for:
sqlite3_bind_text(stmt, 1, itemName.c_str(), -1, SQLITE_TRANSIENT);
if(sqlite3_step(stmt) == SQLITE_ROW )
{
int id=sqlite3_column_int(stmt,0);
std::cout << "Found id=" << id << std::endl;
}
sqlite3_finalize(stmt);
sqlite3_close(db);
I have the following C++ code for testing purposes in conjunction with SQLite3.
It's a class called customer with a callback function declared. This callback function is called whenever sqlite3_exec() returns results (records) from the SQLite database.
What I don't like about this construction is that source code to process the results is located in a call back function outside of the class rather than the results being processed by the class method from which sqlite3_exec() is called.
I could use global variables that will be used in the class method after the callback function has finished extracting the values from the SQL query results. But what if there is more than one record and the call back function is called several times. Then I need to work with arrays unless I make sure that I will only have single results.
Do I need to forget about the callback function and go into deeper calls of the SQLite API?
Or do I need to go to a C++ wrapper, I suppose that there is no call back mechanism there and the results being passed back to the class method itself?
// customer
#include "Customer\customer.h"
//## begin module%50E6CCB50119.additionalDeclarations preserve=yes
static int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
int i;
char* columnName;
char* columnValueString;
short int columnValueShortInt = 0;
int columnValueInt = 0;
cout << "begin of callback function\n";
for(i=0; i<argc; i++)
{
columnName = azColName[i];
if (strcmp(columnName, "FirstName")==0 || strcmp(columnName, "LastName")==0)
{
columnValueString = argv[i];
cout << "columnName = " << columnName << "; value = " << columnValueString <<"\n";
}
else
{
if(strcmp(columnName, "Age")==0)
{
stringstream(argv[i]) >> columnValueShortInt;
cout << "columnName = " << columnName << "; value = " << columnValueShortInt <<"\n";
}
else // strcmp(columnName, "Id")==0)
{
stringstream(argv[i]) >> columnValueInt;
cout << "columnName = " << columnName << "; value = " << columnValueInt <<"\n";
}
}
}
cout << "end of call back function \n";
return 0;
}
//## end module%50E6CCB50119.additionalDeclarations
// Class customer
customer::customer ()
//## begin customer::customer%50F969EE01E4.hasinit preserve=no
//## end customer::customer%50F969EE01E4.hasinit
//## begin customer::customer%50F969EE01E4.initialization preserve=yes
//## end customer::customer%50F969EE01E4.initialization
{
//## begin customer::customer%50F969EE01E4.body preserve=yes
customerId = 0;
zErrMsg = 0;
customerDataBaseRc = sqlite3_open("customerdb", &customerDataBase);
if(customerDataBaseRc)
{
fprintf(stderr, "Can't open database %s\n", sqlite3_errmsg(customerDataBase));
sqlite3_close(customerDataBase);
}
const char * pSQL[6];
const char * sqlStatement;
pSQL[0] = "create table customerTable (Id int, FirstName varchar(30), LastName varchar(30), Age smallint)";
// execute all the sql statements
for(int i = 0; i < 1; i++)
{
customerDataBaseRc = sqlite3_exec(customerDataBase, pSQL[i], callback, 0, &zErrMsg);
if( customerDataBaseRc !=SQLITE_OK )
{
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
break; // break the loop if error occur
}
}
//## end customer::customer%50F969EE01E4.body
}
customer::~customer ()
{
//## begin customer::~customer%50F93279003E.body preserve=yes
const char *pSQL[6];
// Remove all data in customerTable
pSQL[0] = "delete from customerTable";
// Drop the table from database
pSQL[1] = "drop table customerTable";
// execute all the sql statements
for(int i = 0; i < 2; i++)
{
customerDataBaseRc = sqlite3_exec(customerDataBase, pSQL[i], callback, 0, &zErrMsg);
if( customerDataBaseRc !=SQLITE_OK )
{
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
break; // break the loop if error occur
}
}
cout << "destructor";
//## end customer::~customer%50F93279003E.body
}
//## Other Operations (implementation)
unsigned int customer::createCustomer (char iCustomerFirstName[20], char iCustomerLastName[20], unsigned short iCustomerAge)
{
//## begin customer::createCustomer%50EBFFA3036B.body preserve=yes
const char *sqlStatement;
string result; // string which will contain the result
ostringstream convert; // stream used for the conversion
convert << "insert into customerTable (Id, FirstName, LastName, Age) values (" << customerId << ", '" << iCustomerFirstName << "', '" << iCustomerLastName << "', " << iCustomerAge << ")";
result = convert.str(); // set 'Result' to the contents of the stream
sqlStatement = result.c_str();
// Execute sql statement
customerDataBaseRc = sqlite3_exec(customerDataBase, sqlStatement, callback, 0, &zErrMsg);
// Check for errors
if(customerDataBaseRc !=SQLITE_OK )
{
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
return customerId++;
//## end customer::createCustomer%50EBFFA3036B.body
}
char * customer::getCustomer (unsigned int iCustomerId)
{
//## begin customer::getCustomer%50ED3D700186.body preserve=yes
const char *sqlStatement;
char *tmp ="blabla";
string result; // string which will contain the result
ostringstream convert; // stream used for the conversion
convert << "select * from customerTable where Id = " << iCustomerId;
result = convert.str(); // set 'Result' to the contents of the stream
sqlStatement = result.c_str();
// Execute the sql statement
customerDataBaseRc = sqlite3_exec(customerDataBase, sqlStatement, callback, 0, &zErrMsg);
// Check for errors
if(customerDataBaseRc !=SQLITE_OK )
{
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
return tmp;
//## end customer::getCustomer%50ED3D700186.body
}
// Additional Declarations
//## begin customer%50E6CCB50119.declarations preserve=yes
//## end customer%50E6CCB50119.declarations
//## begin module%50E6CCB50119.epilog preserve=yes
//## end module%50E6CCB50119.epilog
What one typically does in this case is take advantage of the void * (which you call NotUsed) parameter of the callback -- a parameter you define when you install the callback. For C++, you would typically set that parameter to the this pointer to your interested object, and you would make the callback (an extern "C" function in a c++ source file) a friend method to your class (if necessary).
This would look like this:
class customer
{
...
public:
int callback(int argc, char **argv, char **azColName);
};
static int c_callback(void *param, int argc, char **argv, char **azColName)
{
customer* cust = reinterpret_cast<customer*>(param);
return cust->callback(argc, argv, azColName);
}
char* customer::getCustomer(int id)
{
...
rc = sqlite3_exec(db, sql, c_callback, this, &errMsg);
...
}
int customer::callback(int argc, char **argv, char **azColName)
{
...
}
Using sqlite3_exec has the disadvantages that you have to convert some values back from a string to a number, and that it needs to allocate memory for all result records (which can lead to problems when reading large tables).
Furthermore, the callback always is a separate function (even if it's in the same class).
For your example query, using the sqlite3_prepare/sqlite3_step/sqlite3_finalize API would look like this:
void one_customer::readFromDB(sqlite3* db, int id)
{
sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, "SELECT FirstName, LastName, Age"
" FROM customerTable"
" WHERE Id = ?", -1, &stmt, NULL);
if (rc != SQLITE_OK)
throw string(sqlite3_errmsg(db));
rc = sqlite3_bind_int(stmt, 1, id); // Using parameters ("?") is not
if (rc != SQLITE_OK) { // really necessary, but recommended
string errmsg(sqlite3_errmsg(db)); // (especially for strings) to avoid
sqlite3_finalize(stmt); // formatting problems and SQL
throw errmsg; // injection attacks.
}
rc = sqlite3_step(stmt);
if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
string errmsg(sqlite3_errmsg(db));
sqlite3_finalize(stmt);
throw errmsg;
}
if (rc == SQLITE_DONE) {
sqlite3_finalize(stmt);
throw string("customer not found");
}
this->id = id;
this->first_name = string(sqlite3_column_text(stmt, 0));
this->last_name = string(sqlite3_column_text(stmt, 1));
this->age = sqlite3_column_int(stmt, 2);
sqlite3_finalize(stmt);
}
(This code handles errors by just throwing a string with the error message.)