<feed xmlns='http://www.w3.org/2005/Atom'>
<title>postgresql.git/src/test/isolation, branch master</title>
<subtitle>This is the main PostgreSQL git repository.</subtitle>
<id>http://git.postgresql.org/cgit/postgresql.git/atom?h=master</id>
<link rel='self' href='http://git.postgresql.org/cgit/postgresql.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/'/>
<updated>2026-09-15T10:47:05Z</updated>
<entry>
<title>Fix missing SIREAD lock on the row found by ON CONFLICT.</title>
<updated>2026-09-15T10:47:05Z</updated>
<author>
<name>Dean Rasheed</name>
</author>
<published>2026-09-15T10:47:05Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=fb60892f4034017e77b8d4376d3ca8937dcbbab2'/>
<id>urn:sha1:fb60892f4034017e77b8d4376d3ca8937dcbbab2</id>
<content type='text'>
INSERT ... ON CONFLICT decides what to do based on the conflicting row
found by the arbiter index probe, but SSI never saw that read: the
probe runs with a dirty snapshot, which predicate locking ignores, and
the later fetch of the row uses SnapshotAny.  When the statement then
writes nothing, as with DO NOTHING, DO UPDATE with a WHERE clause
rejecting the row, or DO SELECT, nothing records the read at all.  A
concurrent writer of that row went unnoticed and write skew could
commit at SERIALIZABLE, even though the same schedule with a plain
SELECT of the row fails with a serialization error.

To fix, read the conflicting tuple again with the query snapshot,
right where the probe finds it.  The table AM takes the SIREAD lock
and checks for a concurrent writer of the tuple as part of that read,
both under the buffer lock, so a writer either sees the lock or is
seen.  A predicate lock by itself acquired separately after the probe
could not offer that: a writer passing its conflict check in between
would be missed.  Doing this in the probe covers every conflict
action, including rows that the WHERE clause of DO UPDATE or DO SELECT
then rejects.

The DO NOTHING and DO UPDATE cases have been broken since ON CONFLICT
was added in 9.5; DO SELECT is new in v19.  Backpatch to all supported
branches.

Author: Zsolt Parragi &lt;zsolt.parragi@percona.com&gt;
Author: Andrey Borodin &lt;x4mmm@yandex-team.ru&gt;
Reported-by: Andrey Borodin &lt;x4mmm@yandex-team.ru&gt;
Reported-by: Zsolt Parragi &lt;zsolt.parragi@percona.com&gt;
Discussion: https://postgr.es/m/787936C5-4155-4CF9-939D-39DC0EC1C892@yandex-team.ru
Discussion: https://postgr.es/m/CAN4CZFM1GkHJkpMeo4G5rxtacVsfeKCJYiik9E9AKX1E9VYQ1w@mail.gmail.com
Backpatch-through: 14
</content>
</entry>
<entry>
<title>Revert UPDATE/DELETE FOR PORTION OF</title>
<updated>2026-09-15T10:12:37Z</updated>
<author>
<name>Peter Eisentraut</name>
</author>
<published>2026-09-15T10:12:37Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=a4b26b8f7cd07a3e7f0cba550c30db142329e065'/>
<id>urn:sha1:a4b26b8f7cd07a3e7f0cba550c30db142329e065</id>
<content type='text'>
List of commits reverted:

  8e72d914c52  Add UPDATE/DELETE FOR PORTION OF
  b6ccd30d8ff  Add isolation tests for UPDATE/DELETE FOR PORTION OF
  33db6c4baf1  Fix DELETE/UPDATE FOR PORTION OF with rules
  7b22f15a015  Add psql tab completion for FOR PORTION OF clause
  7ca8c942967  Fix FOR PORTION OF with non-updatable view columns
  993a7aa0e4a  Fix cross-leftover pollution in FOR PORTION OF insert triggers
  7ac030d5b15  Require UPDATE permission on FOR PORTION OF column
  f0aedc7cb0e  Small terminology fixes in comments
  7d13b03a2e6  Fix FOR PORTION OF for inheritance children
  a272a58b942  Move FOR PORTION OF volatile check into planner
  a40fdf65886  Reject child partition FDWs in FOR PORTION OF
  bc3ae886a75  Forbid FOR PORTION OF with WHERE CURRENT OF
  e994f956e48  Forbid generated columns in FOR PORTION OF
  dfce19c2300  Forbid FOR PORTION OF on views with INSTEAD OF triggers
  20fe90bbb93  Fix RLS checks for FOR PORTION OF leftover rows
  9170c8b7169  Test what BEFORE UPDATE triggers do to FOR PORTION OF
  7090c696cc9  Deparse FOR PORTION OF using the range column's current name.
  62d1a5f8be8  Avoid RETURNING side effects for FOR PORTION OF leftovers.
  9924e2d900b  Enforce WITH CHECK OPTION on DELETE FOR PORTION OF leftovers
  c16a1b4f2ce  Fix error code for null FOR PORTION OF target
  610976420a3  Fix assertion failures in DELETE FOR PORTION OF tuple routing
  438f027238c  Resolve untyped parameters in FOR PORTION OF FROM/TO bounds
  140fdfcdf12  Don't evaluate the FOR PORTION OF target under EXPLAIN

