]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix wrong unsafe-flag test in check_output_expressions()
authorRichard Guo <rguo@postgresql.org>
Wed, 3 Jun 2026 00:36:52 +0000 (09:36 +0900)
committerRichard Guo <rguo@postgresql.org>
Wed, 3 Jun 2026 00:42:52 +0000 (09:42 +0900)
The check for window functions (point 4) guarded on the wrong bit: it
tested UNSAFE_NOTIN_DISTINCTON_CLAUSE while setting
UNSAFE_NOTIN_PARTITIONBY_CLAUSE.  Each check in this loop guards on
the same bit it is about to set, as an idempotency optimization, since
unsafeFlags[] is accumulated across the arms of a set operation and
there is no point recomputing a column's status once its bit is
present.

This is not a live bug.  When UNSAFE_NOTIN_PARTITIONBY_CLAUSE is
already set but UNSAFE_NOTIN_DISTINCTON_CLAUSE is not, the guard fails
to skip targetIsInAllPartitionLists() and recomputes it, but setting
the same bit again changes nothing.  When
UNSAFE_NOTIN_DISTINCTON_CLAUSE is already set, point 4 is skipped and
UNSAFE_NOTIN_PARTITIONBY_CLAUSE is left unset; but such a column is
already unsafe for pushdown via UNSAFE_NOTIN_DISTINCTON_CLAUSE, so the
outcome is unchanged.

To fix, test UNSAFE_NOTIN_PARTITIONBY_CLAUSE, matching the bit being
set and the pattern of the surrounding checks.

Back-patch to v15, where the buggy check was introduced.

Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Tender Wang <tndrwang@gmail.com>
Reviewed-by: David Rowley <dgrowleyml@gmail.com>
Discussion: https://postgr.es/m/CAMbWs49Q_xnF_P2QSUyDzJ34MnrO7dh-cUAaK2HJPgSgh88NcA@mail.gmail.com
Backpatch-through: 15

src/backend/optimizer/path/allpaths.c

index 4e02439ce36dd2bc62c85028210874ee8b785c7b..11ff839462d462bf042b8e298eee7daeabfba9d8 100644 (file)
@@ -3730,7 +3730,7 @@ check_output_expressions(Query *subquery, pushdown_safety_info *safetyInfo)
                /* If subquery uses window functions, check point 4 */
                if (subquery->hasWindowFuncs &&
                        (safetyInfo->unsafeFlags[tle->resno] &
-                        UNSAFE_NOTIN_DISTINCTON_CLAUSE) == 0 &&
+                        UNSAFE_NOTIN_PARTITIONBY_CLAUSE) == 0 &&
                        !targetIsInAllPartitionLists(tle, subquery))
                {
                        /* not present in all PARTITION BY clauses, so mark it unsafe */