Changeset: 73a544cd77f8 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=73a544cd77f8
Modified Files:
        sql/server/rel_select.c
        sql/server/rel_select.h
        sql/server/rel_updates.c
        sql/test/miscellaneous/Tests/update_delete_aliases.stable.err
Branch: Oct2020
Log Message:

More scalable solution for sqlancer07 issue. Instead of calculating the 
distinct relation names, pass the existing list of table references under 
table_ref. Later at the end of possible sub-relation build, test for a 
duplicate name on the list


diffs (truncated from 478 to 300 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
@@ -153,11 +153,11 @@ rel_orderby(mvc *sql, sql_rel *l)
 
 /* forward refs */
 static sql_rel * rel_setquery(sql_query *query, symbol *sq);
-static sql_rel * rel_joinquery(sql_query *query, sql_rel *rel, symbol *sq);
-static sql_rel * rel_crossquery(sql_query *query, sql_rel *rel, symbol *q);
+static sql_rel * rel_joinquery(sql_query *query, sql_rel *rel, symbol *sq, 
list *refs);
+static sql_rel * rel_crossquery(sql_query *query, sql_rel *rel, symbol *q, 
list *refs);
 
 static sql_rel *
-rel_table_optname(mvc *sql, sql_rel *sq, symbol *optname)
+rel_table_optname(mvc *sql, sql_rel *sq, symbol *optname, list *refs)
 {
        sql_rel *osq = sq;
        node *ne;
@@ -206,6 +206,11 @@ rel_table_optname(mvc *sql, sql_rel *sq,
                                }
                        }
                }
