Changeset: 4869d170e82c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/4869d170e82c
Modified Files:
        sql/include/sql_relation.h
        sql/server/rel_unnest.c
Branch: nested
Log Message:

merged with default


diffs (truncated from 353 to 300 lines):

diff --git a/sql/common/sql_list.c b/sql/common/sql_list.c
--- a/sql/common/sql_list.c
+++ b/sql/common/sql_list.c
@@ -715,6 +715,8 @@ list_join(list *l, list *data)
 {
        if (!l)
                return data;
+       if (!data)
+               return l;
        assert(data->sa);
        assert(data->sa == l->sa);
        assert(!l->ht);
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -313,6 +313,7 @@ typedef struct relation {
         card:2,        /* 0, 1 (row), 2 aggr, 3 */
         dependent:1,   /* dependent join */
         distinct:1,
+        fv_distinct:1, /* set during general unnest */
         processed:1,   /* fully processed or still in the process of building 
*/
         outer:1,       /* used as outer (ungrouped) */
         grouped:1,     /* groupby processed all the group by exps */
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
@@ -79,16 +79,18 @@ exps_set_freevar(mvc *sql, list *exps, s
 
 /* check if the set is distinct (ie we did a domain reduction for the general 
unnest) for the set of free variables */
 static int
-is_distinct_set(mvc *sql, sql_rel *rel, list *ad)
+is_distinct_set(mvc *sql, sql_rel *rel, list *ad, bool need_join)
 {
        int distinct = 0;
        if (ad && is_groupby(rel->op) && (list_empty(rel->r) || 
exp_match_list(rel->r, ad)))
                return 1;
        distinct = need_distinct(rel);
+       if (need_join)
+               distinct &= rel->fv_distinct;
        if (is_project(rel->op) && rel->l && !distinct)
-               distinct = is_distinct_set(sql, rel->l, ad);
+               distinct = is_distinct_set(sql, rel->l, ad, need_join);
        if (is_semi(rel->op))
-               distinct = is_distinct_set(sql, rel->l, ad);
+               distinct = is_distinct_set(sql, rel->l, ad, need_join);
        prop *p = NULL;
        if (is_base(rel->op) && (p = find_prop(rel->p, PROP_UKEY)) != NULL)
                return exp_match_list(p->value.pval, ad);
@@ -925,6 +927,7 @@ rel_general_unnest(mvc *sql, sql_rel *re
                /* rewrite T1 dependent join T2 -> T1 join D dependent join T2, 
where the T1/D join adds (equality) predicates (for the Domain (ad)) and D is 
are the distinct(projected(ad) from T1)  */
                sql_rel *D = rel_project(sql->sa, rel_dup(l), exps_copy(sql, 
ad));
                set_distinct(D);
+               D->fv_distinct = true;
 
                int single = is_single(r);
                reset_single(r);
@@ -1245,7 +1248,14 @@ push_up_topn_and_sample(mvc *sql, sql_re
                if (r && (is_topn(r->op) || is_sample(r->op))) {
                        /* remove old topn/sample */
                        sql_rel *(*func) (allocator *, sql_rel *, list *) = 
is_topn(r->op) ? rel_topn : rel_sample;
+                       sql_rel *l = r->l;
                        rel->r = rel_dup(r->l);
+                       list *obes = (l->op == op_project)?l->r:NULL;
+                       if (obes) {
+                               obes = exps_copy(sql, obes);
+                               list_join(l->exps, l->r);
+                               l->r = NULL;
+                       }
                        rel = func(sql->sa, rel, r->exps);
                        if (r->op == op_topn && !list_empty(ad)) { /* topn per 
freevar */
                                /* add rel_project(), ordering on freevar */
@@ -1255,7 +1265,7 @@ push_up_topn_and_sample(mvc *sql, sql_re
                                        sql_exp *e = n->data;
                                        set_partitioning(e);
                                }
-                               p->r = ad;
+                               p->r = list_join(ad, obes);
                                rel->grouped = 1;
                        }
                        set_processed(rel);
@@ -1389,7 +1399,7 @@ push_up_groupby(mvc *sql, sql_rel *rel, 
                sql_rel *l = rel->l, *r = rel->r;
 
                /* left of rel should be a set */
-               if (l && is_distinct_set(sql, l, ad) && r && is_groupby(r->op)) 
{
+               if (l && is_distinct_set(sql, l, ad, false) && r && 
is_groupby(r->op)) {
                        list *sexps, *jexps, *a = rel_projections(sql, rel->l, 
NULL, 1, 1);
                        node *n;
                        sql_exp *id = NULL;
@@ -1570,6 +1580,45 @@ static sql_rel * rel_unnest_dependent(mv
 
 static sql_rel * rewrite_outer2inner_union(visitor *v, sql_rel *rel);
 
+static void
+add_natural_exps(mvc *sql, sql_rel *d, sql_rel *n, bool labelleft)
+{
+       /* add nr->l exps with labels */
+       if (!n->exps)
+               n->exps = sa_list(sql->sa);
+       if (!list_empty(d->exps)) {
+               sql_rel *nl = n->l = rel_project(sql->sa, n->l, 
rel_projections(sql, n->l, NULL, 1, 1));
+               sql_rel *nr = n->r;
+               nr = n->r = rel_project(sql->sa, n->r, 
is_semi(nr->op)?sa_list(sql->sa):rel_projections(sql, nr->r, NULL, 1, 1));
+               for (node *m = d->exps->h; m; m = m->next) {
+                       sql_exp *e = m->data, *le, *re, *je;
+
+                       le = exp_ref(sql, e);
+                       re = exp_ref(sql, e);
+
+                       if (labelleft) {
+                               sql_exp *f = NULL;
+                               if ((f=rel_find_exp(nl, le)) != NULL)
+                                       le = f;
+                               if (!has_label(le))
+                                       le = exp_label(sql->sa, le, 
++sql->label);
+                               if (!f)
+                                       append(nl->exps, le);
+                               le = exp_ref(sql, le);
+                       }
+
+                       if (!labelleft)
+                               re = exp_label(sql->sa, re, ++sql->label);
+                       append(nr->exps, re);
+                       re = exp_ref(sql, re);
+                       je = exp_compare(sql->sa, le, re, cmp_equal);
+                       set_semantics(je);
+                       append(n->exps, je);
+               }
+               list_hash_clear(nl->exps);
+       }
+}
+
 static sql_rel *
 push_up_join(mvc *sql, sql_rel *rel, list *ad)
 {
@@ -1578,7 +1627,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis
                sql_rel *d = rel->l, *j = rel->r;
 
                /* left of rel should be a set */
-               if (d && is_distinct_set(sql, d, ad) && j && (is_join(j->op) || 
is_semi(j->op))) {
+               if (d && is_distinct_set(sql, d, ad, is_outerjoin(j->op)) && j 
&& (is_join(j->op) || is_semi(j->op))) {
                        sql_rel *jl = j->l, *jr = j->r;
                        /* op_join if F(jl) intersect A(D) = empty -> jl join 
(D djoin jr)
                         *            F(jr) intersect A(D) = empty -> (D djoin 
jl) join jr
@@ -1616,8 +1665,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis
                        }
 
                        if (ld && rd) {
-                               node *m;
-                               sql_rel *n, *nr, *nj, *nl;
+                               sql_rel *n;
                                list *inner_exps = exps_copy(sql, j->exps);
                                list *outer_exps = exps_copy(sql, rel->exps);
                                list *attr = j->attr?exps_copy(sql, 
j->attr):NULL;
@@ -1637,12 +1685,13 @@ push_up_join(mvc *sql, sql_rel *rel, lis
 
                                rel->r = rel_dup(jl);
                                rel->exps = sa_list(sql->sa);
-                               nj = rel_crossproduct(sql->sa, rel_dup(d), 
rel_dup(jr), j->op);
+                               sql_rel *nj = rel_crossproduct(sql->sa, 
rel_dup(d), rel_dup(jr), rel->op);
                                set_processed(nj);
+                               int op = j->op;
                                rel_destroy(sql, j);
                                j = nj;
                                set_dependent(j);
-                               n = rel_crossproduct(sql->sa, rel, j, j->op);
+                               n = rel_crossproduct(sql->sa, rel, j, op);
                                n->exps = outer_exps;
                                if (single)
                                        set_single(n);
@@ -1655,41 +1704,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis
                                        j->op = op_left;
                                        rel->op = op_left;
                                }
-                               nl = n->l = rel_project(sql->sa, n->l, 
rel_projections(sql, n->l, NULL, 1, 1));
-                               nr = n->r;
-                               nr = n->r = rel_project(sql->sa, n->r, 
is_semi(nr->op)?sa_list(sql->sa):rel_projections(sql, nr->r, NULL, 1, 1));
-                               /* add nr->l exps with labels */
-                               /* create jexps */
-                               if (!n->exps)
-                                       n->exps = sa_list(sql->sa);
-                               if (!list_empty(d->exps)) {
-                                       for (m = d->exps->h; m; m = m->next) {
-                                               sql_exp *e = m->data, *le, *re, 
*je;
-
-                                               le = exp_ref(sql, e);
-                                               re = exp_ref(sql, e);
-
-                                               if (labelleft) {
-                                                       sql_exp *f = NULL;
-                                                       if ((f=rel_find_exp(nl, 
le)) != NULL)
-                                                               le = f;
-                                                       if (!has_label(le))
-                                                               le = 
exp_label(sql->sa, le, ++sql->label);
-                                                       if (!f)
-                                                               
append(nl->exps, le);
-                                                       le = exp_ref(sql, le);
-                                               }
-
-                                               if (!labelleft)
-                                                       re = exp_label(sql->sa, 
re, ++sql->label);
-                                               append(nr->exps, re);
-                                               re = exp_ref(sql, re);
-                                               je = exp_compare(sql->sa, le, 
re, cmp_equal);
-                                               set_semantics(je);
-                                               append(n->exps, je);
-                                       }
-                               }
-                               list_hash_clear(nl->exps);
+                               add_natural_exps(sql, d, n, labelleft); /* 
create jexps */
                                n->attr = attr;
                                set_processed(n);
                                rel_bind_vars(sql, n, n->exps);
@@ -1744,7 +1759,7 @@ push_up_set(mvc *sql, sql_rel *rel, list
                int need_distinct = is_semi(rel->op) && need_distinct(d);
 
                /* left of rel should be a set */
-               if (d && is_distinct_set(sql, d, ad) && s && is_set(s->op)) {
+               if (d && is_distinct_set(sql, d, ad, false) && s && 
is_set(s->op)) {
                        sql_rel *sl = s->l, *sr = s->r, *ns;
 
                        sl = rel_project(sql->sa, rel_dup(sl), 
rel_projections(sql, sl, NULL, 1, 1));
@@ -1829,7 +1844,7 @@ push_up_munion(mvc *sql, sql_rel *rel, l
 
                /* left of rel should be a set */
                list *rlist = sa_list(sql->sa);
-               if (d && is_distinct_set(sql, d, ad) && s && is_munion(s->op)) {
+               if (d && is_distinct_set(sql, d, ad, false) && s && 
is_munion(s->op)) {
                        list *iu = s->l;
                        if (rec) {
                                sql_rel *r = iu->h->data;
@@ -2099,12 +2114,12 @@ rel_unnest_dependent(mvc *sql, sql_rel *
                                }
                        }
 
-                       if (r && is_simple_project(r->op) && ((!r->r && 
!exps_have_rank(r->exps)) || (!exps_have_freevar(sql, r->exps) && 
!exps_have_unsafe(r->exps, true, false)) || is_distinct_set(sql, l, ad))) {
+                       if (r && is_simple_project(r->op) && ((!r->r && 
!exps_have_rank(r->exps)) || (!exps_have_freevar(sql, r->exps) && 
!exps_have_unsafe(r->exps, true, false)) || is_distinct_set(sql, l, ad, 
false))) {
                                rel = push_up_project(sql, rel, ad);
                                return rel_unnest_dependent(sql, rel);
                        }
 
-                       if (r && (is_topn(r->op) || is_sample(r->op)) && 
is_distinct_set(sql, l, ad)) {
+                       if (r && (is_topn(r->op) || is_sample(r->op)) && 
is_distinct_set(sql, l, ad, false)) {
                                sql_rel *l = r->l;
                                if (is_left(rel->op) && l && is_project(l->op) 
&& !l->r && !project_unsafe(l, 1)) {
                                        rel = push_down_topn_and_sample(sql, 
rel);
@@ -2120,22 +2135,22 @@ rel_unnest_dependent(mvc *sql, sql_rel *
                                return rel_unnest_dependent(sql, rel);
                        }
 
-                       if (r && is_groupby(r->op) && !is_left(rel->op) && 
is_distinct_set(sql, l, ad)) {
+                       if (r && is_groupby(r->op) && !is_left(rel->op) && 
is_distinct_set(sql, l, ad, false)) {
                                rel = push_up_groupby(sql, rel, ad);
                                return rel_unnest_dependent(sql, rel);
                        }
 
-                       if (r && (is_join(r->op) || is_semi(r->op)) && 
is_distinct_set(sql, l, ad)) {
+                       if (r && (is_join(r->op) || is_semi(r->op)) && 
is_distinct_set(sql, l, ad, is_outerjoin(r->op))) {
                                rel = push_up_join(sql, rel, ad);
                                return rel_unnest_dependent(sql, rel);
                        }
 
-                       if (r && is_set(r->op) && !is_left(rel->op) && rel->op 
!= op_anti && is_distinct_set(sql, l, ad)) {
+                       if (r && is_set(r->op) && !is_left(rel->op) && rel->op 
!= op_anti && is_distinct_set(sql, l, ad, false)) {
                                rel = push_up_set(sql, rel, ad);
                                return rel_unnest_dependent(sql, rel);
                        }
 
-                       if (r && is_munion(r->op) && !is_left(rel->op) && 
is_distinct_set(sql, l, ad)) {
+                       if (r && is_munion(r->op) && !is_left(rel->op) && 
is_distinct_set(sql, l, ad, false)) {
                                rel = push_up_munion(sql, rel, ad);
                                return rel_unnest_dependent(sql, rel);
                        }
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
@@ -459,7 +459,7 @@ DROP TABLE v0
 -- 31.sql
 onlyif has-hugeint
 query I nosort
-SELECT ALL ( SELECT - - - - - - - - - - - 1 - - - - - - 16 FROM ( SELECT NULL 
- - - - - - - - - - - - - - - - 1 FROM ( SELECT - - - - 1 * - - - - - - 
2147483648 * - - - 43 * 77745222.000000 ) AS v1 ( v1 ) GROUP BY GROUPING SETS ( 
GROUPING SETS ( CUBE ( v1 ) ) ) ORDER BY v1 , - - - 86 + - - power(93 , v1) , 
v1 LIMIT 21 ) AS v1 UNION SELECT - - - - - - - - - - - - 93 WHERE - v1 < - 
63226945.000000 - - - - - - - - - - 68 ) FROM ( VALUES ( - - - - - - - - - 40 / 
- ( SELECT - - - - - - - - 0 WHERE - - - - - - - 40 = - - - - - 0 ) ) , ( - - 
88 ) ) v1 ( v1 )
+SELECT ALL ( SELECT - - - - - - - - - - - 1 - - - - - - 16 FROM ( SELECT NULL 
- - - - - - - - - - - - - - - - 1 FROM ( SELECT - - - - 1 * - - - - - - 
2147483648 * - - - 43 * 77745222.000000 ) AS v1 ( v1 ) GROUP BY GROUPING SETS ( 
GROUPING SETS ( CUBE ( v1 ) ) ) ORDER BY v1 , - - - 86 + - - 93 ^ 2 , v1 LIMIT 
21 ) AS v1 UNION SELECT - - - - - - - - - - - - 93 WHERE - v1 < - 
63226945.000000 - - - - - - - - - - 68 ) FROM ( VALUES ( - - - - - - - - - 40 / 
- ( SELECT - - - - - - - - 0 WHERE - - - - - - - 40 = - - - - - 0 ) ) , ( - - 
88 ) ) v1 ( v1 )
 ----
 15
 15
diff --git 
a/sql/test/BugTracker-2026/Tests/7834-BATsubcross-more-than-one-match.test 
b/sql/test/BugTracker-2026/Tests/7834-BATsubcross-more-than-one-match.test
--- a/sql/test/BugTracker-2026/Tests/7834-BATsubcross-more-than-one-match.test
+++ b/sql/test/BugTracker-2026/Tests/7834-BATsubcross-more-than-one-match.test
@@ -1,4 +1,4 @@
-statement error GDK reported error: BATsubcross: more than one match
+statement error 42000!row frame bound must be non negative and non null.
 SELECT x , x , STDDEV_POP ( NULLIF ( ( WITH RECURSIVE x ( x ) AS ( WITH 
RECURSIVE x ( x ) AS ( SELECT 440 UNION SELECT 1 - x FROM x ) SELECT * FROM 
generate_series ( 0 , 10 ) WHERE x < 5 ) SELECT - COUNT ( * ) OVER ( ROWS 
BETWEEN 2 PRECEDING AND 3 >= ( SELECT CASE WHEN x = 12 THEN 1 ELSE CASE WHEN 
length ( 'abcdefg' ) >= 1 THEN substr ( ( SELECT SUM ( 0 ) OVER ( ) ) , locate 
( RPAD ( 'abc' , 1 , ( SELECT 1 ) > ANY ( 1 ) ) , 'joeuser@mydatabase@test' , 9 
) , 1 ) ELSE 'nil' END END FROM ( SELECT 1 x HAVING COUNT ( * ) > ( SELECT - 
CASE - ( 0 ) WHEN 18 + - 60 THEN NULL WHEN - CASE - 67 WHEN - 79 * ROW_NUMBER ( 
) OVER ( ORDER BY ( SELECT * FROM ( SELECT 1 AS x ) WHERE x IN ( SELECT ( 
row_number ( ) OVER ( ) ) ) ) ) <= -5.500000 / 30 - 32 * 69 THEN sign ( CAST( 
'-9223372036854775808.5' AS FLOAT ) ) + 0 ELSE NULL END * ( 45 ) + 19 * 17 THEN 
20 WHEN SUM ( 78 ) + 69 THEN 1234567954432.000000 % 119070 % '' * 74 ELSE 
NULLIF ( 82 , 72 + 26 ) * 7 END * - 92 WHERE FALSE ) UNION SELECT 1 + 1 AS x
  INTERSECT SELECT 3 ) AS x ) FOLLOWING ) FROM x AS x WHERE NOT ( - x ) BETWEEN 
- x AND NULL ) , NULL ) ) OVER ( ORDER BY CASE WHEN x % 2 = 0 THEN 0 ELSE 1 END 
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) AS x FROM ( SELECT rank ( ) 
OVER ( PARTITION BY 'x' , 1 , 1 , 'x' ) AS x UNION SELECT 0 AS x UNION SELECT 3 
AS x ) ORDER BY 1 , 2 , 3
 
 onlyif has-hugeintxs
diff --git a/sql/test/BugTracker-2026/Tests/7859-getModule-crash.test 
b/sql/test/BugTracker-2026/Tests/7859-getModule-crash.test
--- a/sql/test/BugTracker-2026/Tests/7859-getModule-crash.test
+++ b/sql/test/BugTracker-2026/Tests/7859-getModule-crash.test
@@ -7,7 +7,7 @@ SELECT x NOT IN (
 
 query II rowsort
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to