Changeset: 2058190fb1d3 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2058190fb1d3
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimizer.c
        sql/server/rel_unnest.c
        sql/test/SQLancer/Tests/sqlancer23.test
        sql/test/astro/Tests/astro.test
Branch: default
Log Message:

push up select expressions with freevars first
added some missing binding attempts


diffs (truncated from 477 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
@@ -3404,3 +3404,17 @@ rel_set_type_recurse(mvc *sql, sql_subty
        }
        return 0;
 }
+
+sql_exp *
+list_find_exp( list *exps, sql_exp *e)
+{
+       sql_exp *ne = NULL;
+
+       if (e->type != e_column)
+               return NULL;
+       if (( e->l && (ne=exps_bind_column2(exps, e->l, e->r, NULL)) != NULL) ||
+          ((!e->l && (ne=exps_bind_column(exps, e->r, NULL, NULL, 1)) != 
NULL)))
+               return ne;
+       return NULL;
+}
+
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
@@ -186,6 +186,7 @@ extern sql_rel *find_one_rel(list *rels,
 extern sql_exp *exps_bind_column(list *exps, const char *cname, int 
*ambiguous, int *multiple, int no_tname /* set if expressions should be without 
a tname */);
 extern sql_exp *exps_bind_column2(list *exps, const char *rname, const char 
*cname, int *multiple);
 extern sql_exp *exps_bind_alias(list *exps, const char *rname, const char 
*cname);
+extern sql_exp * list_find_exp( list *exps, sql_exp *e);
 
 extern unsigned int exps_card( list *l );
 extern void exps_fix_card( list *exps, unsigned int card);
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
@@ -52,19 +52,6 @@ sjexp_col(sql_exp *e, sql_rel *r)
        return res;
 }
 
-static sql_exp *
-list_find_exp( list *exps, sql_exp *e)
-{
-       sql_exp *ne = NULL;
-
-       if (e->type != e_column)
-               return NULL;
-       if (( e->l && (ne=exps_bind_column2(exps, e->l, e->r, NULL)) != NULL) ||
-          ((!e->l && (ne=exps_bind_column(exps, e->r, NULL, NULL, 1)) != 
NULL)))
-               return ne;
-       return NULL;
-}
-
 static int
 kc_column_cmp(sql_kc *kc, sql_column *c)
 {
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
@@ -503,6 +503,15 @@ rel_bind_var(mvc *sql, sql_rel *rel, sql
        }
 }
 
+static void
+rel_bind_vars(mvc *sql, sql_rel *rel, list *exps)
+{
+       if (list_empty(exps))
+               return;
+       for(node *n=exps->h; n; n = n->next)
+               rel_bind_var(sql, rel, n->data);
+}
+
 static sql_exp * push_up_project_exp(mvc *sql, sql_rel *rel, sql_exp *e);
 
 static list *
@@ -700,7 +709,7 @@ rel_bound_exp(mvc *sql, sql_rel *rel )
 
                        if (exp_is_atom(e))
                                return e;
-                       if (!is_freevar(e))
+                       if (!exp_has_freevar(sql, e))
                                return exp_ref(sql, e);
                }
        }
@@ -859,7 +868,7 @@ push_up_project(mvc *sql, sql_rel *rel, 
                                break;
                        }
 
