Changeset: c0b5e08a910f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=c0b5e08a910f
Modified Files:
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/server/rel_rel.h
        sql/server/rel_select.c
Branch: subquery
Log Message:

fixing crashes, ie save handling of expressions in order/rank and group by


diffs (truncated from 570 to 300 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
@@ -6821,6 +6821,18 @@ rel_dce(mvc *sql, sql_rel *rel)
        }
 
        rel_dce_refs(sql, rel, refs);
+       if (refs) {
+               node *n;
+
+               for(n = refs->h; n; n = n->next) {
+                       sql_rel *i = n->data;
+
+                       while (!rel_is_ref(i) && i->l && !is_base(i->op))
+                               i = i->l;
+                       if (i)
+                               rel_used(i);
+               }
+       }
        rel = rel_add_projects(sql, rel);
        rel_used(rel);
        rel_dce_sub(sql, rel, refs);
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -265,7 +265,7 @@ rel_bind_column( mvc *sql, sql_rel *rel,
 {
        sql_rel *p = NULL;
 
-       if (is_sql_sel(f) && rel && is_project(rel->op) && !is_processed(rel))
+       if (is_sql_sel(f) && rel && is_simple_project(rel->op) && 
!is_processed(rel))
                rel = rel->l;
 
        if (!rel || (rel = rel_bind_column_(sql, &p, rel, cname)) == NULL)
diff --git a/sql/server/rel_rel.h b/sql/server/rel_rel.h
--- a/sql/server/rel_rel.h
+++ b/sql/server/rel_rel.h
@@ -19,6 +19,7 @@
 #define sql_orderby 16
 #define sql_groupby 32 //ORed
 #define sql_partitionby 64 //ORed
+#define sql_aggr 128 //ORed
 
 #define is_sql_from(X)    ((X & sql_from) == sql_from)
 #define is_sql_where(X)   ((X & sql_where) == sql_where)
@@ -27,6 +28,7 @@
 #define is_sql_orderby(X) ((X & sql_orderby) == sql_orderby)
 #define is_sql_groupby(X) ((X & sql_groupby) == sql_groupby)
 #define is_sql_partitionby(X) ((X & sql_partitionby) == sql_partitionby)
+#define is_sql_aggr(X)    ((X & sql_aggr) == sql_aggr)
 
 #define ERR_AMBIGUOUS          050000
 
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
@@ -998,7 +998,7 @@ rel_column_ref(sql_query *query, sql_rel
                        return rel_var_ref(sql, name, 0);
                }
                if (!exp && !var) {
-                       if (rel && *rel && (*rel)->card <= CARD_AGGR && 
is_sql_sel(f)) {
+                       if (rel && *rel && (*rel)->card <= CARD_AGGR && 
is_sql_sel(f) && !is_sql_aggr(f)) {
                                sql_rel *gb = *rel;
 
                                while(gb->l && !is_groupby(gb->op))
@@ -1010,6 +1010,9 @@ rel_column_ref(sql_query *query, sql_rel
                                return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: cannot use non GROUP BY column '%s' in query results without an 
aggregate function", name);
                        return sql_error(sql, 02, SQLSTATE(42000) "SELECT: 
identifier '%s' unknown", name);
                }
+               if (exp && rel && *rel && (*rel)->card <= CARD_AGGR && 
exp->card > CARD_AGGR && is_sql_sel(f) && !is_sql_aggr(f)) {
+                       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: 
cannot use non GROUP BY column '%s' in query results without an aggregate 
function", name);
+               }
                
        } else if (dlist_length(l) == 2) {
                char *tname = l->h->data.sval;
@@ -1043,7 +1046,7 @@ rel_column_ref(sql_query *query, sql_rel
                        }
                }
                if (!exp) {
-                       if (rel && *rel && (*rel)->card == CARD_AGGR && 
is_sql_sel(f)) {
+                       if (rel && *rel && (*rel)->card == CARD_AGGR && 
is_sql_sel(f) && !is_sql_aggr(f)) {
                                sql_rel *gb = *rel;
 
                                while(gb->l && !is_groupby(gb->op) && 
is_project(gb->op))
@@ -1055,6 +1058,9 @@ rel_column_ref(sql_query *query, sql_rel
                                return sql_error(sql, 02, SQLSTATE(42S22) 
"SELECT: cannot use non GROUP BY column '%s.%s' in query results without an 
aggregate function", tname, cname);
                        return sql_error(sql, 02, SQLSTATE(42S22) "SELECT: no 
such column '%s.%s'", tname, cname);
                }
+               if (exp && rel && *rel && (*rel)->card == CARD_AGGR && 
exp->card > CARD_AGGR && is_sql_sel(f) && !is_sql_aggr(f)) {
+                       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: 
cannot use non GROUP BY column '%s.%s' in query results without an aggregate 
function", tname, cname);
+               }
        } else if (dlist_length(l) >= 3) {
                return sql_error(sql, 02, SQLSTATE(42000) "TODO: column names 
of level >= 3");
        }
@@ -1934,13 +1940,13 @@ rel_in_value_exp(sql_query *query, sql_r
                for (; n; n = n->next) {
                        sql_rel *z = NULL;
 
-                       r = rel_value_exp(query, &z, n->data.sym, sql_where /* 
ie no result project */, ek);
+                       r = rel_value_exp(query, &z, n->data.sym, f /* ie no 
result project */, ek);
                        if (l && !r) {
                                /* reset error */
                                sql->session->status = 0;
                                sql->errstr[0] = 0;
 
-                               r = rel_value_exp(query, &left, n->data.sym, 
sql_where /* ie no result project */, ek);
+                               r = rel_value_exp(query, &left, n->data.sym, f 
/* ie no result project */, ek);
                                if (r && !pexps) 
                                        *rel = left; 
                        }
@@ -1995,7 +2001,7 @@ rel_in_value_exp(sql_query *query, sql_r
                                sql->errstr[0] = 0;
 
                                query_push_outer(query, left);
-                               r = rel_value_exp(query, &z, n->data.sym, 
sql_where /* ie no result project */, ek);
+                               r = rel_value_exp(query, &z, n->data.sym, f /* 
ie no result project */, ek);
                                query_pop_outer(query);
                                if (z)
                                        r = rel_lastexp(sql, z);
@@ -2659,14 +2665,14 @@ rel_in_exp(sql_query *query, sql_rel *re
                for (; n; n = n->next) {
                        sql_rel *z = NULL;
 
-                       r = rel_value_exp(query, &z, n->data.sym, sql_where /* 
ie no result project */, ek);
+                       r = rel_value_exp(query, &z, n->data.sym, f /* ie no 
result project */, ek);
                        
                        if (!r) {
                                /* reset error */
                                sql->session->status = 0;
                                sql->errstr[0] = 0;
 
-                               r = rel_value_exp(query, &left, n->data.sym, 
sql_where /* ie no result project */, ek);
+                               r = rel_value_exp(query, &left, n->data.sym, f 
/* ie no result project */, ek);
                                if (r)
                                        l_used = is_join(left->op);
                        }
@@ -2676,7 +2682,7 @@ rel_in_exp(sql_query *query, sql_rel *re
                                sql->errstr[0] = 0;
 
                                query_push_outer(query, left);
-                               r = rel_value_exp(query, &z, n->data.sym, 
sql_where /* ie no result project */, ek);
+                               r = rel_value_exp(query, &z, n->data.sym, f /* 
ie no result project */, ek);
                                query_pop_outer(query);
                                if (!r)
                                        return NULL;
@@ -3799,41 +3805,6 @@ rel_intermediates_add_exp(mvc *sql, sql_
        }
 }
 
-static sql_rel *
-rel_bind_groupby(sql_query *query, sql_rel **rel)
-{
-       mvc *sql = query->sql;
-       sql_rel *groupby = *rel, *l;
-       
-       if (!groupby)
-               return NULL;
-       if (!groupby->l) { 
-               if (groupby->op != op_groupby)
-                       *rel = groupby = rel_project2groupby(sql, groupby);
-               return groupby;
-       }
-       l = groupby->l;
-       if (groupby && groupby->l && !is_processed(groupby) && 
!is_groupby(groupby->op) && is_groupby(l->op))
-               groupby = groupby->l;
-       if (groupby->op != op_groupby) {                /* implicit groupby */
-               sql_rel *np = rel_project2groupby(sql, groupby);
-
-               if (*rel == groupby) {
-                       *rel = np;
-               } else {
-                       sql_rel *l = *rel;
-                       while(l->l && l->l != groupby) {
-                               l = l->l;
-                       }
-                       if (l->l && l->l == groupby)
-                               l->l = np;
-               }
-       }
-       if (!*rel)
-               return NULL;
-       return groupby;
-}
-
 static sql_exp *
 _rel_aggr(sql_query *query, sql_rel **rel, int distinct, sql_schema *s, char 
*aname, dnode *args, int f)
 {
@@ -3841,24 +3812,25 @@ static sql_exp *
        exp_kind ek = {type_value, card_column, FALSE};
        sql_subaggr *a = NULL;
        int no_nil = 0, group = 0, freevar = 1;
-       sql_rel *groupby = *rel, *gr = NULL;//, *sel = NULL, *og = NULL, *r = 
(groupby)?groupby->l:NULL;
+       sql_rel *groupby = *rel, *sel = NULL, *gr, *og = NULL;
        list *exps = NULL;
 
-#if 0
+       (void)sel;
+
        /* find having select */
        if (groupby && groupby->l && !is_processed(groupby) && 
is_sql_having(f)) { 
-               sql_rel *gl = groupby->l;
+               sql_rel *gl = NULL;
 
                og = groupby;
-               while(groupby->l && !is_processed(groupby)) {
+               while(groupby->l && !is_processed(groupby) && 
!is_base(groupby->op)) {
                        gl = groupby->l;
                        if (is_select(gl->op))
                                break;
                        groupby = gl;
                }
-               if (gl && is_select(gl->op)) {
+               if (groupby && is_select(groupby->op) && 
!is_processed(groupby)) {
                        group = 1;
-                       sel = groupby = gl;
+                       sel = groupby;
                        /* At the end we switch back to the old projection 
relation og. 
                         * During the partitioning and ordering we add the 
expressions to the intermediate relations. */
                }
@@ -3867,12 +3839,6 @@ static sql_exp *
 
                if (sel && sel->l)
                        groupby = sel->l;
-
-               if (groupby && groupby->op == op_project && groupby->l)
-                       r = groupby->l;
-
-               if (r && r->op == op_groupby)
-                       groupby = r;
        }
 
        /* find groupby */
@@ -3880,7 +3846,7 @@ static sql_exp *
                sql_rel *gl = groupby->l;
 
                og = groupby;
-               while(groupby->l && !is_processed(groupby)) {
+               while(groupby->l && !is_processed(groupby) && 
!is_base(groupby->op)) {
                        gl = groupby->l;
                        if (gl->op == op_groupby)
                                break;
@@ -3903,7 +3869,7 @@ static sql_exp *
                if (uaname)
                        GDKfree(uaname);
                return e;
-       } else if(is_sql_groupby(f) || (is_sql_partitionby(f) && !r && r->op != 
op_groupby)) {
+       } else if(is_sql_groupby(f) || (is_sql_partitionby(f) && groupby->op != 
op_groupby)) {
                const char *clause = is_sql_groupby(f) ? "GROUP BY":"PARTITION 
BY";
                char *uaname = GDKmalloc(strlen(aname) + 1);
                sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate 
function '%s' not allowed in %s clause",
@@ -3913,18 +3879,18 @@ static sql_exp *
                return e;
        }
 
-       if (!query_has_outer(query) && groupby->op != op_groupby) {             
/* implicit groupby */
-               sql_rel *ng = rel_project2groupby(sql, groupby);
+       if (groupby->op != op_groupby) {                /* implicit groupby */
+               sql_rel *np = rel_project2groupby(sql, groupby);
 
                if (*rel == groupby) {
-                       *rel = ng;
+                       *rel = np;
                } else {
                        sql_rel *l = *rel;
                        while(l->l && l->l != groupby) {
                                l = l->l;
                        }
                        if (l->l && l->l == groupby)
-                               l->l = ng;
+                               l->l = np;
                }
        }
        if (!*rel)
@@ -3938,20 +3904,9 @@ static sql_exp *
                        GDKfree(uaname);
                return e;
        }
-#endif
-       if (!(groupby = rel_bind_groupby(query, 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;
-       }
-       gr = groupby;
        
        if (!args->data.sym) {  /* count(*) case */
                sql_exp *e;
-               sql_rel *p = groupby;
 
                if (strcmp(aname, "count") != 0) {
                        char *uaname = GDKmalloc(strlen(aname) + 1);
@@ -3961,34 +3916,48 @@ static sql_exp *
                                GDKfree(uaname);
                        return e;
                }
-
                a = sql_bind_aggr(sql->sa, s, aname, NULL);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to