MSVC2017 Statically linking SQLite3 - c++

I have a Microsoft Visual Code 2017 console application which I want to link statically against sqlite3. I have linked the sqlite3.lib file and included the sqlite3.h file. However, when I execute the program it still pops-up the message that it is missing sqlite3.dll. I thought that sqlite3 would be linked statically, what am I doing wrong?
Compiling goes without errors
This is my code:
#include "stdafx.h"
#include "sqlite3.h"
#pragma comment(lib, "sqlite3.lib")
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, _TCHAR* 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;
}
rc = sqlite3_exec(db, "create table stuff ( name )", callback, 0, &zErrMsg);
rc = sqlite3_exec(db, "insert into stuff values ('hello')", callback, 0, &zErrMsg);
rc = sqlite3_exec(db, "select * from stuff", callback, 0, &zErrMsg);
if(rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return 0;
}

You can include the sqlite3.c file alongside your other .c or .cpp files. This is a single large file for the whole thing. Then it will be statically linked without dealing with .lib or .dll files.

Related

how to write the result of sqlite3_exec not in stdout

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;
}

Why can´t I implement Primary key in my SQL Table?

I try to save Data in my esp32. In my table there should be a primary key so that I can´t save something twice with the same id. But I get an error
The Error Code:
SQL error: disk I/O error
That´s the whole Code :
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_spiffs.h"
#include "esp_timer.h"
#include "sqlite3.h"
static const char *TAG = "sqlite3_spiffs";
const char* data = "Callback function called";
static int callback(void *data, int argc, char **argv, char **azColName) {
int i;
printf("%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 db_open(const char *filename, sqlite3 **db) {
int rc = sqlite3_open(filename, db);
if (rc) {
printf("Can't open database: %s\n", sqlite3_errmsg(*db));
return rc;
} else {
printf("Opened database successfully\n");
}
return rc;
}
char *zErrMsg = 0;
int db_exec(sqlite3 *db, const char *sql) {
printf("%s\n", sql);
int64_t start = esp_timer_get_time();
int rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
if (rc != SQLITE_OK) {
printf("SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
printf("Operation done successfully\n");
}
printf("Time taken: %lld\n", esp_timer_get_time()-start);
return rc;
}
void setup()
{
sqlite3 *db1;
int rc;
ESP_LOGI(TAG, "Initializing SPIFFS");
esp_vfs_spiffs_conf_t conf = {
.base_path = "/spiffs",
//.partition_label = "storage",
.partition_label = NULL,
.max_files = 5,
.format_if_mount_failed = true
};
// Use settings defined above to initialize and mount SPIFFS filesystem.
// Note: esp_vfs_spiffs_register is an all-in-one convenience function.
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount or format filesystem");
} else if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
} else {
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
}
return;
}
size_t total = 0, used = 0;
ret = esp_spiffs_info(NULL, &total, &used);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
} else {
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
}
// remove existing file
unlink("/spiffs/test1.db");
unlink("/spiffs/test2.db");
sqlite3_initialize();
if (db_open("/spiffs/test1.db", &db1))
return;
rc = db_exec(db1, "CREATE TABLE entries(id STRING PRIMARY KEY, value ,section)");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
return;
}
rc = db_exec(db1, "INSERT INTO entries VALUES ('ROOMNAME', 'HH180L23G', 'general');");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
return;
}
rc = db_exec(db1, "SELECT * FROM entries");
if (rc != SQLITE_OK) {
sqlite3_close(db1);
return;
}
sqlite3_close(db1);
// All done, unmount partition and disable SPIFFS
esp_vfs_spiffs_unregister(NULL);
ESP_LOGI(TAG, "SPIFFS unmounted");
//while(1);
}
void loop() {
// put your main code here, to run repeatedly:
}
I have ideas like that it has something to do with spiffs or with the mounting ..
I tried both partition.labels .. it´s the same error ..
I can´t figure out why it doesn´t let me take a primary key .. the same thing as I can´t implement unique Text or something I get the same error..
Did someone have experienced it before ?
It would be such a huge support
Log Monitor:
Opened database successfully
CREATE TABLE entries(id STRING PRIMARY KEY, value ,section)
SQL error: disk I/O error
Time taken: 179044
Looks like a known problem: https://github.com/siara-cc/esp32_arduino_sqlite3_lib/issues/18
Somebody has posted a workaround/fix, which doesn't look very promising to me - they explicitly specify the label of the SPIFFS partition when mounting it. Try it, see if it works.
https://github.com/siara-cc/esp32-idf-sqlite3/issues/13

Get return codes from sql operations

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;
}

sqlite3_exec callback is not called

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;
}

sqlite3 error: no such table: when checking if table exists

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%'