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 -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org