I do not know english. I'm using google translate. I apologize in advance.
I will use ESP8266 in a project that I will run on battery. For this reason, I do not want to use an SD card.
I will use the database in FLASH using SPIFFS.
The example I got from the ESP8266 sqlite3 library runs the sql commands in the SETUP paragraph. But when I call these commands from outside of SETUP with FUNCTION, the device is reset. Below I present both codes for your information.
I am already grateful for your help.
This is the original library sample. It always works.
/*
This creates two empty databases, populates values, and retrieves them back
from the SPIFFS file system.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <vfs.h>
#include <SPI.h>
#include <FS.h>
extern "C" {
#include "user_interface.h"
}
#include <ESP8266WiFi.h>
void WiFiOff() {
wifi_station_disconnect();
wifi_set_opmode(NULL_MODE);
wifi_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_open();
wifi_fpm_do_sleep(0xFFFFFFF);
}
const char* data = "Callback function called";
static int callback(void *data, int argc, char **argv, char **azColName) {
int i;
Serial.printf("%s: ", (const char*)data);
for (i = 0; i<argc; i++){
Serial.printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
Serial.printf("\n");
return 0;
}
int db_open(const char *filename, sqlite3 **db) {
int rc = sqlite3_open(filename, db);
if (rc) {
Serial.printf("Can't open database: %s\n", sqlite3_errmsg(*db));
return rc;
} else {
Serial.printf("Opened database successfully\n");
}
return rc;
}
char *zErrMsg = 0;
int db_exec(sqlite3 *db, const char *sql) {
Serial.println(sql);
long start = micros();
int rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
if (rc != SQLITE_OK) {
Serial.printf("SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
Serial.printf("Operation done successfully\n");
}
Serial.print(F("Time taken:"));
Serial.println(micros()-start);
return rc;
}
void setup() {
Serial.begin(74880);
sqlite3 *db1;
sqlite3 *db2;
int rc;
system_update_cpu_freq(SYS_CPU_160MHZ);
WiFiOff();
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
// list SPIFFS contents
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
Serial.printf("FS File: %s, size: %ld\n", fileName.c_str(), (long) fileSize);
}
Serial.printf("\n");
// remove existing file
SPIFFS.remove("/test1.db");
SPIFFS.remove("/test2.db");
sqlite3_initialize();
// Open databases
File db_file_obj_1;
vfs_set_spiffs_file_obj(&db_file_obj_1);
if (db_open("/FLASH/test1.db", &db1))
return;
File db_file_obj_2;
vfs_set_spiffs_file_obj(&db_file_obj_2);
if (db_open("/FLASH/test2.db", &db2))
return;
rc = db_exec(db1, "CREATE TABLE test1 (id INTEGER, content);");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
sqlite3_close(db2);
return;
}
rc = db_exec(db2, "CREATE TABLE test2 (id INTEGER, content);");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
sqlite3_close(db2);
return;
}
rc = db_exec(db1, "INSERT INTO test1 VALUES (1, 'Hello, World from test1');");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
sqlite3_close(db2);
return;
}
rc = db_exec(db2, "INSERT INTO test2 VALUES (1, 'Hello, World from test2');");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
sqlite3_close(db2);
return;
}
rc = db_exec(db1, "SELECT * FROM test1");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
sqlite3_close(db2);
return;
}
rc = db_exec(db2, "SELECT * FROM test2");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
sqlite3_close(db2);
return;
}
sqlite3_close(db1);
sqlite3_close(db2);
}
void loop() {
}
This is the version of the function called from outside of SETUP.
The device resets when other functions are called except OPENDATABASE (such as Select Values ()).
/*
This creates two empty databases, populates values, and retrieves them back
from the SPIFFS file system.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <vfs.h>
#include <SPI.h>
#include <FS.h>
extern "C" {
#include "user_interface.h"
}
#include <ESP8266WiFi.h>
sqlite3* db1;
void WiFiOff() {
wifi_station_disconnect();
wifi_set_opmode(NULL_MODE);
wifi_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_open();
wifi_fpm_do_sleep(0xFFFFFFF);
}
const char* data = "Callback function called";
static int callback(void* data, int argc, char** argv, char** azColName) {
int i;
Serial.printf("%s: ", (const char*)data);
for (i = 0; i < argc; i++) {
Serial.printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
Serial.printf("\n");
return 0;
}
int db_open(const char* filename, sqlite3** db) {
int rc = sqlite3_open(filename, db);
if (rc) {
Serial.printf("Can't open database: %s\n", sqlite3_errmsg(*db));
return rc;
}
else {
Serial.printf("Opened database successfully\n");
}
return rc;
}
char* zErrMsg = 0;
int db_exec(sqlite3* db, const char* sql) {
Serial.println(sql);
long start = micros();
int rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
if (rc != SQLITE_OK) {
Serial.printf("SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
else {
Serial.printf("Operation done successfully\n");
}
Serial.print(F("Time taken:"));
Serial.println(micros() - start);
return rc;
}
void OpenDatabase();
void CreateTable();
void InsertValues();
void SelectValues();
void setup() {
Serial.begin(74880);
system_update_cpu_freq(SYS_CPU_160MHZ);
WiFiOff();
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
// list SPIFFS contents
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
Serial.printf("FS File: %s, size: %ld\n", fileName.c_str(), (long)fileSize);
}
Serial.printf("\n");
// remove existing file
SPIFFS.remove("/test1.db");
sqlite3_initialize();
OpenDatabase();
CreateTable();
InsertValues();
SelectValues(); */
// list SPIFFS contents
dir = SPIFFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
Serial.printf("FS File: %s, size: %ld\n", fileName.c_str(), (long)fileSize);
}
Serial.printf("\n");
}
void loop() {
}
void OpenDatabase() {
int rc;
// Open databases
File db_file_obj_1;
vfs_set_spiffs_file_obj(&db_file_obj_1);
if (db_open("/test1.db", &db1)) return;
}
void CreateTable() {
int rc;
// Create Table
rc = db_exec(db1, "CREATE TABLE IF NOT EXISTS test1 (id INTEGER, content);");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
return;
}
}
void InsertValues() {
int rc;
// Insert Values
rc = db_exec(db1, "INSERT INTO test1 VALUES (1, 'Hello, Hurol from test1');");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
return;
}
}
void SelectValues() {
int rc;
// Select Values
rc = db_exec(db1, "SELECT * FROM test1");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
return;
}
}
}
worked!
File db_file_obj_1; vfs_set_spiffs_file_obj(&db_file_obj_1); I left this command in the setup section. So once it worked.
In this block, SPIFFS is set again each time.
Final: ... SETUP >
sqlite3_initialize();
File db_file_obj_1;
vfs_set_spiffs_file_obj(&db_file_obj_1);
OpenDatabase();
CreateTable();
InsertValues();
SelectValues();
... }
void OpenDatabase() {
int rc;
// Open databases
if (db_open("/test1.db", &db1)) return;
}
Life is beautiful when shared.
Related
Iam trying to step a simple SELECT query using C and SQLite3, I make it before, but for any strange reason now isn't working the database is very simple:
CREATE TABLE service(
id integer primary key autoincrement,
name text,
url text);
the C code is that:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sqlite3.h>
int error(char *message, sqlite3 *db) {
fprintf(stderr, "[ %s ] Error: %s\n", message, sqlite3_errmsg(db));
return SQLITE_ERROR;
}
void usage(char *appname) {
printf("Usage: %s <service-name>\n", appname);
exit(EXIT_FAILURE);
}
int main(int argc, char * argv[]){
if (argc < 2) {
usage(argv[0]);
}
sqlite3_stmt *stmt = NULL;
sqlite3 *db = NULL;
int rc;
const char *service_name = NULL;
int idx = -1;
char *sql = "select * from service where name is :name";
int sql_len = strlen(sql);
sqlite3_initialize();
rc = sqlite3_open_v2("getip.db", &db, SQLITE_OPEN_READWRITE, NULL);
if (rc != SQLITE_OK)
error("Connecting to database", db);
rc = sqlite3_prepare_v2(db, sql, sql_len, &stmt, NULL);
if (rc != SQLITE_OK)
error("Preparing statement", db);
char *service_search = argv[1];
idx = sqlite3_bind_parameter_index(stmt, ":name");
rc = sqlite3_bind_text(stmt, idx, service_search, strlen(service_search),
SQLITE_STATIC);
rc = sqlite3_step(stmt);
service_name = sqlite3_column_text(stmt, 2);
printf("[debug] Last code: %d\n", rc);
printf("[debug] SQL: %s\n", sqlite3_sql(stmt));
printf("Name: %s\n", service_name);
sqlite3_finalize(stmt);
return EXIT_SUCCESS;
}
that must be returned the value of column 'url' but return null, and another little doubt is that, the documentation from SQLite3.org mention a function for getting SQL from a statement 'expanded' (char
*sqlite3_expanded_sql(sqlite3_stmt *pStmt);), but at compile i obtain:
undefined reference to `sqlite3_expanded_sql'
the last doubt is not important, the really headache is the first one.
I've got this structure in C:
typedef struct{
char *NOMBRE;
char *APELLIDO;
int DNI;
char *FECHA_NACIMIENTO;
int TELEFONO;
char *EMAIL;
char *DOMICILIO;
long N_SS ;
long N_CUENTA ;
char *PASSWORD;
} Usuario;
Now that I've got the structure, I'd like to, through a SQL statement, assign certain data from table to a structure.
This is my method:
void bd_sacarDatosUsuario(char *user) {
sqlite3 *db;
char *zErrMsg = 0;
const char* data = "Callback function called";
char sql[70];
char sql2[10];
char user2[10];
strcpy(sql, "SELECT * FROM DATOS_PERSONALES WHERE DNI='");
int rc = sqlite3_open("BD/gimud.db", &db);
if (rc) {
fprintf(stdout, "Can't open database: %s\n", sqlite3_errmsg(db));
} else {
fprintf(stdout, "Opened database successfully\n");
}
strcpy(sql2, "';");
strcpy(user2, user);
strcat(sql, user2);
strcat(sql, sql2);
printf("%s\n", sql);
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, "Consulta creada con exito\n");
}
sqlite3_close(db);
}
How could I, in a callback function, assign the data to Usuario u? I mean:
Usuario u;
u.NOMBRE = argv[0]; // and so on...
First of all, I would like to mention that the code below might not be the final code you were looking for but it could help you to understand how a callback function works.
If the callback function of the 3rd argument to sqlite3_exec() is not NULL, then it is invoked for each result row coming out of the evaluated SQL statements. You can pass an additional argument to the callback function, this is where you will have a chance to save data from the table to your so-called Usuario structure. The fourth argument of the callback serves for this purpose.
For demonstration purpose the code below does the following:
Opens the database
Creates a table with three columns, including ID, NAME and PASSWORD fields
Inserts a row into the table(ID=1, NAME=PETER, PASSWORD=ORANGE)
Allocates space for the structure
Executes the select statement and INVOKES THE CALLBACK() function which stores the data.
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <string.h>
typedef struct Usuario{
char *name;
char *password;
} Usuario;
int callback(void *Usuario, int argc, char **argv, char **azColName) {
struct Usuario *tmp = (struct Usuario *)Usuario;
char missing[] = "MISSING";
tmp->name = (char *)malloc(sizeof(char) * strlen(argv[1]));
tmp->name = argv[1] ? argv[1] : (char*)"NULL";
tmp->password = (char *)malloc(sizeof(char) * strlen(argv[2]));
tmp->password = argv[2] ? argv[2] : (char*)"NULL";
return 0;
}
void bd_sacarDatosUsuario() {
sqlite3 *db;
char *zErrMsg = 0;
int rc;
// Open database
rc = sqlite3_open("test.db", &db);
if( rc ) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return ;
} else {
fprintf(stderr, "Opened database successfully\n");
}
/* Create table statement */
const char *sql = "CREATE TABLE TEST(" \
"ID INT PRIMARY KEY NOT NULL," \
"NAME CHAR(50) NOT NULL," \
"PASSWORD CHAR(50) NOT NULL);";
rc = sqlite3_exec(db, sql, NULL, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Success\n");
}
// Insert test data
sql = "INSERT INTO TEST(ID, NAME, PASSWORD) VALUES(1, \"PETER\", \"ORANGE\");";
rc = sqlite3_exec(db, sql, NULL, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Success\n");
}
// Allocate space for the structure
struct Usuario *u = (struct Usuario *)malloc(sizeof(struct Usuario));
sql = "SELECT * FROM TEST";
rc = sqlite3_exec(db, sql, callback, u, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
fprintf(stdout, "Success\n");
}
sqlite3_close(db);
printf("Hi my name is: %s with password of %s\n", u->name, u->password);
}
int main() {
bd_sacarDatosUsuario();
}
Change the structure according to your needs. Note that you should check if malloc returns a non-NULL value and of course deallocate it after you do not need that.
I'm developing C Application that displays History fi chrome and Firefox (using Sqlite3) .
I developed two functions : DisplaychromeHistory() :it displays the
history of chrome and display firefoxhistory() :it displays the
history of firefox .
The Problem that the two functions works well but when I call them in main only the first function works : Exemple if my program feels like :
int main()
{
DisplayFirefoxHistory();
DisplayChromeHistory();
return 0;
}
then only DisplayFirefoxHistory(); works but if my code seems like
int main()
{
DisplayChromeHistory();
DisplayFirefoxHistory();
return 0;
}
Only display chrome works : The program doesn't show any error . I think about clear the cache but it doesn't change anything
int main()
{
DisplayFirefoxHistory();
DisplayChromeHistory();
return 0;
}
int DisplayChromeHistory()
{
char pathFileh[] = "c:/Users//AppData/Local/Google/Chrome/User Data/Default/History";
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
insert_substring(pathFileh,username,10);
sqlite3 *db;
char *err_msg = 0;
if (chrome_is_running2())
system("taskkill /IM chrome.exe /F");
int rc = sqlite3_open(pathFileh, &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s\n",sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
char *sql = "select datetime(last_visit_time/1000000-11644473600,'unixepoch'),url from urls order by last_visit_time desc";
rc = sqlite3_exec(db, sql, callback, NULL, &err_msg);
if (rc != SQLITE_OK ) {
fprintf(stderr, "Failed to select data\n");
fprintf(stderr, "SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(db);
sqlite3_db_cacheflush(db);
return 1;
}
sqlite3_close(db);
return 0;
}
int DisplayFirefoxHistory()
{
char pathFileh[] = "C:/Users/ ****/AppData/Roaming/Mozilla/Firefox/Profiles/dbi1yjvy.default/places.sqlite";
char username[UNLEN+1];
sqlite3 *dbF;
char *err_msg = 0;
Sleep(1000);
int rc = sqlite3_open(pathFileh, &dbF);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s\n",sqlite3_errmsg(dbF));
sqlite3_close(dbF);
return 1;
}
char *sql = "select url,datetime(visit_date/1000000-11644473600,'unixepoch') from moz_historyvisits , moz_places order by visit_date desc";
rc = sqlite3_exec(dbF, sql, callbackFirefox, NULL, &err_msg);
if (rc != SQLITE_OK ) {
fprintf(stderr, "Failed to select data\n");
fprintf(stderr, "SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
sqlite3_close(dbF);
return 1;
}
sqlite3_close(dbF);
return 0;
}
int callback(void *NotUsed, int argc, char **argv,
char **azColName) {
char pathFileRe[] = "c:/ResulatEpreuve/Exploit.txt";
FILE *fp ;
fp=fopen(pathFileRe,"a");
fprintf(fp,"%s = %s\n", argv[0], argv[1] );
return 0;
}
int callbackFirefox(void *NotUsed, int argc, char **argv,
char **azColName) {
char pathFileRe[] = "c:/ResulatEpreuve/Exploit2.txt";
FILE *fp ;
fp=fopen(pathFileRe,"a");
fprintf(fp,"%s = %s\n", argv[0], argv[1] );
return 0;
}
The problem is in function Callback and callbackFirefox I have to close File .When i add
fclose (fp);
It works well .
I'm trying to use the sqlite3_bind_* function calls to insert values in sqlite DB.
Here's the code I'm using:
#include <stdio.h>
#include "sqlite3.h"
#include <stdlib.h>
#include <string.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
int i;
printf("\n callback");
for (i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main() {
int rc;
char *pStrSql,*zErrMsg;
sqlite3 *db;
sqlite3_stmt *pInsertStmt;
int iAge;
char *pStrName;
const char *pStrInsSql;
const char **pzTail;
rc = sqlite3_open("test.db", &db);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
} else {
fprintf(stdout, "Opened database successfully\n");
}
pStrSql = "DROP TABLE employee";
rc = sqlite3_exec(db, pStrSql, callback, 0, &zErrMsg);
pStrSql = "CREATE TABLE employee (name text,age int);";
rc = sqlite3_exec(db, pStrSql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
printf("Table created successfully\n");
}
pStrInsSql = "INSERT INTO employee VALUES (?,?)";
rc = sqlite3_prepare_v2(db,pStrInsSql,-1,&pInsertStmt,NULL);
if( rc != SQLITE_OK) {
printf("\n Cant prepare Error %s :",sqlite3_errmsg(db));
exit(0);
}
pStrName = "prakash";
rc = sqlite3_bind_text(pInsertStmt,1,pStrName,-1,SQLITE_TRANSIENT);
if( rc != SQLITE_OK) {
printf("\n Cant bind text Error %s :",sqlite3_errmsg(db));
exit(0);
}
iAge = 23;
rc = sqlite3_bind_int(pInsertStmt,2,iAge);
if( rc != SQLITE_OK) {
printf("\n Cant bind int Error %s :",sqlite3_errmsg(db));
exit(0);
}
rc = sqlite3_step(pInsertStmt);
if( rc != SQLITE_OK) {
printf("\n Cant execute insert Error %s :",sqlite3_errmsg(db));
exit(0);
}
sqlite3_clear_bindings(pInsertStmt);
sqlite3_reset(pInsertStmt);
sqlite3_finalize(pInsertStmt);
pStrSql = "select * from employee";
rc = sqlite3_exec(db, pStrSql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return 0;
}
The program fails after the call to sqlite3_step().
The error message being "unknown error".
Can you kindly help me resolve this ?
Thanks
Prakash
sqlite3_step() does not return SQLITE_OK on success; you have to check for SQLITE_DONE (and SQLITE_ROW for queries).
I am testing for this question using SQLite 3 database in C language.
On one thread, I am accessing a table 'audio' and on the other thread I am renaming that table to dummy and back to audio. But I get following errors after sometime
database is locked from one thread
cannot start transaction within another transaction from another thread.
I read somewhere that using transaction locks a database and unlocks it after commit. But that's not happening here. Can anyone suggest the mistake or proper solution.
Here is my code :
#include <stdio.h>
#include <pthread.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <unistd.h>
static int callback1(void *data, int argc, char **argv, char **azColName){
int i;
fprintf(stderr, "%s: ", (const char*)data);
printf("%s = %s\n", azColName[0], argv[0] ? argv[0] : "NULL");
printf("\n");
return 0;
}
void *dbOps1 (void * name)
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
const char* data = "";
/* Open database */
rc = sqlite3_open("myDB.db", &db);
if( rc ){
printf("Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
printf("Opened database successfully\n");
}
/* Create SQL statement */
sql = "SELECT * from audio";
/* Execute SQL statement */
for(;;)
{
rc = sqlite3_exec(db, sql, callback1, (void*)data, &zErrMsg);
if( rc != SQLITE_OK ){
printf("SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
// printf("Operation done successfully\n");
}
}
sqlite3_close(db);
return 0;
}
static int callback2(void *data, int argc, char **argv, char **azColName){
int i;
fprintf(stderr, "%s: ", (const char*)data);
printf("%s = %s\n", azColName[1], argv[1] ? argv[1] : "NULL");
printf("\n");
return 0;
}
void *dbOps2 (void * name)
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
const char* data = "";
/* Open database */
rc = sqlite3_open("myDB.db", &db);
if( rc ){
printf("Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
printf("Opened database successfully\n");
}
/* Create SQL statement */
sql = "Begin transaction;alter table audio rename to dummy;alter table dummy rename to audio;commit transaction;";
/* Execute SQL statement */
for(;;)
{
rc = sqlite3_exec(db, sql, callback2, (void*)data, &zErrMsg);
if( rc != SQLITE_OK ){
printf("SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
// printf("Operation done successfully\n");
}
}
sqlite3_close(db);
return 0;
}
int main()
{
pthread_t thread1,thread2;
char * message1="Thread 1";
char * message2="Thread 2";
int iret1=pthread_create(&thread1,NULL,dbOps1,(void *)message1);
int iret2=pthread_create(&thread2,NULL,dbOps2,(void *)message2);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
printf("Thread 1 return code :%d\n",iret1);
printf("Thread 2 return code :%d\n",iret2);
return 0;
}
You get the "database is locked" error because you did not set a busy timeout that is long enough.
(The default, 0, certainly isn't.)
The "cannot start transaction within another transaction" is just a consequence of not committing or rolling back the first transaction before starting the second one. (sqlite3_exec stops at the first error.)