Changeset: da2d87168785 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/da2d87168785
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql.c
        sql/server/rel_rel.c
        sql/server/rel_rel.h
        sql/server/rel_select.c
        sql/server/rel_statistics.c
        sql/server/rel_unnest.c
        sql/test/BugTracker-2024/Tests/7473-SQLunionfunc.test
        sql/test/SQLancer/Tests/sqlancer11.test
Branch: unnest2
Log Message:

handle table returning functions with correlation, cleanup old code


diffs (truncated from 2346 to 300 lines):

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
@@ -2603,7 +2603,6 @@ rel2bin_table(backend *be, sql_rel *rel,
                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;
@@ -2621,22 +2620,31 @@ rel2bin_table(backend *be, sql_rel *rel,
                }
 
                assert(f);
-               if (f->func->res && list_length(f->func->res) + 1 == 
list_length(rel->exps) && !f->func->varres) {
+               list *outers = NULL;
+               if (f->func->res && rel->nr_outers && list_length(f->func->res) 
+ rel->nr_outers == 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;
+                       outers = sa_list(be->mvc->sa);
                        ops = sa_list(be->mvc->sa);
                        if (exps) {
-                               for (node *en = exps->h; en; en = en->next) {
+                               node *en = exps->h;
+                               for (int c = 0; en && c < rel->nr_outers; en = 
en->next, c++) {
                                        sql_exp *e = en->data;
 
                                        /* find column */
                                        stmt *s = exp_bin(be, e, sub, NULL, 
NULL, NULL, NULL, NULL, 0, 0, 0);
                                        if (!s)
                                                return NULL;
-                                       if (en->next)
-                                               append(ops, s);
-                                       else /* last added exp is the ids (todo 
use name base lookup !!) */
-                                               ids = s;
+                                       append(outers, s);
+                               }
+                               for (; en; en = en->next) {
+                                       sql_exp *e = en->data;
+
+                                       /* find column */
+                                       stmt *s = exp_bin(be, e, sub, NULL, 
NULL, NULL, NULL, NULL, 0, 0, 0);
+                                       if (!s)
+                                               return NULL;
+                                       append(ops, s);
                                }
                        }
                } else {
@@ -2663,18 +2671,21 @@ rel2bin_table(backend *be, sql_rel *rel,
                                int i = 0;
 
                                /* correlated table returning function */
-                               if (list_length(f->func->res) + 1 == 
list_length(rel->exps)) {
+                               if (rel->nr_outers && 
(list_length(f->func->res) + rel->nr_outers) == 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
+                                        * output a table of (input) row, the 
output of the table producing function
                                         */
                                        /* make sure the input for 
sql.unionfunc are bats */
-                                       if (ids)
-                                               ids = column(be, ids);
+                                       if (outers)
+                                               for(node *n = outers->h; n; n = 
n->next)
+                                                       n->data = column(be, 
n->data);
                                        if (ops)
                                                for (node *en = ops->h; en; en 
= en->next)
                                                        en->data = column(be, 
(stmt *) en->data);
 
-                                       int narg = 3 + list_length(rel->exps);
+                                       int narg = 2 + list_length(rel->exps);
+                                       if (outers)
+                                               narg += list_length(outers);
                                        if (ops)
                                                narg += list_length(ops);
                                        InstrPtr q = newStmtArgs(be->mb, 
sqlRef, "unionfunc", narg);
@@ -2702,14 +2713,18 @@ rel2bin_table(backend *be, sql_rel *rel,
                                        str fcn = backend_function_imp(be, 
f->func);
                                        q = pushStr(be->mb, q, mod);
                                        q = pushStr(be->mb, q, fcn);
+                                       q = pushInt(be->mb, q, rel->nr_outers);
                                        psub = stmt_direct_func(be, q);
                                        if (psub == NULL) {
                                                freeInstruction(be->mb, q);
                                                return NULL;
                                        }
 
-                                       if (ids) /* push input rowids column */
-                                               q = pushArgument(be->mb, q, 
ids->nr);
+                                       if (outers) /* push input row column */
+                                               for (node *n = outers->h; n; n 
= n->next) {
+                                                       stmt *outer = n->data;
+                                                       q = 
pushArgument(be->mb, q, outer->nr);
+                                               }
 
                                        /* add inputs in correct order ie loop 
through args of f and pass column */
                                        if (ops) {
@@ -2722,9 +2737,8 @@ rel2bin_table(backend *be, sql_rel *rel,
                                        pushInstruction(be->mb, q);
 
                                        /* 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++) {
+                                       //int len = 
list_length(rel->exps)-list_length(f->func->res);
+                                       for (i=0, m=rel->exps->h; m; m = 
m->next, i++) {
                                                sql_exp *exp = m->data;
                                                stmt *s = stmt_rs_column(be, 
psub, i, exp_subtype(exp));
 
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
@@ -4981,9 +4981,9 @@ 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
+/*
+ * for each input row call function(with row-input-values) return table
+ * return for each input row the table, ie input-row (*length of table) and 
table results
  */
 str
 SQLunionfunc(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
@@ -4997,21 +4997,22 @@ SQLunionfunc(Client cntxt, MalBlkPtr mb,
                return createException(MAL, "sql.unionfunc", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
        mod = *getArgReference_str(stk, pci, arg++);
        fcn = *getArgReference_str(stk, pci, arg++);
+       int nr_outers = *getArgReference_int(stk, pci, arg++);
        npci = newStmtArgs(nmb, mod, fcn, pci->argc);
        if (npci == NULL) {
                freeMalBlk(nmb);
                return createException(MAL, "sql.unionfunc", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
        }
 
-       for (int i = 1; i < pci->retc; i++) {
+       for (int i = nr_outers; i < pci->retc; i++) {
                int type = getArgType(mb, pci, i);
 
-               if (i==1)
+               if (i==nr_outers)
                        getArg(npci, 0) = newTmpVariable(nmb, type);
                else
                        npci = pushReturn(nmb, npci, newTmpVariable(nmb, type));
        }
-       for (int i = pci->retc+2+1; i < pci->argc; i++) {
+       for (int i = pci->retc+3+nr_outers; i < pci->argc; i++) {
                int type = getBatType(getArgType(mb, pci, i));
 
                npci = pushNil(nmb, npci, type);
@@ -5027,7 +5028,7 @@ SQLunionfunc(Client cntxt, MalBlkPtr mb,
                BAT **res = NULL, **input = NULL;
                BATiter *bi = NULL;
                BUN cnt = 0;
-               int nrinput = pci->argc - 2 - pci->retc;
+               int nrinput = pci->argc - 3 - pci->retc;
                MalStkPtr env = NULL;
                InstrPtr q = NULL;
 
@@ -5039,8 +5040,8 @@ SQLunionfunc(Client cntxt, MalBlkPtr mb,
                        ret = createException(MAL, "sql.unionfunc", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
                        goto finalize;
                }
-               assert(pci->retc + 2 + nrinput == pci->argc);
-               for (int i = 0, j = pci->retc+2; j < pci->argc; i++, j++) {
+               assert(pci->retc + 3 + nrinput == pci->argc);
+               for (int i = 0, j = pci->retc+3; 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");
@@ -5100,8 +5101,8 @@ SQLunionfunc(Client cntxt, MalBlkPtr mb,
                        if (!nstk) { /* needed for result */
                                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++, i++) {
+                               /* copy (input) arguments onto destination 
stack, skipping input row value columns */
+                               for (i = nr_outers, ii = q->retc; ii < q->argc 
&& !ret; ii++, i++) {
                                        ValPtr lhs = &nstk->stk[q->argv[ii]];
                                        ptr rhs = (ptr)BUNtail(&bi[i], cur);
 
@@ -5116,21 +5117,24 @@ SQLunionfunc(Client cntxt, MalBlkPtr mb,
                                                ret = runMALsequence(cntxt, 
nmb, start, nmb->stop, nstk, env /* copy result in nstk first instruction*/, q);
 
                                        if (!ret) {
-                                               /* insert into result */
-                                               if (!(fres = 
BBPquickdesc(omb?env->stk[q->argv[0]].val.bval:nstk->stk[q->argv[0]].val.bval)))
 {
-                                                       ret = 
createException(MAL, "sql.unionfunc", SQLSTATE(HY005) "Cannot access column 
descriptor");
-                                               } else {
-                                                       BAT *p = 
BATconstant(fres->hseqbase, res[0]->ttype, (ptr)BUNtail(&bi[0], cur), 
BATcount(fres), TRANSIENT);
-
-                                                       if (p) {
-                                                               if 
(BATappend(res[0], p, NULL, FALSE) != GDK_SUCCEED)
+                                               /* insert into result, input 
column values */
+                                               for (int i = 0; i<nr_outers; 
i++) {
+                                                       if (!(fres = 
BBPquickdesc(omb?env->stk[q->argv[0]].val.bval:nstk->stk[q->argv[0]].val.bval)))
 {
+                                                               ret = 
createException(MAL, "sql.unionfunc", SQLSTATE(HY005) "Cannot access column 
descriptor");
+                                                       } else {
+                                                               BAT *p = 
BATconstant(fres->hseqbase, res[i]->ttype, (ptr)BUNtail(&bi[i], cur), 
BATcount(fres), TRANSIENT);
+
+                                                               if (p) {
+                                                                       if 
(BATappend(res[i], p, NULL, FALSE) != GDK_SUCCEED)
+                                                                               
ret = createException(MAL, "sql.unionfunc", GDK_EXCEPTION);
+                                                                       
BBPunfix(p->batCacheid);
+                                                               } else {
                                                                        ret = 
createException(MAL, "sql.unionfunc", GDK_EXCEPTION);
-                                                               
BBPunfix(p->batCacheid);
-                                                       } else {
-                                                               ret = 
createException(MAL, "sql.unionfunc", GDK_EXCEPTION);
+                                                               }
                                                        }
                                                }
-                                               i=1;
+                                               i=nr_outers;
+                                               /* insert into result */
                                                for (ii = 0; i < pci->retc && 
!ret; ii++, i++) {
                                                        BAT *b;
                                                        ValPtr vp = omb ? 
env->stk + q->argv[ii] : nstk->stk + q->argv[ii];
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -1026,7 +1026,7 @@ rel_select_add_exp(allocator *sa, sql_re
        return l;
 }
 
-void
+sql_rel *
 rel_join_add_exp( allocator *sa, sql_rel *rel, sql_exp *e)
 {
        assert(is_join(rel->op) || is_semi(rel->op) || is_select(rel->op));
@@ -1036,6 +1036,7 @@ rel_join_add_exp( allocator *sa, sql_rel
        append(rel->exps, e);
        if (e->card > rel->card)
                rel->card = e->card;
+       return rel;
 }
 
 sql_exp *
@@ -1548,6 +1549,8 @@ rel_select_push_exp_down(mvc *sql, sql_r
 sql_rel *
 rel_push_select(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *e, int f)
 {
+       if (rel && rel->op == op_select)
+               return rel_select_add_exp(sql->sa, rel, e);
        list *l = rel_bind_path(sql, rel, ls, sa_list(sql->sa));
        node *n;
        sql_rel *lrel = NULL, *p = NULL;
@@ -1686,7 +1689,7 @@ rel_push_join(mvc *sql, sql_rel *rel, sq
                return rel;
        }
 
-       rel_join_add_exp( sql->sa, p, e);
+       (void) rel_join_add_exp( sql->sa, p, e);
        return rel;
 }
 
diff --git a/sql/server/rel_rel.h b/sql/server/rel_rel.h
--- a/sql/server/rel_rel.h
+++ b/sql/server/rel_rel.h
@@ -109,7 +109,7 @@ extern sql_rel *rel_sample(allocator *sa
 extern sql_rel *rel_label( mvc *sql, sql_rel *r, int all);
 extern sql_exp *rel_project_add_exp( mvc *sql, sql_rel *rel, sql_exp *e);
 extern sql_rel *rel_select_add_exp(allocator *sa, sql_rel *l, sql_exp *e);
-extern void rel_join_add_exp(allocator *sa, sql_rel *rel, sql_exp *e);
+extern sql_rel *rel_join_add_exp(allocator *sa, sql_rel *rel, sql_exp *e);
 extern sql_exp *rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e);
 
 extern sql_rel *rel_select(allocator *sa, sql_rel *l, sql_exp *e);
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -1895,11 +1895,9 @@ push_select_exp(mvc *sql, sql_rel *rel, 
 {
        if (is_outerjoin(rel->op)) {
                if ((is_left(rel->op) || is_full(rel->op)) && 
rel_find_exp(rel->l, ls)) {
-                       rel_join_add_exp(sql->sa, rel, e);
-                       return rel;
+                       return rel_join_add_exp(sql->sa, rel, e);
                } else if ((is_right(rel->op) || is_full(rel->op)) && 
rel_find_exp(rel->r, ls)) {
-                       rel_join_add_exp(sql->sa, rel, e);
-                       return rel;
+                       return rel_join_add_exp(sql->sa, rel, e);
                }
                if (is_left(rel->op) && rel_find_exp(rel->r, ls)) {
                        rel->r = rel_push_select(sql, rel->r, ls, e, f);
@@ -1918,14 +1916,12 @@ push_join_exp(mvc *sql, sql_rel *rel, sq
 {
        sql_rel *r;
        if (/*is_semi(rel->op) ||*/ (is_outerjoin(rel->op) && 
!is_processed((rel)))) {
-               rel_join_add_exp(sql->sa, rel, e);
-               return rel;
+               return rel_join_add_exp(sql->sa, rel, e);
        }
        /* push join into the given relation */
        if ((r = rel_push_join(sql, rel, L, R, R2, e, f)) != NULL)
                return r;
-       rel_join_add_exp(sql->sa, rel, e);
-       return rel;
+       return rel_join_add_exp(sql->sa, rel, e);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to