Changeset: ed47c5d014b3 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/ed47c5d014b3
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_optimize_others.c
        sql/server/rel_optimize_proj.c
        sql/server/rel_select.c
        sql/server/rel_unnest.c
        sql/test/BugTracker-2023/Tests/misc-crashes-7390.test
        sql/test/BugTracker-2026/Tests/7833-assertion-failure.test
        sql/test/BugTracker-2026/Tests/7843-assertion-failure.test
        sql/test/BugTracker-2026/Tests/7845-assertion-failure.test
        
sql/test/BugTracker-2026/Tests/7846-do_covariance_and_correlation-crash.test
        sql/test/BugTracker-2026/Tests/7847-assertion-failure.test
        sql/test/BugTracker-2026/Tests/7849-assertion-failure.test
        sql/test/BugTracker-2026/Tests/All
        sql/test/Dependencies/Tests/dependency_DBobjects.test
        sql/test/Dependencies/Tests/dependency_owner_schema_3.test
        sql/test/emptydb/Tests/check.stable.out
        sql/test/emptydb/Tests/check.stable.out.32bit
        sql/test/emptydb/Tests/check.stable.out.int128
        sql/test/sql_dump/Tests/dump.test
        sql/test/subquery/Tests/subquery5.test
Branch: Dec2025
Log Message:

fixed exp_has_aggr, properly detect aggr function in compare expression
fixed exp_push_down_prj, properly find expression in group by list (not 
projection list)
fixed simplify_groupby_columns, properly add (simplified) expression to the 
projection list
of a lower projection when needed (skipping over selects inbetween)
fixed rel_order_by, make copy of expression, don't directly reuse expression 
(would later lead to use after free)
fixed push_up_project_exp, when replacing an expression with an inner one, keep 
the freevar st
atus.
fixed push_up_join, in case of push up of group joins, directly reorder the 
joins.
fixed rel_unnest_dependent, removed blind reorder of op_right into op_left
fixed rewrite_ifthenelse, no longer needed, handled by later rewrites.

Solving issues #7781, #7791, #7793, #7794, #7795, #7797, #7800, #7801, #7833, 
#7843, #7845, #7
846, #7847, #7848, #7849, #7850 and #7851