Discussion: https://www.postgresql.org/message-id/62bf70cc-dc33-4188-8070-a8c177bb61de%40eisentraut.org
</content>
</entry>
<entry>
<title>Switch pg_column_toast_chunk_id() return value from oid to oid8</title>
<updated>2026-09-14T02:02:21Z</updated>
<author>
<name>Michael Paquier</name>
</author>
<published>2026-09-14T02:02:21Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=4000ab1decb6138a11fb4423237589376cb9ff54'/>
<id>urn:sha1:4000ab1decb6138a11fb4423237589376cb9ff54</id>
<content type='text'>
This is required for a follow-up commit that will add support for 8-byte
TOAST values, with this function being changed so as it is able to
support the largest TOAST value type available.

Most of the changes in this commit are in the regression tests that use
pg_column_toast_chunk_id(), that need to use some oid8-ish changes.  The
change is surprisingly not invasive as casts from oid to oid8 are
possible (the opposite cast oid8-&gt;oid is not supported).

Bump catalog version.

Author: Michael Paquier &lt;michael@paquier.xyz&gt;
Reviewed-by: Greg Burd &lt;greg@burd.me&gt;
Reviewed-by: Bharath Rupireddy &lt;bharath.rupireddyforpostgres@gmail.com&gt;
Reviewed-by: Yugo Nagata &lt;nagata@sraoss.co.jp&gt;
Discussion: https://postgr.es/m/af19kUjwjhaoUTLn@paquier.xy
</content>
</entry>
<entry>
<title>Fix crash on UPDATE or DELETE of a partition pending detach.</title>
<updated>2026-09-11T09:51:03Z</updated>
<author>
<name>Amit Kapila</name>
</author>
<published>2026-09-11T09:51:03Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=479a931155c6758831e57ba76f9671565c1e5553'/>
<id>urn:sha1:479a931155c6758831e57ba76f9671565c1e5553</id>
<content type='text'>
ALTER TABLE ... DETACH PARTITION ... CONCURRENTLY leaves the partition
marked as detach-pending if its wait is interrupted, and only DETACH
PARTITION ... FINALIZE clears that mark. In that state pg_class still says
relispartition while get_partition_ancestors() already reports nothing,
which RelationBuildPublicationDesc() was not ready for. It took
relispartition to mean that the ancestor list is not empty and asked for
its last element, which is an assertion failure, or a NULL pointer
dereference without assertions. CheckCmdReplicaIdentity() needs the
descriptor for every UPDATE and DELETE of a publishable relation and
builds it on first use, so no publication has to exist for this, and a
plain UPDATE crashes the backend.

