public inbox for [email protected]  
help / color / mirror / Atom feed
From: Tender Wang <[email protected]>
To: [email protected]
To: [email protected]
Subject: Re: BUG #19534: Qual pushdown across a window subquery is unsafe with nondeterministic partition collations
Date: Sun, 28 Jun 2026 19:33:47 +0800
Message-ID: <CAHewXNk8xt1pNepcEiCx_e6_SW_=bm1GNnU7+bPczoZJuLC5qQ@mail.gmail.com> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>

PG Bug reporting form <[email protected]> 于2026年6月27日周六 20:55写道:
>
> The following bug has been logged on the website:
>
> Bug reference:      19534
> Logged by:          Qifan Liu
> Email address:      [email protected]
> PostgreSQL version: 18.4
> Operating system:   Ubuntu 20.04 x86-64, docker image postgres:18.4
> Description:
>
> ## Expected Behavior
>
> The window query should return the same result as the reference query. Since
> `'abc'` and `'ABC'` are in the same nondeterministic partition, the
> partition sum for row `'abc'` should be `3`.
>
> ## Actual Behavior
>
> The window query returns `abc | 1 | 1`, while the reference query returns
> `abc | 1 | 3`. `EXPLAIN` shows that the strict-collation filter is pushed
> below `WindowAgg`, which changes the partition before the window sum is
> computed.
>

Yes, I can reproduce this on HEAD.
The whereClause was pushed down to the scan level of table t_window_ci.
So the row with 'ABC' was ignored by the filter.

In current logic, we have no logic to process a nondeterministic
partition clause when considering whether the
qual can be pushed down to the subquery.

I try to fix this with the attached patch.
I add a new flag UNSAFE_HAS_NONDETERMINITIC for
pushdown_safety_info.unsafeFlags.
If the var is in the partition clause and it is nondeterministic, we
set this flag.
In qual_is_pushdown_safe(), we check the qual's inputcollid; if it is
deterministic, but the var in
the partition clause is nondeterministic, it is PUSHDOWN_UNSAFE.

Any thoughts?
-- 
Thanks,
Tender Wang


Attachments:

  [application/octet-stream] 0001-Fix-qual-pushdown-with-nondeterministic-partition-co.patch (2.8K, ../CAHewXNk8xt1pNepcEiCx_e6_SW_=bm1GNnU7+bPczoZJuLC5qQ@mail.gmail.com/2-0001-Fix-qual-pushdown-with-nondeterministic-partition-co.patch)
  download | inline diff:
From c99dcb3de3d0e42d03af71027ca4b1cd6d130127 Mon Sep 17 00:00:00 2001
From: Ubuntu <[email protected]>
Date: Sun, 28 Jun 2026 19:21:40 +0800
Subject: [PATCH] Fix qual pushdown with nondeterministic partition collations

---
 src/backend/optimizer/path/allpaths.c | 37 +++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index c134594a21a..995972e15dc 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -57,6 +57,7 @@
 #define UNSAFE_NOTIN_DISTINCTON_CLAUSE	(1 << 2)
 #define UNSAFE_NOTIN_PARTITIONBY_CLAUSE	(1 << 3)
 #define UNSAFE_TYPE_MISMATCH			(1 << 4)
+#define UNSAFE_HAS_NONDETERMINITIC		(1 << 5)
 
 /* results of subquery_is_pushdown_safe */
 typedef struct pushdown_safety_info
@@ -159,6 +160,7 @@ static void check_output_expressions(Query *subquery,
 static void compare_tlist_datatypes(List *tlist, List *colTypes,
 									pushdown_safety_info *safetyInfo);
 static bool targetIsInAllPartitionLists(TargetEntry *tle, Query *query);
+static bool contain_nondeterministic_partition_clause(TargetEntry *tle, Query *query);
 static pushdown_safe_type qual_is_pushdown_safe(Query *subquery, Index rti,
 												RestrictInfo *rinfo,
 												pushdown_safety_info *safetyInfo);
@@ -4345,6 +4347,16 @@ check_output_expressions(Query *subquery, pushdown_safety_info *safetyInfo)
 			safetyInfo->unsafeFlags[tle->resno] |= UNSAFE_NOTIN_PARTITIONBY_CLAUSE;
 			continue;
 		}
+
+		if (subquery->hasWindowFuncs &&
+			(safetyInfo->unsafeFlags[tle->resno] &
+			 UNSAFE_HAS_NONDETERMINITIC) == 0 &&
+			contain_nondeterministic_partition_clause(tle, subquery))
+		{
+			/* has nondeterministic partition collations */
+			safetyInfo->unsafeFlags[tle->resno] |= UNSAFE_HAS_NONDETERMINITIC;
+			continue;
+		}
 	}
 }
 
@@ -4413,6 +4425,22 @@ targetIsInAllPartitionLists(TargetEntry *tle, Query *query)
 	return true;
 }
 
+static bool
+contain_nondeterministic_partition_clause(TargetEntry *tle, Query *query)
+{
+	Oid collid;
+
+	if (!targetIsInAllPartitionLists(tle, query))
+		return false;
+
+	collid = exprCollation((Node *) tle->expr);
+
+	if (OidIsValid(collid))
+		return !get_collation_isdeterministic(collid);
+
+	return false;
+}
+
 /*
  * qual_is_pushdown_safe - is a particular rinfo safe to push down?
  *
@@ -4525,6 +4553,15 @@ qual_is_pushdown_safe(Query *subquery, Index rti, RestrictInfo *rinfo,
 				safe = PUSHDOWN_UNSAFE;
 				break;
 			}
+			else if (safetyInfo->unsafeFlags[var->varattno] &
+					 UNSAFE_HAS_NONDETERMINITIC)
+			{
+				if (get_collation_isdeterministic(exprInputCollation(qual)))
+				{
+					safe = PUSHDOWN_UNSAFE;
+					break;
+				}
+			}
 			else
 			{
 				/* UNSAFE_NOTIN_PARTITIONBY_CLAUSE is ok for run conditions */
-- 
2.34.1



view thread (6+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected]
  Subject: Re: BUG #19534: Qual pushdown across a window subquery is unsafe with nondeterministic partition collations
  In-Reply-To: <CAHewXNk8xt1pNepcEiCx_e6_SW_=bm1GNnU7+bPczoZJuLC5qQ@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox