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