Changeset: 2cf57a162ab7 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2cf57a162ab7
Added Files:
        sql/test/miscellaneous/Tests/three_level_lookup.sql
Modified Files:
        sql/server/rel_dump.c
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/server/rel_rel.h
        sql/server/rel_select.c
        sql/test/miscellaneous/Tests/All
Branch: groupby-expressions
Log Message:

Closing groupby-expressions branch after merge into default


diffs (236 lines):

diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -816,9 +816,9 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re
                                exp = exp_alias_or_copy(sql, tname, cname, 
lrel, exp);
                }
                if (!exp && lrel) { 
-                       exp = rel_bind_column2(sql, lrel, tname, cname, 0);
+                       exp = rel_bind_column23(sql, lrel, NULL, tname, cname, 
0);
                        if (!exp && rrel)
-                               exp = rel_bind_column2(sql, rrel, tname, cname, 
0);
+                               exp = rel_bind_column23(sql, rrel, NULL, tname, 
cname, 0);
                } else if (!exp) {
                        exp = exp_column(sql->sa, tname, cname, NULL, 
CARD_ATOM, 1, (strchr(cname,'%') != NULL));
                }
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
@@ -1229,7 +1229,7 @@ exp_rename(mvc *sql, sql_exp *e, sql_rel
                        return e;
                e = NULL;
                if (ne->name && ne->r && ne->l) 
-                       e = rel_bind_column2(sql, t, ne->l, ne->r, 0);
+                       e = rel_bind_column23(sql, t, NULL, ne->l, ne->r, 0);
                if (!e && ne->r)
                        e = rel_bind_column(sql, t, ne->r, 0);
                if (!e && ne->type == e_column) {
@@ -1339,7 +1339,7 @@ static sql_exp *
                        return list_fetch(t->exps, p);
                }
                if (e->l) { 
-                       ne = rel_bind_column2(sql, f, e->l, e->r, 0);
+                       ne = rel_bind_column23(sql, f, NULL, e->l, e->r, 0);
                        /* if relation name matches expressions relation name, 
find column based on column name alone */
                }
                if (!ne && !e->l)
@@ -1349,16 +1349,16 @@ static sql_exp *
                e = NULL;
                /*
                if (ne->name && ne->rname)
-                       e = rel_bind_column2(sql, t, ne->rname, ne->name, 0);
+                       e = rel_bind_column23(sql, t, NULL, ne->rname, 
ne->name, 0);
                if (!e && ne->name && !ne->rname)
                        e = rel_bind_column(sql, t, ne->name, 0);
                if (!e && ne->name && ne->r && ne->l) 
-                       e = rel_bind_column2(sql, t, ne->l, ne->r, 0);
+                       e = rel_bind_column23(sql, t, NULL, ne->l, ne->r, 0);
                if (!e && ne->r && !ne->l)
                        e = rel_bind_column(sql, t, ne->r, 0);
                        */
                if (ne->l && ne->r)
-                       e = rel_bind_column2(sql, t, ne->l, ne->r, 0);
+                       e = rel_bind_column23(sql, t, NULL, ne->l, ne->r, 0);
                if (!e && ne->r && !ne->l)
                        e = rel_bind_column(sql, t, ne->r, 0);
                sql->session->status = 0;
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
@@ -280,25 +280,40 @@ rel_bind_column( mvc *sql, sql_rel *rel,
 }
 
 sql_exp *
-rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char 
*cname, int f )
+rel_bind_column23( mvc *sql, sql_rel *rel, const char *sname, const char 
*tname, const char *cname, int f )
 {
        (void)f;
+       bool is_table_on_schema = false;
 
        if (!rel)
                return NULL;
 
-       if (rel->exps && (is_project(rel->op) || is_base(rel->op))) {
+       if (sname && is_base(rel->op)) { //sname parameter is optional, if 
provided then do a schema lookup
+               if (rel->op == op_basetable) {
+                       sql_table *t = (sql_table*)rel->l;
+                       is_table_on_schema = strcmp(t->s->base.name, sname) == 
0;
+               } else if (rel->op == op_table) {
+                       if (rel->flag == 0) { //table returning function
+                               sql_exp *op = (sql_exp*) rel->r;
+                               sql_func *func = ((sql_subfunc*) op->f)->func;
+                               is_table_on_schema = strcmp(func->s->base.name, 
sname) == 0;
+                       }
+               } else {
+                       assert(0);
+               }
+       }
+       if (rel->exps && (((is_project(rel->op) || is_base(rel->op)) && !sname) 
|| is_table_on_schema)) {
                sql_exp *e = exps_bind_column2(rel->exps, tname, cname);
                if (e)
                        return exp_alias_or_copy(sql, tname, cname, rel, e);
        }
        if (is_project(rel->op) && rel->l) {
                if (!is_processed(rel))
-                       return rel_bind_column2(sql, rel->l, tname, cname, f);
+                       return rel_bind_column23(sql, rel->l, sname, tname, 
cname, f);
        } else if (is_join(rel->op)) {
-               sql_exp *e = rel_bind_column2(sql, rel->l, tname, cname, f);
+               sql_exp *e = rel_bind_column23(sql, rel->l, sname, tname, 
cname, f);
                if (!e)
-                       e = rel_bind_column2(sql, rel->r, tname, cname, f);
+                       e = rel_bind_column23(sql, rel->r, sname, tname, cname, 
f);
                return e;
        } else if (is_set(rel->op) ||
                   is_sort(rel) ||
@@ -306,14 +321,14 @@ rel_bind_column2( mvc *sql, sql_rel *rel
                   is_select(rel->op) ||
                   is_topn(rel->op)) {
                if (rel->l)
-                       return rel_bind_column2(sql, rel->l, tname, cname, f);
+                       return rel_bind_column23(sql, rel->l, sname, tname, 
cname, f);
        } else if (is_apply(rel->op)) {
                sql_exp *e = NULL;
 
                if (!e && rel->l)
-                       e = rel_bind_column2(sql, rel->l, tname, cname, f);
+                       e = rel_bind_column23(sql, rel->l, sname, tname, cname, 
f);
                if (!e && rel->r && (rel->flag == APPLY_JOIN || rel->flag == 
APPLY_LOJ))
-                       return rel_bind_column2(sql, rel->r, tname, cname, f);
+                       return rel_bind_column23(sql, rel->r, sname, tname, 
cname, f);
                return e;
        }
        return 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
@@ -47,7 +47,7 @@ extern sql_rel *rel_copy(sql_allocator *
 extern sql_rel *rel_select_copy(sql_allocator *sa, sql_rel *l, list *exps);
 
 extern sql_exp *rel_bind_column( mvc *sql, sql_rel *rel, const char *cname, 
int f );
-extern sql_exp *rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname, 
const char *cname, int f );
+extern sql_exp *rel_bind_column23( mvc *sql, sql_rel *rel, const char *sname, 
const char *tname, const char *cname, int f );
 
 extern sql_rel *rel_inplace_setop(sql_rel *rel, sql_rel *l, sql_rel *r, 
operator_type setop, list *exps);
 extern sql_rel *rel_inplace_project(sql_allocator *sa, sql_rel *rel, sql_rel 
*l, list *e);
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
@@ -1115,24 +1115,26 @@ rel_column_ref(mvc *sql, sql_rel **rel, 
                        return sql_error(sql, 02, SQLSTATE(42000) "SELECT: 
identifier '%s' unknown", name);
                }
                
-       } else if (dlist_length(l) == 2) {
-               char *tname = l->h->data.sval;
-               char *cname = l->h->next->data.sval;
+       } else if (dlist_length(l) == 2 || dlist_length(l) == 3) {
+               bool depth2 = dlist_length(l) == 2;
+               char *sname = depth2 ? NULL : l->h->data.sval;
+               char *tname = depth2 ? l->h->data.sval : l->h->next->data.sval;
+               char *cname = depth2 ? l->h->next->data.sval : 
l->h->next->next->data.sval;
 
                if (rel && *rel)
-                       exp = rel_bind_column2(sql, *rel, tname, cname, f);
+                       exp = rel_bind_column23(sql, *rel, sname, tname, cname, 
f);
 
                /* some views are just in the stack,
                   like before and after updates views */
                if (rel && !exp && sql->use_views) {
-                       sql_rel *v = stack_find_rel_view(sql, tname);
+                       sql_rel *v = stack_find_rel_view(sql, tname); //schema 
lookup is not needed here (this is used for with statements)
 
                        if (v) {
                                if (*rel)
                                        *rel = rel_crossproduct(sql->sa, *rel, 
v, op_join);
                                else
                                        *rel = v;
-                               exp = rel_bind_column2(sql, *rel, tname, cname, 
f);
+                               exp = rel_bind_column23(sql, *rel, sname, 
tname, cname, f);
                        }
                }
                if (!exp) {
@@ -1141,15 +1143,15 @@ rel_column_ref(mvc *sql, sql_rel **rel, 
 
                                while(gb->l && !is_groupby(gb->op) && 
is_project(gb->op))
                                        gb = gb->l;
-                               if (gb && is_groupby(gb->op) && gb->l && 
rel_bind_column2(sql, gb->l, tname, cname, 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);
+                               if (gb && is_groupby(gb->op) && gb->l && 
rel_bind_column23(sql, gb->l, sname, tname, cname, f))
+                                       return sql_error(sql, 02, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s%s%s.%s' in query 
results without an aggregate function", depth2 ? "" : sname, depth2 ? "" : ".", 
tname, cname);
                        }
                        if (is_sql_having(f))
-                               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);
-               }
-       } else if (dlist_length(l) >= 3) {
-               return sql_error(sql, 02, SQLSTATE(42000) "TODO: column names 
of level >= 3");
+                               return sql_error(sql, 02, SQLSTATE(42S22) 
"SELECT: cannot use non GROUP BY column '%s%s%s.%s' in query results without an 
aggregate function", depth2 ? "" : sname, depth2 ? "" : ".", tname, cname);
+                       return sql_error(sql, 02, SQLSTATE(42S22) "SELECT: no 
such column '%s%s%s.%s'", depth2 ? "" : sname, depth2 ? "" : ".", tname, cname);
+               }
+       } else if (dlist_length(l) > 3) {
+               assert(0);
        }
        return exp;
 }
@@ -4161,7 +4163,7 @@ rel_order_by_simple_column_exp(mvc *sql,
                char *tname = l->h->data.sval;
                char *name = l->h->next->data.sval;
 
-               e = rel_bind_column2(sql, r, tname, name, sql_sel | 
sql_orderby);
+               e = rel_bind_column23(sql, r, NULL, tname, name, sql_sel | 
sql_orderby);
        }
        if (!e) {
                /* now we need to rewrite r
@@ -5179,7 +5181,7 @@ rel_value_exp2(mvc *sql, sql_rel **rel, 
                                                sql_exp *ne = NULL;
 
                                                if (e->l && e->r)
-                                                       ne = 
rel_bind_column2(sql, r, e->l, e->r, 0);
+                                                       ne = 
rel_bind_column23(sql, r, NULL, e->l, e->r, 0);
                                                else if (!e->l && e->r && /* 
DISABLES CODE */ (0)) {
                                                        ne = 
rel_bind_column(sql, r, e->r, 0);
                                                }
diff --git a/sql/test/miscellaneous/Tests/All b/sql/test/miscellaneous/Tests/All
--- a/sql/test/miscellaneous/Tests/All
+++ b/sql/test/miscellaneous/Tests/All
@@ -3,3 +3,4 @@ declared_tables
 trace_test
 simple_selects
 groupby_expressions
+three_level_lookup
diff --git a/sql/test/miscellaneous/Tests/three_level_lookup.sql 
b/sql/test/miscellaneous/Tests/three_level_lookup.sql
new file mode 100644
--- /dev/null
+++ b/sql/test/miscellaneous/Tests/three_level_lookup.sql
@@ -0,0 +1,11 @@
+start transaction;
+create schema testme;
+create table sys.testme (aa int);
+create table testme.testme (aa int);
+insert into sys.testme values (1), (2), (3);
+insert into testme.testme values (4), (12);
+select sys.testme.aa from sys.testme;
+select testme.testme.aa from testme.testme;
+select sys.testme.aa, testme.testme.aa from sys.testme, testme.testme;
+select count(testme.testme.aa) from sys.testme, testme.testme where 
sys.testme.aa = 1;
+rollback;
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to