Changeset: 979bf33a3ac1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/979bf33a3ac1
Modified Files:
        sql/server/rel_rel.c
Branch: Oct2020
Log Message:

Bind grouping columns in a cleaner way on single name references. Also don't 
bind the the same expression twice on projections


diffs (167 lines):

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
@@ -231,99 +231,71 @@ rel_select_copy(sql_allocator *sa, sql_r
        return rel;
 }
 
-static sql_rel *
-rel_bind_column_(mvc *sql, int *exp_has_nil, sql_rel *rel, const char *cname, 
int no_tname)
+sql_exp *
+rel_bind_column( mvc *sql, sql_rel *rel, const char *cname, int f, int 
no_tname)
 {
        int ambiguous = 0, multi = 0;
-       sql_rel *l = NULL, *r = NULL;
 
+       if (!rel)
+               return NULL;
        if (THRhighwater())
                return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: 
running out of stack space");
 
-       switch(rel->op) {
-       case op_join:
-       case op_left:
-       case op_right:
-       case op_full: {
-               r = rel_bind_column_(sql, exp_has_nil, rel->r, cname, no_tname);
-               sql_exp *e = r?exps_bind_column(r->exps, cname, &ambiguous, 
&multi, 0):NULL;
+       if ((is_project(rel->op) || is_base(rel->op))) {
+               sql_exp *e = NULL;
 
-               if (!r || !e || !is_freevar(e)) {
-                       l = rel_bind_column_(sql, exp_has_nil, rel->l, cname, 
no_tname);
-                       if (l && r && !is_dependent(rel))
+               if (!list_empty(rel->exps)) {
+                       e = exps_bind_column(rel->exps, cname, &ambiguous, 
&multi, no_tname);
+                       if (ambiguous || multi)
+                               return sql_error(sql, ERR_AMBIGUOUS, 
SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
+                       if (!e && is_groupby(rel->op) && rel->r) {
+                               e = exps_bind_alias(rel->r, NULL, cname);
+                               if (e) {
+                                       e = exps_bind_column(rel->r, cname, 
&ambiguous, &multi, no_tname);
+                                       if (ambiguous || multi)
+                                               return sql_error(sql, 
ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
+                                       return e;
+                               }
+                       }
+               }
+               if (!e && (is_sql_sel(f) || is_sql_having(f) || !f) && 
is_groupby(rel->op) && rel->r) {
+                       e = exps_bind_column(rel->r, cname, &ambiguous, &multi, 
no_tname);
+                       if (ambiguous || multi)
+                               return sql_error(sql, ERR_AMBIGUOUS, 
SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
+                       if (e) {
+                               e = exp_ref(sql, e);
+                               e->card = rel->card;
+                               return e;
+                       }
+               }
+               if (e)
+                       return exp_alias_or_copy(sql, exp_relname(e), cname, 
rel, e);
+       }
+       if ((is_simple_project(rel->op) || is_groupby(rel->op)) && rel->l) {
+               if (!is_processed(rel))
+                       return rel_bind_column(sql, rel->l, cname, f, no_tname);
+       } else if (is_set(rel->op)) {
+               assert(is_processed(rel));
+               return NULL;
+       } else if (is_join(rel->op)) {
+               sql_exp *e1 = rel_bind_column(sql, rel->l, cname, f, no_tname), 
*e2 = NULL;
+
+               if (e1 && (is_right(rel->op) || is_full(rel->op)))
+                       set_has_nil(e1);
+               if (!e1 || !is_freevar(e1)) {
+                       e2 = rel_bind_column(sql, rel->r, cname, f, no_tname);
+                       if (e2 && (is_left(rel->op) || is_full(rel->op)))
+                               set_has_nil(e2);
+                       if (e1 && e2 && !is_dependent(rel))
                                return sql_error(sql, ERR_AMBIGUOUS, 
SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
                }
-               if (sql->session->status == -ERR_AMBIGUOUS)
-                       return NULL;
-               if (l && !r) {
-                       if (is_full(rel->op) || is_right(rel->op))
-                               *exp_has_nil = 1;
-                       return l;
-               }
-               if (r && (is_full(rel->op) || is_left(rel->op)))
-                       *exp_has_nil = 1;
-               return r;
-       }
-       case op_union:
-       case op_except:
-       case op_inter:
-       case op_groupby:
-       case op_project:
-       case op_table:
-       case op_basetable: {
-               sql_exp *found = NULL;
-
-               if (rel->exps)
-                       found = exps_bind_column(rel->exps, cname, &ambiguous, 
&multi, no_tname);
-               if (!found && rel->r && is_groupby(rel->op))
-                       found = exps_bind_column(rel->r, cname, &ambiguous, 
&multi, no_tname);
-               if (ambiguous || multi)
-                       return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) 
"SELECT: identifier '%s' ambiguous", cname);
-               if (found)
-                       return rel;
-               if (is_processed(rel))
-                       return NULL;
-               if (rel->l && !(is_base(rel->op)))
-                       return rel_bind_column_(sql, exp_has_nil, rel->l, 
cname, no_tname);
-               } break;
-       case op_semi:
-       case op_anti:
-
-       case op_select:
-       case op_topn:
-       case op_sample:
+               return e1 ? e1 : e2;
+       } else if (is_semi(rel->op) ||
+                  is_select(rel->op) ||
+                  is_topn(rel->op) ||
+                  is_sample(rel->op)) {
                if (rel->l)
-                       return rel_bind_column_(sql, exp_has_nil, rel->l, 
cname, no_tname);
-               /* fall through */
-       default:
-               return NULL;
-       }
-       return NULL;
-}
-
-sql_exp *
-rel_bind_column( mvc *sql, sql_rel *rel, const char *cname, int f, int 
no_tname)
-{
-       int exp_has_nil = 0; /* mark if we passed any outer joins */
-
-       if (is_sql_sel(f) && rel && is_simple_project(rel->op) && 
!is_processed(rel))
-               rel = rel->l;
-
-       if (!rel || (rel = rel_bind_column_(sql, &exp_has_nil, rel, cname, 
no_tname)) == NULL)
-               return NULL;
-
-       if ((is_project(rel->op) || is_base(rel->op)) && rel->exps) {
-               sql_exp *e = exps_bind_column(rel->exps, cname, NULL, NULL, 
no_tname);
-               if (e)
-                       e = exp_alias_or_copy(sql, exp_relname(e), cname, rel, 
e);
-               if (!e && is_groupby(rel->op) && rel->r) {
-                       e = exps_bind_column(rel->r, cname, NULL, NULL, 
no_tname);
-                       if (e)
-                               e = exp_alias_or_copy(sql, exp_relname(e), 
cname, rel, e);
-               }
-               if (e && exp_has_nil)
-                       set_has_nil(e);
-               return e;
+                       return rel_bind_column(sql, rel->l, cname, f, no_tname);
        }
        return NULL;
 }
@@ -335,6 +307,8 @@ rel_bind_column2( mvc *sql, sql_rel *rel
 
        if (!rel)
                return NULL;
+       if (THRhighwater())
+               return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: 
running out of stack space");
 
        if ((is_project(rel->op) || is_base(rel->op))) {
                sql_exp *e = NULL;
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to