Changeset: a99be5810cad for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=a99be5810cad
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_optimizer.c
        sql/test/bugs/Tests/groupby_having-bug-sf-947600.stable.out
        sql/test/xquery/Tests/q01.stable.out
Branch: default
Log Message:

fixes for 'in' list handling. Also for (tpch q19) reimplemented rel_merge_rse,
which now correctly rewrites
a select (a = x) or (a = y) or (a in z,k) into
        ((a = x) or (a = y) or (a in z,k)) and a in (x,y,z,k)


diffs (truncated from 507 to 300 lines):

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
@@ -472,17 +472,25 @@
        if (e1->type != e_cmp || e2->type != e_cmp)
                return 0;
 
-       if (!is_complex_exp(e1->flag) && e1_r && e1_r->card == 1 &&
-           !is_complex_exp(e2->flag) && e2_r && e2_r->card == 1)
+       if (!is_complex_exp(e1->flag) && e1_r && e1_r->card == CARD_ATOM &&
+           !is_complex_exp(e2->flag) && e2_r && e2_r->card == CARD_ATOM)
                return exp_match_exp(e1->l, e2->l);
 
-       if (!is_complex_exp(e1->flag) && e1_r && e1_r->card == 1 &&
+       if (!is_complex_exp(e1->flag) && e1_r && e1_r->card == CARD_ATOM &&
+           (e2->flag == cmp_in || e2->flag == cmp_notin))
+               return exp_match_exp(e1->l, e2->l); 
+
+       if ((e1->flag == cmp_in || e1->flag == cmp_notin) &&
+           (e2->flag == cmp_in || e2->flag == cmp_notin))
+               return exp_match_exp(e1->l, e2->l); 
+
+       if (!is_complex_exp(e1->flag) && e1_r && e1_r->card == CARD_ATOM &&
            e2->flag == cmp_or)
                return exp_match_col_exps(e1->l, e2->l) &&
                       exp_match_col_exps(e1->l, e2->r); 
 
        if (e1->flag == cmp_or &&
-           !is_complex_exp(e2->flag) && e2_r && e2_r->card == 1)
+           !is_complex_exp(e2->flag) && e2_r && e2_r->card == CARD_ATOM)
                return exp_match_col_exps(e2->l, e1->l) &&
                       exp_match_col_exps(e2->l, e1->r); 
 
@@ -552,6 +560,11 @@
                            exp_match_list(e1->l, e2->l) && 
                            exp_match_list(e1->r, e2->r))
                                return 1;