+               if (refs) { /* if this relation is under a FROM clause, check 
for duplicate names */
+                       if (list_find(refs, tname, (fcmp) &strcmp))
+                               return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: relation name \"%s\" specified more than once", tname);
+                       list_append(refs, tname);
+               }
        } else {
                if (!is_project(sq->op) || is_topn(sq->op) || is_sample(sq->op) 
|| ((is_simple_project(sq->op) || is_groupby(sq->op)) && sq->r)) {
                        sq = rel_project(sql->sa, sq, rel_projections(sql, sq, 
NULL, 1, 1));
@@ -222,7 +227,7 @@ rel_table_optname(mvc *sql, sql_rel *sq,
 }
 
 static sql_rel *
-rel_subquery_optname(sql_query *query, sql_rel *rel, symbol *ast)
+rel_subquery_optname(sql_query *query, sql_rel *rel, symbol *ast, list *refs)
 {
        mvc *sql = query->sql;
        SelectNode *sn = (SelectNode *) ast;
@@ -233,7 +238,7 @@ rel_subquery_optname(sql_query *query, s
        if (!sq)
                return NULL;
 
-       return rel_table_optname(sql, sq, sn->name);
+       return rel_table_optname(sql, sq, sn->name, refs);
 }
 
 sql_rel *
@@ -297,7 +302,7 @@ rel_with_query(sql_query *query, symbol 
 }
 
 static sql_rel *
-query_exp_optname(sql_query *query, sql_rel *r, symbol *q)
+query_exp_optname(sql_query *query, sql_rel *r, symbol *q, list *refs)
 {
        mvc *sql = query->sql;
        switch (q->token) {
@@ -308,34 +313,35 @@ query_exp_optname(sql_query *query, sql_
                if (!tq)
                        return NULL;
                if (q->data.lval->t->type == type_symbol)
-                       return rel_table_optname(sql, tq, 
q->data.lval->t->data.sym);
+                       return rel_table_optname(sql, tq, 
q->data.lval->t->data.sym, refs);
                return tq;
        }
        case SQL_UNION:
        case SQL_EXCEPT:
        case SQL_INTERSECT:
        {
+               /* subqueries will be called, ie no need to test for duplicate 
references */
                sql_rel *tq = rel_setquery(query, q);
 
                if (!tq)
                        return NULL;
-               return rel_table_optname(sql, tq, q->data.lval->t->data.sym);
+               return rel_table_optname(sql, tq, q->data.lval->t->data.sym, 
NULL);
        }
        case SQL_JOIN:
        {
-               sql_rel *tq = rel_joinquery(query, r, q);
+               sql_rel *tq = rel_joinquery(query, r, q, refs);
 
                if (!tq)
                        return NULL;
-               return rel_table_optname(sql, tq, q->data.lval->t->data.sym);
+               return rel_table_optname(sql, tq, q->data.lval->t->data.sym, 
NULL);
        }
        case SQL_CROSS:
        {
-               sql_rel *tq = rel_crossquery(query, r, q);
+               sql_rel *tq = rel_crossquery(query, r, q, refs);
 
                if (!tq)
                        return NULL;
-               return rel_table_optname(sql, tq, q->data.lval->t->data.sym);
+               return rel_table_optname(sql, tq, q->data.lval->t->data.sym, 
NULL);
        }
        default:
                (void) sql_error(sql, 02, SQLSTATE(42000) "case %d %s", (int) 
q->token, token2string(q->token));
@@ -532,7 +538,7 @@ find_table_function(mvc *sql, sql_schema
 }
 
 static sql_rel *
-rel_named_table_function(sql_query *query, sql_rel *rel, symbol *ast, int 
lateral)
+rel_named_table_function(sql_query *query, sql_rel *rel, symbol *ast, int 
lateral, list *refs)
 {
        mvc *sql = query->sql;
        list *exps = NULL, *tl;
@@ -637,8 +643,13 @@ rel_named_table_function(sql_query *quer
                append(exps, e);
        }
        rel = rel_table_func(sql->sa, rel, e, exps, 
(sq)?TABLE_FROM_RELATION:TABLE_PROD_FUNC);
-       if (ast->data.lval->h->next->data.sym && 
ast->data.lval->h->next->data.sym->data.lval->h->next->data.lval)
-               rel = rel_table_optname(sql, rel, 
ast->data.lval->h->next->data.sym);
+       if (ast->data.lval->h->next->data.sym && 
ast->data.lval->h->next->data.sym->data.lval->h->next->data.lval) {
+               rel = rel_table_optname(sql, rel, 
ast->data.lval->h->next->data.sym, refs);
+       } else if (refs) { /* if this relation is under a FROM clause, check 
for duplicate names */
+               if (list_find(refs, tname, (fcmp) &strcmp))
+                       return sql_error(sql, 02, SQLSTATE(42000) "SELECT: 
relation name \"%s\" specified more than once", tname);
+               list_append(refs, tname);
+       }
        return rel;
 }
 
@@ -764,7 +775,7 @@ tuples_check_types(mvc *sql, list *tuple
 }
 
 static sql_rel *
-rel_values(sql_query *query, symbol *tableref)
+rel_values(sql_query *query, symbol *tableref, list *refs)
 {
        mvc *sql = query->sql;
        sql_rel *r = NULL;
@@ -818,7 +829,7 @@ rel_values(sql_query *query, symbol *tab
        r = rel_project(sql->sa, NULL, exps);
        r->nrcols = list_length(exps);
        r->card = card;
-       return rel_table_optname(sql, r, optname);
+       return rel_table_optname(sql, r, optname, refs);
 }
 
 static int
@@ -858,7 +869,7 @@ rel_reduce_on_column_privileges(mvc *sql
 }
 
 sql_rel *
-table_ref(sql_query *query, sql_rel *rel, symbol *tableref, int lateral)
+table_ref(sql_query *query, sql_rel *rel, symbol *tableref, int lateral, list 
*refs)
 {
        mvc *sql = query->sql;
        char *tname = NULL;
@@ -958,17 +969,22 @@ table_ref(sql_query *query, sql_rel *rel
                        if (!res)
                                return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: access denied for %s to table '%s.%s'", 
sqlvar_get_string(find_global_var(sql, mvc_bind_schema(sql, "sys"), 
"current_user")), s->base.name, tname);
                }
-               if (tableref->data.lval->h->next->data.sym && 
tableref->data.lval->h->next->data.sym->data.lval->h->next->data.lval) /* AS 
with column aliases */
-                       res = rel_table_optname(sql, res, 
tableref->data.lval->h->next->data.sym);
+               if (tableref->data.lval->h->next->data.sym && 
tableref->data.lval->h->next->data.sym->data.lval->h->next->data.lval) { /* AS 
with column aliases */
+                       res = rel_table_optname(sql, res, 
tableref->data.lval->h->next->data.sym, refs);
+               } else if (refs) { /* if this relation is under a FROM clause, 
check for duplicate names */
+                       if (list_find(refs, tname, (fcmp) &strcmp))
+                               return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: relation name \"%s\" specified more than once", tname);
+                       list_append(refs, tname);
+               }
                return res;
        } else if (tableref->token == SQL_VALUES) {
-               return rel_values(query, tableref);
+               return rel_values(query, tableref, refs);
        } else if (tableref->token == SQL_TABLE) {
-               return rel_named_table_function(query, rel, tableref, lateral);
+               return rel_named_table_function(query, rel, tableref, lateral, 
refs);
        } else if (tableref->token == SQL_SELECT) {
-               return rel_subquery_optname(query, rel, tableref);
+               return rel_subquery_optname(query, rel, tableref, refs);
        } else {
-               return query_exp_optname(query, rel, tableref);
+               return query_exp_optname(query, rel, tableref, refs);
        }
 }
 
@@ -4933,7 +4949,7 @@ rel_value_exp2(sql_query *query, sql_rel
                if (se->token == SQL_WITH) {
                        r = rel_with_query(query, se);
                } else if (se->token == SQL_VALUES) {
-                       r = rel_values(query, se);
+                       r = rel_values(query, se, NULL);
                } else {
                        assert(se->token == SQL_SELECT);
                        r = rel_subquery(query, NULL, se, ek);
@@ -5105,7 +5121,7 @@ rel_table_exp(sql_query *query, sql_rel 
 
                if (!is_project((*rel)->op))
                        return NULL;
-               r = rel_named_table_function( query, (*rel)->l, column_e, 0);
+               r = rel_named_table_function(query, (*rel)->l, column_e, 0, 
NULL);
                if (!r)
                        return NULL;
                *rel = r;
@@ -5460,15 +5476,6 @@ rel_unique_names(mvc *sql, sql_rel *rel)
        return rel;
 }
 
-static int
-exp_relname_cmp(sql_exp *e1, sql_exp *e2)
-{
-       const char *r1 = exp_relname(e1), *r2 = exp_relname(e2);
-       if (!r1 || !r2)
-               return -1;
-       return strcmp(r1, r2);
-}
-
 static sql_rel *
 rel_query(sql_query *query, sql_rel *rel, symbol *sq, int toplevel, exp_kind 
ek)
 {
@@ -5477,7 +5484,7 @@ rel_query(sql_query *query, sql_rel *rel
        SelectNode *sn = NULL;
 
        if (sq->token != SQL_SELECT)
-               return table_ref(query, rel, sq, 0);
+               return table_ref(query, rel, sq, 0, NULL);
 
        /* select ... into is currently not handled here ! */
        sn = (SelectNode *) sq;
@@ -5501,43 +5508,27 @@ rel_query(sql_query *query, sql_rel *rel
                }
        }
 
-       if (sn->from) {         /* keep variable list with tables and names */
+       if (sn->from) {
                dlist *fl = sn->from->data.lval;
                sql_rel *fnd = NULL;
-               list *names = new_exp_list(sql->sa);
+               list *refs = new_exp_list(sql->sa); /* Keep list of relation 
names in order to test for duplicates */
 
                for (dnode *n = fl->h; n ; n = n->next) {
                        int lateral = check_is_lateral(n->data.sym);
-                       list *projs, *projs_distinct_names;
 
                        /* just used current expression */
-                       fnd = table_ref(query, NULL, n->data.sym, lateral);
+                       fnd = table_ref(query, NULL, n->data.sym, lateral, 
refs);
                        if (!fnd && res && lateral && sql->session->status != 
-ERR_AMBIGUOUS) {
                                /* reset error */
                                sql->session->status = 0;
                                sql->errstr[0] = 0;
 
                                query_push_outer(query, res, sql_from);
-                               fnd = table_ref(query, NULL, n->data.sym, 
lateral);
+                               fnd = table_ref(query, NULL, n->data.sym, 
lateral, refs);
                                res = query_pop_outer(query);
                        }
                        if (!fnd)
                                break;
-                       projs = rel_projections(sql, fnd, NULL, 1, 0);
-                       projs_distinct_names = list_distinct(projs, (fcmp) 
exp_relname_cmp, (fdup) NULL);
-
-                       for (node *m = projs_distinct_names->h ; m ; m = 
m->next) {
-                               char *nrame = (char *)exp_relname((sql_exp 
*)m->data);
-
-                               if (nrame) {
-                                       if (list_find(names, nrame, (fcmp) 
&strcmp)) {
-                                               if (res)
-                                                       rel_destroy(res);
-                                               return sql_error(sql, 01, 
SQLSTATE(42000) "SELECT: relation name \"%s\" specified more than once", nrame);
-                                       } else
-                                               list_append(names, nrame);
-                               }
-                       }
                        if (res) {
                                res = rel_crossproduct(sql->sa, res, fnd, 
op_join);
                                if (lateral)
@@ -5598,10 +5589,10 @@ rel_setquery(sql_query *query, symbol *q
        sql_rel *t1, *t2;
 
        assert(n->next->type == type_int);
-       t1 = table_ref(query, NULL, tab_ref1, 0);
+       t1 = table_ref(query, NULL, tab_ref1, 0, NULL);
        if (!t1)
                return NULL;
-       t2 = table_ref(query, NULL, tab_ref2, 0);
+       t2 = table_ref(query, NULL, tab_ref2, 0, NULL);
        if (!t2)
                return NULL;
 
@@ -5636,7 +5627,7 @@ rel_setquery(sql_query *query, symbol *q
 }
 
 static sql_rel *
-rel_joinquery_(sql_query *query, sql_rel *rel, symbol *tab1, int natural, jt 
jointype, symbol *tab2, symbol *js)
+rel_joinquery_(sql_query *query, sql_rel *rel, symbol *tab1, int natural, jt 
jointype, symbol *tab2, symbol *js, list *refs)
 {
        mvc *sql = query->sql;
        operator_type op = op_join;
@@ -5660,22 +5651,22 @@ rel_joinquery_(sql_query *query, sql_rel
        }
 
        lateral = check_is_lateral(tab2);
-       t1 = table_ref(query, NULL, tab1, 0);
+       t1 = table_ref(query, NULL, tab1, 0, NULL);
        if (rel && !t1 && sql->session->status != -ERR_AMBIGUOUS) {
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to