Changeset: 44ecb2621293 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/44ecb2621293
Modified Files:
sql/server/rel_optimizer.c
sql/test/mergetables/Tests/mergequery.test
sql/test/miscellaneous/Tests/simple_plans.test
Branch: Jul2021
Log Message:
Don't call exp_convert directly. Also extend possibilities to merge ranges
(more can be done later)
diffs (259 lines):
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
@@ -3916,6 +3916,21 @@ exps_merge_select_rse( mvc *sql, list *l
return nexps;
}
+static int
+is_numeric_upcast(sql_exp *e)
+{
+ if (is_convert(e->type)) {
+ sql_subtype *f = exp_fromtype(e);
+ sql_subtype *t = exp_totype(e);
+
+ if (f->type->eclass == t->type->eclass &&
EC_COMPUTE(f->type->eclass)) {
+ if (f->type->localtype < t->type->localtype)
+ return 1;
+ }
+ }
+ return 0;
+}
+
static sql_exp *
rel_merge_project_rse(visitor *v, sql_rel *rel, sql_exp *e, int depth)
{
@@ -3934,28 +3949,32 @@ rel_merge_project_rse(visitor *v, sql_re
if (is_func(l->type) && is_func(r->type)) {
list *lfexps = l->l;
list *rfexps = r->l;
- sql_subfunc *lf = l->f;
- sql_subfunc *rf = r->f;
-
- if (((strcmp(lf->func->base.name, ">=") == 0 ||
strcmp(lf->func->base.name, ">") == 0) && list_length(lfexps) == 2) &&
- ((strcmp(rf->func->base.name, "<=") == 0 ||
strcmp(rf->func->base.name, "<") == 0) && list_length(rfexps) == 2)
- && exp_equal(list_fetch(lfexps,0),
list_fetch(rfexps,0)) == 0) {
- sql_exp *e1 = list_fetch(lfexps, 0),
*e2 = list_fetch(lfexps, 1), *e3 = list_fetch(rfexps, 1), *ne = NULL;
- sql_subtype *t1 = exp_subtype(e1), *t3
= exp_subtype(e3), super;
-
- supertype(&super, t1, t3); /* e1 and e2
must have the same type */
- if (!(e1 = exp_check_type(v->sql,
&super, rel, e1, type_equal)) ||
- !(e2 = exp_check_type(v->sql,
&super, rel, e2, type_equal)) ||
- !(e3 = exp_check_type(v->sql,
&super, rel, e3, type_equal))) {
- v->sql->session->status
= 0;
- v->sql->errstr[0] = 0;
- return e;
+ sql_subfunc *lff = l->f;
+ sql_subfunc *rff = r->f;
+
+ if (((strcmp(lff->func->base.name, ">=") == 0
|| strcmp(lff->func->base.name, ">") == 0) && list_length(lfexps) == 2) &&
+ ((strcmp(rff->func->base.name, "<=") == 0
|| strcmp(rff->func->base.name, "<") == 0) && list_length(rfexps) == 2)) {
+ sql_exp *le = list_fetch(lfexps,0), *lf
= list_fetch(rfexps,0);
+ 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 =
list_fetch(lfexps, 1), *rf = list_fetch(rfexps, 1), *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, compare_funcs2range(lff->func->base.name,
rff->func->base.name)))) {
+ if (exp_name(e))
+
exp_prop_alias(v->sql->sa, ne, e);
+ e = ne;
+ v->changes++;
}
- if ((ne = exp_compare2(v->sql->sa, e1,
e2, e3, compare_funcs2range(lf->func->base.name, rf->func->base.name)))) {
- if (exp_name(e))
-
exp_prop_alias(v->sql->sa, ne, e);
- e = ne;
- v->changes++;
}
}
}
@@ -8085,23 +8104,8 @@ rel_split_select(visitor *v, sql_rel *re
return rel;
}
-static int
-is_numeric_upcast(sql_exp *e)
-{
- if (is_convert(e->type)) {
- sql_subtype *f = exp_fromtype(e);
- sql_subtype *t = exp_totype(e);
-
- if (f->type->eclass == t->type->eclass &&
EC_COMPUTE(f->type->eclass)) {
- if (f->type->localtype < t->type->localtype)
- return 1;
- }
- }
- return 0;
-}
-
static list *
-exp_merge_range(visitor *v, list *exps)
+exp_merge_range(visitor *v, sql_rel *rel, list *exps)
{
node *n, *m;
for (n=exps->h; n; n = n->next) {
@@ -8111,8 +8115,8 @@ exp_merge_range(visitor *v, list *exps)
/* handle the and's in the or lists */
if (e->type == e_cmp && e->flag == cmp_or && !is_anti(e)) {
- e->l = exp_merge_range(v, e->l);
- e->r = exp_merge_range(v, e->r);
+ 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 */
} else if (n->next &&
e->type == e_cmp && e->flag < cmp_equal && !e->f &&
@@ -8121,12 +8125,14 @@ exp_merge_range(visitor *v, list *exps)
sql_exp *f = m->data;
sql_exp *lf = f->l;
sql_exp *rf = f->r;
+ int c_le = is_numeric_upcast(le), c_lf =
is_numeric_upcast(lf);
if (f->type == e_cmp && f->flag < cmp_equal &&
!f->f &&
rf->card == CARD_ATOM && !is_anti(f) &&
- exp_match_exp(le, lf)) {
+ exp_match_exp(c_le?le->l:le,
c_lf?lf->l:lf)) {
sql_exp *ne;
int swap = 0, lt = 0, gt = 0;
+ sql_subtype super;
/* for now only c1 <[=] x <[=] c2 */
swap = lt = (e->flag == cmp_lt ||
e->flag == cmp_lte);
@@ -8140,6 +8146,15 @@ exp_merge_range(visitor *v, list *exps)
(f->flag == cmp_lt ||
f->flag == cmp_lte))
continue;
+
+ supertype(&super, exp_subtype(le),
exp_subtype(lf));
+ if (!(rf = exp_check_type(v->sql,
&super, rel, rf, type_equal)) ||
+ !(le = exp_check_type(v->sql,
&super, rel, le, type_equal)) ||
+ !(re = exp_check_type(v->sql,
&super, rel, re, type_equal))) {
+ v->sql->session->status
= 0;
+ v->sql->errstr[0] = 0;
+ continue;
+ }
if (!swap)
ne = exp_compare2(v->sql->sa,
le, re, rf, CMP_BETWEEN|compare2range(e->flag, f->flag));
else
@@ -8149,7 +8164,7 @@ exp_merge_range(visitor *v, list *exps)
list_remove_data(exps, NULL, f);
list_append(exps, ne);
v->changes++;
- return exp_merge_range(v, exps);
+ return exp_merge_range(v, rel, exps);
}
}
} else if (n->next &&
@@ -8167,6 +8182,7 @@ exp_merge_range(visitor *v, list *exps)
comp_type ef = (comp_type) e->flag, ff
= (comp_type) f->flag;
int c_re = is_numeric_upcast(re), c_rf
= is_numeric_upcast(rf);
int c_le = is_numeric_upcast(le), c_lf
= is_numeric_upcast(lf), c;
+ sql_subtype super;
/* both swapped ? */
if (exp_match_exp(c_re?re->l:re,
c_rf?rf->l:rf)) {
@@ -8211,12 +8227,15 @@ exp_merge_range(visitor *v, list *exps)
continue;
if (lt && (ff == cmp_lt || ff ==
cmp_lte))
continue;
- if (c_le) {
- rf = exp_convert(v->sql->sa,
rf, exp_subtype(rf), exp_subtype(le));
- } else if (c_lf) {
- le = exp_convert(v->sql->sa,
le, exp_subtype(le), exp_subtype(lf));
- re = exp_convert(v->sql->sa,
re, exp_subtype(re), exp_subtype(lf));
- }
+
+ supertype(&super, exp_subtype(le),
exp_subtype(lf));
+ if (!(rf = exp_check_type(v->sql,
&super, rel, rf, type_equal)) ||
+ !(le = exp_check_type(v->sql,
&super, rel, le, type_equal)) ||
+ !(re = exp_check_type(v->sql,
&super, rel, re, type_equal))) {
+ v->sql->session->status
= 0;
+ v->sql->errstr[0] = 0;
+ continue;
+ }
if (!swap)
ne = exp_compare2(v->sql->sa,
le, re, rf, CMP_BETWEEN|compare2range(ef, ff));
else
@@ -8226,7 +8245,7 @@ exp_merge_range(visitor *v, list *exps)
list_remove_data(exps, NULL, f);
list_append(exps, ne);
v->changes++;
- return exp_merge_range(v, exps);
+ return exp_merge_range(v, rel, exps);
}
}
}
@@ -9605,7 +9624,7 @@ rel_optimize_select_and_joins_bottomup(v
return rel;
int level = *(int*) v->data;
- rel->exps = exp_merge_range(v, rel->exps);
+ rel->exps = exp_merge_range(v, rel, rel->exps);
if (v->value_based_opt)
rel = rel_reduce_casts(v, rel);
rel = rel_select_cse(v, rel);
diff --git a/sql/test/mergetables/Tests/mergequery.test
b/sql/test/mergetables/Tests/mergequery.test
--- a/sql/test/mergetables/Tests/mergequery.test
+++ b/sql/test/mergetables/Tests/mergequery.test
@@ -148,7 +148,7 @@ PLAN SELECT * FROM complete where x >= 1
project (
| select (
| | table("sys"."part1") [ "part1"."x" as "complete"."x", "part1"."y" as
"complete"."y", "part1"."z" as "complete"."z" ] COUNT
-| ) [ double(53,1) "1" <= "complete"."x" < double(53,1) "2" BETWEEN ]
+| ) [ double "1" <= "complete"."x" < double "2" BETWEEN ]
) [ "complete"."x", "complete"."y", "complete"."z" ]
query RRR rowsort
@@ -167,7 +167,7 @@ PLAN SELECT * FROM complete where x > 1.
project (
| select (
| | table("sys"."part2") [ "part2"."x" as "complete"."x", "part2"."y" as
"complete"."y", "part2"."z" as "complete"."z" ] COUNT
-| ) [ double(53,1) "1" < "complete"."x" <= double(53,1) "2" BETWEEN ]
+| ) [ double "1" < "complete"."x" <= double "2" BETWEEN ]
) [ "complete"."x", "complete"."y", "complete"."z" ]
query RRR rowsort
@@ -200,12 +200,12 @@ union (
| project (
| | select (
| | | table("sys"."part1") [ "part1"."x" as "complete"."x", "part1"."y" as
"complete"."y", "part1"."z" as "complete"."z" ] COUNT
-| | ) [ double(53,1) "1" <= "complete"."x" <= double(53,1) "2" BETWEEN ]
+| | ) [ double "1" <= "complete"."x" <= double "2" BETWEEN ]
| ) [ "complete"."x", "complete"."y", "complete"."z" ],
| project (
| | select (
| | | table("sys"."part2") [ "part2"."x" as "complete"."x", "part2"."y" as
"complete"."y", "part2"."z" as "complete"."z" ] COUNT
-| | ) [ double(53,1) "1" <= "complete"."x" <= double(53,1) "2" BETWEEN ]
+| | ) [ double "1" <= "complete"."x" <= double "2" BETWEEN ]
| ) [ "complete"."x", "complete"."y", "complete"."z" ]
) [ "complete"."x", "complete"."y", "complete"."z" ]
diff --git a/sql/test/miscellaneous/Tests/simple_plans.test
b/sql/test/miscellaneous/Tests/simple_plans.test
--- a/sql/test/miscellaneous/Tests/simple_plans.test
+++ b/sql/test/miscellaneous/Tests/simple_plans.test
@@ -336,6 +336,15 @@ project (
) [ tinyint "1" ]
query T nosort
+PLAN SELECT 1 FROM another_t WHERE col1 > 1 and cast(col1 as bigint) < 2
+----
+project (
+| select (
+| | table("sys"."another_t") [ "another_t"."col1" ] COUNT
+| ) [ bigint "1" < bigint["another_t"."col1"] < bigint "2" BETWEEN ]
+) [ tinyint "1" ]
+
+query T nosort
PLAN SELECT (col1 >= 1 AND col1 <= 2) OR col2 IS NULL FROM another_t
----
project (
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list