Changeset: 9946d1c9055c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/9946d1c9055c
Modified Files:
        clients/mapiclient/dump.c
        cmake/monetdb-defines.cmake
        common/utils/mstring.h
        monetdb_config.h.in
        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/All
        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
Branch: default
Log Message:

Merge with Dec2025 branch.


diffs (truncated from 772 to 300 lines):

diff --git a/common/utils/mstring.h b/common/utils/mstring.h
--- a/common/utils/mstring.h
+++ b/common/utils/mstring.h
@@ -63,35 +63,6 @@
  * stpe*: chainable with end-of-buffer pointer.
  */
 
-#ifndef HAVE_STRNLEN
-__attribute__((__pure__))
-__attribute__((__nonnull__(1)))
-__attribute__((__access__(read_only, 1, 2)))
-static inline size_t
-strnlen(const char *s, size_t n)
-{
-       for (size_t i = 0; i < n; i++)
-               if (s[i] == 0)
-                       return i;
-       return n;
-}
-#endif
-
-#ifndef HAVE_STRNDUP
-__attribute__((__nonnull__(1)))
-static inline char *
-strndup(const char *s, size_t n)
-{
-       n = strnlen(s, n);
-       char *p = malloc(n + 1);
-       if (p != NULL) {
-               memcpy(p, s, n);
-               p[n] = 0;
-       }
-       return p;
-}
-#endif
-
 #ifndef HAVE_STRLCPY
 /* Copy the input string into a destination string.  If the destination
  * buffer, limited by its size, isn't large enough to hold the copy, the
diff --git a/monetdb_config.h.in b/monetdb_config.h.in
--- a/monetdb_config.h.in
+++ b/monetdb_config.h.in
@@ -398,6 +398,36 @@ typedef __uint128_t uhge;
 #define STRERROR_R_CHARP 1
 #endif
 
+#ifndef HAVE_STRNLEN
+__attribute__((__pure__))
+__attribute__((__nonnull__(1)))
+__attribute__((__access__(read_only, 1, 2)))
+static inline size_t
+strnlen(const char *s, size_t n)
+{
+       for (size_t i = 0; i < n; i++)
+               if (s[i] == 0)
+                       return i;
+       return n;
+}
+#endif
+
+#ifndef HAVE_STRNDUP
+__attribute__((__nonnull__(1)))
+static inline char *
+strndup(const char *s, size_t n)
+{
+       n = strnlen(s, n);
+       char *p = malloc(n + 1);
+       if (p != NULL) {
+               memcpy(p, s, n);
+               p[n] = 0;
+       }
+       return p;
+}
+#endif
+
+
 #ifdef _MSC_VER
 
 #define strdup(s)      _strdup(s)
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
@@ -2347,8 +2347,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
@@ -1483,8 +1483,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 */
@@ -1557,7 +1561,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);
@@ -1588,7 +1592,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_rel.h b/sql/server/rel_rel.h
--- a/sql/server/rel_rel.h
+++ b/sql/server/rel_rel.h
@@ -24,18 +24,19 @@
 #define sql_aggr         (1 << 6)  //ORed
 #define sql_farg         (1 << 7)  //ORed
 #define sql_window       (1 << 8)  //ORed
-#define sql_join         (1 << 9)  //ORed
-#define sql_outer        (1 << 10) //ORed
-#define sql_group_totals (1 << 11) //ORed
-#define sql_update_set   (1 << 12) //ORed
-#define sql_psm          (1 << 13) //ORed
-#define sql_values       (1 << 14) //ORed
-#define psm_call         (1 << 15) //ORed
-#define sql_or           (1 << 16) //ORed
-#define sql_merge        (1 << 17) //ORed
-#define sql_no_subquery  (1 << 18) //ORed
-#define sql_qualify      (1 << 19) //ORed
-#define sql_check        (1 << 20) //ORed
+#define sql_window_rows  (1 << 9)  //ORed
+#define sql_join         (1 << 10)  //ORed
+#define sql_outer        (1 << 11) //ORed
+#define sql_group_totals (1 << 12) //ORed
+#define sql_update_set   (1 << 13) //ORed
+#define sql_psm          (1 << 14) //ORed
+#define sql_values       (1 << 15) //ORed
+#define psm_call         (1 << 16) //ORed
+#define sql_or           (1 << 17) //ORed
+#define sql_merge        (1 << 18) //ORed
+#define sql_no_subquery  (1 << 19) //ORed
+#define sql_qualify      (1 << 20) //ORed
+#define sql_check        (1 << 21) //ORed
 
 #define is_sql_from(X)         ((X & sql_from) == sql_from)
 #define is_sql_where(X)        ((X & sql_where) == sql_where)
@@ -46,6 +47,7 @@
 #define is_sql_aggr(X)         ((X & sql_aggr) == sql_aggr)
 #define is_sql_farg(X)         ((X & sql_farg) == sql_farg)
 #define is_sql_window(X)       ((X & sql_window) == sql_window)