Treat such a partition as a standalone table, as after the detach is
finalized. It is then published by FOR ALL TABLES publications, but cannot
be added to an EXCEPT clause until the detach completes, which is now
reported with a hint to run DETACH PARTITION ... FINALIZE.

Oversight in fd366065e06a, which added the exclusion.

Author: Mikhail Nikalayeu &lt;mihailnikalayeu@gmail.com&gt;
Author: shveta malik &lt;shveta.malik@gmail.com&gt;
Author: Nisha Moond &lt;nisha.moond412@gmail.com&gt;
Reviewed-by: shveta malik &lt;shveta.malik@gmail.com&gt;
Reviewed-by: Amit Kapila &lt;amit.kapila16@gmail.com&gt;
Reviewed-by: Zhijie Hou &lt;houzj.fnst@fujitsu.com&gt;
Reviewed-by: Álvaro Herrera &lt;alvherre@kurilemu.de&gt;
Reviewed-by: Nisha Moond &lt;nisha.moond412@gmail.com&gt;
Discussion: https://postgr.es/m/CADzfLwWoFPT%2Ba73%3DA%3DbsNWRMZQ98NpBEMgE%3Dt1FS4O4_%3DQVLfA%40mail.gmail.com
Backpatch-through: 19, where it was introduced
</content>
</entry>
<entry>
<title>Take RI fast-path snapshot after locking referenced relation</title>
<updated>2026-09-10T04:34:37Z</updated>
<author>
<name>Amit Langote</name>
</author>
<published>2026-09-10T04:31:09Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=3f660d86ba65d9747d5e2da418e24bd023271241'/>
<id>urn:sha1:3f660d86ba65d9747d5e2da418e24bd023271241</id>
<content type='text'>
ri_FastPathCheck() acquired its scan snapshot before opening the
referenced relation.  If it then waited for the relation lock in READ
COMMITTED mode, a referenced row committed during the wait would not be
visible to the old snapshot.  The check could consequently report a
foreign key violation even though the referenced row existed.

The batched path acquires its scan snapshot after opening the relations,
so it does not have the lock-wait problem.  The per-row path remains
reachable during constraint validation and checks re-entered from a
batch flush.

Take the snapshot after opening the referenced relation and reloading
the constraint information.  This also agrees with the SPI path, which
acquires the referenced-relation lock before selecting the snapshot
used for the check.

Also make the scan snapshot active for the duration of the check, so
STABLE cast and equality functions use the same snapshot as the index
scan.  Otherwise, a STABLE cast can miss rows inserted by earlier AFTER
triggers and cause a valid foreign key to be rejected.  Add a
regression test comparing this case with the SPI path.

Finally, also advance the command counter after acquiring the
referenced-relation lock and before reloading the constraint
information, so local invalidations are processed under the lock, as in
the SPI path.

Add an injection-point test that pauses a per-row check before locking
the referenced relation, commits the missing referenced row in another
session, and verifies that validation succeeds.  Force per-row
validation by using a role without SELECT privilege on the referenced
table, so the test exercises this path even with batching enabled.

Add isolation-test coverage for the visibility of a referenced row
committed after the referencing transaction has executed an earlier
command.  A later command can see such a row in READ COMMITTED, but not
in REPEATABLE READ or SERIALIZABLE.

Reviewed-by: Chao Li &lt;li.evan.chao@gmail.com&gt;
Reviewed-by: Amit Kapila &lt;amit.kapila16@gmail.com&gt;
Discussion: https://postgr.es/m/CA+HiwqEhm+_=bs=2wavAJz-UqC+1KebD31++mapJQQGweE8iQQ@mail.gmail.com
Backpatch-through: 19
</content>
</entry>
<entry>
<title>Fix concurrency issues with DROP TABLESPACE</title>
<updated>2026-09-09T15:03:39Z</updated>
<author>
<name>Andrew Dunstan</name>
</author>
<published>2026-09-09T14:50:09Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=a12600b762c36d91450ce085fa25ef75250bc1c2'/>
<id>urn:sha1:a12600b762c36d91450ce085fa25ef75250bc1c2</id>
<content type='text'>
DROP TABLESPACE checked pg_shdepend for dependent objects without
first locking the tablespace.  A concurrent command that recorded a
shared dependency on the tablespace right after that check could still
commit, leaving an object whose pg_shdepend entry (or, for a relation,
pg_class.reltablespace) pointed to a tablespace that no longer existed.

