Changeset: cd9001283c0d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=cd9001283c0d
Modified Files:
        sql/server/rel_exp.c
        sql/test/SQLancer/Tests/sqlancer07.sql
        sql/test/SQLancer/Tests/sqlancer07.stable.out
Branch: octbugs
Log Message:

Fix for crashing SQLancer query, when updating a relation expression column 
references, do it recursively, because they may be behind expressions such as 
conversions


diffs (167 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
@@ -1929,18 +1929,16 @@ exp_is_atom( sql_exp *e )
                return exp_is_atom(e->l);
        case e_func:
        case e_aggr:
-       {
-               int r = (e->card == CARD_ATOM);
-               node *n;
-               list *l = e->l;
-
-               if (r && l)
-                       for (n = l->h; n && r; n = n->next)
-                               r &= exp_is_atom(n->data);
-               return r;
-       }
+               return e->card == CARD_ATOM && exps_are_atoms(e->l);
+       case e_cmp:
+               if (e->card != CARD_ATOM)
+                       return 0;
+               if (e->flag == cmp_or || e->flag == cmp_filter)
+                       return exps_are_atoms(e->l) && exps_are_atoms(e->r);
+               if (e->flag == cmp_in || e->flag == cmp_notin)
+                       return exp_is_atom(e->l) && exps_are_atoms(e->r);
+               return exp_is_atom(e->l) && exp_is_atom(e->r) && (!e->f || 
exp_is_atom(e->f));
        case e_column:
-       case e_cmp:
        case e_psm:
                return 0;
        }
@@ -2060,6 +2058,56 @@ exp_rel_get_rel(sql_allocator *sa, sql_e
        return NULL;
 }
 
+static void exp_rel_update_set_freevar(sql_exp *e);
+
+static void
+exps_rel_update_set_freevar(list *exps)
+{
+       if (!list_empty(exps))
+               for (node *n=exps->h; n ; n=n->next)
+                       exp_rel_update_set_freevar(n->data);
+}
+
+static void
+exp_rel_update_set_freevar(sql_exp *e)
+{
+       if (!e)
+               return ;
+
+       switch(e->type){
+       case e_func:
+       case e_aggr:
+               exps_rel_update_set_freevar(e->l);
+               break;
+       case e_cmp:
+               if (e->flag == cmp_or || e->flag == cmp_filter) {
+                       exps_rel_update_set_freevar(e->l);
+                       exps_rel_update_set_freevar(e->r);
+               } else if (e->flag == cmp_in || e->flag == cmp_notin) {
+                       exp_rel_update_set_freevar(e->l);
+                       exps_rel_update_set_freevar(e->r);
+               } else {
+                       exp_rel_update_set_freevar(e->l);
+                       exp_rel_update_set_freevar(e->r);
+                       if (e->f)
+                               exp_rel_update_set_freevar(e->f);
+               }
+               break;
+       case e_convert:
+               exp_rel_update_set_freevar(e->l);
+               break;
+       case e_atom:
+               if (e->f)
+                       exps_rel_update_set_freevar(e->f);
+               break;
+       case e_column:
+               set_freevar(e, 1);
+               break;
+       case e_psm:
+               break;
+       }
+}
+
 static list *
 exp_rel_update_exps(mvc *sql, list *exps)
 {
@@ -2071,7 +2119,7 @@ exp_rel_update_exps(mvc *sql, list *exps
                if (exp_has_rel(e))
                        n->data = exp_rel_update_exp(sql, e);
                else if (!exp_is_atom(e))
-                       set_freevar(e,1);
+                       exp_rel_update_set_freevar(e);
        }
        list_hash_clear(exps);
        return exps;
@@ -2086,7 +2134,8 @@ exp_rel_update_exp(mvc *sql, sql_exp *e)
        switch(e->type){
        case e_func:
        case e_aggr:
-               e->l = exp_rel_update_exps(sql, e->l);
+               if (exps_have_rel_exp(e->l))
+                       e->l = exp_rel_update_exps(sql, e->l);
                return e;
        case e_cmp:
                if (e->flag == cmp_or || e->flag == cmp_filter) {
@@ -2109,7 +2158,8 @@ exp_rel_update_exp(mvc *sql, sql_exp *e)
                }
                return e;
        case e_convert:
-               e->l = exp_rel_update_exp(sql, e->l);
+               if (exp_has_rel(e->l))
+                       e->l = exp_rel_update_exp(sql, e->l);
                return e;
        case e_psm:
                if (exp_is_rel(e)) {
@@ -2143,7 +2193,7 @@ int
 exps_are_atoms( list *exps)
 {
        int atoms = 1;
-       if (exps)
+       if (!list_empty(exps))
                for(node *n=exps->h; n && atoms; n=n->next)
                        atoms &= exp_is_atom(n->data);
        return atoms;
diff --git a/sql/test/SQLancer/Tests/sqlancer07.sql 
b/sql/test/SQLancer/Tests/sqlancer07.sql
--- a/sql/test/SQLancer/Tests/sqlancer07.sql
+++ b/sql/test/SQLancer/Tests/sqlancer07.sql
@@ -310,8 +310,10 @@ create view v0(vc0) as (values (interval
 create view v3(vc0) as (select 1638520390);
 create view v4(vc0) as (values (-1548784118));
 
-SELECT 1 FROM (select 2) v4(vc0) WHERE (0.6) IN (CASE WHEN v4.vc0 THEN (SELECT 
0.2 WHERE TRUE) END);
+SELECT 1 FROM (SELECT 2) v4(vc0) WHERE (0.6) IN (CASE WHEN v4.vc0 THEN (SELECT 
0.2 WHERE TRUE) END);
        -- empty
+SELECT 1 FROM (SELECT 1) as v3(c0) RIGHT JOIN (SELECT 2) as v4(c0) ON (0.6) 
NOT IN (0.5, (SELECT 0.2));
+       -- 1
 SELECT FALSE FROM v3, v0 FULL OUTER JOIN v4 ON sql_max(FALSE, (0.6902854) NOT 
IN (0.5854332103580835, CASE WHEN v4.vc0 THEN (SELECT 0.023816515 WHERE TRUE) 
END));
        -- False
 ROLLBACK;
diff --git a/sql/test/SQLancer/Tests/sqlancer07.stable.out 
b/sql/test/SQLancer/Tests/sqlancer07.stable.out
--- a/sql/test/SQLancer/Tests/sqlancer07.stable.out
+++ b/sql/test/SQLancer/Tests/sqlancer07.stable.out
@@ -445,6 +445,22 @@ stdout of test 'sqlancer07` in directory
 % 1 # length
 [ 0    ]
 #ROLLBACK;
+#START TRANSACTION;
+#create view v0(vc0) as (values (interval '100' second));
+#create view v3(vc0) as (select 1638520390);
+#create view v4(vc0) as (values (-1548784118));
+#SELECT 1 FROM (select 2) v4(vc0) WHERE (0.6) IN (CASE WHEN v4.vc0 THEN 
(SELECT 0.2 WHERE TRUE) END);
+% .%10 # table_name
+% %10 # name
+% tinyint # type
+% 1 # length
+#SELECT FALSE FROM v3, v0 FULL OUTER JOIN v4 ON sql_max(FALSE, (0.6902854) NOT 
IN (0.5854332103580835, CASE WHEN v4.vc0 THEN (SELECT 0.023816515 WHERE TRUE) 
END));
+% .%16 # table_name
+% %16 # name
+% boolean # type
+% 5 # length
+[ false        ]
+#ROLLBACK;
 
 # 10:16:14 >  
 # 10:16:14 >  "Done."
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to