Changeset: 70fc84f8e50b for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/70fc84f8e50b
Modified Files:
sql/backends/monet5/rel_bin.c
sql/include/sql_relation.h
sql/server/rel_optimizer.c
sql/server/rel_rel.c
sql/server/rel_unnest.c
sql/test/BugTracker-2010/Tests/ORDER_BY_over_UNION_EXCEPT_INTERSECT.Bug-2606.test
Branch: balanced_union
Log Message:
added unnest of munion's
introduced is_mset.
handle reduced unions (in number of cols)
diffs (truncated from 340 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
@@ -3810,7 +3810,7 @@ rel2bin_munion(backend *be, sql_rel *rel
list *l, *rstmts;
node *n, *m;
stmt *rel_stmt = NULL, *sub;
- int i, len;
+ int i, len = 0;
/* convert to stmt and store the munion operands in rstmts list */
rstmts = sa_list(sql->sa);
@@ -3820,13 +3820,15 @@ rel2bin_munion(backend *be, sql_rel *rel
if (!rel_stmt)
return NULL;
list_append(rstmts, rel_stmt);
+ if (!len || len > list_length(rel_stmt->op4.lval))
+ len = list_length(rel_stmt->op4.lval);
}
/* construct relation */
l = sa_list(sql->sa);
/* for every op4 lval node */
- len = list_length(((stmt*)rstmts->h->data)->op4.lval);
+ //len = list_length(((stmt*)rstmts->h->data)->op4.lval);
for (i = 0; i < len; i++) {
/* extract t and c name from the first stmt */
stmt *s = list_fetch(((stmt*)rstmts->h->data)->op4.lval, i);
@@ -3845,7 +3847,6 @@ rel2bin_munion(backend *be, sql_rel *rel
if (s == NULL)
return NULL;
}
- // TODO: do we maybe need the alias after every append?
s = stmt_alias(be, s, rnme, nme);
if (s == NULL)
return NULL;
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
@@ -198,6 +198,7 @@ typedef enum operator_type {
#define is_joinop(op) (is_join(op) || is_semi(op))
#define is_select(op) (op == op_select)
#define is_set(op) (op == op_union || op == op_inter || op
== op_except)
+#define is_mset(op) (op == op_munion || op == op_inter || op ==
op_except)
#define is_union(op) (op == op_union)
#define is_inter(op) (op == op_inter)
#define is_except(op) (op == op_except)
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
@@ -73,6 +73,7 @@ rel_wrap_select_around_table(visitor *v,
return t;
}
+#if 0
static sql_rel *
rel_unionize_mt_tables_balanced(visitor *v, sql_rel* mt, list* tables,
merge_table_prune_info *info)
{
@@ -101,6 +102,7 @@ rel_unionize_mt_tables_balanced(visitor
}
return rel_unionize_mt_tables_balanced(v, mt, tables, info);
}
+#endif
static sql_rel *
rel_unionize_mt_tables_munion(visitor *v, sql_rel* mt, list* tables,
merge_table_prune_info *info)
@@ -420,9 +422,16 @@ merge_table_prune_and_unionize(visitor *
if (tables->cnt == 1) {
nrel = rel_wrap_select_around_table(v,
tables->h->data, info);
} else {
- nrel = rel_unionize_mt_tables_balanced(v,
mt_rel, tables, info);
+ //nrel = rel_unionize_mt_tables_balanced(v,
mt_rel, tables, info);
+ nrel = rel_setop_n_ary(v->sql->sa, tables,
op_munion);
}
} else if (mvc_debug_on(v->sql, 32)) {
+ if (tables->cnt == 1) {
+ nrel = rel_wrap_select_around_table(v,
tables->h->data, info);
+ } else {
+ nrel = rel_unionize_mt_tables_munion(v, mt_rel,
tables, info);
+ }
+ } else {
for (node *n = tables->h; n ; n = n->next) {
sql_rel *next = n->data;
sql_table *subt = (sql_table *) next->l;
@@ -444,12 +453,6 @@ merge_table_prune_and_unionize(visitor *
nrel = next;
}
}
- } else {
- if (tables->cnt == 1) {
- nrel = rel_wrap_select_around_table(v,
tables->h->data, info);
- } else {
- nrel = rel_unionize_mt_tables_munion(v, mt_rel,
tables, info);
- }
}
}
return nrel;
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
@@ -782,6 +782,7 @@ rel_setop_n_ary(sql_allocator *sa, list
if (!rels)
return NULL;
+ assert(list_length(rels) >= 2);
sql_rel *rel = rel_create(sa);
if(!rel)
return NULL;
@@ -1975,7 +1976,7 @@ rel_return_zero_or_one(mvc *sql, sql_rel
if (ek.card < card_set && rel->card > CARD_ATOM) {
list *exps = rel->exps;
- assert (is_simple_project(rel->op) || is_set(rel->op));
+ assert (is_simple_project(rel->op) || is_mset(rel->op));
rel = rel_groupby(sql, rel, NULL);
for(node *n = exps->h; n; n=n->next) {
sql_exp *e = n->data;
@@ -1999,7 +2000,7 @@ rel_zero_or_one(mvc *sql, sql_rel *rel,
if (is_topn(rel->op) || is_sample(rel->op))
rel = rel_project(sql->sa, rel, rel_projections(sql, rel, NULL,
1, 0));
if (ek.card < card_set && rel->card > CARD_ATOM) {
- assert (is_simple_project(rel->op) || is_set(rel->op));
+ assert (is_simple_project(rel->op) || is_mset(rel->op));
list *exps = rel->exps;
for(node *n = exps->h; n; n=n->next) {
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
@@ -164,6 +164,12 @@ rel_has_freevar(mvc *sql, sql_rel *rel)
} else if (is_join(rel->op) || is_set(rel->op) || is_semi(rel->op) ||
is_modify(rel->op)) {
return exps_have_freevar(sql, rel->exps) ||
rel_has_freevar(sql, rel->l) || rel_has_freevar(sql,
rel->r);
+ } else if (is_munion(rel->op)) {
+ int v = exps_have_freevar(sql, rel->exps);
+ list *l = rel->l;
+ for (node *n = l->h; n && !v; n = n->next)
+ v = rel_has_freevar(sql, n->data);
+ return v;
}
return 0;
}
@@ -270,6 +276,11 @@ rel_only_freevar(sql_query *query, sql_r
exps_only_freevar(query, rel->exps, arguments_correlated,
found_one_freevar, ungrouped_cols);
rel_only_freevar(query, rel->l, arguments_correlated,
found_one_freevar, ungrouped_cols);
rel_only_freevar(query, rel->r, arguments_correlated,
found_one_freevar, ungrouped_cols);
+ } else if (is_munion(rel->op)) {
+ exps_only_freevar(query, rel->exps, arguments_correlated,
found_one_freevar, ungrouped_cols);
+ list *l = rel->l;
+ for (node *n = l->h; n; n = n->next)
+ rel_only_freevar(query, n->data, arguments_correlated,
found_one_freevar, ungrouped_cols);
}
return ;
}
@@ -1559,6 +1570,93 @@ push_up_set(mvc *sql, sql_rel *rel, list
return rel;
}
+static sql_rel *
+push_up_munion(mvc *sql, sql_rel *rel, list *ad)
+{
+ if (rel && (is_join(rel->op) || is_semi(rel->op)) && is_dependent(rel))
{
+ int single = is_single(rel);
+ sql_rel *d = rel->l, *s = rel->r;
+ int need_distinct = is_semi(rel->op) && need_distinct(d);
+ int len = 0, need_length_reduction = 0;
+
+ /* left of rel should be a set */
+ list *rlist = sa_list(sql->sa);
+ if (d && is_distinct_set(sql, d, ad) && s && is_munion(s->op)) {
+ list *iu = s->l;
+ for(node *n = iu->h; n; n = n->next) {
+ sql_rel *sl = n->data;
+ sl = rel_project(sql->sa, rel_dup(sl),
rel_projections(sql, sl, NULL, 1, 1));
+ for (node *n = sl->exps->h, *m = s->exps->h; n
&& m; n = n->next, m = m->next)
+ exp_prop_alias(sql->sa, n->data,
m->data);
+ list_hash_clear(sl->exps);
+ rlist = append(rlist, sl);
+ if (len && len != list_length(sl->exps))
+ need_length_reduction = 1;
+ if (!len || len > list_length(sl->exps))
+ len = list_length(sl->exps);
+ }
+
+ if (need_length_reduction) {
+ for(node *n = rlist->h; n; n = n->next) {
+ sql_rel *r = n->data;
+ if (list_length(r->exps) > len) {
+ list *nr = sa_list(sql->sa);
+ int l = 0;
+ for(node *m = r->exps->h ; m &&
l < len; m=m->next, l++)
+ append(nr, n->data);
+ r->exps = nr;
+ r->nrcols = list_length(nr);
+ }
+ }
+ }
+
+ for(node *n = rlist->h; n; n = n->next) {
+ /* D djoin (sl setop sr) -> (D djoin sl) setop
(D djoin sr) */
+ sql_rel *sl = n->data;
+ sl = rel_crossproduct(sql->sa, rel_dup(d), sl,
rel->op);
+ sl->exps = exps_copy(sql, rel->exps);
+ set_dependent(sl);
+ set_processed(sl);
+ n->data = sl;
+ }
+
+ sql_rel *ns = rel_setop_n_ary(sql->sa, rlist, s->op);
+ ns->exps = exps_copy(sql, s->exps);
+ set_processed(ns);
+ if (single || is_single(s))
+ set_single(ns);
+ if (need_distinct || need_distinct(s))
+ set_distinct(ns);
+
+ if (is_join(rel->op)) {
+ list *sexps = sa_list(sql->sa), *dexps =
rel_projections(sql, d, NULL, 1, 1);
+ for (node *m = dexps->h; m; m = m->next) {
+ sql_exp *e = m->data;
+
+ list_append(sexps, exp_ref(sql, e));
+ }
+ ns->exps = list_merge(sexps, ns->exps,
(fdup)NULL);
+ }
+ /* add/remove projections to inner parts of the union
(as we push a join or semijoin down) */
+ for(node *n = rlist->h; n; n = n->next) {
+ sql_rel *sl = n->data;
+ n->data = rel_project(sql->sa, sl,
rel_projections(sql, sl, NULL, 1, 1));
+ }
+ if (is_semi(rel->op)) {
+ assert(0);/* looks wrong */
+ ns->exps = rel_projections(sql, ns->r, NULL, 1,
1);
+ }
+ if (rel->op == op_anti && s->op == op_munion) {
+ assert(0); /* needs to convert list in
left/right again ! */
+ ns->op = op_inter;
+ }
+ rel_destroy(rel);
+ return ns;
+ }
+ }
+ return rel;
+}
+
static sql_rel * rel_unnest_dependent(mvc *sql, sql_rel *rel);
static sql_rel *
@@ -1742,6 +1840,11 @@ rel_unnest_dependent(mvc *sql, sql_rel *
return rel_unnest_dependent(sql, rel);
}
+ if (r && is_munion(r->op) && !is_left(rel->op) &&
is_distinct_set(sql, l, ad)) {
+ rel = push_up_munion(sql, rel, ad);
+ 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);
return rel;
@@ -1764,6 +1867,10 @@ rel_unnest_dependent(mvc *sql, sql_rel *
else if (rel && (is_join(rel->op) || is_semi(rel->op) ||
is_set(rel->op) || is_modify(rel->op) || is_ddl(rel->op))) {
rel->l = rel_unnest_dependent(sql, rel->l);
rel->r = rel_unnest_dependent(sql, rel->r);
+ } else if (rel && (is_munion(rel->op))) {
+ list *l = rel->l;
+ for (node *n = l->h; n; n = n->next)
+ n->data = rel_unnest_dependent(sql, n->data);
}
}
return nrel;
@@ -2312,7 +2419,7 @@ exp_reset_card_and_freevar_set_physical_
}
if (is_simple_project(rel->op) && need_distinct(rel)) /* Need distinct,
all expressions should have CARD_AGGR at max */
e->card = MIN(e->card, CARD_AGGR);
- if (!is_set(rel->op) && (!is_groupby(rel->op) || !list_empty(rel->r)))
/* global groupings have atomic cardinality */
+ if (!is_mset(rel->op) && (!is_groupby(rel->op) || !list_empty(rel->r)))
/* global groupings have atomic cardinality */
rel->card = MAX(e->card, rel->card); /* the relation
cardinality may get updated too */
return e;
}
@@ -2352,6 +2459,19 @@ rel_set_type(visitor *v, sql_rel *rel)
else
exps = NULL;
}
+ } else if (is_munion(rel->op)) {
+ list *l = rel->l;
+ for(node *m = l->h; m; m = m->next) {
+ sql_rel *r = m->data;
+ list *exps = r->exps;
+ for(node *n = exps->h, *m = rel->exps->h; n &&
m; n = n->next, m = m->next) {
+ sql_exp *e = n->data;
+ sql_subtype *t = exp_subtype(e);
+
+ if (t && !t->type->localtype)
+ n->data =
exp_set_type(v->sql->sa, m->data, e);
+ }
+ }
} else if ((is_simple_project(rel->op) || is_groupby(rel->op))
&& rel->l) {
list *exps = rel->exps;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]