]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add isolation tests for UPDATE/DELETE FOR PORTION OF
authorPeter Eisentraut <peter@eisentraut.org>
Tue, 7 Apr 2026 09:07:59 +0000 (11:07 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Tue, 7 Apr 2026 09:22:11 +0000 (11:22 +0200)
Add documentation about concurrency issues related to UPDATE/DELETE
FOR PORTION OF as well as supporting isolation tests.

Author: Paul A. Jungwirth <pj@illuminatedcomputing.com>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://www.postgresql.org/message-id/flat/ec498c3d-5f2b-48ec-b989-5561c8aa2024%40illuminatedcomputing.com

doc/src/sgml/dml.sgml
doc/src/sgml/images/Makefile
doc/src/sgml/images/meson.build
doc/src/sgml/images/temporal-isolation.svg [new file with mode: 0644]
doc/src/sgml/images/temporal-isolation.txt [new file with mode: 0644]
src/backend/executor/nodeModifyTable.c
src/test/isolation/expected/for-portion-of.out [new file with mode: 0644]
src/test/isolation/isolation_schedule
src/test/isolation/specs/for-portion-of.spec [new file with mode: 0644]

index 86d3865ae90035ffc781ccd6f54e811593e36d7d..429aae9bd7b53296c0c1d053ac454df3990c88b5 100644 (file)
@@ -394,6 +394,44 @@ DELETE FROM products
    triggers are fired, but permission checks for inserting rows are
    skipped.
   </para>
+
+  <para>
+   In <literal>READ COMMITTED</literal> mode, temporal updates and deletes can
+   yield unexpected results when they concurrently touch the same row.  It is
+   possible to lose all or part of the second update or delete.  The scenario
+   is illustrated in <xref linkend="temporal-isolation-figure"/>.  Session 2
+   searches for rows to change, and it finds one that Session 1 has already
+   modified.  It waits for Session 1 to commit. Then it re-checks whether the
+   row still matches its search criteria (including the start/end times
+   targeted by <literal>FOR PORTION OF</literal>).  Session 1 may have changed
+   those times so that they no longer qualify.
+  </para>
+
+  <para>
+   In addition, the temporal leftovers inserted by Session 1 are not visible
+   within Session 2's transaction, because they are not yet committed.
+   Therefore there is nothing for Session 2 to update/delete: neither the
+   modified row nor the leftovers.  The portion of history that Session 2
+   intended to change is not affected.
+  </para>
+
+  <figure id="temporal-isolation-figure">
+   <title>Temporal Isolation Example</title>
+   <mediaobject>
+    <imageobject>
+     <imagedata fileref="images/temporal-isolation.svg" format="SVG" width="35%"/>
+    </imageobject>
+   </mediaobject>
+  </figure>
+
+  <para>
+   To solve these problems, precede every temporal update/delete with a
+   <literal>SELECT FOR UPDATE</literal> matching the same criteria (including
+   the targeted portion of application time).  That way the actual
+   update/delete doesn't begin until the lock is held, and all concurrent
+   leftovers will be visible.  In higher transaction isolation levels, this
+   lock is not required.
+  </para>
  </sect1>
 
  <sect1 id="dml-returning">
index 7b8ac0fbb323a9931f8e18065ec1160d518d0f78..9362c30998e2a1cab07980334353fd8a7001095e 100644 (file)
@@ -10,7 +10,8 @@ ALL_IMAGES = \
        temporal-entities.svg \
        temporal-references.svg \
        temporal-update.svg \
-       temporal-delete.svg
+       temporal-delete.svg \
+       temporal-isolation.svg
 
 DITAA = ditaa
 DOT = dot
index ea1fdee39015556db847a2cb14dea93964d3c494..220e3eaafb832d998a2cf3ffaa18542c3602669c 100644 (file)
@@ -18,6 +18,7 @@ all_files = [
   'temporal-references.txt',
   'temporal-update.txt',
   'temporal-delete.txt',
+  'temporal-isolation.txt',
 ]
 
 foreach file : all_files
diff --git a/doc/src/sgml/images/temporal-isolation.svg b/doc/src/sgml/images/temporal-isolation.svg
new file mode 100644 (file)
index 0000000..6f88c76
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 672" width="350" height="672" shape-rendering="geometricPrecision" version="1.0">
+  <defs>
+    <filter id="f2" x="0" y="0" width="200%" height="200%">
+      <feOffset result="offOut" in="SourceGraphic" dx="5" dy="5"/>
+      <feGaussianBlur result="blurOut" in="offOut" stdDeviation="3"/>
+      <feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
+    </filter>
+  </defs>
+  <g stroke-width="1" stroke-linecap="square" stroke-linejoin="round">
+    <rect x="0" y="0" width="350" height="672" style="fill: #ffffff"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#ffff33" d="M205.0 301.0 L205.0 371.0 L325.0 371.0 L325.0 301.0 z"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#ffff33" d="M325.0 469.0 L325.0 539.0 L205.0 539.0 L205.0 469.0 z"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#99dd99" d="M25.0 35.0 L25.0 91.0 L145.0 91.0 L145.0 35.0 z"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#99dd99" d="M25.0 133.0 L25.0 189.0 L145.0 189.0 L145.0 133.0 z"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#99dd99" d="M25.0 287.0 L145.0 287.0 L145.0 231.0 L25.0 231.0 z"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#ffff33" d="M205.0 133.0 L205.0 189.0 L325.0 189.0 L325.0 133.0 z"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#ffff33" d="M325.0 581.0 L205.0 581.0 L205.0 637.0 L325.0 637.0 z"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#ffff33" d="M205.0 91.0 L325.0 91.0 L325.0 35.0 L205.0 35.0 z"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#99dd99" d="M145.0 399.0 L145.0 455.0 L25.0 455.0 L25.0 399.0 z"/>
+    <path stroke="none" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#000000" d="M80.0 112.0 L85.0 126.0 L90.0 112.0 z"/>
+    <path stroke="none" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#000000" d="M260.0 112.0 L265.0 126.0 L270.0 112.0 z"/>
+    <path stroke="none" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#000000" d="M80.0 210.0 L85.0 224.0 L90.0 210.0 z"/>
+    <path stroke="none" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#000000" d="M260.0 280.0 L265.0 294.0 L270.0 280.0 z"/>
+    <path stroke="none" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#000000" d="M80.0 378.0 L85.0 392.0 L90.0 378.0 z"/>
+    <path stroke="none" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#000000" d="M260.0 448.0 L265.0 462.0 L270.0 448.0 z"/>
+    <path stroke="none" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="#000000" d="M260.0 560.0 L265.0 574.0 L270.0 560.0 z"/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="none" d="M85.0 91.0 L85.0 119.0 "/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="none" d="M85.0 189.0 L85.0 217.0 "/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="none" d="M265.0 539.0 L265.0 567.0 "/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="none" d="M265.0 91.0 L265.0 119.0 "/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="none" d="M265.0 371.0 L265.0 455.0 "/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="none" d="M85.0 385.0 L85.0 287.0 "/>
+    <path stroke="#000000" stroke-width="1.000000" stroke-linecap="round" stroke-linejoin="round" fill="none" d="M265.0 189.0 L265.0 287.0 "/>
+    <text x="46" y="68" font-family="Courier" font-size="13" stroke="none" fill="#000000">Session 1</text>
+    <text x="220" y="334" font-family="Courier" font-size="13" stroke="none" fill="#000000">UPDATE;</text>
+    <text x="220" y="348" font-family="Courier" font-size="13" stroke="none" fill="#000000">waits...</text>
+    <text x="48" y="166" font-family="Courier" font-size="13" stroke="none" fill="#000000">BEGIN;</text>
+    <text x="228" y="166" font-family="Courier" font-size="13" stroke="none" fill="#000000">BEGIN;</text>
+    <text x="226" y="68" font-family="Courier" font-size="13" stroke="none" fill="#000000">Session 2</text>
+    <text x="47" y="264" font-family="Courier" font-size="13" stroke="none" fill="#000000">UPDATE;</text>
+    <text x="46" y="432" font-family="Courier" font-size="13" stroke="none" fill="#000000">COMMIT;</text>
+    <text x="226" y="614" font-family="Courier" font-size="13" stroke="none" fill="#000000">COMMIT;</text>
+    <text x="220" y="502" font-family="Courier" font-size="13" stroke="none" fill="#000000">...resumes</text>
+    <text x="220" y="516" font-family="Courier" font-size="13" stroke="none" fill="#000000">rechecks</text>
+  </g>
+</svg>
diff --git a/doc/src/sgml/images/temporal-isolation.txt b/doc/src/sgml/images/temporal-isolation.txt
new file mode 100644 (file)
index 0000000..870db7b
--- /dev/null
@@ -0,0 +1,44 @@
++-----------+     +-----------+
+| cGRE      |     | cYEL      |
+|Session 1  |     |Session 2  |
+|           |     |           |
++-----+-----+     +-----+-----+
+      |                 |
+      v                 v
++-----+-----+     +-----+-----+
+| cGRE      |     | cYEL      |
+| BEGIN;    |     | BEGIN;    |
+|           |     |           |
++-----+-----+     +-----+-----+
+      |                 |
+      v                 |
++-----+-----+           |
+| cGRE      |           |
+| UPDATE;   |           |
+|           |           |
++-----+-----+           v
+      |           +-----+-----+
+      |           | cYEL      |
+      |           | UPDATE;   |
+      |           | waits...  |
+      |           |           |
+      |           +-----+-----+
+      v                 |
++-----+-----+           |
+| cGRE      |           |
+| COMMIT;   |           |
+|           |           |
++-----------+           v
+                  +-----+-----+
+                  | cYEL      |
+                  | ...resumes|
+                  | rechecks  |
+                  |           |
+                  +-----+-----+
+                        |
+                        v
+                  +-----+-----+
+                  | cYEL      |
+                  | COMMIT;   |
+                  |           |
+                  +-----------+
index dfd7b33aa9b5dbc51dc89f0a8e7ba975fe470b41..ef2a6bc6e9d11dee0c4d0fa2c6f92fdf012c99ec 100644 (file)
@@ -1465,6 +1465,10 @@ ExecForPortionOfLeftovers(ModifyTableContext *context,
         * We have already locked the tuple in ExecUpdate/ExecDelete, and it has
         * passed EvalPlanQual. This ensures that concurrent updates in READ
         * COMMITTED can't insert conflicting temporal leftovers.
+        *
+        * It does *not* protect against concurrent update/deletes overlooking
+        * each others' leftovers though. See our isolation tests for details
+        * about that and a viable workaround.
         */
        if (!table_tuple_fetch_row_version(resultRelInfo->ri_RelationDesc, tupleid, SnapshotAny, oldtupleSlot))
                elog(ERROR, "failed to fetch tuple for FOR PORTION OF");
diff --git a/src/test/isolation/expected/for-portion-of.out b/src/test/isolation/expected/for-portion-of.out
new file mode 100644 (file)
index 0000000..2438c46
--- /dev/null
@@ -0,0 +1,4089 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1rc s2rc s2lock2027 s2upd2027 s2c s1lock2025 s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rc s2rc s2lock202503 s2upd202503 s2c s1lock2025 s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(3 rows)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-03-01,2025-04-01)| 8.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rc s2rc s2lock20252026 s2upd20252026 s2c s1lock2025 s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2025-06-01,2026-06-01)|10.00
+(2 rows)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2025-06-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1upd2025 s1c s2lock2027 s2upd2027 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1upd2025 s1c s2lock202503 s2upd202503 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+(1 row)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1upd2025 s1c s2lock20252026 s2upd20252026 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2025-06-01,2026-01-01)|10.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rc s2rc s2upd2027 s1upd2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2lock2027 s2upd2027 s1lock2025 s2c s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rc s2rc s2upd202503 s1upd2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-03-01,2025-04-01)| 8.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2lock202503 s2upd202503 s1lock2025 s2c s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2025-03-01,2025-04-01)|10.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-03-01,2025-04-01)| 8.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rc s2rc s2upd20252026 s1upd2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2025-06-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s2lock20252026 s2upd20252026 s1lock2025 s2c s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2025-06-01,2026-06-01)|10.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2025-06-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rc s2rc s2lock2027 s2del2027 s2c s1lock2025 s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s2lock202503 s2del202503 s2c s1lock2025 s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s2lock20252026 s2del20252026 s2c s1lock2025 s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1upd2025 s1c s2lock2027 s2del2027 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1upd2025 s1c s2lock202503 s2del202503 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+(1 row)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1upd2025 s1c s2lock20252026 s2del20252026 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2del2027 s1upd2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2lock2027 s2del2027 s1lock2025 s2c s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s2del202503 s1upd2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2lock202503 s2del202503 s1lock2025 s2c s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s2del20252026 s1upd2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2lock20252026 s2del20252026 s1lock2025 s2c s1upd2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2lock2027 s2upd2027 s2c s1lock2025 s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s2lock202503 s2upd202503 s2c s1lock2025 s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(3 rows)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2lock20252026 s2upd20252026 s2c s1lock2025 s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2025-06-01,2026-06-01)|10.00
+(2 rows)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1del2025 s1c s2lock2027 s2upd2027 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1del2025 s1c s2lock202503 s2upd202503 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1del2025 s1c s2lock20252026 s2upd20252026 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2upd2027 s1del2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2lock2027 s2upd2027 s1lock2025 s2c s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rc s2rc s2upd202503 s1del2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2lock202503 s2upd202503 s1lock2025 s2c s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2025-03-01,2025-04-01)|10.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2upd20252026 s1del2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2lock20252026 s2upd20252026 s1lock2025 s2c s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2025-06-01,2026-06-01)|10.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2lock2027 s2del2027 s2c s1lock2025 s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2lock202503 s2del202503 s2c s1lock2025 s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2lock20252026 s2del20252026 s2c s1lock2025 s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1del2025 s1c s2lock2027 s2del2027 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1del2025 s1c s2lock202503 s2del202503 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s1lock2025 s1del2025 s1c s2lock20252026 s2del20252026 s2c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2del2027 s1del2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2lock2027 s2del2027 s1lock2025 s2c s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock2027: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rc s2rc s2del202503 s1del2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2lock202503 s2del202503 s1lock2025 s2c s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock202503: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2del20252026 s1del2025 s2c s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rc s2rc s2lock20252026 s2del20252026 s1lock2025 s2c s1del2025 s1c s1q
+step s1rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2rc: BEGIN ISOLATION LEVEL READ COMMITTED;
+step s2lock20252026: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s1lock2025: 
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+ <waiting ...>
+step s2c: COMMIT;
+step s1lock2025: <... completed>
+id|valid_at|price
+--+--------+-----
+(0 rows)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s2upd2027 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rr s2rr s2upd202503 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-03-01,2025-04-01)| 8.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rr s2rr s2upd20252026 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2025-06-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rr s2rr s1upd2025 s1c s2upd2027 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rr s2rr s1upd2025 s1c s2upd202503 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rr s2rr s1upd2025 s1c s2upd20252026 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2025-06-01,2026-01-01)|10.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rr s2rr s2upd2027 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s2upd202503 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s2upd20252026 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2025-06-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd2027 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd202503 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd20252026 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2025-06-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s1upd2025 s1c s2upd2027 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rr s2rr s1q s1upd2025 s1c s2upd202503 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rr s2rr s1q s1upd2025 s1c s2upd20252026 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2025-06-01,2026-01-01)|10.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd2027 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd202503 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd20252026 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2025-06-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s2del2027 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rr s2rr s2del202503 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rr s2rr s2del20252026 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1upd2025 s1c s2del2027 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rr s2rr s1upd2025 s1c s2del202503 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rr s2rr s1upd2025 s1c s2del20252026 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s2del2027 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s2del202503 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s2del20252026 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del2027 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del202503 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del20252026 s2c s1upd2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s1upd2025 s1c s2del2027 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rr s2rr s1q s1upd2025 s1c s2del202503 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-03-01)| 8.00
+[1,2)|[2025-04-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rr s2rr s1q s1upd2025 s1c s2del20252026 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del2027 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del202503 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del20252026 s1upd2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1upd2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s2upd2027 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rr s2rr s2upd202503 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s2upd20252026 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1del2025 s1c s2upd2027 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rr s2rr s1del2025 s1c s2upd202503 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1del2025 s1c s2upd20252026 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s2upd2027 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s2upd202503 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s2upd20252026 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2025-06-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd2027 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd202503 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd20252026 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2025-06-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s1del2025 s1c s2upd2027 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(4 rows)
+
+
+starting permutation: s1rr s2rr s1q s1del2025 s1c s2upd202503 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s1del2025 s1c s2upd20252026 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd2027 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd202503 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd202503: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-03-01,2025-04-01)|10.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s2upd20252026 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent update
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2025-06-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s2del2027 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s2del202503 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s2del20252026 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1del2025 s1c s2del2027 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1del2025 s1c s2del202503 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1del2025 s1c s2del20252026 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s2del2027 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s2del202503 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s2del20252026 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del2027 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del202503 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del20252026 s2c s1del2025 s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s1del2025 s1c s2del2027 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(3 rows)
+
+
+starting permutation: s1rr s2rr s1q s1del2025 s1c s2del202503 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s1del2025 s1c s2del20252026 s2c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del2027 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del2027: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2027-01-01)| 5.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del202503 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del202503: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-03-01)| 5.00
+[1,2)|[2025-04-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1rr s2rr s1q s2del20252026 s1del2025 s2c s1c s1q
+step s1rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s2rr: BEGIN ISOLATION LEVEL REPEATABLE READ;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2030-01-01)| 5.00
+(1 row)
+
+step s2del20252026: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+
+step s1del2025: 
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+ <waiting ...>
+step s2c: COMMIT;
+step s1del2025: <... completed>
+ERROR:  could not serialize access due to concurrent delete
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-06-01)| 5.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(2 rows)
+
+
+starting permutation: s1ser s2ser s2upd2027 s2c s1upd2025 s1c s1q
+step s1ser: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2ser: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2upd2027: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2027-01-01)| 5.00
+[1,2)|[2027-01-01,2028-01-01)|10.00
+[1,2)|[2028-01-01,2030-01-01)| 5.00
+(5 rows)
+
+
+starting permutation: s1ser s2ser s2upd20252026 s2c s1upd2025 s1c s1q
+step s1ser: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2ser: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s2upd20252026: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+
+step s2c: COMMIT;
+step s1upd2025: 
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+
+step s1c: COMMIT;
+step s1q: SELECT * FROM products ORDER BY id, valid_at;
+id   |valid_at               |price
+-----+-----------------------+-----
+[1,2)|[2020-01-01,2025-01-01)| 5.00
+[1,2)|[2025-01-01,2025-06-01)| 8.00
+[1,2)|[2025-06-01,2026-01-01)| 8.00
+[1,2)|[2026-01-01,2026-06-01)|10.00
+[1,2)|[2026-06-01,2030-01-01)| 5.00
+(5 rows)
+
index c1a999bf1d235864d6c2808555d38ebd8b9f488d..1578ba191c80121a79210e974500c88569434eae 100644 (file)
@@ -125,3 +125,4 @@ test: serializable-parallel-2
 test: serializable-parallel-3
 test: matview-write-skew
 test: lock-nowait
