Changeset: 8489391ed2ba for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/8489391ed2ba
Modified Files:
sql/backends/monet5/rel_bin.c
sql/include/sql_relation.h
sql/server/rel_exp.c
sql/server/rel_exp.h
sql/server/rel_optimize_exps.c
sql/server/rel_optimize_others.c
sql/server/rel_optimize_proj.c
sql/server/rel_optimize_sel.c
sql/server/rel_propagate.c
sql/server/rel_rel.c
sql/server/rel_rel.h
sql/server/rel_select.c
sql/server/rel_unnest.c
sql/test/BugTracker/Tests/bug_in_selection.SF-1892413.test
sql/test/rel-optimizers/Tests/merge-ors-single-col-eq-to-cmp_in.test
sql/test/subquery/Tests/correlated.test
Branch: reducedstack
Log Message:
improved optimizers for new or/and handling
diffs (truncated from 1076 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
@@ -829,7 +829,13 @@ exp_bin_conjunctive(backend *be, sql_exp
s = stmt_binop(be, sel1, s, sin, f);
} else if (reduce && ((sel1 && (sel1->nrcols == 0 || s->nrcols
== 0)) || c->type != e_cmp)) {
if (s->nrcols) {
- s = stmt_uselect(be, s, stmt_bool(be, 1),
cmp_equal, sel1, anti, is_semantics(c));
+ if (sel1 && (sel1->nrcols == 0 || s->nrcols ==
0)) {
+ stmt *predicate =
bin_find_smallest_column(be, left);
+
+ predicate = stmt_const(be, predicate,
stmt_bool(be, 1));
+ s = stmt_uselect(be, predicate, sel1,
cmp_equal, s, anti, is_semantics(c));
+ } else
+ s = stmt_uselect(be, s, stmt_bool(be,
1), cmp_equal, sel1, anti, is_semantics(c));
} else {
stmt *predicate = bin_find_smallest_column(be,
left);
@@ -861,7 +867,6 @@ exp_bin_disjunctive(backend *be, sql_exp
stmt *s = NULL, *cur = NULL;
int anti = is_anti(e);
- assert(!anti);
for (n = l->h; n; n = n->next) {
sql_exp *c = n->data;
@@ -881,7 +886,10 @@ exp_bin_disjunctive(backend *be, sql_exp
}
if (cur) {
if (reduce) {
- s = stmt_tunion(be, s, cur);
+ if (anti)
+ s = stmt_project(be, stmt_tinter(be, s,
cur, false), s);
+ else
+ s = stmt_tunion(be, s, cur);
} else {
sql_subfunc *f = sql_bind_func(be->mvc, "sys",
anti?"and":"or", bt, bt, F_FUNC, true, true);
assert(f);
@@ -4832,6 +4840,19 @@ rel2bin_project(backend *be, sql_rel *re
return NULL;
}
}
+ if (!lpiv) {
+ stmt *orderbycolstmt = pl->h->data;
+ //stmt *orderbycolstmt = exp_bin(be, orderbycole, sub,
psub, NULL, NULL, NULL, NULL, 0, 0, 0);
+
+ if (!orderbycolstmt)
+ return NULL;
+
+ orderbycolstmt = column(be, orderbycolstmt);
+ limit = stmt_limit(be, orderbycolstmt, NULL, grp,
stmt_atom_lng(be, 0), l, distinct, 0, 0, nr_obe, 1);
+ lpiv = limit;
+ if (!lpiv)
+ return NULL;
+ }
limit = lpiv;
if (limit && grp)
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
@@ -247,6 +247,7 @@ typedef enum operator_type {
#define set_not_unique(e) (e)->unique = 0
#define is_anti(e) ((e)->anti)
#define set_anti(e) (e)->anti = 1
+#define reset_anti(e) (e)->anti = 0
#define is_semantics(e) ((e)->semantics)
#define set_semantics(e) (e)->semantics = 1
#define is_any(e) ((e)->any)
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -376,6 +376,16 @@ exp_disjunctive(allocator *sa, list *exp
return e;
}
+sql_exp *
+exp_disjunctive2(allocator *sa, sql_exp *e1, sql_exp *e2)
+{
+ if (e1->type == e_cmp && e1->flag == cmp_dis && !is_anti(e1)) {
+ append(e1->l, e2);
+ return e1;
+ }
+ return exp_disjunctive(sa, append(append(sa_list(sa), e1), e2));
+}
+
static sql_subtype*
dup_subtype(allocator *sa, sql_subtype *st)
{
@@ -2067,6 +2077,34 @@ exp_or_exp_is_false(sql_exp* e)
}
static inline bool
+exp_con_exp_is_false(sql_exp* e)
+{
+ assert(e->type == e_cmp && e->flag == cmp_con);
+ if (is_anti(e))
+ return false;
+ list* exps = e->l;
+ for(node* n = exps->h; n; n=n->next) {
+ if (exp_is_false(n->data))
+ return true;
+ }
+ return false;
+}
+
+static inline bool
+exp_dis_exp_is_false(sql_exp* e)
+{
+ assert(e->type == e_cmp && e->flag == cmp_dis);
+ list* exps = e->l;
+ if (is_anti(e))
+ return false;
+ for(node* n = exps->h; n; n=n->next) {
+ if (!exp_is_false(n->data))
+ return false;
+ }
+ return true;
+}
+
+static inline bool
exp_cmp_exp_is_false(sql_exp* e)
{
assert(e->type == e_cmp);
@@ -2081,6 +2119,10 @@ exp_cmp_exp_is_false(sql_exp* e)
return exp_regular_cmp_exp_is_false(e);
case cmp_or:
return exp_or_exp_is_false(e);
+ case cmp_con:
+ return exp_con_exp_is_false(e);
+ case cmp_dis:
+ return exp_dis_exp_is_false(e);
default:
return false;
}
diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h
--- a/sql/server/rel_exp.h
+++ b/sql/server/rel_exp.h
@@ -50,6 +50,7 @@ extern sql_exp *exp_compare_func(mvc *sq
extern sql_exp *exp_conjunctive(allocator *sa, list *exps);
extern sql_exp *exp_disjunctive(allocator *sa, list *exps);
+extern sql_exp *exp_disjunctive2(allocator *sa, sql_exp *e1, sql_exp *e2);
#define exp_fromtype(e) ((list*)e->r)->h->data
#define exp_totype(e) ((list*)e->r)->h->next->data
diff --git a/sql/server/rel_optimize_exps.c b/sql/server/rel_optimize_exps.c
--- a/sql/server/rel_optimize_exps.c
+++ b/sql/server/rel_optimize_exps.c
@@ -527,6 +527,38 @@ simplify_not_over_equality_exp(visitor *
sql_exp *l = e->l;
sql_exp *r = e->r;
+ if (e->flag == cmp_notequal && is_anti(e) && is_semantics(e)) {
+ reset_anti(e);
+ e->flag = cmp_equal;
+ v->changes++;
+ return e;
+ }
+ if (l->type == e_cmp && (l->flag == cmp_equal || l->flag ==
cmp_notequal)) {
+ /* ( (il ! * = ir) = FALSE ) -> (il * = ir) */
+ if (is_atom(r->type) && r->l && !is_semantics(e) &&
!is_anti(e)) {
+ /* direct literal */
+ atom *a = r->l;
+ if (a && a->data.vtype == TYPE_bit) {
+ if ((exp_is_true(r) && e->flag == cmp_equal) ||
+ (exp_is_false(r) && e->flag ==
cmp_notequal)) {
+ v->changes++;
+ return l;
+ }
+
+ if ((exp_is_false(r) && e->flag == cmp_equal) ||
+ (exp_is_true(r) && e->flag ==
cmp_notequal)) {
+ if (l->flag == cmp_equal)
+ l->flag = cmp_notequal;
+ else
+ l->flag = cmp_equal;
+ v->changes++;
+ return l;
+ }
+ return e;
+ }
+ }
+ }
+
if (!is_func(l->type))
return e;
sql_subfunc *f = l->f;
@@ -872,6 +904,42 @@ rel_remove_alias(visitor *v, sql_rel *re
static inline sql_exp *
rel_merge_project_rse(visitor *v, sql_rel *rel, sql_exp *e)
{
+ if (is_simple_project(rel->op) && is_compare(e->type) && e->flag ==
cmp_con) {
+ list *fexps = e->l;
+
+ if (list_length(fexps) == 2) {
+ sql_exp *l = list_fetch(fexps, 0), *r =
list_fetch(fexps, 1);
+
+ /* check merge into single between */
+ if (is_compare(l->type) && !l->f && is_compare(r->type)
&& !r->f) {
+ if ((l->flag == cmp_gte || l->flag == cmp_gt) &&
+ (r->flag == cmp_lte || r->flag == cmp_lt)) {
+ sql_exp *le = l->l, *lf = r->l;
+ int c_le = is_numeric_upcast(le), c_lf
= is_numeric_upcast(lf);
+
+ if (exp_equal(c_le?le->l:le,
c_lf?lf->l:lf) == 0) {
+ sql_exp *re = l->r, *rf = r->r,
*ne = NULL;
+ sql_subtype super;
+
+ supertype(&super,
exp_subtype(le), exp_subtype(lf)); /* le/re and lf/rf must have the same type */
+ if (!(le =
exp_check_type(v->sql, &super, rel, le, type_equal)) ||
+ !(re =
exp_check_type(v->sql, &super, rel, re, type_equal)) ||
+ !(rf =
exp_check_type(v->sql, &super, rel, rf, type_equal))) {
+
v->sql->session->status = 0;
+
v->sql->errstr[0] = 0;
+ return e;
+ }
+ if ((ne =
exp_compare2(v->sql->sa, le, re, rf, compare2range(l->flag, r->flag), 0))) {
+ if (exp_name(e))
+
exp_prop_alias(v->sql->sa, ne, e);
+ e = ne;
+ v->changes++;
+ }
+ }
+ }
+ }
+ }
+ }
if (is_simple_project(rel->op) && is_func(e->type) && e->l) {
list *fexps = e->l;
sql_subfunc *f = e->f;
diff --git a/sql/server/rel_optimize_others.c b/sql/server/rel_optimize_others.c
--- a/sql/server/rel_optimize_others.c
+++ b/sql/server/rel_optimize_others.c
@@ -1299,7 +1299,7 @@ rel_push_topn_and_sample_down_(visitor *
}
}
- if (r && is_simple_project(r->op) && need_distinct(r))
+ if (r && is_simple_project(r->op) && (need_distinct(r) ||
project_unsafe(r, 1)))
return rel;
/* push topn/sample under projections */
diff --git a/sql/server/rel_optimize_proj.c b/sql/server/rel_optimize_proj.c
--- a/sql/server/rel_optimize_proj.c
+++ b/sql/server/rel_optimize_proj.c
@@ -1147,7 +1147,7 @@ rel_merge_munion(visitor *v, sql_rel *re
}
/* merge, ie. add 'or exp' */
- curs->exps = append(new_exp_list(v->sql->sa),
exp_or(v->sql->sa, cur->exps, s->exps, 0));
+ curs->exps = append(new_exp_list(v->sql->sa),
exp_disjunctive(v->sql->sa, list_merge(cur->exps, s->exps, (fdup)NULL)));
if (!nrels) {
nrels = sa_list(v->sql->sa);
append(nrels, cur);
diff --git a/sql/server/rel_optimize_sel.c b/sql/server/rel_optimize_sel.c
--- a/sql/server/rel_optimize_sel.c
+++ b/sql/server/rel_optimize_sel.c
@@ -194,8 +194,11 @@ exp_merge_range(visitor *v, sql_rel *rel
sql_exp *le = e->l;
sql_exp *re = e->r;
+ /* handle the conjuctive lists */
+ if (e->type == e_cmp && e->flag == cmp_con && !is_anti(e)) {
+ e->l = exp_merge_range(v, rel, e->l);
/* handle the and's in the or lists */
- if (e->type == e_cmp && e->flag == cmp_or && !is_anti(e)) {
+ } else if (e->type == e_cmp && e->flag == cmp_or &&
!is_anti(e)) {
e->l = exp_merge_range(v, rel, e->l);
e->r = exp_merge_range(v, rel, e->r);
/* only look for gt, gte, lte, lt */
@@ -609,12 +612,11 @@ exp_or_chain_groups(mvc *sql, list *exps
*gen_ands = append(*gen_ands, exps);
} else if (list_length(exps) == 1) {
sql_exp *se = exps->h->data;
- sql_exp *le = se->l, *re = se->r;
if (se->type == e_cmp && se->flag == cmp_or && !is_anti(se)) {
/* for a cmp_or expression go down the tree */
- exp_or_chain_groups(sql, (list*)le, gen_ands, mce_ands,
eqs, noneq);
- exp_or_chain_groups(sql, (list*)re, gen_ands, mce_ands,
eqs, noneq);
+ exp_or_chain_groups(sql, se->l, gen_ands, mce_ands,
eqs, noneq);
+ exp_or_chain_groups(sql, se->r, gen_ands, mce_ands,
eqs, noneq);
} else if (eq_only) {
*eqs = append(*eqs, se);
@@ -678,6 +680,126 @@ merge_ors(mvc *sql, list *exps, int *cha
for (node *n = exps->h; n; n = n->next) {
sql_exp *e = n->data;
+ if (e->type == e_cmp && e->flag == cmp_dis && !is_anti(e)) {
+ list *el = e->l;
+
+ /* NOTE: gen_ands and mce_ands are both a list of lists
since the AND association
+ * between expressions is expressed with a list
+ * e.g. [[e1, e2], [e3, e4, e5]] semantically
translates
+ * to [(e1 AND e2), (e3 AND e4 AND e5)]
+ * those (internal) AND list can be then used to
+ * reconstructed an OR tree [[e1, e2], [e3, e4,
e5]] =>
+ * (([e1, e2] OR [e3, e4, e5]) OR <whatever-else>
)
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]