Changeset: 431e1b9348a1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/431e1b9348a1
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/test/SQLancer/Tests/sqlancer17.test
Branch: default
Log Message:

Defensive lines to bind attribute expressions, fixes sqlancer crash


diffs (192 lines):

diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -1678,11 +1678,13 @@ rel_find_exp_and_corresponding_rel_(sql_
                                        ne = e;
                        } else if (rel_base_bind_column_(rel, e->r))
                                ne = e;
-               } else if (rel->exps && (is_project(rel->op) || 
is_base(rel->op))) {
+               } else if ((!list_empty(rel->exps) && (is_project(rel->op) || 
is_base(rel->op))) ||
+                                       (!list_empty(rel->attr) && 
is_join(rel->op))) {
+                       list *l = rel->attr ? rel->attr : rel->exps; 
                        if (e->l) {
-                               ne = exps_bind_column2(rel->exps, e->l, e->r, 
NULL);
+                               ne = exps_bind_column2(l, e->l, e->r, NULL);
                        } else {
-                               ne = exps_bind_column(rel->exps, e->r, NULL, 
NULL, 1);
+                               ne = exps_bind_column(l, e->r, NULL, NULL, 1);
                        }
                }
                if (ne && res)
@@ -1745,8 +1747,6 @@ rel_find_exp_and_corresponding_rel(sql_r
                        ne = rel_find_exp_and_corresponding_rel(rel->l, e, 
subexp, res, under_join);
                        if (!ne && is_join(rel->op))
                                ne = rel_find_exp_and_corresponding_rel(rel->r, 
e, subexp, res, under_join);
-                       if (ne && under_join && is_join(rel->op))
-                               *under_join = true;
                        break;
                case op_table:
                case op_basetable:
@@ -1756,6 +1756,8 @@ rel_find_exp_and_corresponding_rel(sql_r
                                ne = rel_find_exp_and_corresponding_rel(rel->l, 
e, subexp, res, under_join);
                }
        }