diffs (truncated from 550 to 300 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
@@ -2296,8 +2296,6 @@ exp_has_aggr(sql_rel *r, sql_exp *e )
        case e_aggr:
                return true;
        case e_cmp:
-               if (e->card != CARD_ATOM)
-                       return false;
                if (e->flag == cmp_filter)
                        return exps_have_aggr(r, e->l) && exps_have_aggr(r, 
e->r);
                if (e->flag == cmp_con || e->flag == cmp_dis)
diff --git a/sql/server/rel_optimize_others.c b/sql/server/rel_optimize_others.c
--- a/sql/server/rel_optimize_others.c
+++ b/sql/server/rel_optimize_others.c
@@ -117,7 +117,7 @@ exp_push_down_prj(mvc *sql, sql_exp *e, 
                if (is_groupby(f->op) && !list_empty(f->r) && ne->type == 
e_column) {
                        sql_exp *gbe = NULL;
                        if (ne->nid)
-                               gbe = exps_bind_nid(f->exps, ne->nid);
+                               gbe = exps_bind_nid(f->r, ne->nid);
                        ne = gbe;
                        if (!ne || (ne->type != e_column && (ne->type != e_atom 
|| ne->f)))
                                return NULL;
diff --git a/sql/server/rel_optimize_proj.c b/sql/server/rel_optimize_proj.c
--- a/sql/server/rel_optimize_proj.c
+++ b/sql/server/rel_optimize_proj.c
@@ -1523,8 +1523,12 @@ static inline sql_rel *
 rel_simplify_groupby_columns(visitor *v, sql_rel *rel)
 {
        if (is_groupby(rel->op) && !list_empty(rel->r)) {
-               sql_rel *l = rel->l;
-
+               sql_rel *l = rel->l, *p = rel;
+
+               if (l && is_select(l->op)) {
+                       p = l;
+                       l = l->l;
+               }
                for (node *n=((list*)rel->r)->h; n ; n = n->next) {
                        sql_exp *e = n->data;
                        e->used = 0; /* we need to use this flag, clean it 
first */
@@ -1597,7 +1601,7 @@ rel_simplify_groupby_columns(visitor *v,
                                                if (!has_label(e)) /* dangerous 
to merge, skip it */
                                                        continue;
                                                if (!is_simple_project(l->op) 
|| !list_empty(l->r) || rel_is_ref(l) || need_distinct(l))
-                                                       rel->l = l = 
rel_project(v->sql->sa, l, rel_projections(v->sql, l, NULL, 1, 1));
+                                                       p->l = l = 
rel_project(v->sql->sa, l, rel_projections(v->sql, l, NULL, 1, 1));
                                                list_append(l->exps, e);
                                                n->data = e = exp_ref(v->sql, 
e);
                                                list_hash_clear(rel->r);
@@ -1628,7 +1632,7 @@ rel_simplify_groupby_columns(visitor *v,
                                                        if (colf) /* a col 
reference is already there, add a new label */
                                                                
exp_label(v->sql->sa, ne, ++v->sql->label);
                                                        if 
(!is_simple_project(l->op) || !list_empty(l->r) || rel_is_ref(l) || 
need_distinct(l))
-                                                               rel->l = l = 
rel_project(v->sql->sa, l, rel_projections(v->sql, l, NULL, 1, 1));
+                                                               p->l = l = 
rel_project(v->sql->sa, l, rel_projections(v->sql, l, NULL, 1, 1));
                                                        list_append(l->exps, 
ne);
                                                        n->data = 
exp_ref(v->sql, ne);
                                                }
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
@@ -4742,6 +4742,8 @@ rel_order_by(sql_query *query, sql_rel *
                                        }
                                        if (!is_freevar(e) && 
!(is_sql_window(f) && exp_is_atom(e)))
                                                e = exp_ref(sql, e);
+                                       else
+                                               e = exp_copy(sql, e);
                                }
                        }
 
@@ -5980,6 +5982,8 @@ rel_select_exp(sql_query *query, sql_rel
                                                        atom *a = e->l;
                                                        int nr = 
(int)atom_get_int(a);
                                                        if (nr == 
(list_length(pexps) + 1)) {
+                                                               if 
(exp_has_aggr(inner, ce))
+                                                                       return 
sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions are not allowed 
in GROUP BY");
                                                                n->data = ce;
                                                                ce = 
exp_ref(sql, ce);
                                                                ce->card = 
CARD_AGGR;
diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c
--- a/sql/server/rel_unnest.c
+++ b/sql/server/rel_unnest.c
@@ -599,6 +599,7 @@ push_up_project_exp(mvc *sql, sql_rel *r
                                        e->l = ne->l;
                                        e->r = ne->r;
                                        e->nid = ne->nid;
+                                       e->freevar = ne->freevar;
                                } else {
                                        ne = exp_copy(sql, ne);
                                        return push_up_project_exp(sql, rel, 
ne);
@@ -1428,6 +1429,8 @@ bind_join_vars(mvc *sql, sql_rel *rel)
        }
 }
 
+static sql_rel * rel_unnest_dependent(mvc *sql, sql_rel *rel);
+
 static sql_rel * rewrite_outer2inner_union(visitor *v, sql_rel *rel);
 
 static sql_rel *
@@ -1471,6 +1474,19 @@ push_up_join(mvc *sql, sql_rel *rel, lis
                                list *attr = j->attr?exps_copy(sql, 
j->attr):NULL;
                                int single = is_single(j);
 
+                               if (attr && exps_uses_exp(rel->exps, 
attr->h->data)) {
+                                       if (!rel_is_ref(rel) && !rel_is_ref(j) 
&&
+                                               rel->op == op_left && j->op == 
op_left) {
+
+                                               j->l = rel->l;
+                                               rel->l = jl;
+                                               set_dependent(j);
+                                               rel->r = 
rel_unnest_dependent(sql, j);
+                                               return rel;
+                                       }
+                                       assert(0);
+                               }
+
                                rel->r = rel_dup(jl);
                                rel->exps = sa_list(sql->sa);
                                nj = rel_crossproduct(sql->sa, rel_dup(d), 
rel_dup(jr), j->op);
@@ -1654,8 +1670,6 @@ push_up_set(mvc *sql, sql_rel *rel, list
        return rel;
 }
 
-static sql_rel * rel_unnest_dependent(mvc *sql, sql_rel *rel);
-
 static sql_rel *
 push_up_munion(mvc *sql, sql_rel *rel, list *ad)
 {
@@ -1874,14 +1888,8 @@ rel_unnest_dependent(mvc *sql, sql_rel *
                if (rel_has_freevar(sql, l)) {
                        rel->l = rel_unnest_dependent(sql, rel->l);
                        if (rel_has_freevar(sql, rel->l)) {
-                               if (rel->op == op_right) {
-                                       sql_rel *l = rel->l;
-
-                                       rel->l = rel->r;
-                                       rel->r = l;
-                                       rel->op = op_left;
-                                       return rel_unnest_dependent(sql, rel);
-                               } else if (rel->op == op_left && 
list_empty(rel->attr) && !rel_has_freevar(sql, rel->r) && 
rel_dependent_var(sql, rel->r, rel->l)) {
+                               if (rel->op == op_left && list_empty(rel->attr) 
&& !rel_has_freevar(sql, rel->r) && rel_dependent_var(sql, rel->r, rel->l)) {
+assert(0);
                                        sql_rel *l = rel->l;
 
                                        rel->l = rel->r;
@@ -3926,90 +3934,6 @@ rewrite_ifthenelse(visitor *v, sql_rel *
                v->changes++;
                return exp_ref(v->sql, e);
        }
-
-       sql_subfunc *sf;
-       if (e->type != e_func)
-               return e;
-
-       sf = e->f;
-       /* TODO also handle ifthenelse with more than 3 arguments */
-       if (is_case_func(sf) && !list_empty(e->l) && list_length(e->l) == 3) {
-               list *l = e->l;
-
-               /* remove unnecessary = true expressions under ifthenelse */
-               for (node *n = l->h ; n ; n = n->next) {
-                       sql_exp *e = n->data;
-
-                       if (e->type == e_cmp && e->flag == cmp_equal && 
exp_is_true(e) && exp_is_true(e->r)) {
-                               sql_subtype *t = exp_subtype(e->r);
-                               if (t->type->localtype == TYPE_bit)
-                                       n->data = e->l;
-                       }
-               }
-
-               sql_exp *cond = l->h->data;
-               sql_exp *then_exp = l->h->next->data;
-               sql_exp *else_exp = l->h->next->next->data;
-               sql_exp *not_cond;
-
-               if (!exp_has_rel(cond) && (exp_has_rel(then_exp) || 
exp_has_rel(else_exp))) {
-                       if (!rel_has_freevar(v->sql, rel))
-                               return e;
-                       bool single = false;
-                       /* return sql_error(v->sql, 10, SQLSTATE(42000) "time 
to rewrite into union\n");
-                          union(
-                               select(
-                                       project [then]
-                               )[cond]
-                               select(
-                                       project [else]
-                               )[not(cond) or cond is null]
-                         ) [ cols ] */
-                       sql_rel *lsq = NULL, *rsq = NULL, *usq = NULL;
-                       list *urs = sa_list(v->sql->sa);
-
-                       if (exp_has_rel(then_exp)) {
-                               lsq = exp_rel_get_rel(v->sql->sa, then_exp);
-                               then_exp = exp_rel_update_exp(v->sql, then_exp, 
false);
-                               if (is_single(lsq))
-                                       single = true;
-                               reset_single(lsq);
-                       }
-                       exp_set_freevar(v->sql, then_exp, lsq);
-                       exp_label(v->sql->sa, then_exp, ++v->sql->label);
-                       lsq = rel_project(v->sql->sa, lsq, 
append(sa_list(v->sql->sa), then_exp));
-                       exp_set_freevar(v->sql, cond, lsq);
-                       set_processed(lsq);
-                       lsq = rel_select(v->sql->sa, lsq, 
exp_compare(v->sql->sa, cond, exp_atom_bool(v->sql->sa, 1), cmp_equal));
-                       set_processed(lsq);
-                       if (exp_has_rel(else_exp)) {
-                               rsq = exp_rel_get_rel(v->sql->sa, else_exp);
-                               else_exp = exp_rel_update_exp(v->sql, else_exp, 
false);
-                               if (is_single(rsq))
-                                       single = true;
-                               reset_single(rsq);
-                       }
-                       exp_set_freevar(v->sql, else_exp, rsq);
-                       exp_label(v->sql->sa, else_exp, ++v->sql->label);
-                       rsq = rel_project(v->sql->sa, rsq, 
append(sa_list(v->sql->sa), else_exp));
-                       cond = exp_copy(v->sql, cond);
-                       exp_set_freevar(v->sql, cond, rsq);
-                       not_cond = exp_compare(v->sql->sa, cond, 
exp_atom_bool(v->sql->sa, 1), cmp_notequal);
-                       set_semantics(not_cond); /* also compare nulls */
-                       set_processed(rsq);
-                       rsq = rel_select(v->sql->sa, rsq, not_cond);
-                       set_processed(rsq);
-                       urs = append(urs, lsq);
-                       urs = append(urs, rsq);
-                       usq = rel_setop_n_ary(v->sql->sa, urs, op_munion);
-                       rel_setop_n_ary_set_exps(v->sql, usq, 
append(sa_list(v->sql->sa), exp_ref(v->sql, e)), false);
-                       if (single)
-                               set_single(usq);
-                       set_processed(usq);
-                       e = exp_rel(v->sql, usq);
-                       v->changes++;
-               }
-       }
        return e;
 }
 
diff --git a/sql/test/BugTracker-2023/Tests/misc-crashes-7390.test 
b/sql/test/BugTracker-2023/Tests/misc-crashes-7390.test
--- a/sql/test/BugTracker-2023/Tests/misc-crashes-7390.test
+++ b/sql/test/BugTracker-2023/Tests/misc-crashes-7390.test
@@ -400,7 +400,7 @@ INSERT INTO v0 VALUES (-1),(127),(4),(-1
 statement error 42000!SELECT: identifier 'v1' ambiguous
 WITH v0 AS (SELECT -1, * FROM v0) INSERT INTO v0 SELECT v1 * 29 FROM v0 AS v3, 
v0, v0 AS v2, v0 AS v4, v0 ORDER BY v1 * 0 ^ 83
 
-statement ok
+statement error 42000!row frame bound must be non negative and non null.
 UPDATE v0 SET v1 = -1 WHERE CASE WHEN v1 > -1 THEN (SELECT STDDEV_SAMP((18 * 
v1 + (v1 IN (21 , -1)))) OVER (ROWS BETWEEN CURRENT ROW AND v1 - NULL 
FOLLOWING) * 17) > v1 / (SELECT -1 WHERE (88 IN (96))) ELSE 82 END ^ -128 ^ v1
 
 statement ok
diff --git a/sql/test/BugTracker-2026/Tests/7833-assertion-failure.test 
b/sql/test/BugTracker-2026/Tests/7833-assertion-failure.test
--- a/sql/test/BugTracker-2026/Tests/7833-assertion-failure.test
+++ b/sql/test/BugTracker-2026/Tests/7833-assertion-failure.test
@@ -1,4 +1,3 @@
-query II
+statement error Illegal argument
 SELECT 301 AS x , 5 IN ( SELECT 5 FROM ( SELECT 5 UNION SELECT RANK ( ) OVER ( 
) FROM generate_series ( 285 , 298 ) AS x GROUP BY x HAVING NOT x < ANY ( NOT 
MAX ( 561 ) < x * AVG ( x + x ) * x ) ) AS x ) AND 6 IN ( SELECT MAX ( x ) , 
MIN ( x ) , MAX ( x ) , MIN ( x ) , MAX ( x ) , MIN ( x ) LIMIT 0 OFFSET 0 ) 
GROUP BY x , x HAVING x = 1
-----
 
diff --git a/sql/test/BugTracker-2026/Tests/7843-assertion-failure.test 
b/sql/test/BugTracker-2026/Tests/7843-assertion-failure.test
--- a/sql/test/BugTracker-2026/Tests/7843-assertion-failure.test
+++ b/sql/test/BugTracker-2026/Tests/7843-assertion-failure.test
@@ -68,4 +68,4 @@ SELECT x , CASE WHEN x > 12 THEN 1 ELSE 
 13
 1
 NULL
-0
+NULL
diff --git a/sql/test/BugTracker-2026/Tests/7845-assertion-failure.test 
b/sql/test/BugTracker-2026/Tests/7845-assertion-failure.test
--- a/sql/test/BugTracker-2026/Tests/7845-assertion-failure.test
+++ b/sql/test/BugTracker-2026/Tests/7845-assertion-failure.test
@@ -5,7 +5,7 @@ a
 b
 
 -- assertion failure in exp_bin (be=0x7f96b81a61b0, e=0x7f96b81b5760, 
left=0x7f96b821d130, right=0x7f96b821d310, grp=0x0, ext=0x0, cnt=0x0, sel=0x0, 
depth=1, reduce=0, push=0) at sql/backends/monet5/rel_bin.c:1899
-query I rowsort
+statement error 42000!SELECT: aggregate functions are not allowed in GROUP BY
 SELECT * FROM ( SELECT 11 AS x )
  JOIN ( SELECT * FROM ( SELECT * FROM ( SELECT 10 AS x ) ) UNION SELECT * FROM 
generate_series ( CAST( 0.000000 AS REAL ) , CAST( 123.999496 AS REAL ) , CAST( 
1.600000 AS REAL ) ) ORDER BY COALESCE ( x , 0 ) + COALESCE ( x , 0 ) ) USING ( 
x )
   WHERE x BETWEEN ( SELECT 1 AS x WHERE ( SELECT x AS x WHERE x IN ( SELECT x 
FROM ( WITH RECURSIVE x ( x ) AS ( SELECT count ( * ) = - 36 * - 33 * - 49 * 
CASE 50 WHEN - 21 + 0 + - COUNT ( * ) THEN NULL WHEN 99 * - 43 + - - 35 THEN - 
75 ELSE NULL END * - - 51 * 0 GROUP BY 1 ) SELECT x FROM x WHERE x = 2 UNION 
SELECT x FROM x WHERE x = 3 ORDER BY x , x LIMIT 4 ) ) ) ) AND x
diff --git 
a/sql/test/BugTracker-2026/Tests/7846-do_covariance_and_correlation-crash.test 
b/sql/test/BugTracker-2026/Tests/7846-do_covariance_and_correlation-crash.test
--- 
a/sql/test/BugTracker-2026/Tests/7846-do_covariance_and_correlation-crash.test
+++ 
b/sql/test/BugTracker-2026/Tests/7846-do_covariance_and_correlation-crash.test
@@ -1,7 +1,7 @@
 query I nosort
-SELECT count(*) FROM ( SELECT 1 AS x UNION SELECT 0 AS x UNION SELECT DISTINCT 
* FROM generate_series ( CAST( 65536 AS REAL ) , CAST( 1.900000 AS REAL ) ) AS 
x WHERE 625 )
+SELECT count(*) FROM ( SELECT 1 AS x UNION SELECT 0 AS x UNION SELECT DISTINCT 
* FROM generate_series ( CAST( 200 AS REAL ) , CAST( 1.900000 AS REAL ) ) AS x 
WHERE 625 )
 ----
-65536
+200
 
 query RRIRR rowsort
 SELECT DISTINCT covar_pop ( 1 , 1 ) OVER ( ) ,
@@ -9,7 +9,7 @@ SELECT DISTINCT covar_pop ( 1 , 1 ) OVER
  MAX ( CASE x WHEN 1 THEN x END ) OVER ( ) ,
  covar_samp ( 1 , NULL ) OVER ( ) ,
  corr ( 1 , NULL ) OVER ( )
-FROM ( SELECT 1 AS x UNION SELECT 0 AS x UNION SELECT DISTINCT * FROM 
generate_series ( CAST( 65536 AS REAL ) , CAST( 1.900000 AS REAL ) ) AS x WHERE 
625 )
+FROM ( SELECT 1 AS x UNION SELECT 0 AS x UNION SELECT DISTINCT * FROM 
generate_series ( CAST( 200 AS REAL ) , CAST( 1.900000 AS REAL ) ) AS x WHERE 
625 )
 ----
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to