Changeset: 32295630b035 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/32295630b035
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_unnest.c
Branch: default
Log Message:

only push up selects through projections if the expressions aren't fallible


diffs (88 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
@@ -2833,6 +2833,60 @@ exp_unsafe(sql_exp *e, bool allow_identi
        return 0;
 }
 
+bool
+exps_have_fallible(list *exps)
+{
+       if (!exps)
+               return false;
+       for (node *n = exps->h; n; n = n->next)
+               if (exp_is_fallible(n->data))
+                       return true;
+       return false;
+}
+
+bool
+exp_is_fallible(sql_exp *e)
+{
+       switch (e->type) {
+       case e_convert:
+               {
+                       sql_subtype *t = exp_totype(e);
+                       sql_subtype *f = exp_fromtype(e);
+                       if (t->type->eclass == EC_FLT && (f->type->eclass == 
EC_DEC || f->type->eclass == EC_NUM))
+                               return exp_is_fallible(e->l);
+                       if (f->type->localtype > t->type->localtype)
+                               return true;
+                       /* TODO for types with digits check if t->digits is 
large enough
+                        * for types with scale etc */
+                       return exp_is_fallible(e->l);
+               }
+       case e_aggr:
+       case e_func: {
+               sql_subfunc *f = e->f;
+
+               if (IS_ANALYTIC(f->func) || !LANG_INT_OR_MAL(f->func->lang) || 
f->func->side_effect)
+                       return true;
+               return exps_have_fallible(e->l);
+       } break;
+       case e_cmp: {
+               if (e->flag == cmp_con || e->flag == cmp_dis) {
+                       return exps_have_fallible(e->l);
+               } else if (e->flag == cmp_in || e->flag == cmp_notin) {
+                       return exp_is_fallible(e->l) || 
exps_have_fallible(e->r);
+               } else if (e->flag == cmp_filter) {
+                       return exps_have_fallible(e->l) || 
exps_have_fallible(e->r);
+               } else {
+                       return exp_is_fallible(e->l) || exp_is_fallible(e->r) 
|| (e->f && exp_is_fallible(e->f));
+               }
+       } break;
+       case e_atom:
+       case e_column:
+       case e_psm:
+               return false;
+       }
+       return false;
+}
+
 static inline int
 exp_key( sql_exp *e )
 {
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
@@ -187,6 +187,8 @@ extern bool exps_have_unsafe(list *exps,
                                                                                
                                                                  unsafeness 
(conversions for example) */);
 extern bool exp_unsafe(sql_exp *e, bool allow_identity, bool card);
 extern int exp_has_sideeffect(sql_exp *e);
+extern bool exp_is_fallible(sql_exp *e); /* exp could result in an error, ie 
push up of lower restricting expressions isn't possible */
+extern bool exps_have_fallible(list *l);
 
 extern sql_exp *exps_find_prop(list *exps, rel_prop kind);
 
diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c
--- a/sql/server/rel_unnest.c
+++ b/sql/server/rel_unnest.c
@@ -2150,7 +2150,7 @@ static sql_rel *
        sql_rel *l = rel->l;
        sql_rel *r = rel->r;
        /* try to push select up */
-       if (!rel_is_ref(rel) && ((is_simple_project(rel->op) && !rel->r && l && 
is_select(l->op) && exps_have_freevar(v->sql, l->exps) && !rel_is_ref(l)) ||
+       if (!rel_is_ref(rel) && ((is_simple_project(rel->op) && 
!exps_have_fallible(rel->exps) && !rel->r && l && is_select(l->op) && 
exps_have_freevar(v->sql, l->exps) && !rel_is_ref(l)) ||
            (is_join(rel->op) && l && is_select(l->op) && 
exps_have_freevar(v->sql, l->exps) && !rel_is_ref(l)) ||
            (is_join(rel->op) && r && is_select(r->op) && 
exps_have_freevar(v->sql, r->exps) && !rel_is_ref(r)))) {
                rel = push_up_select2(v, rel);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to