Changeset: 2dbfe607172b for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2dbfe607172b
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: Dec2023
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.
(grafted from e58485a8f184d65b758f54b1e73a59970670d83e)
diffs (truncated from 653 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
@@ -1285,6 +1285,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
@@ -268,6 +268,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;
@@ -528,6 +529,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
@@ -268,6 +268,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
@@ -59,7 +59,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
}
@@ -431,7 +430,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
@@ -580,6 +580,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
@@ -4792,6 +4792,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;
@@ -4800,7 +4811,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);
@@ -4810,10 +4821,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 */
@@ -4831,7 +4842,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
@@ -1560,7 +1560,7 @@ push_up_set(mvc *sql, sql_rel *rel, list
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))
{
@@ -1568,33 +1568,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 */
@@ -1606,8 +1602,8 @@ 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);
- //set_semantics(e);
if (!rel->exps)
rel->exps = sa_list(sql->sa);
list_append(rel->exps, ne);
@@ -1742,8 +1738,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
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]