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

Reply via email to