i have created a .db file using Berkeley DB using C. I want to view the contents inside the .db file. How to achieve this when I ahve no GUI on a linux machine?
if you system had been installed the Berkeley DB, you could use it like this, it is a demo to test, hope it could solve your problem:
#include <stdio.h>
#include <stdlib.h>
#include <db.h>
#define DATABASE "test.db"
typedef struct _data_struct {
int data_id;
char data[20];
} data_struct;
int main()
{
DBT key, data;
DB *dbp;
int ret;
data_struct my_data;
ret = db_create(&dbp, NULL, 0); // create the DB handle
if (ret != 0)
{
perror("create");
return 1;
}
ret = dbp->open(dbp, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0); // open the database
if (ret != 0)
{
perror("open");
return 1;
}
my_data.data_id = 1;
strcpy(my_data.data, "some data");
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &(my_data.data_id);
key.size = sizeof(my_data.data_id);
data.data = &my_data;
data.size = sizeof(my_data);
ret = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE); // add the new data into the database
if (ret != 0)
{
printf("Data ID exists\n");
}
dbp->close(dbp, 0); // close the database
return 0;
}
Related
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.
I'm writing my very first C program and I was really doing well. The application talks to RESTful server. All was good until I decided to use an embedded database(libdb) for storage. I got this code below that was part of my entire program. My problem is it keeps on crashing on this line:
my_archive->db_home_dir = DEFAULT_HOMEDIR;
I thought I was running out of stack so I malloc'd all my lengthy variables but the problem was still occuring so I decided to separate this libdb part into a new code, but the problem still remains.
Any idea what has gone wrong here?
P.S. I'm doing all the coding in Xcode and stepping through each line after debug breakpoint right after main() doesn't help me a bit. Always ends up on the same error line. Or perhaps I just don't know what I'm doing.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
#include "db.h"
#define DEFAULT_HOMEDIR "/Users/mark/Documents/bdb/"
#define URLSDB "urls"
typedef struct archive_dbs {
DB *URLS_dbp;
char *db_home_dir;
char *URLS_db_name;
} ARCHIVE_DBS;
void initialize_archivedbs(ARCHIVE_DBS *my_archive)
{
my_archive->db_home_dir = DEFAULT_HOMEDIR; //CRASHES HERE: Thread 1: EXC_BAD_ACCESS (code=2, address=0x1000061da)
my_archive->URLS_dbp = NULL;
my_archive->URLS_db_name = NULL;
}
void set_db_filenames(ARCHIVE_DBS *my_archive)
{
size_t size;
size = strlen(my_archive->db_home_dir) + strlen(URLSDB) + 1;
my_archive->URLS_db_name = malloc(size);
snprintf(my_archive->URLS_db_name, size, "%s%s", my_archive->db_home_dir, URLSDB);
}
int open_database(DB **dbpp, const char *file_name, const char *program_name, FILE *error_file_pointer)
{
DB *dbp;
u_int32_t open_flags;
int ret;
ret = db_create(&dbp, NULL, 0);
if (ret != 0) {
fprintf(error_file_pointer, "%s: %s\n", program_name,
db_strerror(ret));
return(ret);
}
*dbpp = dbp;
dbp->set_errfile(dbp, error_file_pointer);
dbp->set_errpfx(dbp, program_name);
open_flags = DB_CREATE;
ret = dbp->open(dbp,
NULL,
file_name,
NULL,
DB_BTREE,
open_flags,
0);
if (ret != 0) {
dbp->err(dbp, ret, "Database '%s' open failed.", file_name);
return(ret);
}
return (0);
}
int databases_setup(ARCHIVE_DBS *my_archive, const char *program_name, FILE *error_file_pointer)
{
int ret;
ret = open_database(&(my_archive->URLS_dbp), my_archive->URLS_db_name, program_name, error_file_pointer);
if (ret != 0)
return (ret);
printf("databases opened successfully\n");
return (0);
}
int databases_close(ARCHIVE_DBS *my_archive)
{
int ret;
if (my_archive->URLS_dbp != NULL) {
ret = my_archive->URLS_dbp->close(my_archive->URLS_dbp, 0);
if (ret != 0)
fprintf(stderr, "URLS database close failed: %s\n",
db_strerror(ret));
}
printf("databases closed.\n");
return (0);
}
int main(void){
ARCHIVE_DBS *archivedbs;
initialize_archivedbs(archivedbs);
set_db_filenames(archivedbs);
databases_setup(archivedbs, "urlfetcher", NULL);
open_database(&archivedbs->URLS_dbp, "URLS.db", "urlfetcher",
NULL);
databases_close(archivedbs);
}
I am using Berkeley DB to store the data persistently in my program. I tested it on my SSD, my SSD speed is 1.4Gb/s for writing. My progrma for testing the storing speed of DB is shown below (error checking is omitted).
const char* db_dir="./.db";
const char* db_name = "node_test_0";
void mk_path(char* dest,const char* prefix,const char* db_name){
memcpy(dest,prefix,strlen(prefix));
dest[strlen(prefix)] = '/';
memcpy(dest+strlen(prefix)+1,db_name,strlen(db_name));
dest[strlen(prefix)+strlen(db_name)+1] = '\0';
return;
}
int main() {
DB* b_db;
DB_ENV* dbenv;
int ret;
int flag = 0;
DBT key, data;
char* full_path = NULL;
if((ret = mkdir(db_dir,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0){
if(errno != EEXIST){
}
}
full_path = (char*)malloc(strlen(db_dir) + strlen(db_name) + 2);
mk_path(full_path, db_dir, db_name);
if ((ret = db_env_create(&dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "Environment Created: %s", db_dir);
}
if ((ret = dbenv->open(dbenv, db_dir, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL|DB_THREAD, 0)) != 0) {
}
if((ret = db_create(&b_db,dbenv,flag)) != 0){
}
if((ret = b_db->open(b_db, NULL, db_name, NULL, DB_BTREE, DB_THREAD|DB_CREATE,0)) != 0){
}
struct timeval start_time;
struct timeval end_time;
unsigned long e_usec;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = "fruit";
key.size = sizeof("fruit");
data.data = "apple";
data.size = sizeof("apple");
gettimeofday(&start_time, NULL);
ret = b_db->put(b_db, NULL, &key, &data, 0);
gettimeofday(&end_time, NULL);
e_usec = ((end_time.tv_sec * 1000000) + end_time.tv_usec) - ((start_time.tv_sec * 1000000) + start_time.tv_usec);
printf("%lu\n", e_usec);
if (ret == 0)
printf("db: %s: key stored.\n", (char *)key.data);
else {
b_db->err(b_db, ret, "DB->put");
}
return 0;
}
The result is about 23 microseconds. It's much slower than I expected. Does anyone have idea on this? What can I do to make my persistent storage as fast as writing to SSD.
BerkeleyDB does a fsync after write's to ensure that the data on disk is saved. You can stub out the fsync(2) vector (just return 0) if you are willing to live with the consequence of possibly catastrophic data loss (which is acceptable for a temporary, non-persistent, data store using BDB)
Below is my code:
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <db.h>
#define DATABASE "access.db"
typedef struct {
char data1[20];
char src[20];
} pearson_record;
I am geting the error:
illegal flag specified to DB->get
DB->get: Invalid argument
Any idea where I am going wrong.
int
main()
{
pearson_record s;
char *papa="1.1.1.1";
char *source="papa";
DB *dbp;
DBT key, data;
int ret, t_ret;
db_recno_t recno;
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
fprintf(stderr, "db_create: %s\n", db_strerror(ret));
exit (1);
}
if ((ret = dbp->open(dbp,
NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
dbp->err(dbp, ret, "%s", DATABASE);
goto err;
}
recno = 10;
#define BUFFER_LENGTH (5 * 1024 * 1024)
data.ulen = BUFFER_LENGTH;
data.flags = DB_DBT_USERMEM;
strncpy(s.data1, papa, strlen(papa)+1);
strncpy(s.src, source, strlen(source)+1);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
//memset(&s, 0, sizeof(struct pearson_record));
key.data = &recno;
key.size = sizeof(recno);
data.data = &s;
data.size = sizeof(s);
papa="1.1.1.2";
source="papaa";
strncpy(s.data1, papa, strlen(papa)+1);
strncpy(s.src, source, strlen(source)+1);
if ((ret = dbp->put(dbp, NULL, &key,&data,0)) == 0)
printf("db: %d: key stored.\n", *(int *)key.data);
else
{
dbp->err(dbp, ret, "DB->put");
goto err;
}
recno = 11;
strncpy(s.data1, papa, strlen(papa)+1);
strncpy(s.src, source, strlen(source)+1);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
//memset(&s, 0, sizeof(struct pearson_record));
key.data = &recno;
key.size = sizeof(recno);
data.data = &s;
data.size = sizeof(s);
papa="1.1.1.2";
source="papaa";
strncpy(s.data1, papa, strlen(papa)+1);
strncpy(s.src, source, strlen(source)+1);
if ((ret = dbp->put(dbp, NULL, &key,&data,0)) == 0)
printf("db: %d: key stored.\n", *(int *)key.data);
else
{
dbp->err(dbp, ret, "DB->put");
goto err;
}
pearson_record *ppr;
if ((ret = dbp->get(dbp, NULL, &key, &data, DB_SET_RECNO)) == 0) {
ppr = (pearson_record *) data.data;
printf("db: %d: key retrieved: data was %s,%s. %d\n",
*(int *)key.data, ppr->data1,ppr->src, data.size);
}
else {
dbp->err(dbp, ret, "DB->get");
goto err;
}
if ((ret = dbp->get(dbp, NULL, &key, &data, DB_SET_RECNO)) == 0) {
ppr = (pearson_record *) data.data;
printf("db: %d: key retrieved: data was %s,%s. %d\n",
*(int *)key.data, ppr->data1,ppr->src, data.size);
}
else {
dbp->err(dbp, ret, "DB->get");
goto err;
}
err: if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
ret = t_ret;
exit(ret);
}
A quick glance at the documentation for DB->get says: "For DB_SET_RECNO to be specified, the underlying database must be of type Btree, and it must have been created with the DB_RECNUM flag."
It doesn't look like you created the database with that flag. I haven't looked through the rest of your code, but that's one obvious place that needs to be fixed.
You can also ask these questions on the online Berkeley DB forum.
Regards,
Dave
I am trying to develop a database using Berkeley Db in C. I want to have multiple data inside the database and then access them. my code is below:
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <db.h>
#define DATABASE "access.db"
typedef struct {
int id;
char data1[20];
char src[20];
} pearson_record;
int
main()
{
pearson_record s;
char *papa="1.1.1.1";
char *source="papa";
DB *dbp;
DBT key, data;
int ret, t_ret;
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
fprintf(stderr, "db_create: %s\n", db_strerror(ret));
exit (1);
}
if ((ret = dbp->open(dbp, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
dbp->err(dbp, ret, "%s", DATABASE);
goto err;
}
s.id = 10;
strncpy(s.data1, papa, strlen(papa)+1);
strncpy(s.src, source, strlen(source)+1);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
//memset(&s, 0, sizeof(struct pearson_record));
key.data = &(s.id);
key.size = sizeof(int);
data.data = &s;
data.size = sizeof(s);
papa="1.1.1.2";
source="papaa";
strncpy(s.data1, papa, strlen(papa)+1);
strncpy(s.src, source, strlen(source)+1);
if ((ret = dbp->put(dbp, NULL, &key,&data,DB_NOOVERWRITE)) == 0)
printf("db: %d: key stored.\n", *(int *)key.data);
else
{
dbp->err(dbp, ret, "DB->put");
goto err;
}
s.id = 11;
strncpy(s.data1, papa, strlen(papa)+1);
strncpy(s.src, source, strlen(source)+1);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
//memset(&s, 0, sizeof(struct pearson_record));
key.data = &(s.id);
key.size = sizeof(int);
data.data = &s;
data.size = sizeof(s);
papa="1.1.1.2";
source="papaa";
strncpy(s.data1, papa, strlen(papa)+1);
strncpy(s.src, source, strlen(source)+1);
if ((ret = dbp->put(dbp, NULL, &key,&data,DB_NOOVERWRITE)) == 0)
printf("db: %d: key stored.\n", *(int *)key.data);
else
{
dbp->err(dbp, ret, "DB->put");
goto err;
}
pearson_record *ppr;
if ((ret = dbp->get(dbp, NULL, &key, &data, DB_MULTIPLE)) == 0) {
ppr = (pearson_record *) data.data;
printf("db: %d: key retrieved: data was %s,%s. %d\n",
*(int *)key.data, ppr->data1,ppr->src, data.size);
} else {
dbp->err(dbp, ret, "DB->get");
goto err;
}
if ((ret = dbp->get(dbp, NULL, &key, &data, DB_MULTIPLE)) == 0) {
ppr = (pearson_record *) data.data;
printf("db: %d: key retrieved: data was %s,%s. %d\n",
*(int *)key.data, ppr->data1,ppr->src, data.size);
} else {
dbp->err(dbp, ret, "DB->get");
goto err;
}
err:
if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0)
ret = t_ret;
exit(ret);
}
Right now it says DB_DBT_MULTIPLE has to be set. I don't know how to do that. Previously without the flags i was only getting the last entry. Any kind of help would be appreciated. Thanks in advance
If I'm reading your code correctly, you are calling get twice with the same key, which returns the same data for obvious reasons.
If you want to iterate over the records, you will need to use a Cursor, see Chapter 4 of Getting Started with Berkeley DB for a good reference for same.