Changeset: ac5b509f2038 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=ac5b509f2038
Modified Files:
        sql/server/rel_select.c
        sql/server/rel_unnest.c
        sql/test/subquery/Tests/correlated.stable.err
        sql/test/subquery/Tests/subquery2.sql
        sql/test/subquery/Tests/subquery3.sql
Branch: sq2
Log Message:

small fixes for rewriting or query
check full result projection expressions for proper cardinality


diffs (200 lines):

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
@@ -946,6 +946,39 @@ exps_get_exp(list *exps, int nth)
        return NULL;
 }
 
+static sql_rel *
+rel_find_groupby(sql_rel *groupby)
+{
+       if (groupby && !is_processed(groupby) && !is_base(groupby->op)) { 
+               while(!is_processed(groupby) && !is_base(groupby->op)) {
+                       if (groupby->op == op_groupby || !groupby->l)
+                               break;
+                       if (groupby->l)
+                               groupby = groupby->l;
+               }
+               if (groupby && groupby->op == op_groupby)
+                       return groupby;
+       }
+       return NULL;
+}
+
+static int
+is_groupby_col(sql_rel *gb, sql_exp *e)
+{
+       gb = rel_find_groupby(gb);
+
+       if (gb) {
+               if (exp_relname(e)) { 
+                       if (exp_name(e) && exps_bind_column2(gb->r, 
exp_relname(e), exp_name(e))) 
+                               return 1;
+               } else {
+                       if (exp_name(e) && exps_bind_column(gb->r, exp_name(e), 
NULL)) 
+                               return 1;
+               }
+       }
+       return 0;
+}
+
 static sql_exp *
 rel_column_ref(sql_query *query, sql_rel **rel, symbol *column_r, int f)
 {
@@ -1004,7 +1037,7 @@ rel_column_ref(sql_query *query, sql_rel
                                if (exp && is_simple_project(outer->op) && 
!rel_find_exp(outer, exp)) {
                                        exp = rel_project_add_exp(sql, outer, 
exp);
                                }
-                               if (exp && is_sql_aggr(f) && 
is_sql_aggr(sql_state)) {
+                               if (exp && is_sql_aggr(f) && 
is_sql_aggr(sql_state) && !is_groupby_col(outer, exp)) {
                                        return sql_error(sql, 05, 
SQLSTATE(42000) "SELECT: aggregate function calls cannot be nested");
                                }
                                if (exp)
@@ -1070,7 +1103,7 @@ rel_column_ref(sql_query *query, sql_rel
                                if (exp && is_simple_project(outer->op) && 
!rel_find_exp(outer, exp)) {
                                        exp = rel_project_add_exp(sql, outer, 
exp);
                                }
-                               if (exp && is_sql_aggr(f) && 
is_sql_aggr(sql_state)) {
+                               if (exp && is_sql_aggr(f) && 
is_sql_aggr(sql_state) && !is_groupby_col(outer, exp)) {
                                        return sql_error(sql, 05, 
SQLSTATE(42000) "SELECT: aggregate function calls cannot be nested");
                                }
                                if (exp)
@@ -3305,22 +3338,6 @@ rel_check_card(sql_rel *rel, sql_exp *l 
        return 0;
 }
 
-static sql_rel *
-rel_find_groupby(sql_rel *groupby)
-{
-       if (groupby && !is_processed(groupby) && !is_base(groupby->op)) { 
-               while(!is_processed(groupby) && !is_base(groupby->op)) {
-                       if (groupby->op == op_groupby || !groupby->l)
-                               break;
-                       if (groupby->l)
-                               groupby = groupby->l;
-               }
-               if (groupby && groupby->op == op_groupby)
-                       return groupby;
-       }
-       return NULL;
-}
-
 static sql_exp *
 rel_binop(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek)
 {
@@ -5446,6 +5463,7 @@ rel_select_exp(sql_query *query, sql_rel
                sql_exp *ce = rel_column_exp(query, &inner, n->data.sym, 
sql_sel);
 
                if (ce && exp_subtype(ce)) {
+                       /*
                        if (inner && inner->card < ce->card) {
                                if (exp_name(ce)) {
                                        return sql_error(sql, 05, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results 
without an aggregate function", exp_name(ce));
@@ -5453,6 +5471,7 @@ rel_select_exp(sql_query *query, sql_rel
                                        return sql_error(sql, 05, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results 
without an aggregate function");
                                }
                        }
+                       */
                        pexps = append(pexps, ce);
                        rel = inner;
                        continue;
@@ -5471,6 +5490,18 @@ rel_select_exp(sql_query *query, sql_rel
                 */
                pexps = list_merge(pexps, te, (fdup)NULL);
        }
+       if (is_groupby(rel->op) && !sn->groupby) {
+               for (node *n=pexps->h; n; n = n->next) {
+                       sql_exp *ce = n->data;
+                       if (rel->card < ce->card) {
+                               if (exp_name(ce)) {
+                                       return sql_error(sql, 05, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results 
without an aggregate function", exp_name(ce));
+                               } else {
+                                       return sql_error(sql, 05, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results 
without an aggregate function");
+                               }
+                       }
+               }
+       }
        rel = rel_project(sql->sa, rel, pexps);
 
        rel = rel_having_limits_nodes(query, rel, sn, ek);
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
@@ -1483,7 +1483,8 @@ rewrite_or_exp(mvc *sql, sql_rel *rel)
                                        /* rewrite into setop */
                                        sql_rel *l = rel; 
                                        sql_rel *r = rel_dup(rel);
-                                       
+                                       list *exps = rel_projections(sql, rel, 
NULL, 1, 1);
+
                                        l = rel_select(sql->sa, l, NULL);
                                        l->exps = e->l;
                                        r = rel_select(sql->sa, r, NULL);
@@ -1492,6 +1493,7 @@ rewrite_or_exp(mvc *sql, sql_rel *rel)
                                        list_remove_node(rel->exps, n); /* 
remove or expression */
                                        rel = rel_setop(sql->sa, l, r, 
op_union);
                                        rel = rel_distinct(rel);
+                                       rel->exps = exps;
                                        return rewrite_or_exp(sql, rel);
                                }
                        }       
diff --git a/sql/test/subquery/Tests/correlated.stable.err 
b/sql/test/subquery/Tests/correlated.stable.err
--- a/sql/test/subquery/Tests/correlated.stable.err
+++ b/sql/test/subquery/Tests/correlated.stable.err
@@ -56,7 +56,7 @@ ERROR = !SELECT: cannot use non GROUP BY
 CODE  = 42000
 MAPI  = (monetdb) /var/tmp/mtest-8372/.s.monetdb.37437
 QUERY = SELECT i+1, (SELECT SUM(i1.i)) FROM integers i1;
-ERROR = !SELECT: cannot use non GROUP BY column 'i' in query results without 
an aggregate function
+ERROR = !SELECT: cannot use non GROUP BY column in query results without an 
aggregate function
 CODE  = 42000
 MAPI  = (monetdb) /var/tmp/mtest-17692/.s.monetdb.32120
 QUERY = SELECT i1.i FROM integers i1 INNER JOIN integers i ON SUM(i1.i) = 
SUM(i.i); --error, aggregations not allowed in join conditions
diff --git a/sql/test/subquery/Tests/subquery2.sql 
b/sql/test/subquery/Tests/subquery2.sql
--- a/sql/test/subquery/Tests/subquery2.sql
+++ b/sql/test/subquery/Tests/subquery2.sql
@@ -122,7 +122,6 @@ GROUP BY col1, col2, col5, col8;
        -- False True True True
 
 
-/* Wrong output (error) because of CAST (NOT col1 IN (SELECT col2 FROM 
another_T GROUP BY col2) AS INTEGER) | CAST (col2 IN (SELECT col2 FROM 
another_T GROUP BY col2) AS INTEGER),
 SELECT
        DISTINCT
        NOT col1 * col5 = ALL (SELECT 1 FROM tbl_ProductSales HAVING MAX(col2) 
> 2),
@@ -133,7 +132,6 @@ FROM another_T
 GROUP BY col1, col2, col5;
        -- False False 1 0
        -- True  False 1 0
-*/
 
 SELECT
        SUM(col1) IN (SELECT DISTINCT col2 FROM another_T GROUP BY col2)
@@ -233,11 +231,9 @@ FROM another_T t1;
        -- NULL
        -- NULL
 
-/* BROKEN code generation with a constant in a groupby- aggregation
 SELECT
        CASE WHEN 1 IN (SELECT (SELECT MAX(col7))) THEN 2 ELSE NULL END
 FROM another_T t1;
-*/
        -- NULL
        -- NULL
        -- NULL
diff --git a/sql/test/subquery/Tests/subquery3.sql 
b/sql/test/subquery/Tests/subquery3.sql
--- a/sql/test/subquery/Tests/subquery3.sql
+++ b/sql/test/subquery/Tests/subquery3.sql
@@ -23,13 +23,11 @@ GROUP BY col1, col2, col5, col8;
        -- 226  98568   1143
        -- 2226 9874568 11443
 
-/* Broken bit_or aggr
 SELECT
     CAST (NOT col1 IN (SELECT col2 FROM another_T GROUP BY col2) AS INTEGER) | 
CAST (col2 IN (SELECT col2 FROM another_T GROUP BY col2) AS INTEGER),
     CAST (EXISTS (SELECT MAX(col5) * MAX(col4) FROM another_T GROUP BY col5, 
col4) AS INTEGER) & CAST (SUM(col4) IN (SELECT DISTINCT col2 FROM another_T 
GROUP BY col2) AS INTEGER)
 FROM another_T
 GROUP BY col1, col2, col5;
-*/
        -- 1    0
        -- 1    0
        -- 1    0
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to