I have pasted my code below. It gives seg fault at sqlite3_get_table (). I want to get the number of row in table and return that. If number of row is greater than 0, the program needs to read all rows.
int countRowsInTable()
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char const *sql;
char ***pazResult;
int *pnRow; /* Number of result rows written here */
int *pnColumn; /* Number of result columns written here */
rc = sqlite3_open("DeviceDetails.db", &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 */
sql = "select * from Device_Details";
/* Execute SQL statement */
// rc = sqlite3_exec(db, sql, 0/*callback*/, 0/*(void*)data*/, &zErrMsg);
rc = sqlite3_get_table(db, sql, pazResult, pnRow, pnColumn, &zErrMsg);
void sqlite3_free_table(char **result);
if( rc != SQLITE_OK )
{
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
else
{
fprintf(stdout, "Operation done successfully\n");
cout<<"rows="<<pnRow<<endl;
sleep(10);
}
sqlite3_close(db);
cout<<"num rows =" << *pnRow <<endl;
}
after reading your suggestion I have changed my code. Now I use select count (*), but where (which) variable will hold the number of rows. Do, I need to implement the callback function in sqlite3_exec. Also I need to get data if row count is greater than zero.If I get the data in call back function, how to pass it to the function calling countRows in table? may be I can keep a global variable. As soon as call back is executed , it will signal the calling function through condition variable. So I have to maintain countRowsInTable function in a new thread. I there any simpler approach?
int countRowsInTable()
{
sqlite3 *db;
char *zErrMsg = new char[64];
int rc;
char const *sql;
char ***pazResult;
int *pnRow = new int; /* Number of result rows written here */
int *pnColumn = new int; /* Number of result columns written here */
//*pnRow = 0;
**pazResult = new char[20480];
rc = sqlite3_open("DeviceDetails.db", &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 */
sql = "select count(*) from Device_Details";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, 0/*callback*/, 0/*(void*)data*/, &zErrMsg);
//rc = sqlite3_get_table(db, sql, pazResult, pnRow, pnColumn, &zErrMsg);
//void sqlite3_free_table(char **result);
if( rc != SQLITE_OK )
{
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
else
{
fprintf(stdout, "Operation done successfully\n");
}
}
Your are not calling the function with the right parameters. You are passing uninitialized pointers, whereas you must create the variables and pass pointers on them so SQLite can write the values.
const char *sql = "select * from Device_Details";
char **result;
int nrow;
int ncolumn;
char *errmsg;
int rc;
rc = sqlite3_get_table(db, sql, &result, &nrow, &ncolumn, &errmsg);
However, you should be aware the SQLite manual discourage the use of the function: "This is a legacy interface that is preserved for backwards compatibility. Use of this interface is not recommended."
Also, you should remove void sqlite3_free_table(char **result) that you probably pasted by mistake.
Related
I want to backup the SQLite database from my file system to in memory database using C++. I read this website and try the example 1. It compiled perfectly but I get an error "Segmentation Fault". The code looks like this:
Ps: The last line printf("foo1"); is not printed
#include <stdio.h>
#include <sqlite3.h>
#include <nlohmann/json.hpp>
using namespace std;
using json = nlohmann::json;
static int callback(void *NotUsed, int count, char **data, char **column) {
int i;
int lastEntry = count - 1;
printf("{");
for (i=0; i<count; i++) {
if (i == lastEntry ) {
printf("\"%s\" : \"%s\"", column[i], data[i] ? data[i] : "NULL");
} else {
printf("\"%s\" : \"%s\",", column[i], data[i] ? data[i] : "NULL");
}
}
printf("}\n");
return 0;
}
int loadOrSaveDb(sqlite3 *pFile, const char *zFilename, int isSave){
int rc; /* Function return code */
sqlite3 *pInMemory; /* Database connection opened on zFilename */
sqlite3_backup *pBackup; /* Backup object used to copy data */
sqlite3 *pTo; /* Database to copy to (pFile or pInMemory) */
sqlite3 *pFrom; /* Database to copy from (pFile or pInMemory) */
/* Open the database file identified by zFilename. Exit early if this fails
** for any reason. */
rc = sqlite3_open(zFilename, &pFile);
if( rc==SQLITE_OK ){
pFrom = (isSave ? pInMemory : pFile);
pTo = (isSave ? pFile : pInMemory);
pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
if( pBackup ){
(void)sqlite3_backup_step(pBackup, -1);
(void)sqlite3_backup_finish(pBackup);
}
printf("foo");
rc = sqlite3_errcode(pTo);
}
/* Close the database connection opened on database file zFilename
** and return the result of this function. */
(void)sqlite3_close(pFile);
return rc;
}
int main(int argc, char* argv[]) {
sqlite3 *db;
char *zErrMsg = 0;
int rc;
string 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(stderr, "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.c_str(), callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Table created successfully\n");
}
/* Insert SQL statement */
sql = "INSERT INTO COMPANY " \
"VALUES (1, 'Paul', 32, 'California', 20000.00 ); " \
"INSERT INTO COMPANY " \
"VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); " \
"INSERT INTO COMPANY " \
"VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" \
"INSERT INTO COMPANY " \
"VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql.c_str(), callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Records created successfully\n");
}
/* Select SQL statement */
//sql = "SELECT * from COMPANY WHERE NAME LIKE 'Paul'";
sql = "SELECT * from COMPANY";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql.c_str(), callback, 0, &zErrMsg);
if( rc != SQLITE_OK ) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Operation done successfully\n");
}
loadOrSaveDb(db, "test.db", 0);
sqlite3_close(db);
printf("foo1");
return 0;
}
The destination for sqlite3_backup_init has to be a database connection handle. In order to use sqlite3 *pInMemory; as the destination, you should initialise it with such a handle:
sqlite3 *pInMemory; /* Database connection opened on zFilename */
sqlite3_open(":memory:", &pInMemory);
I need to execute sql command "select" and return some data from the result of it. I'm trying to do it with sqlite3_exec, but it's only writting in stdout. What I need to do to write the data in array or something like this?
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;
}
void my_exec(char * sql) {
sqlite3 *db;
char *zErrMsg = nullptr;
int rc;
//char * sql;
/* Open database */
rc = sqlite3_open("data_base.db", &db);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
} else {
fprintf(stdout, "Opened database successfully\n");
}
/* Create SQL statement */
// sql
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, nullptr, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Success\n");
}
/* Close database */
sqlite3_close(db);
}
Let's look at the fourth parameter of sqlite3_exec(). This is a pointer that is passed to the callback function. Give sqlite3_exec() a pointer to your data structure and store the results to that pointer in the callback.
You can for example use a vector:
std::vector<std::pair<std::string, std::string>> vec;
rc = sqlite3_exec(db, sql, callback, &vec, &zErrMsg);
The callback:
static int callback(void *dataPtr, int argc, char **argv, char **azColName){
auto vec = static_cast<std::vector<std::pair<std::string, std::string>>*>(dataPtr);
int i;
for(i=0; i<argc; i++){
vec->push_back({azColName[i], argv[i] ? argv[i] : "NULL"});
}
return 0;
}
I am using sqlite library for C++ to work with database. I want to get return values from sqlite3_exec() function as used in below code.
For eg., if I execute a "DELETE from COMPANY where id=2;", I want to distinguish between the results of this query(it it deleted an existing row or it didn't or if the table exists or not).
All I am able to do using below code is execute the SQL statement. Is it possible to do this?
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
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;
}
int main(int argc, char* argv[])
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
const char* data = "Callback function called";
/* Open database */
rc = sqlite3_open("test.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
fprintf(stderr, "Opened database successfully\n");
}
/* Create merged SQL statement */
sql = "DELETE from COMPANY where ID=2; " \
"SELECT * from COMPANY";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "Operation done successfully\n");
}
sqlite3_close(db);
return 0;
}
I have to check if a table exists before it is created, by reading
How do I check in SQLite whether a table exists?, I use sqlite3_exec to do one step query with
SELECT name FROM sqlite_master WHERE type = 'table' AND name
='table1';
and use the callback to set a flag to identify the table exists or not.
Unfortunately, the callback will not be called, if the table is not yet created.
Why the callback is not being called? I know that callback is not called for queries without output results, e.g. "create table" etc, and only called with "SELECT" queries. But I am not aware that it may not even be called for "SELECT".
The following is the code sample to reproduce the problem.
#include <stdio.h>
#include <sqlite3.h>
bool isExist=false;
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
printf("I am being called\n");
if (argc>0) isExist = true;
return 0;
}
int main(int argc, char **argv){
sqlite3 *db;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("test.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
//char* sqlCreateTable = "CREATE TABLE table1(name TEXT);";
//rc = sqlite3_exec(db, sqlCreateTable, callback, 0, &zErrMsg);
// callback will not be called if table is not yet created
char* sql_hasTable = "SELECT name FROM sqlite_master WHERE type = 'table' AND name ='table1';";
rc = sqlite3_exec(db, sql_hasTable, callback, 0, &zErrMsg);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return 0;
}
I have read several posts but still cannot figure out what is wrong here.
I have a c++ wrapper to call the sqlite. I want to test if the table exists before it is created, by reading check-in-sqlite-whether-a-table-exists, I use the following sql statement to check a table exists
"SELECT name FROM test.db WHERE type='table' AND name='table1';"
The main code is the following:
static int callback(void *db, int argc, char **argv, char **azColName){
for(int i=0; i<argc; ++i){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
return 0;
}
class SqliteAccessor {
public:
open(){ sqlite3_open("test.db", &m_db); }
createTable1(){
string sql = "CREATE TABLE table1(one TEXT);";
char *zErrMsg = 0;
int rc = sqlite3_exec(m_db, sql.c_str(), callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
printf("SQL error: %s", zErrMsg);
sqlite3_free(zErrMsg);
}
}
hasTable1(){
string sql = "SELECT name FROM test.db WHERE type='table' AND name='table1'";
char *zErrMsg = 0;
int rc = sqlite3_exec(m_db, sql.c_str(), callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
printf("SQL error: %s", zErrMsg); // Error: no such table: test.db
sqlite3_free(zErrMsg);
}
}
private:
sqlite3* m_db;
}
main(){
SqliteAccessor sql;
sql.open(); // success;
sql.createTable1(); // success;
sql.hasTable1(); // fail
}
I also tried with cli api:
sqlite3 test.db
sqlite> create table table1(one varchar(10));
sqlite> SELECT * FROM test.db;
Error: no such table: test.db
sqlite> SELECT name FROM test.db WHERE type='table' AND name='table1';
Error: no such table: test.db
// however, if I run .tables, then it is there.
sqlite> .tables
table1
it is the same error, but why such error? it is the lastest sqlite amalgamation version.
Look into sqlite_master instead.
SELECT * FROM sqlite_master WHERE name LIKE '%your_table_name%'