Populating a C struct - c

I would like to assign value fetched from sqlite database to a c-struct so I do that as follows:
typedef struct
{
uint16_t shortID;
double temp;
unsigned long timestamp;
} location_t;
static uint8_t prv_set_value(lwm2m_data_t* dataP,
location_t* tempData)
{
uint8_t ret = COAP_205_CONTENT;
sqlite3 *db;
sqlite3_stmt *res;
// connect to sqlite
int rc = sqlite3_open("test.sqlite3", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
else {
fprintf(stderr, "Connection to SQLITE established!.\n" );
}
rc = sqlite3_prepare_v2(db, "SELECT temp FROM envirment ORDER BY ID DESC LIMIT 1", -1, &res, 0);
if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to fetch data: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
rc = sqlite3_step(res);
if (rc == SQLITE_ROW) {
fprintf(stdout, "Temperature value ==== : %s\n", sqlite3_column_double(res, 0));
tempData->temp = sqlite3_column_double(res, 0);
fprintf(stdout, "Temp value from temperature_data_t: %s\n", tempData->temp);
}
sqlite3_finalize(res);
sqlite3_close(db);
}
return ret;
}
Data is fetched from the sqlite database. I'm doing a check to see if the function behaves as intended so I display the value before and after the assignment. The output from the struct assignment tempData->temp = sqlite3_column_double(res, 0);as displayed in next line fprintf(stdout, " Temp value from temperature_data_t: %s\n", tempData->temp); is null. Following is the function output:
Connection to SQLITE established!.
Temperature value ==== : 29.1
Temp value from temperature_data_t: (null)
What is the correct way to assign fetched to tempData->temp?

tempData->temp = sqlite3_column_double(res, 0); is correct but because tempData->temp is a double, not a char*, replace
fprintf(stdout, "Temp value from temperature_data_t: %s\n", tempData->temp) ;
by
fprintf(stdout, "Temp value from temperature_data_t: %f\n", tempData->temp);
I suppose the line
fprintf(stdout, "Temperature value ==== : %s\n", sqlite3_column_double(res, 0));
is in fact
fprintf(stdout, "Temperature value ==== : %s\n", sqlite3_column_text(res, 0));
because sqlite3_column_double doesn't return a char*
May be see also : retrieving float values using sqlite3_column_double

Related

sqlite3_bind_text() not binding placeholders

