sqlite basics
This commit is contained in:
parent
c4b34ea22a
commit
2856f3f1d5
2
Makefile
2
Makefile
@ -13,7 +13,7 @@ endif
|
|||||||
CXXFLAGS += -Isource/ -Iobject/ -Isource/sqlfun/source/
|
CXXFLAGS += -Isource/ -Iobject/ -Isource/sqlfun/source/
|
||||||
LDLIBS += $$(pkg-config --cflags --libs sqlite3 jansson)
|
LDLIBS += $$(pkg-config --cflags --libs sqlite3 jansson)
|
||||||
|
|
||||||
SOURCE := main.cpp Database.cpp
|
SOURCE := main.cpp Database.cpp Sqlite.cpp
|
||||||
OBJECT := $(subst .cpp,.o,${SOURCE})
|
OBJECT := $(subst .cpp,.o,${SOURCE})
|
||||||
SOURCE := $(addprefix source/,${SOURCE})
|
SOURCE := $(addprefix source/,${SOURCE})
|
||||||
OBJECT := $(addprefix object/,${OBJECT})
|
OBJECT := $(addprefix object/,${OBJECT})
|
||||||
|
176
source/Sqlite.cpp
Normal file
176
source/Sqlite.cpp
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
#include <Sqlite.hpp>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char * Sqlite::top() {
|
||||||
|
static const char * const r =
|
||||||
|
"/* This source file was generated with esql.\n"
|
||||||
|
" */\n"
|
||||||
|
"\n"
|
||||||
|
"/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,\n"
|
||||||
|
" They are private implementation details that can be changed or\n"
|
||||||
|
" removed. */\n"
|
||||||
|
"\n"
|
||||||
|
"#include <sqlite3.h>\n"
|
||||||
|
;
|
||||||
|
return (char*)r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * Sqlite::connect(const char * const to, const char * const as) {
|
||||||
|
char * r;
|
||||||
|
/* XXX: check for duplicates; check for not being open
|
||||||
|
*/
|
||||||
|
connection = as;
|
||||||
|
const int a = asprintf(&r,
|
||||||
|
"sqlite3 *%s;\n"
|
||||||
|
"sqlite3_open(\"%s\", &%s);\n",
|
||||||
|
as, to, as
|
||||||
|
);
|
||||||
|
(void)a;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * Sqlite::disconnect() {
|
||||||
|
char * r;
|
||||||
|
const int a = asprintf(&r,
|
||||||
|
"sqlite3_close(%s);\n",
|
||||||
|
connection.c_str()
|
||||||
|
);
|
||||||
|
(void)a;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sqlite::declare(const char * const type, const char * const name) {
|
||||||
|
variables.push_back({name, type, scope});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sqlite::scope_push() {
|
||||||
|
++scope;
|
||||||
|
}
|
||||||
|
void Sqlite::scope_pop() {
|
||||||
|
--scope;
|
||||||
|
for(int i = variables.size()-1; i > -1; i--) {
|
||||||
|
if (variables[i].scope > scope) {
|
||||||
|
variables.erase(variables.begin() + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Sqlite::scope_clear() {
|
||||||
|
scope = 0;
|
||||||
|
variables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
size_t c_var_parser(const char * const s) {
|
||||||
|
size_t r = 0;
|
||||||
|
|
||||||
|
if (s[0] == '$'
|
||||||
|
|| (s[0] >= 'a' && s[0] <= 'z')
|
||||||
|
|| (s[0] >= 'A' && s[0] <= 'Z')) {
|
||||||
|
++r;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const char * i = s+1; *i != '\0'; i++) {
|
||||||
|
if ((*i >= 'a' && *i <= 'z')
|
||||||
|
|| (*i >= 'A' && *i <= 'Z')
|
||||||
|
|| (*i >= '0' && *i <= '9')) {
|
||||||
|
++r;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Sqlite::var_collect_and_placehold(const char * const sql, std::vector<variable*> &collection) {
|
||||||
|
std::string r;
|
||||||
|
for (int i = 0; sql[i] != '\0'; i++) {
|
||||||
|
if (sql[i] == ':') {
|
||||||
|
++i;
|
||||||
|
std::string var(sql + i, c_var_parser(sql + i));
|
||||||
|
bool is_real_var = false;
|
||||||
|
for (auto&& i : variables) {
|
||||||
|
if (var == i.name) {
|
||||||
|
collection.push_back(&i);
|
||||||
|
is_real_var = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not is_real_var) {
|
||||||
|
std::string e = std::string() + "No variable declared under the name '" + var + "'";
|
||||||
|
esql_error(e.c_str());
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
r += '?';
|
||||||
|
} else {
|
||||||
|
r += sql[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Sqlite::statement_to_format_string(const char * const sql, const std::vector<variable*> collection) {
|
||||||
|
std::string r;
|
||||||
|
// XXX: what if there is a '?' in the sql to begin with?
|
||||||
|
struct { // XXX this table is horrible
|
||||||
|
const char * type_name;
|
||||||
|
const char * placeholder;
|
||||||
|
} placeholder_table[] = {
|
||||||
|
{"char", "%c"},
|
||||||
|
{"short", "%hd"},
|
||||||
|
{"int", "%d"},
|
||||||
|
{"long", "%ld"},
|
||||||
|
{"float", "%f"},
|
||||||
|
{"double", "%lf"},
|
||||||
|
{"void*", "%p"},
|
||||||
|
{"char*", "%s"},
|
||||||
|
};
|
||||||
|
auto lookup_placeholder = [&](const char* type_name) -> const char* {
|
||||||
|
for (const auto& entry : placeholder_table) {
|
||||||
|
if (not strcmp(entry.type_name, type_name)) {
|
||||||
|
return entry.placeholder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
int var_counter = 0;
|
||||||
|
for (const char * c = sql; *c != '\0'; c++) {
|
||||||
|
if (*c == '?') {
|
||||||
|
r += lookup_placeholder(collection[var_counter]->type.c_str());
|
||||||
|
} else {
|
||||||
|
r += *c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * Sqlite::exec(const char * const sql) {
|
||||||
|
char * r;
|
||||||
|
std::vector<variable*> variable_collection;
|
||||||
|
std::string sql_with_placeholders = var_collect_and_placehold(sql, variable_collection);
|
||||||
|
|
||||||
|
int v = validate(sql_with_placeholders.c_str());
|
||||||
|
if (v) {
|
||||||
|
std::string e = std::string() + "Invalid SQL \'" + sql + '\'';
|
||||||
|
esql_error(e.c_str());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not variable_collection.size()) {
|
||||||
|
asprintf(&r, "sqlite3_exec(%s, \"%s\", 0, 0, 0);",
|
||||||
|
this->connection.c_str(),
|
||||||
|
sql_with_placeholders.c_str()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
std::string s =
|
||||||
|
"char * _esql_s;\n"
|
||||||
|
"asprintf(&_esql_s,"
|
||||||
|
;
|
||||||
|
s += ");";
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
#ifndef EMBEDED_SQLITE_HPP
|
||||||
|
#define EMBEDED_SQLITE_HPP
|
||||||
#include "Database.hpp"
|
#include "Database.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -18,62 +20,19 @@ class Sqlite : public Database {
|
|||||||
|
|
||||||
std::vector<variable> variables = {};
|
std::vector<variable> variables = {};
|
||||||
|
|
||||||
char * connect(const char * const to, const char * const as) override {
|
char * top();
|
||||||
char * r;
|
|
||||||
/* XXX: check for duplicates; check for not being open
|
|
||||||
*/
|
|
||||||
connection = as;
|
|
||||||
const int a = asprintf(&r,
|
|
||||||
"sqlite3 *%s;\n"
|
|
||||||
"sqlite3_open(\"%s\", &%s);\n",
|
|
||||||
as, to, as
|
|
||||||
);
|
|
||||||
(void)a;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual char * disconnect() {
|
char * connect(const char * const to, const char * const as);
|
||||||
char * r;
|
char * disconnect();
|
||||||
const int a = asprintf(&r,
|
|
||||||
"sqlite3_close(%s);\n",
|
|
||||||
connection.c_str()
|
|
||||||
);
|
|
||||||
(void)a;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual char * declare(const char * const from) {
|
void declare(const char * const type, const char * const name);
|
||||||
return NULL;
|
void scope_push();
|
||||||
}
|
void scope_pop();
|
||||||
|
void scope_clear();
|
||||||
|
|
||||||
virtual void scope_push() {
|
char * exec(const char * const sql);
|
||||||
++scope;
|
|
||||||
}
|
|
||||||
virtual void scope_pop() {
|
|
||||||
--scope;
|
|
||||||
for(int i = variables.size()-1; i > -1; i--) {
|
|
||||||
if (variables[i].scope > scope) {
|
|
||||||
variables.erase(variables.begin() + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual void scope_clear() {
|
|
||||||
scope = 0;
|
|
||||||
variables.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
char * exec(const char * const sql) override {
|
std::string var_collect_and_placehold(const char * const sql, std::vector<variable*> &collection);
|
||||||
char * r;
|
std::string statement_to_format_string(const char * const sql, const std::vector<variable*> collection);
|
||||||
int v = validate(sql);
|
|
||||||
if (v) {
|
|
||||||
std::string e = std::string() + "Invalid SQL \'" + sql + '\'';
|
|
||||||
esql_error(e.c_str());
|
|
||||||
}
|
|
||||||
const int a = asprintf(&r,
|
|
||||||
"sqlite3_exec(%s, \"%s\", 0, 0, NULL);\n",
|
|
||||||
connection.c_str(), sql
|
|
||||||
);
|
|
||||||
(void)a;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user