Changeset: 896b634f58e0 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=896b634f58e0 Modified Files: sql/backends/monet5/sql_gencode.c sql/backends/monet5/sql_upgrades.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 sql/test/BugTracker-2019/Tests/disallow_duplicate_column_aliases.Bug-6723.stable.out sql/test/BugTracker-2019/Tests/prepare-types.Bug-6724.stable.out sql/test/emptydb-upgrade-chain-hge/Tests/upgrade.stable.out.int128 sql/test/emptydb-upgrade-chain-hge/Tests/upgrade.stable.out.powerpc64.int128 sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out.32bit sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out.int128 sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out.powerpc64 sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out.powerpc64.int128 sql/test/emptydb-upgrade-hge/Tests/upgrade.stable.out.int128 sql/test/emptydb-upgrade/Tests/upgrade.stable.out sql/test/emptydb-upgrade/Tests/upgrade.stable.out.32bit sql/test/emptydb-upgrade/Tests/upgrade.stable.out.int128 sql/test/emptydb/Tests/check.stable.out sql/test/emptydb/Tests/check.stable.out.32bit sql/test/emptydb/Tests/check.stable.out.int128 sql/test/testdb-upgrade-chain-hge/Tests/upgrade.stable.out.int128 sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out.32bit sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out.int128 sql/test/testdb-upgrade-hge/Tests/upgrade.stable.out.int128 sql/test/testdb-upgrade/Tests/upgrade.stable.out sql/test/testdb-upgrade/Tests/upgrade.stable.out.32bit sql/test/testdb-upgrade/Tests/upgrade.stable.out.int128 Branch: Nov2019 Log Message:
Merge with Apr2019 branch. diffs (truncated from 952 to 300 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 @@ -833,7 +833,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)) { @@ -855,31 +855,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 @@ -1015,6 +1017,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) { @@ -1026,7 +1105,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/backends/monet5/sql_upgrades.c b/sql/backends/monet5/sql_upgrades.c --- a/sql/backends/monet5/sql_upgrades.c +++ b/sql/backends/monet5/sql_upgrades.c @@ -1879,41 +1879,31 @@ sql_update_apr2019_sp1(Client c) } static str -sql_update_apr2019_sp2(Client c) +sql_update_apr2019_sp2(Client c, mvc *sql, const char *prev_schema, bool *systabfixed) { - /* Determine if system function sys.prod(decimal) exists in sys.functions, if so remove them. - * see also https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=f93d5290abe4 - */ - char *err = NULL; - char *qry = "select f.id from sys.functions f where f.name = 'prod' and func = 'prod'" - " and mod in ('sql', 'aggr') and language = 0 and f.type in (3,6) and f.system" - " and schema_id in (select s.id from sys.schemas s where s.name = 'sys')" - " and f.id in (select a.func_id from sys.args a where a.type = 'decimal'" - " and type_digits in (2,4,9,18,38) and a.name in ('arg','arg_1') and inout = 1 and number = 1);"; - res_table *output = NULL; + size_t bufsize = 1000, pos = 0; + char *buf = GDKmalloc(bufsize), *err; + + if (buf == NULL) + throw(SQL, "sql_update_apr2019_sp2", SQLSTATE(HY001) MAL_MALLOC_FAIL); + + if (!*systabfixed) { + sql_fix_system_tables(c, sql, prev_schema); + *systabfixed = true; + } - err = SQLstatementIntern(c, &qry, "update", true, false, &output); - if (err == NULL) { - BAT *b = BATdescriptor(output->cols[0].b); - if (b) { - if (BATcount(b) > 0) { - /* found entries, we need to remove them sys.functions and sys.args */ - char *upd = "delete from sys.functions f where f.name = 'prod' and func = 'prod'" - " and mod in ('sql', 'aggr') and language = 0 and f.type in (3,6) and f.system" - " and schema_id in (select s.id from sys.schemas s where s.name = 'sys')" - " and f.id in (select a.func_id from sys.args a where a.type = 'decimal'" - " and type_digits in (2,4,9,18,38) and a.name in ('arg','arg_1') and inout = 1 and number = 1);\n" - "delete from sys.args where func_id not in (select id from sys.functions);\n"; + pos += snprintf(buf + pos, bufsize - pos, "set schema sys;\n"); + + /* 11_times.sql */ + pos += snprintf(buf + pos, bufsize - pos, + "drop procedure sys.times();\n"); - printf("Running database upgrade commands:\n%s\n", upd); - err = SQLstatementIntern(c, &upd, "update", true, false, NULL); - } - BBPunfix(b->batCacheid); - } - } - if (output != NULL) - res_tables_destroy(output); + pos += snprintf(buf + pos, bufsize - pos, "set schema \"%s\";\n", prev_schema); + assert(pos < bufsize); + printf("Running database upgrade commands:\n%s\n", buf); + err = SQLstatementIntern(c, &buf, "update", true, false, NULL); + GDKfree(buf); return err; /* usually MAL_SUCCEED */ } @@ -2104,7 +2094,6 @@ sql_update_nov2019(Client c, mvc *sql, c pos = 0; pos += snprintf(buf + pos, bufsize - pos, "set schema \"sys\";\n" - "drop procedure sys.times();\n" "create function sys.deltas (\"schema\" string)" " returns table (\"id\" int, \"cleared\" boolean, \"immutable\" bigint, \"inserted\" bigint, \"updates\" bigint, \"deletes\" bigint, \"level\" int)" " external name \"sql\".\"deltas\";\n" @@ -2503,10 +2492,13 @@ SQLupgrades(Client c, mvc *m) freeException(err); res = -1; } - if (!res && (err = sql_update_apr2019_sp2(c)) != NULL) { - fprintf(stderr, "!%s\n", err); - freeException(err); - res = -1; + + if (!res && sql_bind_func(m->sa, s, "times", NULL, NULL, F_PROC)) { + if (!res && (err = sql_update_apr2019_sp2(c, m, prev_schema, &systabfixed)) != NULL) { + fprintf(stderr, "!%s\n", err); + freeException(err); + res = -1; + } } sql_find_subtype(&tp, "string", 0, 0); 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 @@ -40,6 +40,7 @@ stdout of test 'create_function.Bug-3172 # loading sql script: 40_geom.sql # loading sql script: 80_udf.sql # loading sql script: 99_system.sql +# MonetDB/SQL module loaded # 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 _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list