Changeset: ef5d870af9d2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=ef5d870af9d2
Modified Files:
sql/backends/monet5/sql_gencode.c
sql/test/BugTracker-2012/Tests/create_function.Bug-3172.sql
sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err
sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.out
sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.sql
sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
Branch: Apr2019
Log Message:
Check for backend of SQL function defined in MAL at runtime, when the function
first gets compiled
This happens once per client connection, so the performance penalty it's not
large.
The "imp" field of a MAL function is not set in load_func in store.c. So
determine it during compilation.
Also check for authentication at "monet5_resolve_function".
diffs (245 lines):
diff --git a/sql/backends/monet5/sql_gencode.c
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -838,7 +838,7 @@ backend_call(backend *be, Client c, cq *
sql_subtype *pt = cq->params + i;
if (!atom_cast(m->sa, a, pt)) {
- sql_error(m, 003, SQLSTATE(42000) "wrong type
for argument %d of " "function call: %s, expected %s\n", i + 1,
atom_type(a)->type->sqlname, pt->type->sqlname);
+ sql_error(m, 003, SQLSTATE(42000) "wrong type
for argument %d of function call: %s, expected %s\n", i + 1,
atom_type(a)->type->sqlname, pt->type->sqlname);
break;
}
if (atom_null(a)) {
@@ -860,31 +860,33 @@ backend_call(backend *be, Client c, cq *
int
monet5_resolve_function(ptr M, sql_func *f)
{
+ Client c;
+ Module m;
+ mvc *sql = (mvc *) M;
str mname = getName(f->mod), fname = getName(f->imp);
- (void) M;
if (!mname || !fname)
return 0;
- for (Module m = getModule(mname); m; m = m->link) {
+ /* Some SQL functions MAL mapping such as count(*) aggregate, the
number or arguments don't match */
+ if (mname == calcRef && fname == getName("="))
+ return 1;
+ if (mname == aggrRef && fname == countRef)
+ return 1;
+ if (mname == sqlRef && (fname == first_valueRef || fname == minRef ||
fname == maxRef))
+ return 1;
+
+ c = MCgetClient(sql->clientid);
+ for (m = findModule(c->usermodule, mname); m; m = m->link) {
for (Symbol s = findSymbolInModule(m, fname); s; s = s->peer) {
InstrPtr sig = getSignature(s);
- int argc = sig->argc - sig->retc;
+ int argc = sig->argc - sig->retc, fargs =
list_length(f->ops);
- if ((!f->ops && argc == 0) || list_length(f->ops) ==
argc || (sig->varargs & VARARGS) == VARARGS)
+ if (fargs == argc || (sig->varargs & VARARGS) ==
VARARGS)
return 1;
}
}
return 0;
-/*
- node *n;
- newFcnCall(f->mod, f->imp);
- for (n = f->ops->h; n; n = n->next) {
- sql_arg *a = n->data;
-
- q = push ?type? (mb, q, a->);
- }
-*/
}
static int
@@ -1020,6 +1022,83 @@ backend_create_c_func(backend *be, sql_f
return 0;
}
+/* Parse the SQL query from the function, and extract the MAL function from
the generated abstract syntax tree */
+static int
+mal_function_find_implementation_address(mvc *m, sql_func *f)
+{
+ mvc *o = m;
+ buffer *b = NULL;
+ bstream *bs = NULL;
+ stream *buf = NULL;
+ char *n = NULL;
+ int len = _strlen(f->query);
+ sql_schema *s = cur_schema(m);
+ dlist *l, *ext_name;
+
+ if (!(m = ZNEW(mvc))) {
+ (void) sql_error(o, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ goto bailout;
+ }
+ m->type = Q_PARSE;
+ m->user_id = m->role_id = USER_MONETDB;
+
+ if (!(m->session = sql_session_create(0, 0))) {
+ (void) sql_error(o, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ goto bailout;
+ }
+ if (s)
+ m->session->schema = s;
+
+ if (!(m->sa = sa_create())) {
+ (void) sql_error(o, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ goto bailout;
+ }
+ if (!(b = (buffer*)GDKmalloc(sizeof(buffer)))) {
+ (void) sql_error(o, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ goto bailout;
+ }
+ if (!(n = GDKmalloc(len + 2))) {
+ (void) sql_error(o, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ goto bailout;
+ }
+ snprintf(n, len + 2, "%s\n", f->query);
+ len++;
+ buffer_init(b, n, len);
+ if (!(buf = buffer_rastream(b, "sqlstatement"))) {
+ (void) sql_error(o, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ goto bailout;
+ }
+ if (!(bs = bstream_create(buf, b->len))) {
+ (void) sql_error(o, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ goto bailout;
+ }
+ scanner_init(&m->scanner, bs, NULL);
+ m->scanner.mode = LINE_1;
+ bstream_next(m->scanner.rs);
+
+ (void) sqlparse(m); /* blindly ignore errors */
+ assert(m->sym->token == SQL_CREATE_FUNC);
+ l = m->sym->data.lval;
+ ext_name = l->h->next->next->next->data.lval;
+ f->imp = sa_strdup(f->sa, qname_fname(ext_name)); /* found the
implementation, set it */
+
+bailout:
+ if (m) {
+ bstream_destroy(m->scanner.rs);
+ if (m->session)
+ sql_session_destroy(m->session);
+ if (m->sa)
+ sa_destroy(m->sa);
+ _DELETE(m);
+ }
+ m = o;
+ if (n)
+ GDKfree(n);
+ if (b)
+ GDKfree(b);
+ return m->errstr[0] == '\0'; /* m was set back to o */
+}
+
static int
backend_create_sql_func(backend *be, sql_func *f, list *restypes, list *ops)
{
@@ -1031,7 +1110,18 @@ backend_create_sql_func(backend *be, sql
int i, retseen = 0, sideeffects = 0, vararg = (f->varres || f->vararg),
no_inline = 0;
sql_rel *r;
- /* nothing to do for internal and ready (not recompiling) functions */
+ /* nothing to do for internal and ready (not recompiling) functions,
besides finding respective MAL implementation */
+ if (!f->sql && (f->lang == FUNC_LANG_INT || f->lang == FUNC_LANG_MAL)) {
+ if (f->lang == FUNC_LANG_MAL && !f->imp &&
!mal_function_find_implementation_address(m, f))
+ return -1;
+ if (!backend_resolve_function(be->mvc, f)) {
+ if (f->lang == FUNC_LANG_INT)
+ (void) sql_error(m, 02, SQLSTATE(HY005)
"Implementation for function %s.%s not found", f->mod, f->imp);
+ else
+ (void) sql_error(m, 02, SQLSTATE(HY005)
"Implementation for function %s.%s not found (%s.%s)", f->mod, f->imp,
f->s->base.name, f->base.name);
+ return -1;
+ }
+ }
if (!f->sql || (!vararg && f->sql > 1))
return 0;
if (!vararg)
diff --git a/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.sql
b/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.sql
--- a/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.sql
+++ b/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.sql
@@ -1,5 +1,6 @@
-create function x(a int, b int)
- returns table (c int,d int)
- external name sql.x;
+create function x(a int, b int) returns table (c int,d int) external name
sql.x; --error, sql.x doesn't exist
+start transaction;
+create function x(a int, b int) returns table (c int,d int) begin return
select a, b; end;
select * from x((select id from _tables), (select schema_id from _tables));
+rollback;
diff --git a/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err
b/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err
--- a/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err
+++ b/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.err
@@ -29,7 +29,11 @@ stderr of test 'create_function.Bug-3172
# 16:07:20 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e"
"--host=/var/tmp/mtest-27661" "--port=38365"
# 16:07:20 >
-MAPI = (monetdb) /var/tmp/mtest-27483/.s.monetdb.35395
+MAPI = (monetdb) /var/tmp/mtest-23748/.s.monetdb.37404
+QUERY = create function x(a int, b int) returns table (c int,d int) external
name sql.x; --error, sql.x doesn't exist
+ERROR = !CREATE FUNCTION: external name sql.x not bound (sys.x)
+CODE = 3F000
+MAPI = (monetdb) /var/tmp/mtest-23748/.s.monetdb.37404
QUERY = select * from x((select id from _tables), (select schema_id from
_tables));
ERROR = !SELECT: 'x' requires a single sub query
CODE = 42000
diff --git a/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.out
b/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.out
--- a/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.out
+++ b/sql/test/BugTracker-2012/Tests/create_function.Bug-3172.stable.out
@@ -15,10 +15,6 @@ stdout of test 'create_function.Bug-3172
# Visit http://www.monetdb.org/ for further information
# Listening for connection requests on mapi:monetdb://lodz.ins.cwi.nl:38620/
# MonetDB/GIS module loaded
-# MonetDB/JAQL module loaded
-# MonetDB/SQL module loaded
-
-Ready.
# SQL catalog created, loading sql scripts once
# loading sql script: 09_like.sql
# loading sql script: 10_math.sql
@@ -41,6 +37,9 @@ Ready.
# loading sql script: 40_geom.sql
# loading sql script: 80_udf.sql
# loading sql script: 99_system.sql
+# MonetDB/SQL module loaded
+
+Ready.
# 13:24:28 >
# 13:24:28 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e" "--host=lodz"
"--port=38620"
diff --git
a/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.sql
b/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.sql
---
a/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.sql
+++
b/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.sql
@@ -1,7 +1,6 @@
+create function x(a int, b int) returns table (c int,d int) external name
sql.x; --error, sql.x doesn't exist
start transaction;
-create function x(a int, b int)
- returns table (c int,d int)
- external name sql.x;
+create function x(a int, b int) returns table (c int,d int) begin return
select a, b; end;
select * from x((select id from _tables), (select schema_id from _tables));
rollback;
diff --git
a/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
b/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
---
a/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
+++
b/sql/test/BugTracker-2012/Tests/table_function_with_column_subselects.Bug-3172.stable.err
@@ -27,7 +27,11 @@ stderr of test 'table_function_with_colu
# 13:48:49 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e" "--host=niels"
"--port=32735"
# 13:48:49 >
-MAPI = (monetdb) /var/tmp/mtest-27483/.s.monetdb.35395
+MAPI = (monetdb) /var/tmp/mtest-23419/.s.monetdb.31192
+QUERY = create function x(a int, b int) returns table (c int,d int) external
name sql.x; --error, sql.x doesn't exist
+ERROR = !CREATE FUNCTION: external name sql.x not bound (sys.x)
+CODE = 3F000
+MAPI = (monetdb) /var/tmp/mtest-23419/.s.monetdb.31192
QUERY = select * from x((select id from _tables), (select schema_id from
_tables));
ERROR = !SELECT: 'x' requires a single sub query
CODE = 42000
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list