Close the race by having DropTableSpace() take an AccessExclusiveLock
on the tablespace before calling checkSharedDependencies().  That
conflicts with the AccessShareLock shdepLockAndCheckObject() takes when
recording a new dependency, so the loser of the race blocks and
rechecks once the winner commits.

That AccessExclusiveLock creates a new deadlock: ALTER TABLESPACE
RENAME/SET and the internal ACL/owner updates in DROP OWNED and
REASSIGN OWNED touched the catalog tuple without locking the
tablespace, risking a lock-order cycle with DROP.  Fix by taking an
AccessShareLock first in all four paths, rechecking pg_shdepend after
any wait in the DROP OWNED and REASSIGN OWNED cases.  GRANT, REVOKE,
and ALTER TABLESPACE ... OWNER TO already lock the object.

Add isolation tests covering both orderings of the original race
(dependency-first and drop-first) and all four previously-unlocked
update paths.

Author: Ayush Tiwari &lt;ayushtiwari.slg01@gmail.com&gt;
Reviewed-by: Andrew Dunstan &lt;andrew@dunslane.net&gt;
Discussion: https://postgr.es/m/CAJTYsWXjAQFnGKzXsht3XK8KHhyhontwFJw4JAHsUSfs_ptR4g@mail.gmail.com
Backpatch-through: 14
</content>
</entry>
<entry>
<title>Revert support for ALTER TABLE ... MERGE/SPLIT PARTITION(S) commands</title>
<updated>2026-08-26T21:56:41Z</updated>
<author>
<name>Alexander Korotkov</name>
</author>
<published>2026-08-26T21:56:41Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=7612ae8ed8c941985d9cbf60a0674c48f5b0abe5'/>
<id>urn:sha1:7612ae8ed8c941985d9cbf60a0674c48f5b0abe5</id>
<content type='text'>
This commit reverts f2e4cc4279 and 4b3d173629, and the subsequent fixes and
improvements c5ae07a90a, 713e553e32, 52e629be95, ecb2508aaf, 9354896920,
971017c495, 83df16f1fa, e64a9ba2b4, ff8bec8c46, cdae794af3, 57f19774d6, and
881033ae8b.  d8af730100 and 0392fb900e cancelled each other out and are not
reverted separately.

The feature is reverted due to multiple design issues which are too late to
address in this release cycle.

Discussion: https://postgr.es/m/CAN4CZFNCU%3Dt09M%3D%2Br2t9hHLJuujdM4oQ8hCK_Sx-GpfiwMAicw%40mail.gmail.com
</content>
</entry>
<entry>
<title>Fix cross-type foreign keys in the batched fast-path FK check</title>
<updated>2026-08-18T03:15:51Z</updated>
<author>
<name>Amit Langote</name>
</author>
<published>2026-08-18T03:15:51Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=cc449a504bfe50c91854727844b6fb1782a29417'/>
<id>urn:sha1:cc449a504bfe50c91854727844b6fb1782a29417</id>
<content type='text'>
ri_FastPathFlushArray() rechecked a concurrently updated PK tuple with a
scan key it built itself, putting found_val, the key of the tuple it had
just locked, into sk_argument, and passing that same slot to
recheck_matched_pk_tuple().  Both operands therefore came from the locked
tuple, and since sk_argument is the operator's right-hand input, the PK
value was read as an FK value.  For a foreign key using a cross-type
equality operator, such as a "date" primary key referenced by a "timestamp"
column, that compares days against microseconds, so the recheck always
failed and a batch that had to follow an update chain reported a violation
even though the version it locked still had the key.