I am trying to use placeholder parameters as described in the sqlite documentation.
Below is the code I'm running.
No matter how I position the ? in the sql command, sqlite3_bind_text() doesn't work. I have also tried #table, :table, and ?1 as
placeholders. I even tried replacing the first two exec the calls with explicit prepare
and step calls.
What's interesting is that sqlite3_bind_int() works if I have a clause like:
sql = "SELECT * FROM test WHERE rowid = ?;";
Using sprintf() also works:
sprintf(sql, "SELECT %s FROM test;", "message");
/* gcc -l sqlite3 retrieve.c -o retrieve */
#include <stdio.h>
#include <sqlite3.h>
int main()
{
sqlite3 *db;
sqlite3_stmt *stmt;
int result;
const char *sql;
char *err_msg;
err_msg = 0;
result = sqlite3_open("test.db", &db);
if (result)
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
sql = "CREATE TABLE IF NOT EXISTS test ("
"id INTEGER PRIMARY KEY,"
"message TEXT NOT NULL );";
result = sqlite3_exec(db, sql, NULL, 0, &err_msg);
if (result != SQLITE_OK)
{
fprintf(stderr, "SQL exec error: %s\n", err_msg);
sqlite3_free(err_msg);
}
sql = "INSERT INTO test (message) VALUES ('hi how ya doin');";
result = sqlite3_exec(db, sql, NULL, 0, &err_msg);
if (result != SQLITE_OK)
{
fprintf(stderr, "SQL exec error: %s\n", err_msg);
sqlite3_free(err_msg);
}
sql = "SELECT message FROM ?;"; /* doesn't work */
/* sql = "SELECT ? FROM test;"; /\* doesn't work *\/ */
result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
result = sqlite3_bind_text(stmt, 1, "test", -1, SQLITE_STATIC); /* doesn't work */
/* result = sqlite3_bind_text(stmt, 1, "message", -1, SQLITE_STATIC); /\* doesn't work *\/ */
if (result != SQLITE_OK)
{
fprintf(stderr, "Could not bind string\n");
}
else
{
printf("SQLITE_OK\n");
}
while (sqlite3_step(stmt) == SQLITE_ROW) /* checking for done leaves room for error */
{
printf("%s\n", sqlite3_column_text(stmt, 0));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}

reading junk out of a blob in sqlite

I have a snippet of code which is somehow messing up the reading of bytes of a sqlite database. I've experienced this multiple times: first with a PNG where the last three bytes would differ, second with the king james bible and thirdly with a very simple test case. I'm stumped as to where I'm messing up. In all these cases, the command line sqlite tool can see the data inside the database correctly (both when viewed manually and when using writefile).
So the insertion is definitely working correctly, it's just that somehow my extraction is erroneous somehow. I am quite a novice at C so I expect I may have misallocated memory in someway, I just don't understand how.
#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
static char const dummy_content[] =
"hello world more \n\n\n hello worlds \nlalalala";
int
main(int argc, char **argv) {
sqlite3 *db;
sqlite3_stmt *stmt;
int rc, file_len, sqlite_len;
const char *file_contents;
const char *sqlite_contents;
rc = sqlite3_open("blah.db", &db);
if ( rc ) {
fprintf(stderr, "couldn't open db\n");
return 1;
}
/* initialise the schema */
rc = sqlite3_exec(db,
"BEGIN TRANSACTION;"
"DROP TABLE IF EXISTS blobs;"
"CREATE TABLE blobs(id TEXT NOT NULL, value BLOB, PRIMARY KEY(id));"
"COMMIT;",
NULL, NULL, NULL);
if ( rc ) {
fprintf(stderr, "couldn't initialise schema");
return 1;
}
file_contents = dummy_content;
file_len = sizeof(dummy_content);
/* insert the bytes */
rc = sqlite3_prepare_v2(db,
"INSERT INTO blobs VALUES(?, ?);",
-1,
&stmt, NULL);
if ( rc ) {
fprintf(stderr, "error preparing stmt: %s", sqlite3_errmsg(db));
return 1;
}
printf("prepared stmt\n");
rc = sqlite3_bind_text(stmt, 1, "boring", -1, NULL);
rc = rc | sqlite3_bind_blob(stmt, 2, file_contents, file_len, NULL);
if ( rc ) {
fprintf(stderr, "error binding to sql stmt");
return 1;
}
if ( (rc = sqlite3_step(stmt)) != SQLITE_DONE) {
fprintf(stderr, "something went wrong with execution");
}
sqlite3_finalize(stmt);
if ( rc != SQLITE_DONE ) return 1;
printf("loaded db\n");
/* load the bytes */
rc = sqlite3_prepare_v2(db,
"SELECT value FROM blobs WHERE id = ?;",
-1, &stmt, NULL);
if ( rc ) {
fprintf(stderr, "error preparing stmt: %s", sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_bind_text(stmt, 1, "boring", -1, NULL);
if ( rc ) { fprintf(stderr, "error binding"); return 1; }
sqlite_len = -1;
while ( (rc = sqlite3_step(stmt)) != SQLITE_DONE ) {
if ( rc == SQLITE_ERROR ) {
fprintf(stderr, "error executing sql");
sqlite3_finalize(stmt);
return 1;
} else if ( rc == SQLITE_ROW ) {
sqlite_contents = sqlite3_column_blob(stmt, 0);
sqlite_len = sqlite3_column_bytes(stmt, 0);
}
}
if ( sqlite_len < 0 ) {
fprintf(stderr, "no value found in db");
sqlite3_finalize(stmt);
return 1;
}
printf("sqlite_len: %i file_len: %i\n", sqlite_len, file_len);
printf("from file string: %s\n", file_contents);
printf("from sqlite string: %s\n", sqlite_contents);
/* this frees the memory for the sqlite_contents */
sqlite3_finalize(stmt);
return 0;
}
You can only use the value returned by sqlite3_column_blob() until the next time you call sqlite3_step(). Your code isn't obeying that restriction (You're trying to print out the blob after another call to sqlite3_step() returns SQLITE_DONE)
From the documentation:
The pointers returned are valid until a type conversion occurs as described above, or until sqlite3_step() or sqlite3_reset() or sqlite3_finalize() is called.

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.

How to give the user input as a parameter for the sql statement

I have tried to run this code but when I am trying to add a new broker, as soon as I give the IP address as input on the console, the program exits and throws an error saying segmentation fault. I have used a character array to store the IP address.
I am not sure about how should I give the user inputs as parameters to the sql insert query.
#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\t", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(char c, char* argv[])
{
sqlite3 *db;
int rc;
char *zErrMsg = 0;
char *sql;
int choice;
char option;
int port,priority;
char *nameID,*ip;
rc = sqlite3_open("topology.cnf", &db);
if(rc){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return(0);
}else{
fprintf(stderr, "Opened database successfully\n");
}
// Creation of table
sql = "CREATE TABLE BROKERLIST(" \
"IP CHAR(16) PRIMARY KEY NOT NULL," \
"PORT INT NOT NULL," \
"NAMEID TEXT NOT NULL," \
"PRIORITY INT NOT NULL );";
// Executing 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");
}
do{
printf("Enter choice \n1.Add broker\t2.Remove broker\t3.Change broker priority\t4.Show map");
scanf("%d", &choice);
switch(choice){
case 1: printf("\nEnter IP, Port, NameID, Priority");
scanf("%s%d%s%d",ip,&port,nameID,&priority);
sql = "INSERT INTO BROKERLIST(IP,PORT,NAMEID,PRIORITY) " \
"VALUES('"+ip+"','"+port+"','"+nameID+"','"+priority+"'); " ;
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, "Added broker successfully\n");
}
break;
case 2: printf("\nEnter NameID of the broker to be removed");
scanf("%s",nameID);
sql = "DELETE from BROKERLIST where NAMEID = '"+nameID+"'; " ;
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, "Removed broker successfully\n");
}
break;
case 3: printf("\nEnter NameID of broker whose priority has to be changed and the new priority");
scanf("%s%d",nameID,&priority);
sql = " UPDATE BROKERLIST set PRIORITY = '"+priority+"' where NAMEID = '"+nameID+"'; ";
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, "Updated Priority of broker\n");
}
break;
case 4: sql = "SELECT * from BROKERLIST" ;
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
break;
}
printf("\n Do you want to continue?(Y/N)");
fflush(stdin);
scanf("%c",&option);
}while(option == 'Y' || option == 'y');
return 0;
}
You have not allocated any memory to store IP or name ID. You have just allocated pointers, which point no where, so scanf is writing to some random location and crashing your program.
The simplest fix is to change:
char *nameID,*ip;
to:
char nameID[100];
char IP[100];
assuming of course 100 is more than the user would input.

sqlite c api insert binding

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

Resources