diff --git a/aquery_parser/keywords.py b/aquery_parser/keywords.py index 5ae05bf..b9da28a 100644 --- a/aquery_parser/keywords.py +++ b/aquery_parser/keywords.py @@ -243,8 +243,8 @@ RESERVED = MatchFirst([ WITHIN, INTO, ]) -L_INLINE = Literal("").suppress() -R_INLINE = Literal("").suppress() +L_INLINE = Literal("").suppress() +R_INLINE = Literal("").suppress() LBRACE = Literal("{").suppress() RBRACE = Literal("}").suppress() LSB = Literal("[").suppress() diff --git a/aquery_parser/sql_parser.py b/aquery_parser/sql_parser.py index 5308c2a..9237470 100644 --- a/aquery_parser/sql_parser.py +++ b/aquery_parser/sql_parser.py @@ -66,7 +66,7 @@ def parser(literal_string, ident, sqlserver=False): var_name = ~RESERVED + ident - inline_kblock = (L_INLINE + SkipTo(R_INLINE, include=True))("c") + inline_sqlblock = (L_INLINE + SkipTo(R_INLINE, include=True))("sql") # EXPRESSIONS expr = Forward() column_type, column_definition, column_def_references = get_column_type( @@ -569,8 +569,9 @@ def parser(literal_string, ident, sqlserver=False): | assign("comment", EQ + literal_string) | assign("default character set", EQ + var_name) | assign("default charset", EQ + var_name) - ) - + Optional(AS.suppress() + infix_notation(query, [])("query")) + ) + + Optional(AS.suppress() + query("query")) + # investigate why infix_notation(query, []) eats up the rest of queries )("create_table") create_view = ( @@ -724,7 +725,7 @@ def parser(literal_string, ident, sqlserver=False): )("stmts"), ";") other_stmt = ( - inline_kblock + inline_sqlblock | udf ) ("stmts") diff --git a/reconstruct/ast.py b/reconstruct/ast.py index c5a8f24..c3a3ea8 100644 --- a/reconstruct/ast.py +++ b/reconstruct/ast.py @@ -9,7 +9,6 @@ from engine.utils import (base62alp, base62uuid, enlist, get_innermost, get_legal_name) from reconstruct.storage import ColRef, Context, TableInfo - class ast_node: header = [] types = dict() @@ -1535,7 +1534,25 @@ class udf(ast_node): return udf.ReturnPattern.elemental_return else: return udf.ReturnPattern.bulk_return - + +class passthru_sql(ast_node): + name = 'sql' + first_order = name + import re + # escapestr = r'''(?:((?:[^;"']|"[^"]*"|'[^']*')+)|(?:--[^\r\n]*[\r|\n])+)''' + # escape_comment = fr'''(?:{escapestr}|{escapestr}*-{escapestr}*)''' + seprator = re.compile(r'''((?:[^;"']|"[^"]*"|'[^']*')+)''') + def __init__(self, _, node, context:Context): + sqls = passthru_sql.seprator.split(node['sql']) + for sql in sqls: + sq = sql.strip(' \t\n\r;') + if sq: + context.queries.append('Q' + sql + ';') + lq = sq.lower() + if lq.startswith('select'): + context.queries.append('O') + + class user_module_function(OperatorBase): def __init__(self, name, nargs, ret_type, context : Context): super().__init__(name, nargs, lambda *_: ret_type, call=fn_behavior) diff --git a/server/server.cpp b/server/server.cpp index e4c0a0f..dde84b3 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -197,7 +197,7 @@ inline constexpr static unsigned char monetdbe_type_szs[] = { constexpr uint32_t output_buffer_size = 65536; void print_monetdb_results(Server* srv, const char* sep = " ", const char* end = "\n", uint32_t limit = std::numeric_limits::max()) { - if (!srv->haserror() && limit){ + if (!srv->haserror() && srv->cnt && limit){ char buffer[output_buffer_size]; auto _res = static_cast (srv->res); const auto& ncols = _res->ncols; @@ -209,6 +209,7 @@ void print_monetdb_results(Server* srv, const char* sep = " ", const char* end = const char* err_msg = nullptr; for(uint32_t i = 0; i < ncols; ++i){ err_msg = monetdbe_result_fetch(_res, &cols[i], i); + if(err_msg) { free(cols); return; } col_data[i] = static_cast(cols[i]->data); prtfns[i] = monetdbe_prtfns[cols[i]->type]; szs [i] = monetdbe_type_szs[cols[i]->type];