-                       if (l && (is_select(l->op) || l->op == op_join || 
is_semi(l->op)) && !rel_is_ref(l)) {
+                       if (l && (is_select(l->op) || l->op == op_join || 
is_semi(l->op)) && !rel_is_ref(l) && list_empty(r->attr)) {
                                if (!list_empty(r->exps)) {
                                        for(n=r->exps->h; n; n=n->next) {
                                                sql_exp *e = n->data;
@@ -924,11 +933,6 @@ push_up_project(mvc *sql, sql_rel *rel, 
                        sql_rel *n = rel_project( sql->sa, (r->l)?rel:rel->l,
                                        rel_projections(sql, rel->l, NULL, 1, 
1));
 
-                       /* only pass bound variables */
-                       if (list_empty(rel->attr) && is_left(rel->op) && 
exps_have_freevar(sql, r->exps)) {
-                               id = rel_bound_exp(sql, r);
-                               id = rel_project_add_exp(sql, n, id);
-                       }
                        if (is_left(rel->op) && !list_empty(rel->attr)) {
                                rel_project_add_exp(sql, n, exp_ref(sql, 
rel->attr->h->data));
                        }
@@ -937,11 +941,17 @@ push_up_project(mvc *sql, sql_rel *rel, 
                                        sql_exp *e = m->data;
 
                                        if (!is_freevar(e) || exp_name(e)) { /* 
only skip full freevars */
-                                               if (exp_has_freevar(sql, e)) {
+                                               if (exp_has_freevar(sql, e) || 
is_atom(e->type)) {
                                                        rel_bind_var(sql, 
rel->l, e);
                                                        if (is_left(rel->op)) { 
/* add ifthenelse */
-                                                               /* need bound 
var from r */
                                                                /* if id is 
NULL then NULL else e */
+                                                               if (!id) {
+                                                                       sql_rel 
*l = r->l;
+                                                                       if 
(is_join(l->op))
+                                                                               
id = rel_bound_exp(sql, r);
+                                                                       else
+                                                                               
r->l = rel_add_identity(sql, r->l, &id);
+                                                               }
                                                                sql_exp *ne = 
rel_unop_(sql, NULL, exp_copy(sql, id), "sys", "isnull", card_value);
                                                                
set_has_no_nil(ne);
                                                                ne = 
rel_nop_(sql, NULL, ne, exp_null(sql->sa, exp_subtype(e)), e, NULL, "sys", 
"ifthenelse", card_value);
@@ -983,6 +993,7 @@ push_up_project(mvc *sql, sql_rel *rel, 
 
                /* merge project expressions into the join expressions  */
                rel->exps = push_up_project_exps(sql, r, rel->exps);
+               rel_bind_vars(sql, rel, rel->exps);
 
                if (r && r->op == op_project && r->l) {
                        /* remove old project */
@@ -1396,6 +1407,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis
                                list_hash_clear(nl->exps);
                                n->attr = attr;
                                set_processed(n);
+                               rel_bind_vars(sql, n, n->exps);
                                return n;
                        }
 
@@ -1412,6 +1424,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis
                                if (is_semi(rel->op))
                                        rel->op = op_left;
                                move_join_exps(sql, j, rel);
+                               rel_bind_vars(sql, j, j->exps);
                                return j;
                        }
                        if (!ld) {
@@ -1427,6 +1440,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis
                                if (is_semi(rel->op))
                                        rel->op = op_left;
                                move_join_exps(sql, j, rel);
+                               rel_bind_vars(sql, j, j->exps);
                                return j;
                        }
                        assert(0);
@@ -1440,6 +1454,7 @@ static sql_rel *
 push_up_set(mvc *sql, sql_rel *rel, list *ad)
 {
        if (rel && (is_join(rel->op) || is_semi(rel->op)) && is_dependent(rel)) 
{
+               int single = is_single(rel);
                sql_rel *d = rel->l, *s = rel->r;
 
                /* left of rel should be a set */
@@ -1454,6 +1469,25 @@ push_up_set(mvc *sql, sql_rel *rel, list
                        for (node *n = sr->exps->h, *m = s->exps->h; n && m; n 
= n->next, m = m->next)
                                exp_prop_alias(sql->sa, n->data, m->data);
                        list_hash_clear(sr->exps);
+
+                       int llen = list_length(sl->exps), rlen = 
list_length(sr->exps), l = 0;
+
+                       if (llen != rlen) {
+                               if (llen < rlen) {
+                                       list *nr = sa_list(sql->sa);
+                                       for(node *n = sr->exps->h ; n && l < 
llen; n=n->next, l++)
+                                                       append(nr, n->data);
+                                       sr->exps = nr;
+                                       sr->nrcols = list_length(nr);
+                               } else {
+                                       list *nl = sa_list(sql->sa);
+                                       for(node *n = sl->exps->h; n && l < 
rlen; n=n->next, l++)
+                                                       append(nl, n->data);
+                                       sl->exps = nl;
+                                       sl->nrcols = list_length(nl);
+                               }
+                       }
+
                        /* D djoin (sl setop sr) -> (D djoin sl) setop (D djoin 
sr) */
                        sl = rel_crossproduct(sql->sa, rel_dup(d), sl, rel->op);
                        sl->exps = exps_copy(sql, rel->exps);
@@ -1466,7 +1500,7 @@ push_up_set(mvc *sql, sql_rel *rel, list
                        ns = rel_setop(sql->sa, sl, sr, s->op);
                        ns->exps = exps_copy(sql, s->exps);
                        set_processed(ns);
-                       if (is_single(s))
+                       if (single || is_single(s))
                                set_single(ns);
                        if (need_distinct(s))
                                set_distinct(ns);
@@ -1485,6 +1519,10 @@ push_up_set(mvc *sql, sql_rel *rel, list
                        ns->r = rel_project(sql->sa, ns->r, 
rel_projections(sql, ns->r, NULL, 1, 1));
                        if (is_semi(rel->op))
                                ns->exps = rel_projections(sql, ns->r, NULL, 1, 
1);
+                       if (rel->op == op_anti && s->op == op_union)
+                               ns->op = op_inter;
+                       if (rel->op == op_anti && s->op == op_inter)
+                               ns->op = op_union;
                        rel_destroy(rel);
                        return ns;
                }
@@ -1685,9 +1723,169 @@ rel_unnest_dependent(mvc *sql, sql_rel *
        return nrel;
 }
 
+static list * add_missing_project_exps(mvc *sql, sql_rel *rel, list *exps);
+
+static sql_exp *
+add_missing_project_exp(mvc *sql, sql_rel *rel, sql_exp *e)
+{
+       if (is_freevar(e))
+               return e;
+       if (is_convert(e->type)) {
+               e->l = add_missing_project_exp(sql, rel, e->l);
+       } else if (is_compare(e->type)) {
+               if (e->flag == cmp_in || e->flag == cmp_notin) {
+                       e->l = add_missing_project_exp(sql, rel, e->l);
+                       e->r = add_missing_project_exps(sql, rel, e->r);
+               } else if (e->flag == cmp_or || e->flag == cmp_filter) {
+                       e->l = add_missing_project_exps(sql, rel, e->l);
+                       e->r = add_missing_project_exps(sql, rel, e->r);
+               } else {
+                       e->l = add_missing_project_exp(sql, rel, e->l);
+                       e->r = add_missing_project_exp(sql, rel, e->r);
+                       if (e->f)
+                               e->f = add_missing_project_exp(sql, rel, e->f);
+               }
+       } else if (is_atom(e->type)) {
+               if (is_values(e))
+                       e->f = add_missing_project_exps(sql, rel, e->f);
+               return e;
+       }
+       else if (!list_find_exp(rel->exps, e)) {
+               exp_label(sql->sa, e, ++sql->label);
+               append(rel->exps, e);
+               return exp_ref(sql, e);
+       }
+       return e;
+}
+
+static list *
+add_missing_project_exps(mvc *sql, sql_rel *rel, list *exps)
+{
+       if (list_empty(exps))
+               return exps;
+       for(node *n = exps->h; n; n = n->next)
+               n->data = add_missing_project_exp(sql, rel, n->data);
+       return exps;
+}
+
+static sql_rel *
+push_up_select2(visitor *v, sql_rel *rel)
+{
+       sql_rel *l = rel->l;
+       sql_rel *r = rel->r;
+
+       /* TODO make sure we do not have empty selects */
+       if (is_simple_project(rel->op) && l && is_select(l->op) && 
exps_have_freevar(v->sql, l->exps) && !rel_is_ref(l)) {
+               sql_rel *nl = rel_select(v->sql->sa, rel, NULL);
+               nl->exps = add_missing_project_exps(v->sql, rel, l->exps);
+               l->exps = NULL;
+               rel->l = rel_dup(l->l);
+               rel_destroy(l);
+               rel_bind_vars(v->sql, nl, nl->exps);
+               v->changes++;
+               return nl;
+       }
+       if (!is_single(rel) && is_innerjoin(rel->op) && l && is_select(l->op) 
&& exps_have_freevar(v->sql, l->exps) && !rel_is_ref(l)) {
+               sql_rel *nl = rel_select(v->sql->sa, rel, NULL);
+               nl->exps = l->exps;
+               l->exps = NULL;
+               rel->l = rel_dup(l->l);
+               rel_destroy(l);
+               rel_bind_vars(v->sql, nl, nl->exps);
+               v->changes++;
+               return nl;
+       }
+       if (is_single(rel) && is_innerjoin(rel->op) && l && is_select(l->op) && 
exps_have_freevar(v->sql, l->exps) && !rel_is_ref(l)) {
+               if (rel->exps)
+                       rel->exps = list_merge(rel->exps, l->exps, NULL);
+               else
+                       rel->exps = l->exps;
+               l->exps = NULL;
+               rel->l = rel_dup(l->l);
+               rel_destroy(l);
+               rel_bind_vars(v->sql, rel, rel->exps);
+               v->changes++;
+               return rel;
+       }
+       if (!is_single(rel) && is_innerjoin(rel->op) && r && is_select(r->op) 
&& exps_have_freevar(v->sql, r->exps) && !rel_is_ref(r)) {
+               sql_rel *nr = rel_select(v->sql->sa, rel, NULL);
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to