Changeset: 42daf1d9f892 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=42daf1d9f892
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimizer.c
        sql/server/rel_select.c
        
sql/test/BugTracker-2012/Tests/scalar_subquery_with_alias.Bug-3093.stable.out
        sql/test/BugTracker-2013/Tests/correlated_select.Bug-3250.stable.out
        sql/test/BugTracker-2013/Tests/correlated_subquery.Bug-3317.stable.out
        sql/test/BugTracker-2013/Tests/syntaxerror.Bug-3399.stable.err
        sql/test/BugTracker-2013/Tests/syntaxerror.Bug-3399.stable.out
        
sql/test/BugTracker-2014/Tests/order_by_incorrect_error.Bug-3630.stable.err
        
sql/test/BugTracker-2014/Tests/order_by_incorrect_error.Bug-3630.stable.out
Branch: subquery
Log Message:

push more join expressions down
cleanup some more code

approved some more tests


diffs (truncated from 416 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
@@ -1201,6 +1201,20 @@ rel_has_exps(sql_rel *rel, list *exps)
        return -1;
 }
 
+int
+rel_has_all_exps(sql_rel *rel, list *exps)
+{
+       node *n;
+
+       if (!exps)
+               return -1;
+       for (n = exps->h; n; n = n->next)
+               if (rel_has_exp(rel, n->data) < 0)
+                       return 0;
+       return 1;
+}
+
+
 sql_rel *
 find_rel(list *rels, 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
@@ -136,6 +136,8 @@ extern int exp_has_sideeffect(sql_exp *e
 extern int rel_has_exp(sql_rel *rel, sql_exp *e);
 /* return 0 when the relation contain atleast one of the passed expressions 
else < 0 */
 extern int rel_has_exps(sql_rel *rel, list *e);
+/* return 1 when the relation contains all of the passed expressions else 0 */
+extern int rel_has_all_exps(sql_rel *rel, list *e);
 
 extern sql_rel *find_rel(list *rels, sql_exp *e);
 extern sql_rel *find_one_rel(list *rels, sql_exp *e);
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
@@ -4720,6 +4720,69 @@ rel_uses_part_nr( sql_rel *rel, sql_exp 
        return 0;
 }
 
+static int
+rel_has_cmp_exp(sql_rel *rel, sql_exp *e)
+{
+       if (get_cmp(e) == cmp_or) {
+               return rel_has_exp(rel, e->l) == 0 &&
+                       rel_has_all_exps(rel, e->r);
+       } else if (e->flag == cmp_in || e->flag == cmp_notin || get_cmp(e) == 
cmp_filter) {
+               return rel_has_all_exps(rel, e->l) &&
+                       rel_has_all_exps(rel, e->r);
+       } else {
+               return rel_has_exp(rel, e->l) == 0 &&
+                       rel_has_exp(rel, e->r) == 0 &&
+                       (!e->f || rel_has_exp(rel, e->f) == 0);
+       }
+       return 0;
+}
+
+static sql_rel *
+rel_join_push_exps_down(int *changes, mvc *sql, sql_rel *rel) 
+{
+       if ((is_join(rel->op) && !is_outerjoin(rel->op)) || is_semi(rel->op)) {
+               sql_rel *l = rel->l, *r = rel->r;
+               list *jexps = NULL, *lexps = NULL, *rexps = NULL;
+               node *n;
+
+               if (list_empty(rel->exps))
+                       return rel;
+
+               for(n=rel->exps->h; n; n=n->next) {
+                       sql_exp *e = n->data;
+                       int le = rel_has_cmp_exp(l, e);
+                       int re = rel_has_cmp_exp(r, e);
+
+                       if (le && !re) {
+                               if (!lexps)
+                                       lexps=sa_list(sql->sa);
+                               append(lexps, e);
+                       } else if (!le && re) {
+                               if (!rexps)
+                                       rexps=sa_list(sql->sa);
+                               append(rexps, e);
+                       } else {
+                               if (!jexps)
+                                       jexps=sa_list(sql->sa);
+                               append(jexps, e);
+                       }
+               }
+               if (lexps || rexps)
+                       rel->exps = jexps;
+               if (lexps) {
+                       l = rel->l = rel_select(sql->sa, rel->l, NULL);
+                       l->exps = lexps;
+                       (*changes) = 1;
+               }
+               if (rexps) {
+                       r = rel->r = rel_select(sql->sa, rel->r, NULL);
+                       r->exps = rexps;
+                       (*changes) = 1;
+               }
+       }
+       return rel;
+}
+
 /*
  * Push (semi)joins down unions, this is basically for merge tables, where
  * we know that the fk-indices are split over two clustered merge tables.
@@ -9697,6 +9760,9 @@ optimize_rel(mvc *sql, sql_rel *rel, int
                rel = rewrite(sql, rel, &rel_push_join_down_union, &changes); 
                /* rel_join_order may introduce empty selects */
                rel = rewrite(sql, rel, &rel_remove_empty_select, &e_changes); 
+
+               if (level <= 0)
+                       rel = rewrite(sql, rel, &rel_join_push_exps_down, 
&changes); 
        }
 
        if (gp.cnt[op_join] || gp.cnt[op_left] || gp.cnt[op_right] || 
gp.cnt[op_full]) {
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -1621,20 +1621,6 @@ rel_filter_exp_(mvc *sql, sql_rel *rel, 
        return rel_filter(sql, rel, l, r, "sys", filter_op, anti);
 }
 
-static int
-exp_is_subquery( mvc *sql, sql_exp *e)
-{
-       if (e->type == e_column) {
-               if (e->card == CARD_ATOM) /* free variable? */
-                       return 1;
-               if (mvc_find_subquery(sql, e->l?e->l:e->r, e->r))
-                       return 1;
-       }
-       if (e->type == e_convert) 
-               return exp_is_subquery( sql, e->l);
-       return 0;
-}
-
 static sql_rel *
 rel_compare_exp_(sql_query *query, sql_rel *rel, sql_exp *ls, sql_exp *rs, 
sql_exp *rs2, int type, int anti, int quantifier)
 {
@@ -1693,8 +1679,8 @@ rel_compare_exp_(sql_query *query, sql_r
                else
                        return sql_error(sql, 02, SQLSTATE(42000) "SELECT: 
cannot use non GROUP BY column in query results without an aggregate function");
        }
-       if (rs->card <= CARD_ATOM && (exp_is_atom(rs) || exp_has_freevar(rs)) 
&& 
-          (!rs2 || (rs2->card <= CARD_ATOM && (exp_is_atom(rs2) || 
exp_is_subquery(sql, rs2))))) {
+       if (rs->card <= CARD_ATOM && (exp_is_atom(rs) || exp_has_freevar(rs)) &&
+          (!rs2 || (rs2->card <= CARD_ATOM && (exp_is_atom(rs2) || 
exp_has_freevar(rs2))))) {
                if ((ls->card == rs->card && !rs2) || rel->processed)  /* bin 
compare op */
                        return rel_select(sql->sa, rel, e);
 
@@ -4015,8 +4001,14 @@ static sql_exp *
                return e;
        }
 #endif
-       if (!(groupby = rel_bind_groupby(sql, rel)))
-               return NULL;
+       if (!(groupby = rel_bind_groupby(sql, rel))) {
+               char *uaname = GDKmalloc(strlen(aname) + 1);
+               sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: missing 
group by",
+                                              uaname ? toUpperCopy(uaname, 
aname) : aname);
+               if (uaname)
+                       GDKfree(uaname);
+               return e;
+       }
        
        if (!args->data.sym) {  /* count(*) case */
                sql_exp *e;
@@ -4854,7 +4846,7 @@ simple_selection(symbol *sq)
 
                sn = (SelectNode *) sq;
 
-               if (!sn->from && !sn->where && !sn->distinct)
+               if (!sn->from && !sn->where && !sn->distinct && 
dlist_length(sn->selection) == 1)
                        return sn->selection;
        }
        return NULL;
diff --git 
a/sql/test/BugTracker-2012/Tests/scalar_subquery_with_alias.Bug-3093.stable.out 
b/sql/test/BugTracker-2012/Tests/scalar_subquery_with_alias.Bug-3093.stable.out
--- 
a/sql/test/BugTracker-2012/Tests/scalar_subquery_with_alias.Bug-3093.stable.out
+++ 
b/sql/test/BugTracker-2012/Tests/scalar_subquery_with_alias.Bug-3093.stable.out
@@ -57,7 +57,7 @@ Ready.
 #       ) AS c2
 #  FROM test1 a
 #;
-% .L6, .L17 # table_name
+% .L6, .L14 # table_name
 % c1,  c2 # name
 % bigint,      bigint # type
 % 1,   1 # length
@@ -70,8 +70,8 @@ Ready.
 #       )
 #  FROM test1 a
 #;
-% .L5, .L15 # table_name
-% cnt1,        L15 # name
+% .L5, .L12 # table_name
+% cnt1,        cnt2 # name
 % bigint,      bigint # type
 % 1,   1 # length
 #SELECT (SELECT COUNT(id) AS cnt1 
@@ -83,7 +83,7 @@ Ready.
 #       ) AS c2
 #  FROM test1 a
 #;
-% .L5, .L16 # table_name
+% .L5, .L13 # table_name
 % cnt1,        c2 # name
 % bigint,      bigint # type
 % 1,   1 # length
@@ -96,7 +96,7 @@ Ready.
 #       ) AS c1
 #  FROM test1 a
 #;
-% .L10,        sys.L16 # table_name
+% .L6, .L14 # table_name
 % c2,  c1 # name
 % bigint,      bigint # type
 % 1,   1 # length
@@ -109,7 +109,7 @@ Ready.
 #       ) AS c2
 #  FROM test1 a
 #;
-% .L6, .L17 # table_name
+% .L6, .L14 # table_name
 % c1,  c2 # name
 % bigint,      bigint # type
 % 1,   1 # length
@@ -130,13 +130,13 @@ Ready.
 #       ) AS c2
 #  FROM test1 a
 #;
-% .L6, .L17 # table_name
+% .L6, .L14 # table_name
 % c1,  c2 # name
 % bigint,      bigint # type
 % 1,   1 # length
-[ 3,   1       ]
 [ 3,   0       ]
 [ 3,   0       ]
+[ 3,   1       ]
 #SELECT (SELECT COUNT(id) AS cnt1 
 #          FROM test1 
 #       )
@@ -146,13 +146,13 @@ Ready.
 #       )
 #  FROM test1 a
 #;
-% .L5, .L15 # table_name
-% cnt1,        L15 # name
+% .L5, .L12 # table_name
+% cnt1,        cnt2 # name
 % bigint,      bigint # type
 % 1,   1 # length
-[ 3,   1       ]
 [ 3,   0       ]
 [ 3,   0       ]
+[ 3,   1       ]
 #SELECT (SELECT COUNT(id) AS cnt1 
 #          FROM test1 
 #       )
@@ -162,13 +162,13 @@ Ready.
 #       ) AS c2
 #  FROM test1 a
 #;
-% .L5, .L16 # table_name
+% .L5, .L13 # table_name
 % cnt1,        c2 # name
 % bigint,      bigint # type
 % 1,   1 # length
-[ 3,   1       ]
 [ 3,   0       ]
 [ 3,   0       ]
+[ 3,   1       ]
 #SELECT (SELECT COUNT(b.id) AS cnt2 
 #          FROM test2 b 
 #         WHERE a.id = b.id
@@ -178,13 +178,13 @@ Ready.
 #       ) AS c1
 #  FROM test1 a
 #;
-% .L10,        sys.L16 # table_name
+% .L6, .L14 # table_name
 % c2,  c1 # name
 % bigint,      bigint # type
 % 1,   1 # length
-[ 1,   3       ]
 [ 0,   3       ]
 [ 0,   3       ]
+[ 1,   3       ]
 #SELECT (SELECT COUNT(id) AS cnt1 
 #          FROM test1 
 #       ) AS c1
@@ -194,13 +194,13 @@ Ready.
 #       ) AS c2
 #  FROM test1 a
 #;
-% .L6, .L17 # table_name
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to