Changeset: d3aa4c7ab5ea for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d3aa4c7ab5ea
Branch: default
Log Message:
Merge branch setjoins into default.
diffs (truncated from 715 to 300 lines):
diff --git a/monetdb5/optimizer/opt_mergetable.c
b/monetdb5/optimizer/opt_mergetable.c
--- a/monetdb5/optimizer/opt_mergetable.c
+++ b/monetdb5/optimizer/opt_mergetable.c
@@ -2075,7 +2075,7 @@ OPTmergetableImplementation(Client cntxt
* 3 -> (l,r) range-joins (l,r1,r2)
* NxM -> (l,r) filter-joins (l1,..,ln,r1,..,rm)
*/
- if (match > 0 && isMatJoinOp(p) &&
+ if (match > 0 && isMatJoinOp(p) && !isMatLeftJoinOp(p) &&
p->argc >= 5 && p->retc == 2 && bats+nilbats >= 4) {
if (bats+nilbats == 4) {
m = is_a_mat(getArg(p,p->retc), &ml);
diff --git a/monetdb5/optimizer/opt_postfix.c b/monetdb5/optimizer/opt_postfix.c
--- a/monetdb5/optimizer/opt_postfix.c
+++ b/monetdb5/optimizer/opt_postfix.c
@@ -32,7 +32,7 @@ OPTpostfixImplementation(Client cntxt, M
/* POSTFIX ACTION FOR THE JOIN CASE */
p= getInstrPtr(mb, i);
if ( getModuleId(p) == algebraRef && p->retc == 2) {
- if ( getFunctionId(p) == leftjoinRef ||
getFunctionId(p) == outerjoinRef ||
+ if ( getFunctionId(p) == leftjoinRef ||
/*getFunctionId(p) == outerjoinRef ||*/
getFunctionId(p) == bandjoinRef ||
getFunctionId(p) == rangejoinRef ||
getFunctionId(p) == likejoinRef) {
if ( getVarEolife(mb, getArg(p, p->retc -1)) ==
i) {
@@ -42,7 +42,7 @@ OPTpostfixImplementation(Client cntxt, M
continue;
}
} else if ( getFunctionId(p) == semijoinRef ||
getFunctionId(p) == joinRef ||
- getFunctionId(p) == thetajoinRef ||
getFunctionId(p) == outerjoinRef || getFunctionId(p) == crossRef) {
+ getFunctionId(p) == thetajoinRef ||
/*getFunctionId(p) == outerjoinRef ||*/ getFunctionId(p) == crossRef) {
int is_first_ret_not_used = getVarEolife(mb,
getArg(p, p->retc -2)) == i;
int is_second_ret_not_used = getVarEolife(mb,
getArg(p, p->retc -1)) == i;
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
@@ -611,7 +611,7 @@ inline int
isMatLeftJoinOp(InstrPtr p)
{
return (getModuleId(p) == algebraRef &&
- getFunctionId(p) == leftjoinRef);
+ (getFunctionId(p) == leftjoinRef || getFunctionId(p) ==
outerjoinRef));
}
inline int isDelta(InstrPtr p){
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
@@ -2701,6 +2701,25 @@ rel2bin_join(backend *be, sql_rel *rel,
s = stmt_alias(be, s, rnme, nme);
list_append(l, s);
}
+ if (rel->attr) {
+ sql_exp *e = rel->attr->h->data;
+ const char *rnme = exp_relname(e);
+ const char *nme = exp_name(e);
+ stmt *last = l->t->data;
+ sql_subtype *tp = tail_type(last);
+
+ sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", tp,
NULL, F_FUNC);
+
+ stmt *s = stmt_unop(be, last, NULL, isnil);
+
+ sql_subtype *bt = sql_bind_localtype("bit");
+ sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt,
NULL, F_FUNC);
+
+ s = stmt_unop(be, s, NULL, not);
+ s = stmt_alias(be, s, rnme, nme);
+ list_append(l, s);
+ }
+
res = stmt_list(be, l);
res->extra = l2; /* used for merge statments, this will be cleaned out
on the pushcands branch :) */
return res;
diff --git a/sql/backends/monet5/sql_statement.c
b/sql/backends/monet5/sql_statement.c
--- a/sql/backends/monet5/sql_statement.c
+++ b/sql/backends/monet5/sql_statement.c
@@ -1454,13 +1454,16 @@ stmt_uselect(backend *be, stmt *op1, stm
const char *mod = calcRef;
const char *op = "=";
int k;
+ int notin = 0;
switch (cmptype) {
case mark_in:
- case mark_notin:
case cmp_equal:
op = "=";
break;
+ case mark_notin:
+ notin = 1;
+ /* fall through */
case cmp_notequal:
op = "!=";
break;
@@ -1498,6 +1501,14 @@ stmt_uselect(backend *be, stmt *op1, stm
q = pushBit(mb, q, TRUE);
k = getDestVar(q);
+ if (notin) {
+ q = newStmt(mb, batcalcRef, "ifthenelse");
+ q = pushArgument(mb, q, k);
+ q = pushBit(mb, q, FALSE);
+ q = pushBit(mb, q, TRUE);
+ k = getDestVar(q);
+ }
+
q = newStmtArgs(mb, algebraRef, selectRef, 9);
q = pushArgument(mb, q, k);
if (sub)
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -279,6 +279,13 @@ typedef struct relation {
void *l;
void *r;
list *exps;
+ list *attr; /* attributes: mark-joins return extra attributes */
+ /* later put all 'projection' attributes in
here, ie for set ops, project/group/table/basetable by
+ * select/ (semi/anti/left/outer/right)join
will use exps for predicates
+ * groupby will use exps for group by exps
+ * project can use exps for the order by bits
+ * topn/sample use exps for the input arguments
of the limit/sample
+ */
int nrcols; /* nr of cols */
unsigned int
flag:16,
diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -550,6 +550,8 @@ rel_print_(mvc *sql, stream *fout, sql_
print_indent(sql, fout, depth, decorate);
mnstr_printf(fout, ")");
exps_print(sql, fout, rel->exps, depth, refs, 1, 0);
+ if (is_join(rel->op) && rel->attr) /* mark joins */
+ exps_print(sql, fout, rel->attr, depth, refs, 1, 0);
break;
case op_project:
case op_select:
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -4671,7 +4671,7 @@ rel_push_join_exps_down(visitor *v, sql_
rel_select_add_exp(v->sql->sa, rel->l, e);
list_remove_node(rel->exps, NULL, n);
v->changes++;
- } else if (right && (rel->op != op_anti || (e->flag !=
mark_notin && e->flag != mark_in)) &&
+ } else if (right && ((rel->op != op_anti && rel->op !=
op_left) || (e->flag != mark_notin && e->flag != mark_in)) &&
rel_rebind_exp(v->sql, rel->r, e)) {
/* select expressions on right */
sql_rel *r = rel->r;
if (!is_select(r->op) || rel_is_ref(r)) {
@@ -6508,6 +6508,8 @@ rel_push_project_up(visitor *v, sql_rel
} else if (is_join(rel->op)) {
list *r_exps = rel_projections(v->sql, r, NULL, 1, 1);
list_merge(exps, r_exps, (fdup)NULL);
+ if (rel->attr)
+ append(exps, exp_ref(v->sql,
rel->attr->h->data));
}
/* Here we should check for ambigious names ? */
if (is_join(rel->op) && r) {
@@ -6515,6 +6517,8 @@ rel_push_project_up(visitor *v, sql_rel
l_exps = rel_projections(v->sql, t, NULL, 1, 1);
/* conflict with old right expressions */
r_exps = rel_projections(v->sql, r, NULL, 1, 1);
+ if (rel->attr)
+ append(r_exps, exp_ref(v->sql,
rel->attr->h->data));
for(n = l_exps->h; n; n = n->next) {
sql_exp *e = n->data;
const char *rname = exp_relname(e);
@@ -9876,6 +9880,103 @@ need_optimization(mvc *sql, sql_rel *rel
return 2;
}
+static sql_rel *
+rel_setjoins_2_joingroupby(visitor *v, sql_rel *rel)
+{
+ if (rel && is_join(rel->op) && (rel->exps || rel->attr)) {
+ sql_exp *me = NULL;
+ int needed = 0;
+ if (rel->exps) {
+ for (node *n = rel->exps->h; n; n = n->next) {
+ sql_exp *e = n->data;
+
+ if (e->type == e_cmp && (e->flag == mark_in ||
e->flag == mark_notin)) {
+ me = e;
+ needed++;
+ }
+ }
+ }
+ if (needed && rel->op == op_join) {
+ rel->op = (me->flag == mark_in)?op_semi:op_anti;
+ return rel;
+ }
+ if (needed || rel->attr) {
+ assert(needed || rel->attr);
+ sql_exp *nequal = NULL;
+ sql_exp *lid = NULL, *rid = NULL;
+ sql_rel *l = rel->l, *p = rel;
+ sql_rel *pp = NULL; /* maybe one project in between
(TODO keep list) */
+
+ if (me && rel->op == op_left) {
+ /* find parent of join involving the right hand
side of the mark expression */
+ sql_rel *c = p->r;
+ while (c) {
+ if (is_join(c->op) &&
rel_find_exp(c->r, me->r)) {
+ p = c;
+ c = p->r;
+ } if (!pp && is_project(c->op) && c->l
&& rel_find_exp(c->l, me->r)) {
+ pp = c;
+ c = c->l;
+ } else {
+ c = NULL;
+ }
+ }
+ }
+ if (p && p->r == pp)
+ pp = NULL;
+
+ rel->l = l = rel_add_identity(v->sql, l, &lid);
+ lid = exp_ref(v->sql, lid);
+ if (rel->op == op_left) {
+ p->r = rel_add_identity(v->sql, p->r, &rid);
+ rid = exp_ref(v->sql, rid);
+ if (pp) {
+ append(pp->exps, rid);
+ rid = exp_ref(v->sql, rid);
+ }
+ }
+
+ list *nexps = sa_list(v->sql->sa);
+ list *aexps = sa_list(v->sql->sa);
+ if (rel->exps) {
+ for (node *n = rel->exps->h; n; n = n->next) {
+ sql_exp *e = n->data;
+
+ if (e->type == e_cmp && (e->flag ==
mark_in || e->flag == mark_notin)) {
+ sql_exp *le = e->l;
+ sql_exp *re = e->r;
+ sql_subfunc *ea =
sql_bind_func(v->sql, "sys", e->flag==mark_in?"anyequal":"allnotequal",
exp_subtype(re), NULL, F_AGGR);
+
+ sql_exp *ne =
exp_aggr1(v->sql->sa, le, ea, 0, 0, CARD_AGGR, has_nil(le));
+ append(ne->l, re);
+ if (rid)
+ append(ne->l, rid);
+
+ append(aexps, ne);
+ nequal = ne;
+ } else
+ append(nexps, e);
+ }
+ }
+ rel->exps = nexps;
+
+ if (rel->attr) {
+ sql_exp *a = rel->attr->h->data;
+
+ exp_setname(v->sql->sa, nequal,
exp_find_rel_name(a), exp_name(a));
+ rel->attr = NULL;
+ } else {
+ exp_label(v->sql->sa, nequal, ++v->sql->label);
+ }
+ list *lexps = rel_projections(v->sql, l, NULL, 1, 1);
+ aexps = list_merge(aexps, lexps, (fdup)NULL);
+ rel = rel_groupby(v->sql, rel, exp2list(v->sql->sa,
lid));
+ rel->exps = aexps;
+ }
+ }
+ return rel;
+}
+
/* 'instantiate' means to rewrite logical tables: (merge, remote, replica
tables) */
sql_rel *
rel_optimizer(mvc *sql, sql_rel *rel, int instantiate, int value_based_opt,
int storage_based_opt)
@@ -9916,5 +10017,6 @@ rel_optimizer(mvc *sql, sql_rel *rel, in
v.data = &level;
rel = rel_visitor_bottomup(&v, rel, &rel_remote_func);
}
+ rel = rel_visitor_bottomup(&v, rel, &rel_setjoins_2_joingroupby);
return rel;
}
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
@@ -948,7 +948,7 @@ exps_reset_props(list *exps, bool setnil
list *
_rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int
intern, int basecol /* basecol only */ )
{
- list *lexps, *rexps, *exps;
+ list *lexps, *rexps = NULL, *exps;
if (mvc_highwater(sql))
return sql_error(sql, 10, SQLSTATE(42000) "Query too complex:
running out of stack space");
@@ -966,9 +966,14 @@ list *
case op_full:
lexps = _rel_projections(sql, rel->l, tname, settname, intern,
basecol);
exps_reset_props(lexps, is_right(rel->op) || is_full(rel->op));
- rexps = _rel_projections(sql, rel->r, tname, settname, intern,
basecol);
+ if (!rel->attr)
+ rexps = _rel_projections(sql, rel->r, tname, settname,
intern, basecol);
exps_reset_props(rexps, is_left(rel->op) || is_full(rel->op));
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list