+       if (ne && under_join && is_join(rel->op))
+               *under_join = true;
        return ne;
 }
 
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
@@ -124,6 +124,12 @@ name_find_column( sql_rel *rel, const ch
        case op_anti:
                if (!c)
                        c = name_find_column( rel->l, rname, name, pnr, bt);
+               if (!c && !list_empty(rel->attr)) {
+                       if (rname)
+                               alias = exps_bind_column2(rel->attr, rname, 
name, NULL);
+                       else
+                               alias = exps_bind_column(rel->attr, name, NULL, 
NULL, 1);
+               }
                return c;
        case op_select:
        case op_topn:
@@ -169,7 +175,7 @@ name_find_column( sql_rel *rel, const ch
        case op_merge:
                break;
        }
-       if (alias) { /* we found an expression with the correct name, but
+       if (alias && !is_join(rel->op)) { /* we found an expression with the 
correct name, but
                        we need sql_columns */
                if (rel->l && alias->type == e_column) /* real alias */
                        return name_find_column(rel->l, alias->l, alias->r, 
pnr, bt);
@@ -1204,6 +1210,8 @@ exp_rename(mvc *sql, sql_exp *e, sql_rel
 {
        sql_exp *ne = NULL;
 
+       assert(is_project(f->op));
+
        switch(e->type) {
        case e_column:
                if (e->l) {
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
@@ -336,6 +336,11 @@ rel_bind_column( mvc *sql, sql_rel *rel,
                        if (e1 && e2 && !is_dependent(rel))
                                return sql_error(sql, ERR_AMBIGUOUS, 
SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
                }
+               if (!e1 && !e2 && !list_empty(rel->attr)) {
+                       e1 = exps_bind_column(rel->attr, cname, &ambiguous, 
&multi, no_tname);
+                       if (ambiguous || multi)
+                               return sql_error(sql, ERR_AMBIGUOUS, 
SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
+               }
                res = e1 ? e1 : e2;
                if (res)
                        set_not_unique(res);
@@ -417,6 +422,12 @@ rel_bind_column2( mvc *sql, sql_rel *rel
                        if (e && (is_left(rel->op) || is_full(rel->op)))
                                set_has_nil(e);
                }
+               if (!e && !list_empty(rel->attr)) {
+                       e = exps_bind_column2(rel->attr, tname, cname, &multi);
+                       if (multi)
+                               return sql_error(sql, ERR_AMBIGUOUS, 
SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
+                                                                tname, cname);
+               }
                if (e)
                        set_not_unique(e);
                return e;
@@ -1088,6 +1099,12 @@ rel_bind_path_(mvc *sql, sql_rel *rel, s
                found = rel_bind_path_(sql, rel->r, e, path);
                if (!found)
                        found = rel_bind_path_(sql, rel->l, e, path);
+               if (!found && !list_empty(rel->attr)) {
+                       if (e->l && exps_bind_column2(rel->attr, e->l, e->r, 
NULL))
+                               found = 1;
+                       if (!found && !e->l && exps_bind_column(rel->attr, 
e->r, NULL, NULL, 1))
+                               found = 1;
+               }
                break;
        case op_semi:
        case op_anti:
@@ -1487,20 +1504,27 @@ rel_add_identity2(mvc *sql, sql_rel *rel
        return _rel_add_identity(sql, rel, exp);
 }
 
+static sql_exp *
+rel_find_column_(sql_allocator *sa, list *exps, const char *tname, const char 
*cname)
+{
+       int ambiguous = 0, multi = 0;
+       sql_exp *e = exps_bind_column2(exps, tname, cname, &multi);
+       if (!e && cname[0] == '%' && !tname)
+               e = exps_bind_column(exps, cname, &ambiguous, &multi, 0);
+       if (e && !ambiguous && !multi)
+               return exp_alias(sa, exp_relname(e), exp_name(e), 
exp_relname(e), cname, exp_subtype(e), e->card, has_nil(e), is_unique(e), 
is_intern(e));
+       return NULL;
+}
+
 sql_exp *
-rel_find_column( sql_allocator *sa, sql_rel *rel, const char *tname, const 
char *cname )
+rel_find_column(sql_allocator *sa, sql_rel *rel, const char *tname, const char 
*cname )
 {
+       sql_exp *e = NULL;
+
        if (!rel)
                return NULL;
-
-       if (rel->exps && (is_project(rel->op) || is_base(rel->op))) {
-               int ambiguous = 0, multi = 0;
-               sql_exp *e = exps_bind_column2(rel->exps, tname, cname, &multi);
-               if (!e && cname[0] == '%' && !tname)
-                       e = exps_bind_column(rel->exps, cname, &ambiguous, 
&multi, 0);
-               if (e && !ambiguous && !multi)
-                       return exp_alias(sa, exp_relname(e), exp_name(e), 
exp_relname(e), cname, exp_subtype(e), e->card, has_nil(e), is_unique(e), 
is_intern(e));
-       }
+       if (rel->exps && (is_project(rel->op) || is_base(rel->op)) && (e = 
rel_find_column_(sa, rel->exps, tname, cname)))
+               return e;
        if ((is_simple_project(rel->op) || is_groupby(rel->op)) && rel->l) {
                if (!is_processed(rel))
                        return rel_find_column(sa, rel->l, tname, cname);
@@ -1508,7 +1532,7 @@ rel_find_column( sql_allocator *sa, sql_
                assert(is_processed(rel));
                return NULL;
        } else if (is_join(rel->op)) {
-               sql_exp *e = rel_find_column(sa, rel->l, tname, cname);
+               e = rel_find_column(sa, rel->l, tname, cname);
 
                if (e && (is_right(rel->op) || is_full(rel->op)))
                        set_has_nil(e);
@@ -1517,6 +1541,8 @@ rel_find_column( sql_allocator *sa, sql_
                        if (e && (is_left(rel->op) || is_full(rel->op)))
                                set_has_nil(e);
                }
+               if (!e && !list_empty(rel->attr))
+                       e = rel_find_column_(sa, rel->attr, tname, cname);
                if (e)
                        set_not_unique(e);
                return e;
diff --git a/sql/test/SQLancer/Tests/sqlancer17.test 
b/sql/test/SQLancer/Tests/sqlancer17.test
--- a/sql/test/SQLancer/Tests/sqlancer17.test
+++ b/sql/test/SQLancer/Tests/sqlancer17.test
@@ -566,6 +566,19 @@ statement ok
 START TRANSACTION
 
 statement ok
+CREATE TABLE t2 (c0 VARCHAR(217))
+
+query I nosort
+SELECT 1 FROM t2 WHERE (SELECT tx.c0 = ANY(SELECT 'a' FROM t2) FROM t2 AS tx)
+----
+
+statement ok
+ROLLBACK
+
+statement ok
+START TRANSACTION
+
+statement ok
 CREATE TABLE "rt0" ("c0" REAL,"c1" DECIMAL(18,3))
 
 statement ok
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to