init
This commit is contained in:
commit
8d050f3c30
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
esql
|
||||
object/
|
||||
*.out
|
||||
.gdb_history
|
||||
venv/
|
||||
|
||||
.peru
|
48
Makefile
Normal file
48
Makefile
Normal file
@ -0,0 +1,48 @@
|
||||
ifeq (${DEBUG}, 1)
|
||||
LFLAGS += --debug --trace
|
||||
CFLAGS += -Wall -Wextra -Wpedantic
|
||||
CFLAGS += -DDEBUG -O0 -ggdb -fno-inline
|
||||
CXXFLAGS += -Wall -Wextra -Wpedantic
|
||||
CXXFLAGS += -DDEBUG -O0 -ggdb -fno-inline
|
||||
WRAP := valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all
|
||||
else
|
||||
CXXFLAGS += -O3 -fno-stack-protector -fno-exceptions -fno-rtti
|
||||
endif
|
||||
|
||||
CXXFLAGS += -Isource/ -Iobject/ -Isource/sqlfun/source/
|
||||
LDLIBS += $$(pkg-config --cflags --libs sqlite3 jansson)
|
||||
|
||||
GENSOURCE := object/sqlite.tab.cpp object/sqlite.yy.cpp object/esql.yy.cpp
|
||||
|
||||
GENOBJECT := $(subst .cpp,.o,${GENSOURCE})
|
||||
|
||||
REEEEEEEE := exec.o sql.tab.o lib.o sql.o
|
||||
REEEEEEEE := $(addprefix source/sqlfun/source/,${REEEEEEEE})
|
||||
|
||||
OUTPUT := esql
|
||||
|
||||
object/%.yy.cpp: source/%.l
|
||||
flex ${LFLAGS} --prefix=$(basename $(notdir $<))_ --header-file=object/$(basename $(notdir $<)).yy.h -o $@ $<
|
||||
|
||||
object/%.tab.cpp: source/%.y
|
||||
bison --name-prefix=$(basename $(notdir $<))_ --header=object/$(basename $(notdir $<)).tab.h -o $@ $<
|
||||
|
||||
object/%.o: source/%.c
|
||||
${COMPILE.c} $< -o $@
|
||||
|
||||
object/%.o: source/%.cpp
|
||||
${COMPILE.cpp} $< -o $@
|
||||
|
||||
object/%.o: object/%.c
|
||||
${COMPILE.c} $< -o $@
|
||||
|
||||
object/%.o: object/%.cpp
|
||||
${COMPILE.cpp} $< -o $@
|
||||
|
||||
|
||||
main: ${GENOBJECT} source/main.o ${REEEEEEEE}
|
||||
${LINK.cpp} -o ${OUTPUT} $+ ${LDLIBS}
|
||||
|
||||
clean:
|
||||
-rm object/*
|
||||
-cd source/sqlfun/; make clean
|
62
README.md
Normal file
62
README.md
Normal file
@ -0,0 +1,62 @@
|
||||
# Embeded SQL
|
||||
> Framework and SQLite implementation of DB2 style embeded SQl for C/C++
|
||||
|
||||
## What is embeded SQL?
|
||||
In short, this:
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
signed main(){
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
int i;
|
||||
char c[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
EXEC SQL CONNECT TO testdb AS myconnection;
|
||||
EXEC SQL SELECT i, text INTO :i, :c FROM test WHERE i = 1;
|
||||
|
||||
puts(c);
|
||||
|
||||
return i;
|
||||
}
|
||||
```
|
||||
It, in broad sense, is what PL/SQL is for Ada, for C/C++.
|
||||
|
||||
With an extra step of preprocessing,
|
||||
the above is turned into conventional C,
|
||||
that any compiler will be able to deal with.
|
||||
|
||||
## Why?
|
||||
Embeded SQL provides the following benefits:
|
||||
+ better syntax highlighting compatibility
|
||||
+ compile time SQL syntax checks
|
||||
+ more agile database <-> language type conversions
|
||||
|
||||
## Who is responsible for this?
|
||||
IBM is.
|
||||
The embeded SQL debuted with their DB2.
|
||||
I am awfully unsure,
|
||||
which edition,
|
||||
but I believe it originates from the 80s.
|
||||
|
||||
In 1998,
|
||||
Michael Meskes started Postgresqls on going embeded SQL support
|
||||
with the following comment:
|
||||
|
||||
> Well this is not really a patch.
|
||||
But I mananged to get Linus' old Postgres95 precompiler
|
||||
to compile and work with PostgreSQL.
|
||||
|
||||
What that implies is under investigation.
|
||||
|
||||
Regardles the standard Postgresql tool `ecpg`
|
||||
is highly functional
|
||||
and something I can only recommend for people
|
||||
working with Postgresql in specific.
|
||||
|
||||
However,
|
||||
I find the usage of databases with a server architecture
|
||||
for non-enterprise purposes of rather poor taste.
|
||||
This is why this project sets out to
|
||||
start supporting SQLite/embeded SQL and
|
||||
to create a system where adding arbitrary databases is easy
|
8
debug/static_insert.sqc
Normal file
8
debug/static_insert.sqc
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
signed main(){
|
||||
EXEC SQL CONNECT TO testdb AS myconnection;
|
||||
EXEC SQL INSERT INTO a VALUES (10);
|
||||
|
||||
return i;
|
||||
}
|
File diff suppressed because one or more lines are too long
0
object/.gitkeep
Normal file
0
object/.gitkeep
Normal file
5
peru.yaml
Normal file
5
peru.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
imports:
|
||||
sqlfun: source/sqlfun # This is where we want peru to put the module.
|
||||
|
||||
git module sqlfun:
|
||||
url: http://github.com/agvxov/sqlfun.git
|
5
source/Database.hpp
Normal file
5
source/Database.hpp
Normal file
@ -0,0 +1,5 @@
|
||||
class Database {
|
||||
public:
|
||||
virtual char * connect(const char * const to, const char * const as) = 0;
|
||||
virtual char * eval(const char * const sql) = 0;
|
||||
};
|
57
source/esql.l
Normal file
57
source/esql.l
Normal file
@ -0,0 +1,57 @@
|
||||
%{
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "Database.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern Database * db;
|
||||
|
||||
string sql = "";
|
||||
|
||||
%}
|
||||
|
||||
%option noyywrap
|
||||
%option nodefault
|
||||
|
||||
%x SQL
|
||||
|
||||
ws [ \t\r\v\f]
|
||||
wsnl [ \t\r\v\f\n]
|
||||
|
||||
%%
|
||||
|
||||
<INITIAL>{
|
||||
|
||||
EXEC{wsnl}+SQL{wsnl}+ {
|
||||
BEGIN SQL;
|
||||
}
|
||||
|
||||
. {
|
||||
;
|
||||
}
|
||||
|
||||
\n {
|
||||
++yylineno;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
<SQL>{
|
||||
; {
|
||||
sql += yytext;
|
||||
printf("Found SQL: \"%s\"\n", sql.c_str());
|
||||
db->eval(sql.c_str());
|
||||
sql = "";
|
||||
BEGIN INITIAL;
|
||||
}
|
||||
|
||||
. {
|
||||
sql += yytext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
%%
|
72
source/main.cpp
Normal file
72
source/main.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "esql.yy.h"
|
||||
#include "sqlite.yy.h"
|
||||
|
||||
extern "C" {
|
||||
#include "sql.tab.h"
|
||||
#include "yyl.h"
|
||||
#include "sql.lex.h"
|
||||
#include "sql-parser.h"
|
||||
}
|
||||
|
||||
#include "Database.hpp"
|
||||
#include "sqlite.tab.h"
|
||||
class Sqlite : public Database {
|
||||
struct psql_state *pstate;
|
||||
|
||||
int validate(const char * const sql) {
|
||||
int r;
|
||||
char * dup = strdup(sql);
|
||||
psql_set_string_input(pstate, dup);
|
||||
r = psql_parse(pstate);
|
||||
free(dup);
|
||||
return !r
|
||||
&& !yyerrno;
|
||||
}
|
||||
|
||||
char * connect(const char * const to, const char * const as) override {
|
||||
char * r = NULL;
|
||||
#if DEBUG
|
||||
printf("Connecting to \"%s\" as \"%s\"\n", to, as);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
char * eval(const char * const sql) override {
|
||||
char * r = NULL;
|
||||
int v = validate(sql);
|
||||
#if DEBUG
|
||||
printf("Recieved SQL: \"%s\" (%d)\n", sql, v);
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
public:
|
||||
Sqlite() {
|
||||
pstate = psql_new();
|
||||
if (!pstate) {
|
||||
throw 1;
|
||||
}
|
||||
}
|
||||
|
||||
~Sqlite() {
|
||||
psql_free(pstate);
|
||||
}
|
||||
};
|
||||
|
||||
Database * db;
|
||||
|
||||
signed main(int argc, char * * argv) {
|
||||
esql_in = fopen(argv[1], "r");
|
||||
if (!esql_in) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Sqlite sqlite;
|
||||
db = &sqlite;
|
||||
esql_lex();
|
||||
|
||||
return 0;
|
||||
}
|
23
source/sqlite.l
Normal file
23
source/sqlite.l
Normal file
@ -0,0 +1,23 @@
|
||||
%{
|
||||
|
||||
#include "sqlite.tab.h"
|
||||
|
||||
%}
|
||||
|
||||
%option noyywrap
|
||||
%option nodefault
|
||||
|
||||
%%
|
||||
|
||||
<INITIAL>{
|
||||
CONNECT\ TO { return CONNECT; }
|
||||
AS { return AS; }
|
||||
[a-zA-Z]+ { sqlite_lval.strval = strdup(yytext); return STRING; }
|
||||
\( { sqlite_lval.strval = strdup(yytext); return STRING; }
|
||||
\) { sqlite_lval.strval = strdup(yytext); return STRING; }
|
||||
[0-9]+ { sqlite_lval.strval = strdup(yytext); return STRING; }
|
||||
[ \t\n] { ; }
|
||||
; { return END; }
|
||||
}
|
||||
|
||||
%%
|
47
source/sqlite.y
Normal file
47
source/sqlite.y
Normal file
@ -0,0 +1,47 @@
|
||||
%{
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "Database.hpp"
|
||||
|
||||
extern Database * db;
|
||||
|
||||
extern int sqlite_lex();
|
||||
extern int sqlite_parse();
|
||||
extern FILE* sqlite_in;
|
||||
void sqlite_error(const char *s);
|
||||
|
||||
using namespace std;
|
||||
|
||||
string statement_buffer = "";
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
int intval;
|
||||
char* strval;
|
||||
}
|
||||
|
||||
%token CONNECT AS
|
||||
%token <strval> STRING
|
||||
%token END
|
||||
|
||||
%%
|
||||
|
||||
sql: connect
|
||||
| statement
|
||||
;
|
||||
|
||||
connect: CONNECT STRING AS STRING END { db->connect($2, $4); }
|
||||
;
|
||||
|
||||
statement: STRING { statement_buffer += $1; }
|
||||
| statement STRING { statement_buffer += $2; }
|
||||
| statement END { db->eval(statement_buffer.c_str()); statement_buffer = ""; }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
void sqlite_error(const char *s) {
|
||||
fprintf(stderr, "Error: %s\n", s);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user