Remove the recheck.  For a same-type key it compared the tuple against
itself and so never rejected anything, which was harmless only because the
loop a few lines below does the real work: it already compares found_val,
read after the chain has been followed, against every buffered FK value,
with the arguments in the order the operator expects.  That makes the
recheck redundant as well as wrong.  Detection is not weakened by dropping
it, since the buffered value that led the scan to a tuple can be matched by
no other row visible to our snapshot.

ri_FastPathProbeOne() passes its original scan key, with the FK value still
in sk_argument, and was never affected; nor were single-row statements or
multi-column foreign keys, which go through it.

Add an isolation test covering the cross-type case, a permutation where
the key really does move away, and a same-type permutation that should
behave identically.

Reported-by: Peter Geoghegan &lt;pg@bowt.ie&gt;
Co-authored-by: Peter Geoghegan &lt;pg@bowt.ie&gt;
Discussion: https://postgr.es/m/CAH2-WznQjX3GByh_Ju7unuzMcik_5PJ5D7i_=qhwk=gPEkhfVQ@mail.gmail.com
Backpatch-through: 19
</content>
</entry>
<entry>
<title>Handle nullable referenced key in RI fast-path check</title>
<updated>2026-08-07T08:45:59Z</updated>
<author>
<name>Amit Langote</name>
</author>
<published>2026-08-07T08:39:24Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=0ec3f048bfc15c8eb9933e8228b847593389da1b'/>
<id>urn:sha1:0ec3f048bfc15c8eb9933e8228b847593389da1b</id>
<content type='text'>
The RI fast-path FK check asserted that the referenced key is never
NULL, in ri_FastPathFlushArray() and in recheck_matched_pk_tuple().
That holds for a primary key, but a foreign key may reference any
unique column, and a UNIQUE column is nullable.

The assertion is reachable under READ COMMITTED.  ri_LockPKTuple()
locks the matched PK tuple with TUPLE_LOCK_FLAG_FIND_LAST_VERSION, so
when a concurrent transaction commits a key-changing UPDATE while the
check waits, the lock follows the update chain to the latest version.
If that version now has NULL in the referenced column, the fast path
reaches the assert; in a non-assert build it would compare against the
NULL and treat it as a match.

A NULL referenced key cannot equal any (non-null) FK value, so treat it
as no match and let the ordinary foreign-key violation be raised.  This
matches the SPI path, whose requalifying "pkatt = $n" evaluates to NULL
for such a row, so the row is not returned and the check reports a
violation.

Reported-by: Noah Misch &lt;noah@leadboat.com&gt;
Reviewed-by: Ayush Tiwari &lt;ayushtiwari.slg01@gmail.com&gt;
Discussion: https://postgr.es/m/20260705210533.ee.noahmisch@microsoft.com
Backpatch-through: 19
</content>
</entry>
<entry>
<title>Fix lock release for role membership grants in DROP OWNED BY.</title>
<updated>2026-08-03T19:21:05Z</updated>
<author>
<name>Jeff Davis</name>
</author>
<published>2026-08-03T19:21:05Z</published>
<link rel='alternate' type='text/html' href='http://git.postgresql.org/cgit/postgresql.git/commit/?id=b48caa7dfde8991ee09226593c381bd3442297dc'/>
<id>urn:sha1:b48caa7dfde8991ee09226593c381bd3442297dc</id>
<content type='text'>
Commit 6566133c5f5 added a case for AuthMemRelationId in
AcquireDeletionLock(), but not ReleaseDeletionLock(). The fall-through
case would go to UnlockDatabaseObject(), which would raise a WARNING;
and the lock would be retained until the end of the transaction.

Add the missing branch.

Discussion: https://postgr.es/m/2487ddcd737d4fc8e408e87aa9ad4365eed3bbb3.camel@j-davis.com
Backpatch-through: 16
</content>
</entry>
</feed>
