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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list