Changeset: 56e77337f207 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=56e77337f207 Modified Files: clients/Tests/MAL-signatures.stable.out clients/Tests/MAL-signatures.stable.out.int128 sql/backends/monet5/rel_bin.c sql/backends/monet5/sql.c sql/backends/monet5/sql.h sql/backends/monet5/sql.mal sql/backends/monet5/sql_statement.c sql/backends/monet5/sql_statement.h sql/server/rel_optimizer.c sql/server/rel_rel.c sql/server/rel_rel.h sql/server/rel_select.c sql/server/rel_unnest.c sql/test/subquery/Tests/subquery3.stable.err sql/test/subquery/Tests/subquery3.stable.out sql/test/subquery/Tests/subquery4.sql sql/test/subquery/Tests/subquery4.stable.err sql/test/subquery/Tests/subquery4.stable.out Branch: pushdown Log Message:
merged with default diffs (truncated from 859 to 300 lines): diff --git a/clients/Tests/MAL-signatures.stable.out b/clients/Tests/MAL-signatures.stable.out --- a/clients/Tests/MAL-signatures.stable.out +++ b/clients/Tests/MAL-signatures.stable.out @@ -18886,6 +18886,7 @@ stdout of test 'MAL-signatures` in direc [ "sql", "transaction_commit", "pattern sql.transaction_commit(chain:int, name:str):void ", "SQLtransaction_commit;", "A transaction statement (type can be commit,release,rollback or start)" ] [ "sql", "transaction_release", "pattern sql.transaction_release(chain:int, name:str):void ", "SQLtransaction_release;", "A transaction statement (type can be commit,release,rollback or start)" ] [ "sql", "transaction_rollback", "pattern sql.transaction_rollback(chain:int, name:str):void ", "SQLtransaction_rollback;", "A transaction statement (type can be commit,release,rollback or start)" ] +[ "sql", "unionfunc", "pattern sql.unionfunc(mod:str, fcn:str, X_0:any...):any... ", "SQLunionfunc;", "" ] [ "sql", "update", "pattern sql.update(mvc:int, sname:str, tname:str, cname:str, rids:any, upd:any):int ", "mvc_update_wrap;", "Update the values of the column tname.cname. Returns sequence number for order dependence)" ] [ "sql", "update_schemas", "pattern sql.update_schemas():void ", "SYSupdate_schemas;", "Procedure triggered on update of the sys.schemas table" ] [ "sql", "update_tables", "pattern sql.update_tables():void ", "SYSupdate_tables;", "Procedure triggered on update of the sys._tables table" ] diff --git a/clients/Tests/MAL-signatures.stable.out.int128 b/clients/Tests/MAL-signatures.stable.out.int128 --- a/clients/Tests/MAL-signatures.stable.out.int128 +++ b/clients/Tests/MAL-signatures.stable.out.int128 @@ -26900,6 +26900,7 @@ stdout of test 'MAL-signatures` in direc [ "sql", "transaction_commit", "pattern sql.transaction_commit(chain:int, name:str):void ", "SQLtransaction_commit;", "A transaction statement (type can be commit,release,rollback or start)" ] [ "sql", "transaction_release", "pattern sql.transaction_release(chain:int, name:str):void ", "SQLtransaction_release;", "A transaction statement (type can be commit,release,rollback or start)" ] [ "sql", "transaction_rollback", "pattern sql.transaction_rollback(chain:int, name:str):void ", "SQLtransaction_rollback;", "A transaction statement (type can be commit,release,rollback or start)" ] +[ "sql", "unionfunc", "pattern sql.unionfunc(mod:str, fcn:str, X_0:any...):any... ", "SQLunionfunc;", "" ] [ "sql", "update", "pattern sql.update(mvc:int, sname:str, tname:str, cname:str, rids:any, upd:any):int ", "mvc_update_wrap;", "Update the values of the column tname.cname. Returns sequence number for order dependence)" ] [ "sql", "update_schemas", "pattern sql.update_schemas():void ", "SYSupdate_schemas;", "Procedure triggered on update of the sys.schemas table" ] [ "sql", "update_tables", "pattern sql.update_tables():void ", "SYSupdate_tables;", "Procedure triggered on update of the sys._tables table" ] diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c --- a/sql/backends/monet5/rel_bin.c +++ b/sql/backends/monet5/rel_bin.c @@ -19,6 +19,8 @@ #include "rel_optimizer.h" #include "sql_env.h" #include "sql_optimizer.h" +#include "sql_gencode.h" +#include "mal_builder.h" #define OUTER_ZERO 64 @@ -538,6 +540,10 @@ exp_bin(backend *be, sql_exp *e, stmt *l for(n=lst->op4.lval->h; n; n = n->next) list_append(l, const_column(be, (stmt*)n->data)); r = stmt_list(be, l); + } else if (r->type == st_table && e->card == CARD_ATOM) { /* fetch value */ + r = lst->op4.lval->h->data; + if (!r->aggr) + r = stmt_fetch(be, r); } if (r->type == st_list) r = stmt_table(be, r, 1); @@ -1550,7 +1556,7 @@ exp2bin_args(backend *be, sql_exp *e, li if (THRhighwater()) return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space"); - if (!e) + if (!e || !args) return args; switch(e->type){ case e_column: @@ -1587,7 +1593,7 @@ exp2bin_args(backend *be, sql_exp *e, li } else if (e->r) { char nme[64]; - snprintf(nme, 64, "A%s", (char*)e->r); + snprintf(nme, sizeof(nme), "A%s", (char*)e->r); if (!list_find(args, nme, (fcmp)&alias_cmp)) { stmt *s = stmt_var(be, e->r, &e->tpe, 0, 0); @@ -1597,7 +1603,7 @@ exp2bin_args(backend *be, sql_exp *e, li } else { char nme[16]; - snprintf(nme, 16, "A%u", e->flag); + snprintf(nme, sizeof(nme), "A%u", e->flag); if (!list_find(args, nme, (fcmp)&alias_cmp)) { atom *a = sql->args[e->flag]; stmt *s = stmt_varnr(be, e->flag, &a->tpe); @@ -1628,7 +1634,7 @@ rel2bin_args(backend *be, sql_rel *rel, if (THRhighwater()) return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space"); - if (!rel) + if (!rel || !args) return args; switch(rel->op) { case op_basetable: @@ -1718,6 +1724,8 @@ rel2bin_table(backend *be, sql_rel *rel, int i; sql_subfunc *f = op->f; stmt *psub = NULL; + list *ops = NULL; + stmt *ids = NULL; if (rel->l) { /* first construct the sub relation */ sql_rel *l = rel->l; @@ -1735,10 +1743,30 @@ rel2bin_table(backend *be, sql_rel *rel, } assert(f); - psub = exp_bin(be, op, sub, NULL, NULL, NULL, NULL, NULL); /* table function */ - if (!psub) { - assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */ - return NULL; + if (f->func->res && list_length(f->func->res) + 1 == list_length(rel->exps) && !f->func->varres) { + /* add inputs in correct order ie loop through args of f and pass column */ + list *exps = op->l; + ops = sa_list(be->mvc->sa); + if (exps) { + for (node *en = exps->h; en; en = en->next) { + sql_exp *e = en->data; + + /* find column */ + stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL); + if (!s) + return NULL; + if (en->next) + append(ops, s); + else /* last added exp is the ids (todo use name base lookup !!) */ + ids = s; + } + } + } else { + psub = exp_bin(be, op, sub, NULL, NULL, NULL, NULL, NULL); /* table function */ + if (!psub) { + assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */ + return NULL; + } } l = sa_list(sql->sa); if (f->func->res) { @@ -1753,9 +1781,58 @@ rel2bin_table(backend *be, sql_rel *rel, list_append(l, s); } } else { - assert(list_length(f->func->res) == list_length(rel->exps)); - node *m; - for(i = 0, n = f->func->res->h, m = rel->exps->h; n && m; n = n->next, m = m->next, i++ ) { + node *m = rel->exps->h; + int i = 0; + + /* correlated table returning function */ + if (list_length(f->func->res) + 1 == list_length(rel->exps)) { + /* use a simple nested loop solution for this case, ie + * output a table of (input) row-ids, the output of the table producing function + */ + InstrPtr q = newStmt(be->mb, "sql", "unionfunc"); + /* Generate output rowid column and output of function f */ + for(i=0; m; m = m->next, i++) { + sql_exp *e = m->data; + int type = exp_subtype(e)->type->localtype; + + type = newBatType(type); + if (i) + q = pushReturn(be->mb, q, newTmpVariable(be->mb, type)); + else + getArg(q, 0) = newTmpVariable(be->mb, type); + } + str mod = sql_func_mod(f->func); + str fcn = sql_func_imp(f->func); + q = pushStr(be->mb, q, mod); + q = pushStr(be->mb, q, fcn); + if (backend_create_func(be, f->func, NULL, ops) < 0) + return NULL; + psub = stmt_direct_func(be, q); + + if (ids) /* push input rowids column */ + q = pushArgument(be->mb, q, ids->nr); + + /* add inputs in correct order ie loop through args of f and pass column */ + if (ops) { + for (node *en = ops->h; en; en = en->next) { + stmt *op = en->data; + + q = pushArgument(be->mb, q, op->nr); + } + } + + /* name output of dependent columns, output of function is handled the same as without correlation */ + int len = list_length(rel->exps)-list_length(f->func->res); + assert(len== 1); + for(i=0, m=rel->exps->h; m && i<len; m = m->next, i++ ) { + sql_exp *exp = m->data; + stmt *s = stmt_rs_column(be, psub, i, exp_subtype(exp)); + + s = stmt_alias(be, s, exp->l, exp->r); + list_append(l, s); + } + } + for(n = f->func->res->h; n && m; n = n->next, m = m->next, i++ ) { sql_arg *a = n->data; sql_exp *exp = m->data; stmt *s = stmt_rs_column(be, psub, i, &a->type); @@ -1764,7 +1841,9 @@ rel2bin_table(backend *be, sql_rel *rel, s = stmt_alias(be, s, rnme, a->name); list_append(l, s); } +#if 0 if (list_length(f->res) == list_length(f->func->res) + 1) { + assert(0); /* add missing %TID% column */ sql_subtype *t = f->res->t->data; stmt *s = stmt_rs_column(be, psub, i, t); @@ -1773,6 +1852,7 @@ rel2bin_table(backend *be, sql_rel *rel, s = stmt_alias(be, s, rnme, TID); list_append(l, s); } +#endif } } assert(rel->flag != TABLE_PROD_FUNC || !sub || !(sub->nrcols)); @@ -2605,6 +2685,7 @@ rel_rename(backend *be, sql_rel *rel, st { mvc *sql = be->mvc; + (void) sql; if (rel->exps) { node *en, *n; list *l = sa_list(be->mvc->sa); diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c --- a/sql/backends/monet5/sql.c +++ b/sql/backends/monet5/sql.c @@ -5553,3 +5553,169 @@ bailout: } return msg; } + +/* input id,row-input-values + * for each id call function(with row-input-values) return table + * return for each id the table, ie id (*length of table) and table results + */ +str +SQLunionfunc(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + int arg = pci->retc; + str mod, fcn, ret = MAL_SUCCEED; + InstrPtr npci; + + mod = *getArgReference_str(stk, pci, arg++); + fcn = *getArgReference_str(stk, pci, arg++); + npci = newStmt(mb, mod, fcn); + + for (int i = 1; i < pci->retc; i++) { + int type = getArgType(mb, pci, i); + + if (i==1) + getArg(npci, 0) = newTmpVariable(mb, type); + else + npci = pushReturn(mb, npci, newTmpVariable(mb, type)); + } + for (int i = pci->retc+2+1; i < pci->argc; i++) { + int type = getBatType(getArgType(mb, pci, i)); + + npci = pushNil(mb, npci, type); + } + /* check program to get the proper malblk */ + if (chkInstruction(cntxt->usermodule, mb, npci)) { + freeInstruction(npci); + return createException(MAL, "sql.unionfunc", SQLSTATE(42000) PROGRAM_GENERAL); + } + + if (npci) { + BAT **res = NULL, **input = NULL; + BATiter *bi = NULL; + BUN cnt = 0; + int nrinput = pci->argc - 2 - pci->retc; + MalBlkPtr nmb = NULL; + MalStkPtr env = NULL; + InstrPtr q = NULL; + + if (!(input = GDKzalloc(sizeof(BAT*) * nrinput))) { + ret = createException(MAL, "sql.unionfunc", SQLSTATE(HY013) MAL_MALLOC_FAIL); + goto finalize; + } + if (!(bi = GDKmalloc(sizeof(BATiter) * nrinput))) { + ret = createException(MAL, "sql.unionfunc", SQLSTATE(HY013) MAL_MALLOC_FAIL); + goto finalize; + } + assert(nrinput == pci->retc); + for (int i = 0, j = pci->retc+2; j < pci->argc; i++, j++) { + bat *b = getArgReference_bat(stk, pci, j); + if (!(input[i] = BATdescriptor(*b))) { + ret = createException(MAL, "sql.unionfunc", SQLSTATE(HY005) "Cannot access column descriptor"); + goto finalize; + } + bi[i] = bat_iterator(input[i]); + cnt = BATcount(input[i]); + } + + /* create result bats */ + if (!(res = GDKzalloc(sizeof(BAT*) * pci->retc))) { + ret = createException(MAL, "sql.unionfunc", SQLSTATE(HY013) MAL_MALLOC_FAIL); + goto finalize; + } + for (int i = 0; i<pci->retc; i++) { + int type = getArgType(mb, pci, i); + + if (!(res[i] = COLnew(0, getBatType(type), cnt, TRANSIENT))) { + ret = createException(MAL, "sql.unionfunc", SQLSTATE(HY013) MAL_MALLOC_FAIL); + goto finalize; + } + } + + if (!(nmb = copyMalBlk(npci->blk))) { + ret = createException(MAL, "sql.unionfunc", SQLSTATE(HY013) MAL_MALLOC_FAIL); + goto finalize; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list