#include <iostream>
#include "libpq-fe.h"
using namespace std;
void CloseConn(PGconn *conn)
{
PQfinish(conn);
getchar();
}
PGconn *ConnectDB()
{
PGconn *conn = NULL;
// Make a connection to the database
conn = PQconnectdb("user=postgres password=password dbname=postgres hostaddr=192.168.xxx.xxx port=5432");
// Check to see that the backend connection was successfully made
if (PQstatus(conn) != CONNECTION_OK)
{
cout << "Connection to database failed.\n";
CloseConn(conn);
}
cout << "Connection to database - OK\n";
return conn;
}
void InsertEmployeeRec(PGconn *conn)
{
int nFields;
// Append the SQL statment
std::string sSQL;
// problem start-------------------------
for(int i=0;i<10;i++)
{
sSQL.append("INSERT INTO test(lat,lng) VALUES (i,20)");
}
//problem end----------------------------
// Execute with sql statement
PGresult *res = PQexec(conn, sSQL.c_str());
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
cout << "Insert test record failed\n";
PQclear(res);
CloseConn(conn);
}
cout << "Insert test record - OK";
// Clear result
PQclear(res);
}
int main(int argc, char *argv[ ])
{
PGconn *conn = NULL;
conn = ConnectDB();
if (conn != NULL)
{
InsertEmployeeRec(conn);
CloseConn(conn);
}
return 0;
}
and in terminal
alan#alan-virtual-machine:~/文件$ g++ ex6.cpp -I /usr/include/postgresql -l pq -o ex6
alan#alan-virtual-machine:~/文件$ ./ex6
Connection to database - OK
Insert test record failed
*** Error in `./ex6': corrupted double-linked list: 0x08eadad0 ***
But if I remove for loop and modify
INSERT INTO test(lat,lng) VALUES (i,20)
to
INSERT INTO test(lat,lng) VALUES (20,20)
it can work.
Linux Ubuntu 13.04 g++ compiler
I refer to http://www.askyb.com/cpp/c-postgresql-example/
The problem resides in the fact that 'i' is not been evaluated inside the string. To solve that, you can create the string with correct value and send it to the insert command.
for(int i=0;i<10;i++)
{
char buffer[256];
snprintf(buffer, 256, "INSERT INTO test(lat,lng) VALUES (%d,20)", i);
sSQL.append(buffer);
}
Of course, you need to adjust your buffer adequately
The problem is that you're not sending i. It looks like PQexecParams is the function you want:
PGresult *PQexecParams(PGconn *conn,
const char *command,
int nParams,
const Oid *paramTypes,
const char * const *paramValues,
const int *paramLengths,
const int *paramFormats,
int resultFormat);
Related
I've been making program that need to continuously insert data to a database. I'm new to C++.
I'm using xampp for my database. I want to make insert loop inside one of my function.
my code looks like this
#include "stdio.h"
#include "fstream"
#include "iostream"
#include "mysql.h"
#include "sstream"
void loop();
void print();
int i;
const char* hostname = "localhost";
const char* username = "root";
const char* password = "";
const char* database = "testinsertdb";
unsigned int port = 3306;
const char* unixsocket = NULL;
unsigned long clientflag = 0;
insertion(){
MYSQL* conn;
conn = mysql_init(0);
conn = mysql_real_connect(conn, hostname, username, password, database, port, unixsocket, clientflag);
int qstate=0;
using namespace std;
stringstream ss;
ss << " INSERT INTO test (number) values ('" <<i<<"')";
string query = ss.str ();
const char * q = query.c_str();
qstate = mysql_query(conn, q);
if (qstate == 0)
{
cout <<" Record inserted successfully ..."<<endl;
}
else
{
cout <<" Error, data not inserted..."<<endl;
}
}
int main()
{
print();
return 0;
}
void print()
{
for (int j = 0; j < 1000000; j++) {
loop();
}
}
void loop()
{
i=1;
insertion();
}
When I run the program, I managed to insert some data to the database, but after several seconds the program stopped with code -10737741819 (0xC0000005). On my build log Process the terminated with status -1073741510
How can i solve this?
Preferablly try this one.
Your code is trying to connect database as many times as the loop proceeds.
There is the description of that error from this link
#include "stdio.h"
#include "fstream"
#include "iostream"
#include "mysql.h"
#include "sstream"
void loop();
void print();
MYSQL* conn;
const char* hostname = "localhost";
const char* username = "root";
const char* password = "";
const char* database = "testinsertdb";
unsigned int port = 3306;
const char* unixsocket = NULL;
unsigned long clientflag = 0;
void insertion() {
int qstate=0, i;
using namespace std;
stringstream ss;
ss << " INSERT INTO test (number) values ('" <<i<<"')";
string query = ss.str ();
const char * q = query.c_str();
qstate = mysql_query(conn, q);
if (qstate == 0)
{
cout <<" Record inserted successfully ..."<<endl;
}
else
{
cout <<" Error, data not inserted..."<<endl;
}
}
int main()
{
print();
return 0;
}
void print()
{
conn = mysql_init(0);
conn = mysql_real_connect(conn, hostname, username, password, database, port, unixsocket, clientflag);
for (int j = 0; j < 1000000; j++) {
loop();
mysql_close(conn);
}
void loop()
{
i=1;
insertion();
}
I have a function:
int main()
{
MySQL::Connect("127.0.0.1", 3306, "root", "", "player");
MySQL::ExecuteQuery("select * from player");
while (row = mysql_fetch_row(res))
{
std::cout << row[2] << "\n";
MySQL::SetDatabase("account");
MySQL::ExecuteQuery("select * from account"); // This function causes a problem.
// while (row = mysql_fetch_row(res))
// break;
}
return 0;
}
Which should get everything of player names from player table what it does and what it display in console (I'm posting a screenshot of table in Navicat):
https://i.stack.imgur.com/n6HJQ.png
However, when MySQL::ExecuteQuery("select * from account"); function is used which selects everything in account table, the earlier std::cout display only one player name instead of two:
https://i.stack.imgur.com/q9ZkP.png
What can I do in this situation? Or is there another simple way to connect to MySQL in C++? Please help.
I attach files such as MySQL_Func.cpp and MySQL_Func.h which include problematic function:
.cpp:
#include "MySQL_Func.h"
#include "../Log.hpp"
MYSQL* conn;
MYSQL_ROW row;
MYSQL_RES* res;
std::string conf_ip;
unsigned int conf_port;
std::string conf_db;
std::string conf_login;
std::string conf_password;
std::string error = mysql_error(conn);
int err = 0;
namespace MySQL
{
void Connect(std::string ip, unsigned int port, std::string login, std::string password, std::string db)
{
conf_ip = ip;
conf_port = port;
conf_login = login;
conf_password = password;
conf_db = db;
if (conn != 0)
{
SendLog(0, "MySQL has been restared.");
mysql_close(conn);
}
conn = mysql_init(0);
if (!mysql_real_connect(conn, ip.c_str(), login.c_str(), password.c_str(), db.c_str(), port, NULL, 0))
{
error = mysql_error(conn);
SendLog(1, "Connection with database was failed: " + error + ".");
exit(1);
}
else
{
SendLog(0, "Successfully connected with database!");
}
}
void ExecuteQuery(std::string query)
{
err = mysql_query(conn, query.c_str());
res = mysql_store_result(conn);
if (res != 0) // Protection against NullPointer.
{
int total_rows = mysql_num_fields(res);
if (total_rows != 0) // If total rows isn't 0.
{
if (err)
{
error = mysql_error(conn);
SendLog(1, "Query execute failed:" + error + ".");
mysql_free_result(res);
exit(1);
}
else
{
SendLog(0, "Query has been sent (" + query + ")!");
}
}
else
{
SendLog(1, "Query has been sent: (" + query + ") but its value is 0.");
exit(0);
}
}
else
{
exit(1);
}
}
void SetDatabase(std::string current_db)
{
if (current_db != conf_db) // If current_db isn't conf_db.
MySQL::Connect(conf_ip, conf_port, conf_login, conf_password, current_db);
}
}
.h:
#pragma once
#include <iostream>
#include <mysql.h>
#include <string>
extern MYSQL* conn;
extern MYSQL_ROW row;
extern MYSQL_RES* res;
extern std::string conf_ip;
extern unsigned int conf_port;
extern std::string conf_db;
extern std::string conf_login;
extern std::string conf_password;
namespace MySQL
{
void Connect(std::string ip, unsigned int port, std::string login, std::string password, std::string db);
void ExecuteQuery(std::string query);
void SetDatabase(std::string database);
}
Your two calls to ExecuteQuery share state, namely the "currently active query" and the buffered resultset you downloaded with mysql_result_row.
This is called a non-reentrant function.
Some options:
have a dedicated connection for each query
Do a single query that somehow combines the results (ie JOIN the players and accounts table)
Fetch all the players first into a dedicated datastructure (eg std::vector or std::map), then do the query for accounts later.
I have a column of integers(containing port numbers) in my sqlite data base. Now I want to retrieve list of ports from sqlite in an array form in a function and send data to those port numbers. I tried to make a struct having pointer to Vector but it didn't work out. Making char pointers caused Segmentation error. Here is my code:
struct ConnIDs{
vector<int*> *ids;
};
static int callback(void *NotUsed, int argc, char **argv, char **szColName)
{
ConnIDs *first=(ConnIDs *)NotUsed;
for(int i = 0; i < argc; i++)
{
if (strcmp(szColName[i], "ConnID") == 0)
{
first->ids->push_back(argv[i]);
}
std::cout << szColName[i] << " = " << argv[i] << std::endl;
}
std::cout << "\n";
return 0;
}
int main(){
int result;
sqlite3 *db;
ConnIDs first;
int count = 0;
char *szErrMsg = 0;
int rc = sqlite3_open("Sqlite_Test.db", &db);
if(rc)
{
std::cout << "Can't open database\n";
} else
{
std::cout << "Open database successfully\n";
}
char *pSQL2[1];
pSQL2[0] = "Select * from Subscribers";
rc = sqlite3_exec(db, pSQL2[0], callback, &first, &szErrMsg);
if(rc != SQLITE_OK)
{
std::cout << "SQL Error: " << szErrMsg << std::endl;
sqlite3_free(szErrMsg);
break;
}
else
{
printf("count: %s\n", first.ids);
}
}
This isn't an error regarding sqlite at all, it's just an uninitialised pointer. Let's look at the relevant code:
struct ConnIDs{
vector<int*> *ids;
};
...
ConnIDs first;
rc = sqlite3_exec(db, pSQL2[0], callback, &first, &szErrMsg);
...
static int callback(void *NotUsed, int argc, char **argv, char **szColName)
{
ConnIDs *first=(ConnIDs *)NotUsed;
for(int i = 0; i < argc; i++)
if (strcmp(szColName[i], "ConnID") == 0)
first->ids->push_back(argv[i]);
}
I've omitted unnecessary parts. first is an object of ConnIDs, which is a std::vector<int*>* - it's a pointer to a vector. You pass first into your callback, then immediately try to push into ids; however, you haven't initialised ids, so it's just pointing to rubbish.
The simplest fix is to just not make it a std::vector<int*>* and instead just make it std::vector<int*>, although I'm not certain int* is the correct type here, it will really depend on the data in your database. I would imagine either just int or std::string may be more applicable, but I'll leave that to you:
With the above change, your code will work as-is but you'll need to change first->ids->push_back to first->ids.push_back
Additional notes:
char *pSQL2[1];
pSQL2[0] = "Select * from Subscribers";
rc = sqlite3_exec(db, pSQL2[0], callback, &first, &szErrMsg);
This is kinda weird. I'd probably either just write rc = sqlite3_exec(db, "Select * from Subscribers", ...) or
auto query = "Select * from Subscribers";
rc = sqlite3_exec(db, query.c_str(), callback, &first, &szErrMsg);
I am trying to store the public key (PK) and signature (generated by crypto++ library) to sqlite database. I first encoded the keys as:
pk[node].BEREncode(CryptoPP::StringSink(pkstring).Ref());
and then store them in the database. But as the PK and signature have special characteres, they are not stored correctly into the database. What I used for storing is:
char * PK = (char*) malloc (BC.trans[l].PK.length()+1); //use malloc to manually manage the memory
std::strcpy(PK,BC.trans[l].PK.c_str());
char *zSQL = sqlite3_mprintf("INSERT INTO BC (PK VALUES ('%q');", PK);
rc = sqlite3_exec(db, zSQL, callback, (void*)data, &zErrMsg);// executes the command in sqlite and returns the status (whether stroing was successful or not.
free(PK);
The string should be copied to the char, and the issue happens exactly here in copying the content into the char. I think its because the string has special characters. For hash I have the same follow but it works perfectly fine. Only for PK and signature. I used memcpy and strncpy as well. Nothing works for this and still the keys are not stored correctly in the database.
Any thoughts?
I've updated with the full code. Now I can store the PK and its seems to be fine, but when I ask the database to remove a bunch of records, nothing happens. That means something is wrong again.
Here is the code:
int Network_Nodes =10;
int Block_Size=10;
int BC_lenght=0;
int Fin_BC_size =50;
std::vector<CryptoPP::RSA::PrivateKey> prk;
std::vector<CryptoPP::RSA::PublicKey> pk;
std::vector<std::string> prev_t;
struct Block {
std::string block_hash;
std::string block_num;
struct transactions {
std::string TransactionID;
std::string previousTransactionID;
std::string PK;
std::string Sign;
};
std::vector<transactions> trans;
} BC;
int generatekey()
{
for (int i=0;i<Network_Nodes;i++)
{
CryptoPP::AutoSeededRandomPool rng;
CryptoPP::InvertibleRSAFunction param;
param.GenerateRandomWithKeySize(rng,3072);
CryptoPP::RSA::PrivateKey privatekey(param);
CryptoPP::RSA::PublicKey publickey (param);
prk.push_back(privatekey);
pk.push_back(publickey);
}
return 0;
}
///////////////////////////////////////////////////////////////
void initialization()
{
for (int i=0;i<=Network_Nodes;i++)
{
prev_t.push_back("NULL");
}
//Creating database
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
const char* data = "Callback function called";
/* Open database */
rc = sqlite3_open("RemovableBC.db", &db);
if( rc ) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return;
} else {
// fprintf(stdout, "Opened database successfully\n");
}
sql = "DROP TABLE BC";
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
/* Create a table in the data base to be used for storing data. Create SQL statement */
sql = "CREATE TABLE BC(" \
"T_ID TEXT ," \
"P_T_ID TEXT ," \
"PK BLOB ," \
"Signature BLOB ," \
"Block_ID TEXT );";
/* 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);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
void fill_the_block(std::string block_content)
{
const char* data = "Callback function called";
SHA256 hash;
string digest;
sqlite3 *db=NULL;
char *sql;
char *zErrMsg = 0;
int rc;
char sqlStr[2000];
/* Open database */
rc = sqlite3_open("RemovableBC.db", &db);
if( rc ) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return;
} else {
// fprintf(stdout, "Opened database successfully\n");
}
StringSource s(block_content, true, new HashFilter(hash, new HexEncoder(new StringSink(digest))));
BC.block_hash=digest;
for (int l=0 ; l<Block_Size ; l++)
{
char *begin = sqlStr;
char *end = begin + sizeof(sqlStr);
std::fill(begin, end, 0);
char *zSQL = sqlite3_mprintf("INSERT INTO BC ( T_ID , P_T_ID , PK , Signature , Block_ID ) VALUES ('%q','%q','%q','%q','%q');", BC.trans[l].TransactionID.c_str() ,BC.trans[l].previousTransactionID.c_str() ,BC.trans[l].PK.c_str() ,BC.trans[l].Sign.c_str(),BC.block_hash.c_str());
rc = sqlite3_exec(db, zSQL, callback, (void*)data, &zErrMsg);
sqlite3_free(zSQL);
if( rc != SQLITE_OK ) {
fprintf(stderr, "SQL error in populating : %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
}
sqlite3_close(db); //We close the connection we have with the database
}
///////////////////////////////////////////////////////////////////////////
void populate_bc ()
{
int generated_blocks=0;
int stored_trans_in_block=0;
int node=0;
std::string block_content,trans_cont;
std::string pkstring;
std::string signature;
std::string mes ="This message is going to be singed";
while (BC_lenght <=Fin_BC_size )
{
if (generated_blocks <= 10){
if (node >= Network_Nodes)
{
node=0; //cout << "step 4" <<endl;
}
if (stored_trans_in_block >= Block_Size)
{
cout << "block size is "<< BC_lenght<<endl;
fill_the_block(block_content);
BC_lenght++;
block_content.clear();
stored_trans_in_block=0;
for(int o=0; o<stored_trans_in_block;o++)
{
BC.trans[o] = {};
}
BC.trans = {};
BC ={};
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (prev_t[node]=="NULL")
{
// cout << "We are populating on behafe of "<< node<< endl;
trans_cont="";
BC.trans.push_back(Block::transactions());
BC.trans[stored_trans_in_block].previousTransactionID ="NULL";
// byte public_key[] = pk[node];
std::string endoced_pub;
Base64Encoder pubKeySink(new StringSink(endoced_pub));
pk[node].DEREncode(pubKeySink);
pk[node].BEREncode(CryptoPP::StringSink(pkstring).Ref());
BC.trans[stored_trans_in_block].PK=endoced_pub;
CryptoPP::AutoSeededRandomPool rng;
CryptoPP::RSASSA_PKCS1v15_SHA_Signer signer(prk[node]);
CryptoPP::StringSource ss1(mes, true,
new CryptoPP::SignerFilter(rng, signer,
new CryptoPP::StringSink(signature)
) // SignerFilter
); // StringSource
// cout << "step 1" <<endl;
BC.trans[stored_trans_in_block].Sign=signature;
trans_cont = "NULL" + pkstring + signature;
SHA256 hash;
string digest;
StringSource s(trans_cont, true, new HashFilter(hash, new HexEncoder(new StringSink(digest))));
// cout << "step 2" <<endl;
BC.trans[stored_trans_in_block].TransactionID=digest;
prev_t[node] =digest; // This keeps the previous transaction of each node in an array and thus we can later use to populate the BC
block_content+=digest; // This is to calculate the ID of the block which is the hash of all TIDs (hash of hash of all trnasctions)
node++;
stored_trans_in_block++;
// cout << "step 3" <<endl;
}//end of if (prev_t[node]=="NULL")
else
{// cout << "step 6" <<endl;
trans_cont="";
BC.trans.push_back(Block::transactions());
BC.trans[stored_trans_in_block].previousTransactionID =prev_t[node];
std::string endoced_pub;
Base64Encoder pubKeySink(new StringSink(endoced_pub));
pk[node].DEREncode(pubKeySink);
// pubKeySink.MessageEnd();
// pk[node].BEREncode(CryptoPP::StringSink(pkstring).Ref());
BC.trans[stored_trans_in_block].PK = endoced_pub;
// BC.trans[stored_trans_in_block].PK= pk[node];
CryptoPP::AutoSeededRandomPool rng;
CryptoPP::RSASSA_PKCS1v15_SHA_Signer signer(prk[node]);
CryptoPP::StringSource ss1(mes, true,
new CryptoPP::SignerFilter(rng, signer,
new CryptoPP::StringSink(signature)
) // SignerFilter
); // StringSource
BC.trans[stored_trans_in_block].Sign=signature;
trans_cont = prev_t[node] + pkstring + signature;
SHA256 hash;
string digest;
StringSource s(trans_cont, true, new HashFilter(hash, new HexEncoder(new StringSink(digest))));
BC.trans[stored_trans_in_block].TransactionID=digest;
prev_t[node] =digest;
block_content+=digest;
node++;
stored_trans_in_block++;
}
generated_blocks++;
}
else
{
generated_blocks=0;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
void remove_node (int i)
{
std::string search_node; //This is the ID of the transaction that we need to search for in the BC,
sqlite3 *db;
std::string endoced_pub;
Base64Encoder pubKeySink(new StringSink(endoced_pub));
pk[i].DEREncode(pubKeySink);
// pubKeySink.MessageEnd();
char *sql;
int rc;
char *zErrMsg = 0;
const char* data = "Callback function called";
/* Open database */
rc = sqlite3_open("RemovableBC.db", &db);
if( rc ) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return;
} else {
// fprintf(stderr, "Opened database successfully\n");
}
/* Execute SQL statement */
// char *zSQL = sqlite3_mprintf("DELETE from BC");
char * Search_NODE = (char*) malloc (endoced_pub.length()+1);
std::strcpy(Search_NODE,endoced_pub.c_str());
std::strcpy(Search_NODE,search_node.c_str());
// char *zSQL = sqlite3_mprintf("DELETE from BC where PK = '%q';", Search_NODE);
char *zSQL = sqlite3_mprintf("UPDATE BC set Signature = null and PK = null where PK = '%q';", endoced_pub.c_str());
rc = sqlite3_exec(db, zSQL, callback, (void*)data, &zErrMsg);
cout<< endoced_pub.c_str()<<endl;
if( rc != SQLITE_OK ) {
fprintf(stderr, "SQL error in removing a record: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
// fprintf(stdout, "Operation done successfully\n");
}
sqlite3_close(db);
free(Search_NODE);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main() {
auto initial = std::chrono::high_resolution_clock::now();
generatekey();
cout << "Keys are generated for " <<Network_Nodes << " nodes..." << endl;
clock_t begin_block_pup = clock();
initialization();
cout << "Initializing previous transaction vector..." << endl;
//clock_t ti =clock();
//double time = double (ti)/CLOCKS_PER_SEC;
clock_t ti2 =clock();
double time2 = double (ti2)/CLOCKS_PER_SEC;
//cout << "second time is " << done <<endl;
populate_bc();
cout << "BC has been populated with "<< BC_lenght <<" blocks..." << endl;
return 0;
}
The problem with your system, is that you need to store the PK data as either a BLOB or encode it into 7 bit ASCII.
Sqlite has some internationalization support, and may convert raw binary data stored as a string into a different form. (e.g. UTF-8 conversion)
So either use a blob as in the answer to this question SO : sqlite blob,
or first convert the bytes to 7 bit ascii (e.g. b64 encode), then store the data.
Remembering you would need to b64 decode the results afterwards.
I decided to use SQLite as it allows to store database into a single file. I think I have managed to do a database with SQLite Database Browser.
How can I read that data in a C/C++ program?
A example using sqlite read:
#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
int main(int argc, char** argv)
{
const char* username = "satyam";
char q[999];
sqlite3* db;
sqlite3_stmt* stmt;
int row = 0;
int bytes;
const unsigned char* text;
if (2 == argc) {
username = argv[1];
}
q[sizeof q - 1] = '\0';
snprintf(
q,
sizeof q - 1,
"SELECT ipaddr FROM items WHERE username = '%s'",
username
);
if (sqlite3_open ("test.db", &db) != SQLITE_OK) {
fprintf(stderr, "Error opening database.\n");
return 2;
}
printf("Query: %s\n", q);
sqlite3_prepare(db, q, sizeof q, &stmt, NULL);
bool done = false;
while (!done) {
printf("In select while\n");
switch (sqlite3_step (stmt)) {
case SQLITE_ROW:
bytes = sqlite3_column_bytes(stmt, 0);
text = sqlite3_column_text(stmt, 1);
printf ("count %d: %s (%d bytes)\n", row, text, bytes);
row++;
break;
case SQLITE_DONE:
done = true;
break;
default:
fprintf(stderr, "Failed.\n");
return 1;
}
}
sqlite3_finalize(stmt);
return 0;
}
How about the 'An Introduction to Sqlite C/C++ Interface', and there is a whole C++ example here on CodeProject.
This is bits of the more full sample,
#include "CppSQLite.h"
#include <ctime>
#include <iostream>
using namespace std;
const char* gszFile = "C:\\test.db";
int main(int argc, char** argv)
{
try
{
int i, fld;
time_t tmStart, tmEnd;
CppSQLiteDB db;
cout << "SQLite Version: " << db.SQLiteVersion() << endl;
db.open(gszFile);
cout << db.execScalar("select count(*) from emp;")
<< " rows in emp table in ";
db.Close();
}
catch (CppSQLiteException& e)
{
cerr << e.errorCode() << ":" << e.errorMessage() << endl;
}
}
One way to do it without additional wrappers
#include <stdio.h>
#include <string>
using std::string;
#include <sstream>
using std::stringstream;
#include "sqlite3.h"
bool find_employee(int _id)
{
bool found = false;
sqlite3* db;
sqlite3_stmt* stmt;
stringstream ss;
// create sql statement string
// if _id is not 0, search for id, otherwise print all IDs
// this can also be achieved with the default sqlite3_bind* utilities
if(_id) { ss << "select * from employees where id = " << _id << ";"; }
else { ss << "select * from employees;"; }
string sql(ss.str());
//the resulting sql statement
printf("sql: %s\n", sql.c_str());
//get link to database object
if(sqlite3_open("data/test.db", &db) != SQLITE_OK) {
printf("ERROR: can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return found;
}
// compile sql statement to binary
if(sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, NULL) != SQLITE_OK) {
printf("ERROR: while compiling sql: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
sqlite3_finalize(stmt);
return found;
}
// execute sql statement, and while there are rows returned, print ID
int ret_code = 0;
while((ret_code = sqlite3_step(stmt)) == SQLITE_ROW) {
printf("TEST: ID = %d\n", sqlite3_column_int(stmt, 0));
found = true;
}
if(ret_code != SQLITE_DONE) {
//this error handling could be done better, but it works
printf("ERROR: while performing sql: %s\n", sqlite3_errmsg(db));
printf("ret_code = %d\n", ret_code);
}
printf("entry %s\n", found ? "found" : "not found");
//release resources
sqlite3_finalize(stmt);
sqlite3_close(db);
return found;
}