diff options
author | mwesdorp <mwesdorp> | 2013-08-21 11:26:54 +0000 |
---|---|---|
committer | mwesdorp <mwesdorp> | 2013-08-21 11:26:54 +0000 |
commit | b6391e59e3b967077da008ce1b0d86e0b50d0946 (patch) | |
tree | 3d1dc1b1b10f4d6ca66833c59d00616ffa6a497c /src | |
parent | 0b56a9543189fc4a6afcf8ce1d6b8fa0a12b16fe (diff) |
sqsh-2.4 new features and bugfixes
Diffstat (limited to 'src')
-rw-r--r-- | src/sqsh_parser/sqsh_parser.c | 129 | ||||
-rw-r--r-- | src/sqsh_parser/sqsh_parser.h | 65 | ||||
-rw-r--r-- | src/sqsh_parser/tsql.l | 69 | ||||
-rw-r--r-- | src/sqsh_parser/tsql.y | 25 |
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);} |