Changeset: e58485a8f184 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/e58485a8f184 Modified Files: clients/Tests/exports.stable.out monetdb5/optimizer/opt_prelude.c monetdb5/optimizer/opt_prelude.h monetdb5/optimizer/opt_remap.c monetdb5/optimizer/opt_support.c monetdb5/optimizer/opt_support.h sql/backends/monet5/sql.c sql/server/rel_unnest.c sql/test/BugTracker-2018/Tests/lateral-join-crash.Bug-6613.test sql/test/lateral/Tests/lateral.test Branch: Aug2024 Log Message:
fixed handling of union function (sql table valued functions) with correlation (lateral). Added (new) optimiation of sql.unionfunc (mod, func, ) -> batmod.func when the signatures match (+ bat results). This allows for more efficient many-inputs -> set results and back joining with input rows. diffs (truncated from 651 to 300 lines): diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out --- a/clients/Tests/exports.stable.out +++ b/clients/Tests/exports.stable.out @@ -1322,6 +1322,7 @@ void trimMalVariables(MalBlkPtr mb, MalS void trimMalVariables_(MalBlkPtr mb, MalStkPtr glb); void typeChecker(Module scope, MalBlkPtr mb, InstrPtr p, int p_idx, int silent); const char *umaskRef; +const char *unionfuncRef; const char *uniqueRef; const char *unlockRef; const char *updateRef; diff --git a/monetdb5/optimizer/opt_prelude.c b/monetdb5/optimizer/opt_prelude.c --- a/monetdb5/optimizer/opt_prelude.c +++ b/monetdb5/optimizer/opt_prelude.c @@ -269,6 +269,7 @@ const char *transactionRef; const char *transaction_releaseRef; const char *transaction_rollbackRef; const char *umaskRef; +const char *unionfuncRef; const char *uniqueRef; const char *unlockRef; const char *updateRef; @@ -530,6 +531,7 @@ optimizerInit(void) transaction_releaseRef = putName("transaction_release"); transaction_rollbackRef = putName("transaction_rollback"); umaskRef = putName("umask"); + unionfuncRef = putName("unionfunc"); uniqueRef = putName("unique"); unlockRef = putName("unlock"); updateRef = putName("update"); diff --git a/monetdb5/optimizer/opt_prelude.h b/monetdb5/optimizer/opt_prelude.h --- a/monetdb5/optimizer/opt_prelude.h +++ b/monetdb5/optimizer/opt_prelude.h @@ -269,6 +269,7 @@ mal_export const char *transactionRef; mal_export const char *transaction_releaseRef; mal_export const char *transaction_rollbackRef; mal_export const char *umaskRef; +mal_export const char *unionfuncRef; mal_export const char *uniqueRef; mal_export const char *unlockRef; mal_export const char *updateRef; diff --git a/monetdb5/optimizer/opt_remap.c b/monetdb5/optimizer/opt_remap.c --- a/monetdb5/optimizer/opt_remap.c +++ b/monetdb5/optimizer/opt_remap.c @@ -74,7 +74,6 @@ OPTremapDirect(Client cntxt, MalBlkPtr m p->retc = p->argc = pci->retc; - if (plus_one) { p = pushArgument(mb, p, getArg(pci, pci->retc)); // cardinality argument } @@ -460,7 +459,7 @@ OPTremapImplementation(Client cntxt, Mal for (i = 0; i < limit; i++) { p = old[i]; - if (isMultiplex(p)) { + if (isUnion(p)) { /* * The next step considered is to handle inlined functions. * It means we have already skipped the most obvious ones, diff --git a/monetdb5/optimizer/opt_support.c b/monetdb5/optimizer/opt_support.c --- a/monetdb5/optimizer/opt_support.c +++ b/monetdb5/optimizer/opt_support.c @@ -582,6 +582,14 @@ isMultiplex(InstrPtr p) && getFunctionId(p) == multiplexRef); } +inline int +isUnion(InstrPtr p) +{ + return (malRef && (getModuleId(p) == malRef || getModuleId(p) == batmalRef) + && getFunctionId(p) == multiplexRef) || + (getModuleId(p) == sqlRef && getFunctionId(p) == unionfuncRef); +} + int isFragmentGroup(InstrPtr p) { diff --git a/monetdb5/optimizer/opt_support.h b/monetdb5/optimizer/opt_support.h --- a/monetdb5/optimizer/opt_support.h +++ b/monetdb5/optimizer/opt_support.h @@ -51,6 +51,7 @@ extern int isOrderby(InstrPtr q); extern int isSelect(InstrPtr q); extern int isSubJoin(InstrPtr q); extern int isMultiplex(InstrPtr q); +extern int isUnion(InstrPtr q); extern int isOptimizerEnabled(MalBlkPtr mb, const char *opt); extern int isOptimizerUsed(MalBlkPtr mb, InstrPtr p, const char *opt); 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 @@ -5054,6 +5054,17 @@ SQLunionfunc(Client cntxt, MalBlkPtr mb, } q = getInstrPtr(nmb, 0); + int start = 1; + if (nmb->stop == 1 && (omb || !npci->fcn || npci->token != PATcall)) { + InstrPtr *stmt = nmb->stmt; + nmb->stmt = (InstrPtr*)GDKmalloc(sizeof(InstrPtr*)*3); + nmb->stmt[0] = NULL; /* no main() */ + nmb->stmt[1] = NULL; /* no profiling */ + nmb->stmt[2] = stmt[0]; + nmb->stop = nmb->ssize = 3; + GDKfree(stmt); + start = 2; + } for (BUN cur = 0; cur<cnt && !ret; cur++ ) { MalStkPtr nstk = prepareMALstack(nmb, nmb->vsize); int i,ii; @@ -5062,7 +5073,7 @@ SQLunionfunc(Client cntxt, MalBlkPtr mb, ret = createException(MAL, "sql.unionfunc", SQLSTATE(HY013) MAL_MALLOC_FAIL); } else { /* copy (input) arguments onto destination stack, skipping rowid col */ - for (i = 1, ii = q->retc; ii < q->argc && !ret; ii++) { + for (i = 1, ii = q->retc; ii < q->argc && !ret; ii++, i++) { ValPtr lhs = &nstk->stk[q->argv[ii]]; ptr rhs = (ptr)BUNtail(bi[i], cur); @@ -5071,10 +5082,10 @@ SQLunionfunc(Client cntxt, MalBlkPtr mb, } if (!ret && ii == q->argc) { BAT *fres = NULL; - if (!omb && npci->fcn) + if (!omb && npci->fcn && npci->token == PATcall) /* pattern */ ret = (*(str (*)(Client, MalBlkPtr, MalStkPtr, InstrPtr))npci->fcn)(cntxt, nmb, nstk, npci); else - ret = runMALsequence(cntxt, nmb, 1, nmb->stop, nstk, env /* copy result in nstk first instruction*/, q); + ret = runMALsequence(cntxt, nmb, start, nmb->stop, nstk, env /* copy result in nstk first instruction*/, q); if (!ret) { /* insert into result */ @@ -5092,7 +5103,7 @@ SQLunionfunc(Client cntxt, MalBlkPtr mb, } } i=1; - for (ii = 0; i < pci->retc && !ret; i++) { + for (ii = 0; i < pci->retc && !ret; ii++, i++) { BAT *b; if (!(b = BATdescriptor(omb?env->stk[q->argv[ii]].val.bval:nstk->stk[q->argv[ii]].val.bval))) diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c --- a/sql/server/rel_unnest.c +++ b/sql/server/rel_unnest.c @@ -1670,7 +1670,7 @@ push_up_munion(mvc *sql, sql_rel *rel, l static sql_rel * rel_unnest_dependent(mvc *sql, sql_rel *rel); static sql_rel * -push_up_table(mvc *sql, sql_rel *rel, list *ad) +push_up_table(mvc *sql, sql_rel *rel) { (void)sql; if (rel && (is_join(rel->op) || is_semi(rel->op)) && is_dependent(rel)) { @@ -1678,33 +1678,29 @@ push_up_table(mvc *sql, sql_rel *rel, li sql_exp *id = NULL; /* push d into function */ - if (d && is_distinct_set(sql, d, ad) && tf && is_base(tf->op)) { + /* change join's into cross apply, ie tf(rel) -> (results tf, row-id). */ + if (d && tf && is_base(tf->op)) { if (tf->l) { sql_rel *l = tf->l; assert(tf->flag == TABLE_FROM_RELATION || !l->l); - if (l->l) { - sql_exp *tfe = tf->r; - list *ops = tfe->l; - if (!(rel->l = d = rel_add_identity(sql, d, &id))) - return NULL; - id = exp_ref(sql, id); - list *exps = rel_projections(sql, l, NULL, 1, 1); - list_append(exps, id); - l = tf->l = rel_crossproduct(sql->sa, rel_dup(d), l, op_join); - set_dependent(l); - set_processed(l); - tf->l = rel_unnest_dependent(sql, l); - tf->l = rel_project(sql->sa, tf->l, exps); - id = exp_ref(sql, id); - list_append(ops, id); - id = exp_ref(sql, id); - } else { - l->l = rel_dup(d); - if (is_project(l->op)) - rel_bind_vars(sql, l, l->exps); - } + sql_exp *tfe = tf->r; + list *ops = tfe->l; + if (!(rel->l = d = rel_add_identity(sql, d, &id))) + return NULL; + id = exp_ref(sql, id); + list *exps = rel_projections(sql, l, NULL, 1, 1); + list_append(exps, id); + l = tf->l = rel_crossproduct(sql->sa, rel_dup(d), l, op_join); + set_dependent(l); + set_processed(l); + tf->l = rel_unnest_dependent(sql, l); + tf->l = rel_project(sql->sa, tf->l, exps); + id = exp_ref(sql, id); + list_append(ops, id); + id = exp_ref(sql, id); } else { + assert(0); tf->l = rel_dup(d); } /* we should add the identity in the resulting projection list */ @@ -1716,6 +1712,7 @@ push_up_table(mvc *sql, sql_rel *rel, li list_prepend(tf->exps, ne); ne = exp_ref(sql, ne); + /* join on id */ ne = exp_compare(sql->sa, id, ne, cmp_equal); if (!rel->exps) rel->exps = sa_list(sql->sa); @@ -1856,8 +1853,8 @@ rel_unnest_dependent(mvc *sql, sql_rel * return rel_unnest_dependent(sql, rel); } - if (r && is_base(r->op) && is_distinct_set(sql, l, ad)) { - rel = push_up_table(sql, rel, ad); + if (r && is_base(r->op)) { + rel = push_up_table(sql, rel); /* rewrite into cross apply */ return rel; } diff --git a/sql/test/BugTracker-2018/Tests/lateral-join-crash.Bug-6613.test b/sql/test/BugTracker-2018/Tests/lateral-join-crash.Bug-6613.test --- a/sql/test/BugTracker-2018/Tests/lateral-join-crash.Bug-6613.test +++ b/sql/test/BugTracker-2018/Tests/lateral-join-crash.Bug-6613.test @@ -11,28 +11,16 @@ query I rowsort select t.* from segments as s, lateral generate_series(s.meter, cast(s.meter+s.distance+1 as int)) as t ---- 1 -1 -10 10 11 -11 12 -12 -13 13 14 -14 15 -15 -16 16 17 -17 -18 18 2 -2 -9 9 query III rowsort @@ -41,72 +29,36 @@ select t.value, s.distance, s.speed from 1 1 1 -1 -9 -9 -10 -1 -1 10 9 9 11 -1 -1 -11 9 9 12 -1 -1 -12 9 9 13 -1 -1 -13 9 9 14 -1 -1 -14 9 9 15 -1 -1 -15 9 9 _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org