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