v1-0001-Triggering-Assert-on-query-with-ON-CONFLICT.no_cfbot

text/plain

Filename: v1-0001-Triggering-Assert-on-query-with-ON-CONFLICT.no_cfbot
Type: text/plain
Part: 0
Message: Re: Assert when executing query on partitioned table
From 8780e66fc759872e06746c9c214dec52644b2e93 Mon Sep 17 00:00:00 2001
From: Koval Dmitry <d.koval@postgrespro.ru>
Date: Wed, 19 Feb 2025 13:09:33 +0300
Subject: [PATCH v1] Triggering Assert on query with ON CONFLICT

---
 src/backend/executor/nodeModifyTable.c        |  1 +
 src/test/modules/injection_points/Makefile    |  6 +++-
 .../injection_points/expected/onconflict.out  | 23 ++++++++++++++
 .../injection_points/specs/onconflict.spec    | 30 +++++++++++++++++++
 4 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 src/test/modules/injection_points/expected/onconflict.out
 create mode 100644 src/test/modules/injection_points/specs/onconflict.spec

diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 874b71e660..d131abcd67 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1148,6 +1148,7 @@ ExecInsert(ModifyTableContext *context,
 					 */
 					TupleTableSlot *returning = NULL;
 
+					INJECTION_POINT("before-on-conflict-update", NULL);
 					if (ExecOnConflictUpdate(context, resultRelInfo,
 											 &conflictTid, slot, canSetTag,
 											 &returning))
diff --git a/src/test/modules/injection_points/Makefile b/src/test/modules/injection_points/Makefile
index bfdb3f5337..5420850b39 100644
--- a/src/test/modules/injection_points/Makefile
+++ b/src/test/modules/injection_points/Makefile
@@ -9,7 +9,8 @@ EXTENSION = injection_points
 DATA = injection_points--1.0.sql
 PGFILEDESC = "injection_points - facility for injection points"
 
-REGRESS = injection_points hashagg reindex_conc vacuum
+# Disable regress tests
+#REGRESS = injection_points hashagg reindex_conc vacuum
 REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress
 
 ISOLATION = basic \
@@ -24,6 +25,9 @@ ISOLATION = basic \
 #	    reindex-concurrently-upsert-on-constraint \
 #	    reindex-concurrently-upsert-partitioned
 
+# Enable only one isolation test
+ISOLATION = onconflict
+
 # The injection points are cluster-wide, so disable installcheck
 NO_INSTALLCHECK = 1
 
diff --git a/src/test/modules/injection_points/expected/onconflict.out b/src/test/modules/injection_points/expected/onconflict.out
new file mode 100644
index 0000000000..ee89965592
--- /dev/null
+++ b/src/test/modules/injection_points/expected/onconflict.out
@@ -0,0 +1,23 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1 s1ipa s1i s2 s2u s2ipw s2c s1c
+step s1: BEGIN;
+step s1ipa: SELECT injection_points_attach('before-on-conflict-update', 'wait');
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step s1i: INSERT INTO t_int VALUES (1, 11, 111) ON CONFLICT (i) DO UPDATE SET x = excluded.x; <waiting ...>
+step s2: BEGIN;
+step s2u: UPDATE t_int SET i = i + 150 WHERE i = 1;
+step s2ipw: SELECT injection_points_wakeup('before-on-conflict-update');
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+step s2c: COMMIT;
+step s1i: <... completed>
+ERROR:  tuple to be updated was already moved to another partition due to concurrent update
+step s1c: COMMIT;
diff --git a/src/test/modules/injection_points/specs/onconflict.spec b/src/test/modules/injection_points/specs/onconflict.spec
new file mode 100644
index 0000000000..495449264b
--- /dev/null
+++ b/src/test/modules/injection_points/specs/onconflict.spec
@@ -0,0 +1,30 @@
+setup
+{
+  CREATE EXTENSION injection_points;
+
+  CREATE TABLE t_int (i int PRIMARY KEY, v int, x int) PARTITION BY RANGE (i);
+  CREATE TABLE t_int_1 PARTITION OF t_int FOR VALUES FROM (1) TO (100);
+  CREATE TABLE t_int_2 PARTITION OF t_int FOR VALUES FROM (100) TO (200);
+
+  INSERT INTO t_int VALUES (1, 10, 100);
+}
+
+teardown
+{
+  DROP TABLE t_int;
+  DROP EXTENSION injection_points;
+}
+
+session s1
+step s1		{ BEGIN; }
+step s1ipa	{ SELECT injection_points_attach('before-on-conflict-update', 'wait'); }
+step s1i	{ INSERT INTO t_int VALUES (1, 11, 111) ON CONFLICT (i) DO UPDATE SET x = excluded.x; }
+step s1c	{ COMMIT; }
+
+session s2
+step s2		{ BEGIN; }
+step s2ipw	{ SELECT injection_points_wakeup('before-on-conflict-update'); }
+step s2u	{ UPDATE t_int SET i = i + 150 WHERE i = 1; }
+step s2c	{ COMMIT; }
+
+permutation s1 s1ipa s1i(s2c) s2 s2u s2ipw s2c s1c
-- 
2.43.0