+#define is_sql_window_rows(X)  ((X & sql_window_rows) == sql_window_rows)
 #define is_sql_join(X)         ((X & sql_join) == sql_join)
 #define is_sql_outer(X)        ((X & sql_outer) == sql_outer)
 #define is_sql_group_totals(X) ((X & sql_group_totals) == sql_group_totals)
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
@@ -3585,6 +3585,10 @@ _rel_aggr(sql_query *query, sql_rel **re
                        if (GDKtoupper(ta, &uaname, &(size_t){0}, aname) != 
GDK_SUCCEED)
                                uaname = aname;
                        return sql_error(sql, 02, SQLSTATE(42000) "%s: 
aggregate functions not allowed in WHERE clause", uaname);
+               } else if (is_sql_window_rows(f)) {
+                       if (GDKtoupper(ta, &uaname, &(size_t){0}, aname) != 
GDK_SUCCEED)
+                               uaname = aname;
+                       return sql_error(sql, 02, SQLSTATE(42000) "%s: 
aggregate functions not allowed in window ROWS", uaname);
                } else if (is_sql_update_set(f) || is_sql_psm(f)) {
                        if (GDKtoupper(ta, &uaname, &(size_t){0}, aname) != 
GDK_SUCCEED)
                                uaname = aname;
@@ -3674,6 +3678,10 @@ _rel_aggr(sql_query *query, sql_rel **re
                        if (GDKtoupper(ta, &uaname, &(size_t){0}, aname) != 
GDK_SUCCEED)
                                uaname = aname;
                        return sql_error(sql, 02, SQLSTATE(42000) "%s: 
aggregate functions not allowed in WHERE clause", uaname);
+               } else if (is_sql_window_rows(f)) {
+                       if (GDKtoupper(ta, &uaname, &(size_t){0}, aname) != 
GDK_SUCCEED)
+                               uaname = aname;
+                       return sql_error(sql, 02, SQLSTATE(42000) "%s: 
aggregate functions not allowed in window ROWS", uaname);
                } else if (!all_aggr && !list_empty(ungrouped_cols)) {
                        for (node *n = ungrouped_cols->h ; n ; n = n->next) {
                                sql_rel *outer;
@@ -3701,6 +3709,10 @@ _rel_aggr(sql_query *query, sql_rel **re
                                                if (GDKtoupper(ta, &uaname, 
&(size_t){0}, aname) != GDK_SUCCEED)
                                                        uaname = aname;
                                                return sql_error(sql, 02, 
SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clause", uaname);
+                                       } else if (!used_rel && 
is_sql_window_rows(of)) {
+                                               if (GDKtoupper(ta, &uaname, 
&(size_t){0}, aname) != GDK_SUCCEED)
+                                                       uaname = aname;
+                                               return sql_error(sql, 02, 
SQLSTATE(42000) "%s: aggregate functions not allowed in window ROWS", uaname);
                                        } else if (!is_sql_aggr(of)) {
                                                set_outer(outer);
                                        }
@@ -4409,18 +4421,18 @@ list_power_set(allocator *sa, list* inpu
 }
 
 static list*
-list_rollup(allocator *sa, list* input)
+list_rollup(mvc *sql, list* input)
 {
-       list *res = sa_list(sa);
+       list *res = sa_list(sql->sa);
 
        for (int counter = input->cnt; counter > 0; counter--) {
-               list *ll = sa_list(sa);
+               list *ll = sa_list(sql->sa);
                int j = 0;
                for (node *n = input->h; n && j < counter; j++, n = n->next)
-                       list_append(ll, n->data);
+                       list_append(ll, exps_copy(sql, n->data));
                list_append(res, ll);
        }
-       list_append(res, sa_list(sa)); /* global aggregate case */
+       list_append(res, sa_list(sql->sa)); /* global aggregate case */
        return res;
 }
 
@@ -4512,7 +4524,7 @@ rel_groupings(sql_query *query, sql_rel 
                                }
                                if (is_sql_group_totals(f)) {
                                        if (grouping->token == SQL_ROLLUP)
-                                               next_set = list_rollup(sql->sa, 
set_cols);
+                                               next_set = list_rollup(sql, 
set_cols);
                                        else if (grouping->token == SQL_CUBE)
                                                next_set = 
list_power_set(sql->sa, set_cols);
                                        else /* the list of sets is not used in 
the "GROUP BY a, b, ..." case */
@@ -4746,6 +4758,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);
                                }
                        }
 
@@ -4844,6 +4858,7 @@ calculate_window_bound(sql_query *query,
        sql_subtype *bt, *bound_tp = sql_fetch_localtype(TYPE_lng), *iet = 
exp_subtype(ie);
        sql_exp *res = NULL;
 
+       f = f|sql_window_rows;
        if ((bound->token == SQL_PRECEDING || bound->token == SQL_FOLLOWING || 
bound->token == SQL_CURRENT_ROW) && bound->type == type_int) {
                atom *a = NULL;
                bt = (frame_type == FRAME_ROWS || frame_type == FRAME_GROUPS) ? 
bound_tp : iet;
@@ -5983,6 +5998,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);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to