-
Notifications
You must be signed in to change notification settings - Fork 4
/
sqlitedis.cc
131 lines (105 loc) · 3.12 KB
/
sqlitedis.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* A simple C++ wrapper for sqlite3 to allow for easy testing of extensions
*
* David Basden <[email protected]>
*/
#include <iostream>
#include <memory>
#include "sqlite3.h"
#ifdef STATIC_REDISVFS
extern "C" {
#include "redisvfs.h"
}
#endif
class SQLengine {
sqlite3 *db;
static int _row_print_callback(void *arg, int ncols, char **cols, char **colnames) {
for (int i=0; i<ncols; ++i) {
std::cout << colnames[i] << "=" << cols[i] << " ";
}
std::cout << std::endl;
return 0;
}
public:
explicit SQLengine(const char *dbName = "database.sqlite",
int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI)
{
if (sqlite3_open_v2(dbName, &db, openFlags, NULL)) {
auto err = std::string("sqlite3_open: ") + dbName +": "+ sqlite3_errmsg(db);
throw std::runtime_error(err);
}
}
~SQLengine() {
sqlite3_close(db);
}
void exec(const char *sql) {
char *errmsg = NULL;
if (sqlite3_exec(db, sql, _row_print_callback, NULL, &errmsg)) {
auto err = std::string(errmsg);
sqlite3_free(errmsg);
throw std::runtime_error(err);
};
}
void loadExtension(const char *sharedLib) {
char *errmsg = NULL;
sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL);
if(sqlite3_load_extension(db, sharedLib, NULL, &errmsg)) {
auto err = std::string(errmsg);
sqlite3_free(errmsg);
throw std::runtime_error(err);
};
}
std::string currentVFSname() {
sqlite3_vfs *vfs;
sqlite3_file_control(db, "main", SQLITE_FCNTL_VFS_POINTER, &vfs);
return std::string(vfs->zName);
}
static void loadPersistentExtension(const char *sharedLib) {
// If the know the extension is persistent, we just create a
// memory backed sqlite db load the extension into it, and then
// throw away the db
SQLengine tmpeng(":memory:");
tmpeng.loadExtension(sharedLib);
}
static void dumpvfslist() {
std::cerr << "vfs available:";
for(sqlite3_vfs *vfs=sqlite3_vfs_find(0); vfs; vfs=vfs->pNext){
std::cerr << " " << vfs->zName;
}
std::cerr << std::endl;
std::cerr << "default vfs is " << SQLengine::defaultVFS() << std::endl;
}
static std::string defaultVFS() {
sqlite3_vfs *vfs = sqlite3_vfs_find(0);
return std::string(vfs->zName);
}
};
int main(int argc, const char **argv) {
#ifdef STATIC_REDISVFS
if (redisvfs_register() != SQLITE_OK) {
return 1;
}
#endif
const char* extname = getenv("SQLITE_LOADEXT");
if (extname != NULL) {
//std::cerr << "Loading extension "<<extname <<std::endl;
SQLengine::loadPersistentExtension(extname);
}
if (argc < 2) {
std::cerr << argv[0] << " <SQL statements>" << std::endl <<
std::endl << "optional environment variables: SQLITE_DB SQLITE_LOADEXT" <<std::endl;
SQLengine::dumpvfslist();
return 1;
}
std::shared_ptr<SQLengine> sql;
char *envdbname = getenv("SQLITE_DB");
if (envdbname) {
//std::cerr << "(using database '"<<envdbname<<"' from env SQLITE_DB) " << std::endl;
sql = std::make_shared<SQLengine>(envdbname);
}
else {
sql = std::make_shared<SQLengine>();
}
//std::cerr << "(using vfs " << sql->currentVFSname() << ")" << std::endl;
sql->exec(argv[1]);
return 0;
}