summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormwesdorp <mwesdorp>2013-08-21 11:26:54 +0000
committermwesdorp <mwesdorp>2013-08-21 11:26:54 +0000
commitb6391e59e3b967077da008ce1b0d86e0b50d0946 (patch)
tree3d1dc1b1b10f4d6ca66833c59d00616ffa6a497c /src
parent0b56a9543189fc4a6afcf8ce1d6b8fa0a12b16fe (diff)
sqsh-2.4 new features and bugfixes
Diffstat (limited to 'src')
-rw-r--r--src/sqsh_parser/sqsh_parser.c129
-rw-r--r--src/sqsh_parser/sqsh_parser.h65
-rw-r--r--src/sqsh_parser/tsql.l69
-rw-r--r--src/sqsh_parser/tsql.y25
4 files changed, 288 insertions, 0 deletions
diff --git a/src/sqsh_parser/sqsh_parser.c b/src/sqsh_parser/sqsh_parser.c
new file mode 100644
index 0000000..c7a0540
--- /dev/null
+++ b/src/sqsh_parser/sqsh_parser.c
@@ -0,0 +1,129 @@
+/*
+ * File: main.c
+ * Author: K.-M. Hansche
+ *
+ * Created on 19. Juli 2013, 07:41
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <search.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "sqsh_parser.h"
+
+void* def_root = NULL;
+aliascallback callback = NULL;
+long callbacklparam = 0;
+
+void* xmalloc(size_t size) {
+ void* m = malloc(size);
+ if (m == NULL) {
+ exit(0);
+ }
+ memset(m, 0, size);
+ return m;
+}
+
+void free_node(void *nodep) {
+ t_tdef* datap;
+ datap = (t_tdef*) nodep;
+
+ free(datap->alias);
+ free(datap->table);
+ free(datap);
+
+}
+
+int def_compare(const void *pa, const void *pb) {
+ return strcmp(((t_tdef*) pa)->alias, ((t_tdef*) pb)->alias);
+}
+
+void* addTableDefNode(char* table, char* alias) {
+ if (table == NULL) return NULL;
+ if (alias == NULL || strcmp(alias, "") == 0) alias = table;
+
+ t_tdef* tdef = (t_tdef*) xmalloc(sizeof (t_tdef));
+ tdef->table = (char(*)) xmalloc((strlen(table) + 1) * sizeof (char));
+ tdef->alias = (char(*)) xmalloc((strlen(alias) + 1) * sizeof (char));
+
+ strcpy(tdef->table, table);
+ strcpy(tdef->alias, alias);
+
+ void* p = tsearch(tdef, &def_root, def_compare);
+ if (tdef != *(t_tdef **) p) {
+ free_node(tdef);
+ }
+
+ return p;
+}
+
+void callback_walker(const void *nodep, const VISIT which, const int depth) {
+ t_tdef* datap;
+
+ datap = *(t_tdef**) nodep;
+
+ switch (which) {
+ case preorder:
+ case endorder:
+ break;
+ case postorder:
+ case leaf:
+ callback(datap->table, datap->alias, callbacklparam);
+ break;
+ }
+}
+
+void print_walker(const void *nodep, const VISIT which, const int depth) {
+ t_tdef* datap;
+
+ datap = *(t_tdef**) nodep;
+
+ switch (which) {
+ case preorder:
+ break;
+ case postorder:
+ printf("Table: %s\t alias: %s\t depth: %i\n", datap->table, datap->alias, depth);
+ break;
+ case endorder:
+ break;
+ case leaf:
+ printf("Table: %s\t alias: %s\t depth: %i\tLeaf\n", datap->table, datap->alias, depth);
+ break;
+ }
+}
+
+void delTableDefs(void) {
+#if !defined(_GNU_SOURCE)
+ t_tdef* datap;
+
+ while (def_root != NULL) {
+ datap = *(t_tdef**)def_root;
+ tdelete((void *)datap, &def_root, def_compare);
+ free_node(datap);
+ }
+#else
+ tdestroy(def_root, free_node);
+ def_root = NULL;
+#endif
+}
+
+char* getTableForAlias(char* alias) {
+ t_tdef tdef;
+ t_tdef** res;
+
+ if (alias == NULL) return NULL;
+
+ tdef.alias = alias;
+ res = tfind(&tdef, &def_root, def_compare);
+
+ return res != NULL ? (*res)->table : NULL;
+}
+
+void getTablesAndAliases(aliascallback cb, long lparam){
+ callback=cb;
+ callbacklparam=lparam;
+ twalk(def_root, callback_walker);
+}
+
diff --git a/src/sqsh_parser/sqsh_parser.h b/src/sqsh_parser/sqsh_parser.h
new file mode 100644
index 0000000..b8659bf
--- /dev/null
+++ b/src/sqsh_parser/sqsh_parser.h
@@ -0,0 +1,65 @@
+/*
+ * File: sqsh_parser.h
+ * Author: K.-M. Hansche
+ *
+ * Created on 22. Juli 2013, 17:37
+ */
+
+#ifndef SQSH_PARSER_H
+#define SQSH_PARSER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef void (* aliascallback)(char* table, char* alias, long lparam);
+
+ /**
+ * Extract table/alias combos from an arbitrary sql-statement.
+ * Please call delTabledefs after you are done.
+ *
+ * @param sql A complete or incomplete sql-statement.
+ */
+ extern void parseSql(char* sql);
+
+ /**
+ *
+ * @param alias The alias (or tablename, for simplicity) you want to get the
+ * tablename for.
+ * @return The tablename or NULL. The string will be freed on delTableDefs.
+ */
+ extern char* getTableForAlias(char* alias);
+
+ /**
+ * Free all resources, including strings from getTableForAlias.
+ */
+ extern void delTableDefs(void);
+
+ /**
+ * Insert a tabledefinition into the global tree.
+ * The strings are duplicated internally and freed on delTabledefs.
+ *
+ * @param table A tablename
+ * @param alias The used alias for that name. May be NULL.
+ * @return
+ */
+ extern void* addTableDefNode(char* table, char* alias);
+
+ /**
+ * Iterate over all data. Calls cb for every table/alias-pair.
+ * @param cb A callback defined as typedef void (* aliascallback)(char* table, char* alias, long lparam);
+ * @param lparam The user-defined lparam for cb;
+ */
+ extern void getTablesAndAliases(aliascallback cb, long lparam);
+
+ typedef struct {
+ char* table;
+ char* alias;
+ } t_tdef;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SQSH_PARSER_H */
+
diff --git a/src/sqsh_parser/tsql.l b/src/sqsh_parser/tsql.l
new file mode 100644
index 0000000..219e3fd
--- /dev/null
+++ b/src/sqsh_parser/tsql.l
@@ -0,0 +1,69 @@
+%{
+#include "tsql.h"
+
+#define KW(w) {return w;}
+
+%}
+
+%option noyywrap
+%option warn
+%option 8bit
+%s INFROM
+%s INDML
+
+
+alpha [A-Za-zäöüß_]
+anum [A-Za-z0-9_äöüß_\.\-]
+anumsp [A-Za-z0-9_äöüß_ \.\-]
+ws [ \t\r\n]
+
+%%
+
+<INITIAL>from/{ws}+ {BEGIN INFROM; KW(FROM);}
+<INITIAL>(?i:insert|update|delete)/{ws}+ {BEGIN INDML; KW(INSUP);}
+<INITIAL>(?i:insert{ws}+into)/{ws}+ {BEGIN INDML; KW(INSUP);}
+<INITIAL,INFROM>(?i:join)/{ws}+ {BEGIN INFROM; KW(JOIN);}
+<INFROM>(?i:left|right|outer)/{ws}+ {BEGIN INITIAL;}
+<INFROM>(?i:where|on)/{ws}+ {BEGIN INITIAL;}
+<INFROM>{alpha}{anum}* {KW(TOKEN);}
+<INFROM>\"{alpha}{anumsp}*\" {KW(TOKEN);}
+<INFROM>\[{alpha}{anumsp}*\] {KW(TOKEN);}
+<INDML>{alpha}{anum}* {BEGIN INITIAL; KW(TOKEN);}
+<INDML>\"{alpha}{anumsp}*\" {BEGIN INITIAL; KW(TOKEN);}
+<INDML>\[{alpha}{anumsp}*\] {BEGIN INITIAL; KW(TOKEN);}
+<INFROM>, {KW(COMMA);}
+<INFROM>"(" {BEGIN INITIAL;}
+. ;
+[\n] ;
+
+
+%%
+
+int testlex(char *buffer)
+{
+ yy_scan_string(buffer);
+ int rl;
+
+ while ((rl=yylex())!=0){
+ printf("Token: %i yytext: %s\n", rl, yytext);
+ }
+ yylex_destroy();
+ return 0;
+}
+
+extern void *ParseAlloc(void *(*mallocProc)(size_t));
+extern void ParseFree(void *p, void (*freeProc)(void*));
+extern void Parse(void *yyp, int yymajor, void* yyminor);
+void parseSql(char* sql) {
+ int lr;
+ void* pParser = ParseAlloc(malloc);
+
+ yy_scan_string(sql);
+
+ while ((lr=yylex())!=0){
+ Parse(pParser, lr, strdup(yytext));
+ }
+ Parse(pParser, 0, NULL);
+ ParseFree(pParser, free);
+ yylex_destroy();
+}
diff --git a/src/sqsh_parser/tsql.y b/src/sqsh_parser/tsql.y
new file mode 100644
index 0000000..28001b9
--- /dev/null
+++ b/src/sqsh_parser/tsql.y
@@ -0,0 +1,25 @@
+%include {
+ #include <string.h>
+ #include <assert.h>
+ #include <malloc.h>
+
+ #include "sqsh_parser.h"
+}
+
+%parse_failure {
+ //Actually we don't expect everything to parse.
+}
+
+%token_type {char*}
+%token_destructor {free($$);}
+
+prog ::= statements.
+statements ::= statements statement.
+statements ::= statement.
+statement ::= INSUP TOKEN(B). {addTableDefNode(B, B);free(B);}
+statement ::= FROM tabledefs.
+tabledefs ::= tabledef.
+tabledefs ::= tabledefs COMMA tabledef.
+tabledefs ::= tabledefs JOIN tabledef. // Right, "on"-clauses are filtered by the lexer.
+tabledef ::= TOKEN(B). {addTableDefNode(B, B); free(B);}
+tabledef ::= TOKEN(B) TOKEN(C). {addTableDefNode(B, C); free(B); free(C);}