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]

Reply via email to