How to Lock and then Unlock sqlite database using c? - c

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.)

Related

Null string retrieve in prepared/bound parameter query SQLite on C

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.

Assign certain data to a struct with sqlite3

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.

Calling two functions that use different database using sqlite3 in C

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 .

C Program SQL Errol: Database is Locked

Trying to Create a table into database by using the code.
While running the above code the output is Opened Database successfully but the error is SQL Error:: database is locked.
IDE: Code Block.
OS: Ubuntu.
#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;
}

Write the data values which is read from database to a variable in C program : (Sqlite database is used with c interface)

I am a newbie to sqlite database. I have a table named as FIREWALL_TABLE_LIST and from which i want to extract the CAN_MESSAGE_ID value and store in the message_ID which is a variable declared in my c program. Any help or suggestions?.
#ifdef TEST_VECTORS
#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[])
{
/* INITIALIZATION */
int message_ID = 0;
/* INITIALIZATION for database*/
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
const char* data = "Callback function called";
/* Open database */
rc = sqlite3_open("rt.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
fprintf(stderr, "\nOpened database successfully\n\n");
}
/* Create SQL statement */
sql = "SELECT * from FIREWALL_TABLE_LIST WHERE DATE_TIME = (SELECT MAX(DATE_TIME) FROM FIREWALL_TABLE_LIST)";
/* 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\n");
}
sqlite3_close(db);
fprintf(stderr, "Closed database successfully\n\n");
return 0;
}
#endif /* TEST_VECTORS */
You should not use SELECT * because then the order and count of columns will vary with every change of the database schema.
Just use SELECT CAN_MESSAGE_ID ....
The sqlite3_exec callback receives a bunch of strings, so you have to convert the value back into a number:
message_ID = atoi(argv[0]);

Resources