+                       else if (e1->flag == e2->flag && 
+                               (e1->flag == cmp_in || e1->flag == cmp_notin) &&
+                           exp_match_exp(e1->l, e2->l) && 
+                           exp_match_list(e1->r, e2->r))
+                               return 1;
                        break;
                case e_convert:
                        if (!subtype_cmp(exp_totype(e1), exp_totype(e2)) &&
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
@@ -991,7 +991,7 @@
 static sql_rel *
 rel_join_order(int *changes, mvc *sql, sql_rel *rel) 
 {
-       *changes = 0; 
+       (void)*changes;
        if (is_join(rel->op) && rel->exps) {
                if (rel->op == op_join)
                        rel->exps = push_up_join_exps(rel);
@@ -1798,7 +1798,7 @@
                        return rel;
 
                /* merge, ie. add 'or exp' */
-               *changes = 1;
+               (*changes)++;
                nls = rel_project(sql->sa, rel->l, rel->exps);
                set_processed(nls);
                rel->l = NULL;
@@ -1901,7 +1901,7 @@
 
                        if (e->type == e_cmp && e->flag == cmp_or) {
                                /* split the common expressions */
-                               *changes = exps_cse(sql->sa, nexps, e->l, e->r);
+                               *changes += exps_cse(sql->sa, nexps, e->l, 
e->r);
                        } else {
                                append(nexps, e);
                        }
@@ -1953,11 +1953,10 @@
        
                if (e->type == e_cmp && e->flag == cmp_or) {
                        list *nexps = exps_merge_rse(sa, e->l, e->r);
-                       if (nexps) {
-                               for (o = nexps->h; o; o = o->next) 
-                                       append(lexps, o->data);
-                               nexps = NULL;
-                       }
+                       for (o = nexps->h; o; o = o->next) 
+                               append(lexps, o->data);
+               } else {
+                       append(lexps, e);
                }
        }
        rexps = new_exp_list(sa);
@@ -1966,118 +1965,107 @@
        
                if (e->type == e_cmp && e->flag == cmp_or) {
                        list *nexps = exps_merge_rse(sa, e->l, e->r);
-                       if (nexps) {
-                               for (o = nexps->h; o; o = o->next) 
-                                       append(rexps, o->data);
-                               nexps = NULL;
-                       }
+                       for (o = nexps->h; o; o = o->next) 
+                               append(rexps, o->data);
+               } else {
+                       append(rexps, e);
                }
        }
 
+       nexps = new_exp_list(sa);
+
        /* merge merged lists first ? */
-       nexps = new_exp_list(sa);
-
        for (n = lexps->h; n; n = n->next) {
                sql_exp *le = n->data, *re, *fnd = NULL;
 
-               if (le->type != e_cmp || !is_complex_exp(le->flag))
+               if (le->type != e_cmp || le->flag == cmp_or)
                        continue;
-               for (m = rexps->h; m; m = m->next) {
+               for (m = rexps->h; !fnd && m; m = m->next) {
                        re = m->data;
                        if (exps_match_col_exps(le, re))
                                fnd = re;
                }
-               for (m = r->h; !fnd && m; m = m->next) {
-                       re = m->data;
-                       if (exps_match_col_exps(le, re))
-                               fnd = re;
-               }
+               /* cases
+                * 1) 2 values (cmp_equal)
+                * 2) 1 value (cmp_equal), and cmp_in 
+                *      (also cmp_in, cmp_equal)
+                * 3) 2 cmp_in
+                * TODO case (4,5,6)
+                * 4) 2 values with cmp_lt(e) / cmp_gt(e)
+                * 5) 1 value with cmp_lt(e) and range ()
+                * 6) 2 ranges ()
+                */
                if (fnd) {
                        re = fnd;
-                       fnd = exp_or(sa, append(new_exp_list(sa),le), 
-                                        append(new_exp_list(sa),re));
-                       append(nexps, fnd);
-               }
-       }
-       for (n = l->h; n; n = n->next) {
-               sql_exp *le = n->data, *re, *fnd = NULL;
-
-               if (le->type != e_cmp /*|| 
-                  (le->flag != cmp_or && le->flag != cmp_equal)*/)
-                       continue;
-
-               for (m = lexps->h; !fnd && m; m = m->next) {
-                       re = m->data;
-                       if (exps_match_col_exps(le, re))
-                               fnd = re;
-               }
-               if (fnd)
-                       continue;
-               for (m = rexps->h; m; m = m->next) {
-                       re = m->data;
-                       if (exps_match_col_exps(le, re))
-                               fnd = re;
-               }
-               for (m = r->h; !fnd && m; m = m->next) {
-                       re = m->data;
-                       if (exps_match_col_exps(le, re))
-                               fnd = re;
-               }
-               if (fnd) {
-                       re = fnd;
-                       fnd = exp_or(sa, append(new_exp_list(sa),le), 
-                                        append(new_exp_list(sa),re));
-                       append(nexps, fnd);
+                       fnd = NULL;
+                       if (le->flag == cmp_equal && re->flag == cmp_equal) {
+                               list *exps = new_exp_list(sa);
+
+                               append(exps, le->r);
+                               append(exps, re->r);
+                               fnd = exp_in(sa, le->l, exps, cmp_in);
+                       } else if (le->flag == cmp_equal && re->flag == cmp_in){
+                               list *exps = new_exp_list(sa);
+                               
+                               append(exps, le->r);
+                               list_merge(exps, re->r, NULL);
+                               fnd = exp_in(sa, le->l, exps, cmp_in);
+                       } else if (le->flag == cmp_in && re->flag == cmp_equal){
+                               list *exps = new_exp_list(sa);
+                               
+                               append(exps, re->r);
+                               list_merge(exps, le->r, NULL);
+                               fnd = exp_in(sa, le->l, exps, cmp_in);
+                       } else if (le->flag == cmp_in && re->flag == cmp_in){
+                               list *exps = new_exp_list(sa);
+
+                               list_merge(exps, le->r, NULL);
+                               list_merge(exps, re->r, NULL);
+                               fnd = exp_in(sa, le->l, exps, cmp_in);
+                       }
+                       if (fnd)
+                               append(nexps, fnd);
                }
        }
        return nexps;
 }
 
 
-/* merge related sub expressions */
+/* merge related sub expressions 
+ * 
+ * ie   (x = a and y > 1 and y < 5) or 
+ *      (x = c and y > 1 and y < 10) or 
+ *      (x = e and y > 1 and y < 20) 
+ * ->
+ *     ((x = a and y > 1 and b < 5) or 
+ *      (x = c and y > 1 and y < 5) or 
+ *      (x = e and y > 1 and y < 5)) and
+ *              x in (a,b,c) and
+ *              y > 1 and y < 20
+ * */
 static sql_rel *
 rel_merge_rse(int *changes, mvc *sql, sql_rel *rel) 
 {
-       /* only execute once per select, ie don't return changes */
-
-       (void)sql;
-       *changes = 0;
+       /* only execute once per select */
+       (void)*changes;
+
        if (is_select(rel->op) && !rel_is_ref(rel) && rel->exps) { 
                node *n, *o;
-               list *nexps = NULL;
+               list *nexps = new_exp_list(sql->sa);
 
                for (n=rel->exps->h; n; n = n->next) {
                        sql_exp *e = n->data;
 
                        if (e->type == e_cmp && e->flag == cmp_or) {
                                /* possibly merge related expressions */
-                               list *lexps = exps_merge_rse(sql->sa, e->l, 
e->r);
-                               if (lexps) {
-                                       if (!nexps) {
-                                               nexps = lexps;
-                                       } else {
-                                               for (o = lexps->h; o; o = 
o->next) 
-                                                       append(nexps, o->data);
-                                               lexps = NULL;
-                                       }
-/*
-                               } else {
-                                       if (!nexps) 
-                                               nexps = new_exp_list(sql->sa);
-                                       append(nexps, e);
-*/
-                               }
+                               list *ps = exps_merge_rse(sql->sa, e->l, e->r);
+                               for (o = ps->h; o; o = o->next) 
+                                       append(nexps, o->data);
                        }
                }
-               if (nexps) {
-                       for (o = nexps->h; o; o = o->next) 
+               if (list_length(nexps))
+                      for (o = nexps->h; o; o = o->next)
                                append(rel->exps, o->data);
-                       nexps = NULL;
-               }
-/*
-               if (nexps) 
-                       rel->exps = nexps;
-*/
        }
        return rel;
 }
@@ -2337,7 +2325,7 @@
 
                        if (exp_is_join_exp(e) == 0) {
                                append(r->exps, e);
-                               *changes += 1;
+                               (*changes)++;
                        } else {
                                append(rel->exps, e);
                        }
@@ -2470,8 +2458,7 @@
        list *exps = NULL;
        sql_rel *gb = NULL;
 
-       *changes = 0;
-
+       (void)*changes;
        if (((is_join(rel->op) && rel->exps) || is_semi(rel->op)) && rel->l) {
                gb = rel->r;
                exps = rel->exps;
@@ -2499,7 +2486,7 @@
                                                        fnd = 1;
                                                }
                                                if (fnd) {
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to