+test: for-portion-of
diff --git a/src/test/isolation/specs/for-portion-of.spec b/src/test/isolation/specs/for-portion-of.spec
new file mode 100644 (file)
index 0000000..1ab9b25
--- /dev/null
@@ -0,0 +1,597 @@
+# UPDATE/DELETE FOR PORTION OF test
+#
+# Test inserting temporal leftovers from a FOR PORTION OF update/delete.
+#
+# In READ COMMITTED mode, concurrent updates/deletes to the same records cause
+# weird results. Portions of history that should have been updated/deleted don't
+# get changed. That's because the leftovers from one operation are added too
+# late to be seen by the other. EvalPlanQual will reload the changed-in-common
+# row, but it won't re-scan to find new leftovers.
+#
+# MariaDB similarly gives undesirable results in READ COMMITTED mode (although
+# not the same results). DB2 doesn't have READ COMMITTED, but it gives correct
+# results at all levels, in particular READ STABILITY (which seems closest).
+#
+# A workaround is to lock the part of history you want before changing it (using
+# SELECT FOR UPDATE). That way the search for rows is late enough to see
+# leftovers from the other session(s). This shouldn't impose any new deadlock
+# risks, since the locks are the same as before. Adding a third/fourth/etc.
+# connection also doesn't change the semantics. The READ COMMITTED tests here
+# demonstrate the problem and also show that solving it with manual locks is
+# viable and not vitiated by any bugs. Incidentally, this approach also works in
+# MariaDB.
+#
+# We run the same tests under REPEATABLE READ to show the problem goes away.
+# In general they do what you'd want with no explicit locking required, but some
+# orderings raise a concurrent update/delete failure (as expected). If there is
+# a prior read by s1, concurrent update/delete failures are more common.
+#
+# To save on test time, we only run a couple SERIALIZABLE tests (for the more
+# problematic permutations).
+#
+# We test updates where s2 updates history that is:
+#
+# - non-overlapping with s1,
+# - contained entirely in s1,
+# - partly contained in s1.
+#
+# We don't need to test where s2 entirely contains s1 because of symmetry:
+# we test both when s1 precedes s2 and when s2 precedes s1,  so that scenario is
+# covered.
+#
+# We test various orderings of the update/delete/commit from s1 and s2.
+# Note that `s1lock s2lock s1change` is boring because it's the same as
+# `s1lock s1change s2lock`. In other words it doesn't matter if something
+# interposes between the lock and its change (as long as everyone is following
+# the same policy).
+
+setup
+{
+  CREATE TABLE products (
+       id int4range NOT NULL,
+       valid_at daterange NOT NULL,
+       price decimal NOT NULL,
+       PRIMARY KEY (id, valid_at WITHOUT OVERLAPS));
+  INSERT INTO products VALUES
+       ('[1,2)', '[2020-01-01,2030-01-01)', 5.00);
+}
+
+teardown { DROP TABLE products; }
+
+session s1
+setup          { SET datestyle TO ISO, YMD; }
+step s1rc      { BEGIN ISOLATION LEVEL READ COMMITTED; }
+step s1rr      { BEGIN ISOLATION LEVEL REPEATABLE READ; }
+step s1ser     { BEGIN ISOLATION LEVEL SERIALIZABLE; }
+step s1lock2025 {
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-01-01,2026-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+}
+step s1upd2025 {
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  SET price = 8.00
+  WHERE id = '[1,2)';
+}
+step s1del2025 {
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-01-01' TO '2026-01-01'
+  WHERE id = '[1,2)';
+}
+step s1q       { SELECT * FROM products ORDER BY id, valid_at; }
+step s1c       { COMMIT; }
+
+session s2
+setup          { SET datestyle TO ISO, YMD; }
+step s2rc      { BEGIN ISOLATION LEVEL READ COMMITTED; }
+step s2rr      { BEGIN ISOLATION LEVEL REPEATABLE READ; }
+step s2ser     { BEGIN ISOLATION LEVEL SERIALIZABLE; }
+step s2lock202503 {
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-03-01,2025-04-01)'
+  ORDER BY valid_at FOR UPDATE;
+}
+step s2lock20252026 {
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2025-06-01,2026-06-01)'
+  ORDER BY valid_at FOR UPDATE;
+}
+step s2lock2027 {
+  SELECT * FROM products
+  WHERE id = '[1,2)' AND valid_at && '[2027-01-01,2028-01-01)'
+  ORDER BY valid_at FOR UPDATE;
+}
+step s2upd202503 {
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+}
+step s2upd20252026 {
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+}
+step s2upd2027 {
+  UPDATE products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  SET price = 10.00
+  WHERE id = '[1,2)';
+}
+step s2del202503 {
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-04-01'
+  WHERE id = '[1,2)';
+}
+step s2del20252026 {
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2025-06-01' TO '2026-06-01'
+  WHERE id = '[1,2)';
+}
+step s2del2027 {
+  DELETE FROM products
+  FOR PORTION OF valid_at FROM '2027-01-01' TO '2028-01-01'
+  WHERE id = '[1,2)';
+}
+step s2c       { COMMIT; }
+
+# ########################################
+# READ COMMITTED tests, UPDATE+UPDATE:
+# ########################################
+
+# s1 sees the leftovers
+permutation s1rc s2rc s2lock2027 s2upd2027 s2c s1lock2025 s1upd2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rc s2rc s2lock202503 s2upd202503 s2c s1lock2025 s1upd2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rc s2rc s2lock20252026 s2upd20252026 s2c s1lock2025 s1upd2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rc s2rc s1lock2025 s1upd2025 s1c s2lock2027 s2upd2027 s2c s1q
+
+# s2 loads the updated row
+permutation s1rc s2rc s1lock2025 s1upd2025 s1c s2lock202503 s2upd202503 s2c s1q
+
+# s2 loads the updated row and sees its leftovers
+permutation s1rc s2rc s1lock2025 s1upd2025 s1c s2lock20252026 s2upd20252026 s2c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# and EvalPlanQual no longer matches the row to be updated either.
+permutation s1rc s2rc s2upd2027 s1upd2025 s2c s1c s1q
+
+# Workaround:
+# s1 updates the leftovers from s2
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock2027 s2upd2027 s1lock2025 s2c s1upd2025 s1c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# but EvalPlanQual still matches the row to be updated.
+permutation s1rc s2rc s2upd202503 s1upd2025 s2c s1c s1q
+
+# Workaround:
+# s1 overwrites the row from s2 and sees its leftovers
+permutation s1rc s2rc s2lock202503 s2upd202503 s1lock2025 s2c s1upd2025 s1c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# but EvalPlanQual still matches the row to be updated,
+# and s1's leftovers don't conflict with s2's.
+permutation s1rc s2rc s2upd20252026 s1upd2025 s2c s1c s1q
+
+# Workaround:
+# s1 overwrites the row from s2 and sees its leftovers
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock20252026 s2upd20252026 s1lock2025 s2c s1upd2025 s1c s1q
+
+# ########################################
+# READ COMMITTED tests, UPDATE+DELETE:
+# ########################################
+
+# s1 sees the leftovers
+permutation s1rc s2rc s2lock2027 s2del2027 s2c s1lock2025 s1upd2025 s1c s1q
+
+# s1 ignores the deleted row and sees its leftovers
+permutation s1rc s2rc s2lock202503 s2del202503 s2c s1lock2025 s1upd2025 s1c s1q
+
+# s1 ignores the deleted row and sees its leftovers
+permutation s1rc s2rc s2lock20252026 s2del20252026 s2c s1lock2025 s1upd2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rc s2rc s1lock2025 s1upd2025 s1c s2lock2027 s2del2027 s2c s1q
+
+# s2 loads the updated row
+permutation s1rc s2rc s1lock2025 s1upd2025 s1c s2lock202503 s2del202503 s2c s1q
+
+# s2 loads the updated row and sees its leftovers
+permutation s1rc s2rc s1lock2025 s1upd2025 s1c s2lock20252026 s2del20252026 s2c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# and EvalPlanQual no longer matches the row to be updated either.
+permutation s1rc s2rc s2del2027 s1upd2025 s2c s1c s1q
+
+# Workaround:
+# s1 updates the leftovers from s2
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock2027 s2del2027 s1lock2025 s2c s1upd2025 s1c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# and EvalPlanQual no longer matches the row to be updated either.
+permutation s1rc s2rc s2del202503 s1upd2025 s2c s1c s1q
+
+# Workaround:
+# s1 sees the leftovers from s2
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock202503 s2del202503 s1lock2025 s2c s1upd2025 s1c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# and EvalPlanQual no longer matches the row to be updated either.
+permutation s1rc s2rc s2del20252026 s1upd2025 s2c s1c s1q
+
+# Workaround:
+# s1 sees the leftovers from s2
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock20252026 s2del20252026 s1lock2025 s2c s1upd2025 s1c s1q
+
+# ########################################
+# READ COMMITTED tests, DELETE+UPDATE:
+# ########################################
+
+# s1 sees the leftovers
+permutation s1rc s2rc s2lock2027 s2upd2027 s2c s1lock2025 s1del2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rc s2rc s2lock202503 s2upd202503 s2c s1lock2025 s1del2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rc s2rc s2lock20252026 s2upd20252026 s2c s1lock2025 s1del2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rc s2rc s1lock2025 s1del2025 s1c s2lock2027 s2upd2027 s2c s1q
+
+# s2 ignores the deleted row
+permutation s1rc s2rc s1lock2025 s1del2025 s1c s2lock202503 s2upd202503 s2c s1q
+
+# s2 ignores the deleted row and sees its leftovers
+permutation s1rc s2rc s1lock2025 s1del2025 s1c s2lock20252026 s2upd20252026 s2c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# and EvalPlanQual no longer matches the row to be deleted either.
+permutation s1rc s2rc s2upd2027 s1del2025 s2c s1c s1q
+
+# Workaround:
+# s1 deletes the leftovers from s2
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock2027 s2upd2027 s1lock2025 s2c s1del2025 s1c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# but EvalPlanQual still matches the row to be deleted.
+permutation s1rc s2rc s2upd202503 s1del2025 s2c s1c s1q
+
+# Workaround:
+# s1 deletes the new row from s2 and its leftovers
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock202503 s2upd202503 s1lock2025 s2c s1del2025 s1c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# but EvalPlanQual still matches the row to be deleted,
+# and s1 leaves leftovers from the row created by s2.
+permutation s1rc s2rc s2upd20252026 s1del2025 s2c s1c s1q
+
+# Workaround:
+# s1 deletes the new row from s2 and its leftovers
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock20252026 s2upd20252026 s1lock2025 s2c s1del2025 s1c s1q
+
+# ########################################
+# READ COMMITTED tests, DELETE+DELETE:
+# ########################################
+
+# s1 sees the leftovers
+permutation s1rc s2rc s2lock2027 s2del2027 s2c s1lock2025 s1del2025 s1c s1q
+
+# s1 ignores the deleted row and sees its leftovers
+permutation s1rc s2rc s2lock202503 s2del202503 s2c s1lock2025 s1del2025 s1c s1q
+
+# s1 ignores the deleted row and sees its leftovers
+permutation s1rc s2rc s2lock20252026 s2del20252026 s2c s1lock2025 s1del2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rc s2rc s1lock2025 s1del2025 s1c s2lock2027 s2del2027 s2c s1q
+
+# s2 ignores the deleted row
+permutation s1rc s2rc s1lock2025 s1del2025 s1c s2lock202503 s2del202503 s2c s1q
+
+# s2 ignores the deleted row and sees its leftovers
+permutation s1rc s2rc s1lock2025 s1del2025 s1c s2lock20252026 s2del20252026 s2c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# and EvalPlanQual no longer matches the row to be deleted either.
+permutation s1rc s2rc s2del2027 s1del2025 s2c s1c s1q
+
+# Workaround:
+# s1 deletes the leftovers from s2
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock2027 s2del2027 s1lock2025 s2c s1del2025 s1c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# and EvalPlanQual no longer matches the row to be deleted either.
+permutation s1rc s2rc s2del202503 s1del2025 s2c s1c s1q
+
+# Workaround:
+# s1 deletes the leftovers from s2
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock202503 s2del202503 s1lock2025 s2c s1del2025 s1c s1q
+
+# Problem:
+# s1 (without locking) overlooks the leftovers from s2
+# and EvalPlanQual no longer matches the row to be deleted either.
+permutation s1rc s2rc s2del20252026 s1del2025 s2c s1c s1q
+
+# Workaround:
+# s1 deletes the leftovers from s2
+# Locking is required or s1 won't see the leftovers.
+permutation s1rc s2rc s2lock20252026 s2del20252026 s1lock2025 s2c s1del2025 s1c s1q
+
+# ########################################
+# REPEATABLE READ tests, UPDATE+UPDATE:
+# ########################################
+
+# s1 sees the leftovers
+permutation s1rr s2rr s2upd2027 s2c s1upd2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rr s2rr s2upd202503 s2c s1upd2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rr s2rr s2upd20252026 s2c s1upd2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rr s2rr s1upd2025 s1c s2upd2027 s2c s1q
+
+# s2 loads the updated row and sees its leftovers
+permutation s1rr s2rr s1upd2025 s1c s2upd202503 s2c s1q
+
+# s2 loads the updated row and sees its leftovers
+permutation s1rr s2rr s1upd2025 s1c s2upd20252026 s2c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s2upd2027 s1upd2025 s2c s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s2upd202503 s1upd2025 s2c s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s2upd20252026 s1upd2025 s2c s1c s1q
+
+## with prior read by s1:
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd2027 s2c s1upd2025 s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd202503 s2c s1upd2025 s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd20252026 s2c s1upd2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rr s2rr s1q s1upd2025 s1c s2upd2027 s2c s1q
+
+# s2 loads the updated row
+permutation s1rr s2rr s1q s1upd2025 s1c s2upd202503 s2c s1q
+
+# s2 loads the updated row and sees its leftovers
+permutation s1rr s2rr s1q s1upd2025 s1c s2upd20252026 s2c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd2027 s1upd2025 s2c s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd202503 s1upd2025 s2c s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd20252026 s1upd2025 s2c s1c s1q
+
+# ########################################
+# REPEATABLE READ tests, UPDATE+DELETE:
+# ########################################
+
+# s1 sees the leftovers
+permutation s1rr s2rr s2del2027 s2c s1upd2025 s1c s1q
+
+# s1 ignores the deleted row and sees its leftovers
+permutation s1rr s2rr s2del202503 s2c s1upd2025 s1c s1q
+
+# s1 ignores the deleted row and sees its leftovers
+permutation s1rr s2rr s2del20252026 s2c s1upd2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rr s2rr s1upd2025 s1c s2del2027 s2c s1q
+
+# s2 loads the updated row
+permutation s1rr s2rr s1upd2025 s1c s2del202503 s2c s1q
+
+# s2 loads the updated row and sees its leftovers
+permutation s1rr s2rr s1upd2025 s1c s2del20252026 s2c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s2del2027 s1upd2025 s2c s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s2del202503 s1upd2025 s2c s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s2del20252026 s1upd2025 s2c s1c s1q
+
+## with prior read by s1:
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del2027 s2c s1upd2025 s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del202503 s2c s1upd2025 s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del20252026 s2c s1upd2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rr s2rr s1q s1upd2025 s1c s2del2027 s2c s1q
+
+# s2 loads the updated row
+permutation s1rr s2rr s1q s1upd2025 s1c s2del202503 s2c s1q
+
+# s2 loads the updated row and sees its leftovers
+permutation s1rr s2rr s1q s1upd2025 s1c s2del20252026 s2c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del2027 s1upd2025 s2c s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del202503 s1upd2025 s2c s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del20252026 s1upd2025 s2c s1c s1q
+
+# ########################################
+# REPEATABLE READ tests, DELETE+UPDATE:
+# ########################################
+
+# s1 sees the leftovers
+permutation s1rr s2rr s2upd2027 s2c s1del2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rr s2rr s2upd202503 s2c s1del2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rr s2rr s2upd20252026 s2c s1del2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rr s2rr s1del2025 s1c s2upd2027 s2c s1q
+
+# s2 ignores the deleted row
+permutation s1rr s2rr s1del2025 s1c s2upd202503 s2c s1q
+
+# s2 ignores the deleted row and sees its leftovers
+permutation s1rr s2rr s1del2025 s1c s2upd20252026 s2c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s2upd2027 s1del2025 s2c s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s2upd202503 s1del2025 s2c s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s2upd20252026 s1del2025 s2c s1c s1q
+
+## with prior read by s1:
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd2027 s2c s1del2025 s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd202503 s2c s1del2025 s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd20252026 s2c s1del2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rr s2rr s1q s1del2025 s1c s2upd2027 s2c s1q
+
+# s2 ignores the deleted row
+permutation s1rr s2rr s1q s1del2025 s1c s2upd202503 s2c s1q
+
+# s2 ignores the deleted row and sees its leftovers
+permutation s1rr s2rr s1q s1del2025 s1c s2upd20252026 s2c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd2027 s1del2025 s2c s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd202503 s1del2025 s2c s1c s1q
+
+# s1 fails from concurrent update
+permutation s1rr s2rr s1q s2upd20252026 s1del2025 s2c s1c s1q
+
+# ########################################
+# REPEATABLE READ tests, DELETE+DELETE:
+# ########################################
+
+# s1 sees the leftovers
+permutation s1rr s2rr s2del2027 s2c s1del2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rr s2rr s2del202503 s2c s1del2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1rr s2rr s2del20252026 s2c s1del2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rr s2rr s1del2025 s1c s2del2027 s2c s1q
+
+# s2 ignores the deleted row
+permutation s1rr s2rr s1del2025 s1c s2del202503 s2c s1q
+
+# s2 ignores the deleted row and sees its leftovers
+permutation s1rr s2rr s1del2025 s1c s2del20252026 s2c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s2del2027 s1del2025 s2c s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s2del202503 s1del2025 s2c s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s2del20252026 s1del2025 s2c s1c s1q
+
+## with prior read by s1:
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del2027 s2c s1del2025 s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del202503 s2c s1del2025 s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del20252026 s2c s1del2025 s1c s1q
+
+# s2 sees the leftovers
+permutation s1rr s2rr s1q s1del2025 s1c s2del2027 s2c s1q
+
+# s2 ignores the deleted row
+permutation s1rr s2rr s1q s1del2025 s1c s2del202503 s2c s1q
+
+# s2 ignores the deleted row and sees its leftovers
+permutation s1rr s2rr s1q s1del2025 s1c s2del20252026 s2c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del2027 s1del2025 s2c s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del202503 s1del2025 s2c s1c s1q
+
+# s1 fails from concurrent delete
+permutation s1rr s2rr s1q s2del20252026 s1del2025 s2c s1c s1q
+
+# ########################################
+# SERIALIZABLE tests, UPDATE+UPDATE:
+# ########################################
+
+# s1 sees the leftovers
+permutation s1ser s2ser s2upd2027 s2c s1upd2025 s1c s1q
+
+# s1 reloads the updated row and sees its leftovers
+permutation s1ser s2ser s2upd20252026 s2c s1upd2025 s1c s1q