Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wLCjV-001cE4-03 for pgsql-hackers@arkaria.postgresql.org; Fri, 08 May 2026 04:22:37 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wLCjT-007h7u-2z for pgsql-hackers@arkaria.postgresql.org; Fri, 08 May 2026 04:22:35 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wLCjT-007h7m-1J for pgsql-hackers@lists.postgresql.org; Fri, 08 May 2026 04:22:35 +0000 Received: from mail-pl1-x62f.google.com ([2607:f8b0:4864:20::62f]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wLCjR-00000000kS0-00sK for pgsql-hackers@postgresql.org; Fri, 08 May 2026 04:22:34 +0000 Received: by mail-pl1-x62f.google.com with SMTP id d9443c01a7336-2b9ea536877so10973075ad.1 for ; Thu, 07 May 2026 21:22:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778214152; x=1778818952; darn=postgresql.org; h=to:date:message-id:subject:mime-version:from:from:to:cc:subject :date:message-id:reply-to; bh=n5EEJGEsu6mdSeXdR1gXNXDOyo9KrSIQeHJznI17/7U=; b=ABs6sLFFkzKEZWODUiibq5J38dcAIwjNO0krQeUbBcgYdZYPcf3vtrovBP/1FnYaPv sU1afp8i96nqLATpPBtKagdIcds1wtoHLxVkTki3V2NoGtklZn/abLk7pGaFcEQLfLlo s80zTM14t2pxpJXjbCzSoVW/KV8/jTVxK0JZk/8GMiAqK3CVAFN/3iYeplobm4bcRMOS E+vM8y7tGYh14TqsVtjPMvCLFaaMQWOATnsZrDfFPSUEDeNeqxu8EmXGqrdZqXS8R3yO EKpoj0vMEN+4H51kLXmPNzhlHPpBEViOGHlUSupbhY1VmtF3/WmirdrqM2vCVy7wix4h cB8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778214152; x=1778818952; h=to:date:message-id:subject:mime-version:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=n5EEJGEsu6mdSeXdR1gXNXDOyo9KrSIQeHJznI17/7U=; b=hEN8IpGP1jhiJSa1vtXhZdFBoFMTBDDyRVbT+ahGVoS0XD1OfGk1JW4teehBbYg2S7 USMhVIhJSteMQ5wUG1P1IQ1TUTaSHrjF67lDAiRQI1I6Z1F/3krqxrVhGrQP/oZP1+Wv a37ItMyz4eIADFgtJl1+Q94SrYO9JXxWDUfmBVdpX8HZ9OX8VSsY+cZNEOVrCgnUiemO AvXbVTC0BNVMzMdMhS5p7mxmbIX/6LYlF0XAww77sdD46DAPFrEltXR3yWQ8tIuH2FXj DQUMDwrvouncxf215A1q8fBWs/+VUVvT/IYG92J5oIZsnl+G99VZGCPwAKytZhcpLQiD gDHA== X-Gm-Message-State: AOJu0YxiABVY4NkT0WTNnZTt0BByXG6RXnGE9wZBYB3xNtm35NTyWMgC Pg1GNRhAE3egPaM3YyHDWGrKJ5vnVJMY6pXBq4CaHd8WQVrM6aemckHll8BhPibg X-Gm-Gg: Acq92OHW1j3bD17rVtKxMafl8/x0tjZe9Yms0rgCqYa8tDq3fhZC1o51ItU7AHwmKEs 4EKz6+ceNZL/ykerKaN3U+iJ1nOsS9VSLZ/252x0CUrQuu+DMNNxB/16lFJiWHlhbh/lTorGU8w kSrzUJ4MXTywjCe36TwYAc+WAyM/kzpGeyx0/wZ+hthggVIWZJzPXfHwNXjyKzLujFLjLdSIifK Q7I+vZMddZy+p/3f92Yh66nXwPSUw0tNLlfBpxZH2hgFkIqFc/km/ffZZidQW9/jploMZgq1eng MhNvqBUcU5JHvgmQsrmL6TLzQ7kmujxj3e1F/RHR6WZ1FnX5LuhiAHclQPd8rwDevbvKA39pM31 nZ8bC2iYsxyVXZXGhbuSMWwj9k9QeObMO91NGtPD+lmPzEodZd/b7nlsHyPUJD+nxDM5E0BuUTO 1977MDsWq+6WeN1mC6vFuO9l3HsinqsUU= X-Received: by 2002:a17:902:d58e:b0:2b2:5070:8b with SMTP id d9443c01a7336-2babc649a10mr51954045ad.1.1778214151945; Thu, 07 May 2026 21:22:31 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2baf1ebea72sm4668465ad.77.2026.05.07.21.22.30 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 May 2026 21:22:31 -0700 (PDT) From: Chao Li Content-Type: multipart/mixed; boundary="Apple-Mail=_E88C1AFE-7F58-4061-952B-970FA6B6584F" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.400.21\)) Subject: Fix REPACK with WITHOUT OVERLAPS replica identity indexes Message-Id: <7B0EC0EC-5461-41EF-9B31-F9BBE608DEA5@gmail.com> Date: Fri, 8 May 2026 12:21:53 +0800 To: PostgreSQL-development X-Mailer: Apple Mail (2.3864.400.21) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_E88C1AFE-7F58-4061-952B-970FA6B6584F Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Hi, While testing UPDATE FOR PORTION OF, I started wondering whether REPACK = supports temporal tables. In theory, it should, because temporal WITHOUT = OVERLAPS indexes can be used as replica identity indexes. So I created a = test script, repack_temporal.spec, which is included in the attached = patch, and it failed. I found that REPACK hard-codes BTEqualStrategyNumber when calling = get_opfamily_member(). That seems wrong, because = build_replindex_scan_key() uses IndexAmTranslateCompareType() to get the = equality strategy for COMPARE_EQ. After fixing the hard-coded BTEqualStrategyNumber, the temporal test = passed. Then I added another test for multirange, = repack_temporal_multirange.spec, which also failed. The reason is that = find_target_tuple() uses the identity index to find the first tuple and = returns it directly, but a lossy index scan may return false positives = and require recheck. Please see the attached patch for the fix details and test scripts. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ --Apple-Mail=_E88C1AFE-7F58-4061-952B-970FA6B6584F Content-Disposition: attachment; filename=v1-0001-Fix-REPACK-with-WITHOUT-OVERLAPS-replica-identity.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v1-0001-Fix-REPACK-with-WITHOUT-OVERLAPS-replica-identity.patch" Content-Transfer-Encoding: quoted-printable =46rom=202a5d930499ba65964bdf095218373f85093d5dda=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20"Chao=20Li=20(Evan)"=20=0A= Date:=20Fri,=208=20May=202026=2011:40:18=20+0800=0ASubject:=20[PATCH=20= v1]=20Fix=20REPACK=20with=20WITHOUT=20OVERLAPS=20replica=20identity=20= indexes=0A=0AREPACK=20replay=20builds=20scan=20keys=20for=20the=20= replica=20identity=20index,=20but=20it=0Ahard-coded=20= BTEqualStrategyNumber=20when=20looking=20up=20the=20equality=20operator.=0A= That=20is=20not=20correct=20for=20non-btree=20identity=20indexes,=20such=20= as=20the=20GiST=0Aindexes=20created=20for=20WITHOUT=20OVERLAPS=20primary=20= keys.=20=20In=20addition,=0Afind_target_tuple()=20accepted=20the=20first=20= tuple=20returned=20by=20the=20identity=0Aindex=20scan,=20which=20is=20= unsafe=20for=20lossy=20index=20scans=20because=20the=20index=20AM=20may=0A= return=20false=20positives=20with=20xs_recheck=20set.=0A=0AFix=20this=20= by=20using=20IndexAmTranslateCompareType()=20to=20translate=20COMPARE_EQ=0A= to=20the=20equality=20strategy=20number=20for=20the=20index=20AM,=20and=20= by=20continuing=20the=0Ascan=20when=20recheck=20is=20required=20until=20= a=20candidate=20tuple=20matches=20the=20locator=0Atuple=20on=20all=20= replica=20identity=20key=20columns.=0A=0AThe=20recheck=20uses=20the=20= same=20equality=20operator=20functions=20as=20the=20identity=0Aindex=20= scan=20keys,=20preserving=20ScanKey=20argument=20ordering.=0A=0AAuthor:=20= Chao=20Li=20=0AReviewed-by:=0ADiscussion:=20= https://postgr.es/m/=0A---=0A=20src/backend/commands/repack.c=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20|=20=2063=20++++++++++-=0A=20= src/test/modules/injection_points/Makefile=20=20=20=20|=20=20=202=20+=0A=20= .../expected/repack_temporal.out=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=2068=20++++++++++++=0A=20= .../expected/repack_temporal_multirange.out=20=20=20|=20=2074=20= +++++++++++++=0A=20src/test/modules/injection_points/meson.build=20|=20=20= =202=20+=0A=20.../specs/repack_temporal.spec=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20|=20=2090=20++++++++++++++++=0A=20= .../specs/repack_temporal_multirange.spec=20=20=20=20=20|=20102=20= ++++++++++++++++++=0A=207=20files=20changed,=20397=20insertions(+),=204=20= deletions(-)=0A=20create=20mode=20100644=20= src/test/modules/injection_points/expected/repack_temporal.out=0A=20= create=20mode=20100644=20= src/test/modules/injection_points/expected/repack_temporal_multirange.out=0A= =20create=20mode=20100644=20= src/test/modules/injection_points/specs/repack_temporal.spec=0A=20create=20= mode=20100644=20= src/test/modules/injection_points/specs/repack_temporal_multirange.spec=0A= =0Adiff=20--git=20a/src/backend/commands/repack.c=20= b/src/backend/commands/repack.c=0Aindex=209a199dd9bfb..359109fe470=20= 100644=0A---=20a/src/backend/commands/repack.c=0A+++=20= b/src/backend/commands/repack.c=0A@@=20-182,6=20+182,9=20@@=20static=20= void=20adjust_toast_pointers(Relation=20relation,=20TupleTableSlot=20= *dest,=0A=20static=20bool=20find_target_tuple(Relation=20rel,=20= ChangeContext=20*chgcxt,=0A=20=09=09=09=09=09=09=09=20=20TupleTableSlot=20= *locator,=0A=20=09=09=09=09=09=09=09=20=20TupleTableSlot=20*retrieved);=0A= +static=20bool=20identity_key_equal(ChangeContext=20*chgcxt,=0A+=09=09=09= =09=09=09=09=20=20=20TupleTableSlot=20*locator,=0A+=09=09=09=09=09=09=09=20= =20=20TupleTableSlot=20*candidate);=0A=20static=20void=20= process_concurrent_changes(XLogRecPtr=20end_of_wal,=0A=20=09=09=09=09=09=09= =09=09=09=20=20=20ChangeContext=20*chgcxt,=0A=20=09=09=09=09=09=09=09=09=09= =20=20=20bool=20done);=0A@@=20-2807,7=20+2810,7=20@@=20= find_target_tuple(Relation=20rel,=20ChangeContext=20*chgcxt,=20= TupleTableSlot=20*locator,=0A=20{=0A=20=09Form_pg_index=20idx=20=3D=20= chgcxt->cc_ident_index->rd_index;=0A=20=09IndexScanDesc=20scan;=0A-=09= bool=09=09retval;=0A+=09bool=09=09retval=20=3D=20false;=0A=20=0A=20=09/*=0A= =20=09=20*=20Scan=20key=20is=20passed=20by=20caller,=20so=20it=20does=20= not=20have=20to=20be=20constructed=0A@@=20-2829,12=20+2832,57=20@@=20= find_target_tuple(Relation=20rel,=20ChangeContext=20*chgcxt,=20= TupleTableSlot=20*locator,=0A=20=09scan=20=3D=20index_beginscan(rel,=20= chgcxt->cc_ident_index,=20GetActiveSnapshot(),=0A=20=09=09=09=09=09=09=20= =20=20NULL,=20chgcxt->cc_ident_key_nentries,=200,=200);=0A=20=09= index_rescan(scan,=20chgcxt->cc_ident_key,=20= chgcxt->cc_ident_key_nentries,=20NULL,=200);=0A-=09retval=20=3D=20= index_getnext_slot(scan,=20ForwardScanDirection,=20retrieved);=0A+=09= while=20(index_getnext_slot(scan,=20ForwardScanDirection,=20retrieved))=0A= +=09{=0A+=09=09if=20(scan->xs_recheck=20&&=20!identity_key_equal(chgcxt,=20= locator,=20retrieved))=0A+=09=09=09continue;=0A+=0A+=09=09retval=20=3D=20= true;=0A+=09=09break;=0A+=09}=0A=20=09index_endscan(scan);=0A=20=0A=20=09= return=20retval;=0A=20}=0A=20=0A+/*=0A+=20*=20Check=20whether=20the=20= candidate=20tuple=20matches=20the=20locator=20tuple=20on=20all=20replica=0A= +=20*=20identity=20key=20columns,=20using=20the=20same=20equality=20= operators=20as=20the=20identity=0A+=20*=20index=20scan.=20=20This=20is=20= needed=20to=20filter=20lossy=20index=20matches,=20such=20as=20GiST=0A+=20= *=20multirange=20scans.=0A+=20*/=0A+static=20bool=0A= +identity_key_equal(ChangeContext=20*chgcxt,=20TupleTableSlot=20= *locator,=0A+=09=09=09=09=20=20=20TupleTableSlot=20*candidate)=0A+{=0A+=09= Form_pg_index=20idx=20=3D=20chgcxt->cc_ident_index->rd_index;=0A+=0A+=09= slot_getallattrs(locator);=0A+=09slot_getallattrs(candidate);=0A+=0A+=09= for=20(int=20i=20=3D=200;=20i=20<=20chgcxt->cc_ident_key_nentries;=20= i++)=0A+=09{=0A+=09=09ScanKey=09=09entry=20=3D=20= &chgcxt->cc_ident_key[i];=0A+=09=09AttrNumber=09attno=20=3D=20= idx->indkey.values[i];=0A+=0A+=09=09Assert(attno=20>=200);=0A+=0A+=09=09= if=20(locator->tts_isnull[attno=20-=201]=20!=3D=20= candidate->tts_isnull[attno=20-=201])=0A+=09=09=09return=20false;=0A+=0A= +=09=09if=20(locator->tts_isnull[attno=20-=201])=0A+=09=09=09continue;=0A= +=0A+=09=09if=20(!DatumGetBool(FunctionCall2Coll(&entry->sk_func,=0A+=09=09= =09=09=09=09=09=09=09=09=09entry->sk_collation,=0A+=09=09=09=09=09=09=09=09= =09=09=09candidate->tts_values[attno=20-=201],=0A+=09=09=09=09=09=09=09=09= =09=09=09entry->sk_argument)))=0A+=09=09=09return=20false;=0A+=09}=0A+=0A= +=09return=20true;=0A+}=0A+=0A=20/*=0A=20=20*=20Decode=20and=20apply=20= concurrent=20changes,=20up=20to=20(and=20including)=20the=20record=20= whose=0A=20=20*=20LSN=20is=20'end_of_wal'.=0A@@=20-2944,13=20+2992,20=20= @@=20initialize_change_context(ChangeContext=20*chgcxt,=0A=20=09=09=09=09= =09=09opcintype,=0A=20=09=09=09=09=09=09opno,=0A=20=09=09=09=09=09=09= opcode;=0A+=09=09=09StrategyNumber=20eq_strategy;=0A=20=0A=20=09=09=09= entry=20=3D=20&chgcxt->cc_ident_key[i];=0A=20=0A=20=09=09=09opfamily=20=3D= =20chgcxt->cc_ident_index->rd_opfamily[i];=0A=20=09=09=09opcintype=20=3D=20= chgcxt->cc_ident_index->rd_opcintype[i];=0A+=09=09=09eq_strategy=20=3D=20= IndexAmTranslateCompareType(COMPARE_EQ,=0A+=09=09=09=09=09=09=09=09=09=09= =09=09=09=20=20chgcxt->cc_ident_index->rd_rel->relam,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=20=20opfamily,=20false);=0A+=09=09=09if=20= (eq_strategy=20=3D=3D=20InvalidStrategy)=0A+=09=09=09=09elog(ERROR,=20= "failed=20to=20find=20equality=20strategy=20for=20index=20operator=20= family=20%u=20for=20type=20%u",=0A+=09=09=09=09=09=20opfamily,=20= opcintype);=0A=20=09=09=09opno=20=3D=20get_opfamily_member(opfamily,=20= opcintype,=20opcintype,=0A-=09=09=09=09=09=09=09=09=09=20=20=20= BTEqualStrategyNumber);=0A+=09=09=09=09=09=09=09=09=09=20=20=20= eq_strategy);=0A=20=09=09=09if=20(!OidIsValid(opno))=0A=20=09=09=09=09= elog(ERROR,=20"failed=20to=20find=20=3D=20operator=20for=20type=20%u",=20= opcintype);=0A=20=09=09=09opcode=20=3D=20get_opcode(opno);=0A@@=20= -2960,7=20+3015,7=20@@=20initialize_change_context(ChangeContext=20= *chgcxt,=0A=20=09=09=09/*=20Initialize=20everything=20but=20argument.=20= */=0A=20=09=09=09ScanKeyInit(entry,=0A=20=09=09=09=09=09=09i=20+=201,=0A= -=09=09=09=09=09=09BTEqualStrategyNumber,=20opcode,=0A+=09=09=09=09=09=09= eq_strategy,=20opcode,=0A=20=09=09=09=09=09=09(Datum)=200);=0A=20=09=09=09= entry->sk_collation=20=3D=20chgcxt->cc_ident_index->rd_indcollation[i];=0A= =20=09=09}=0Adiff=20--git=20a/src/test/modules/injection_points/Makefile=20= b/src/test/modules/injection_points/Makefile=0Aindex=20= f057d143d1a..c01d2fb095c=20100644=0A---=20= a/src/test/modules/injection_points/Makefile=0A+++=20= b/src/test/modules/injection_points/Makefile=0A@@=20-15,6=20+15,8=20@@=20= REGRESS_OPTS=20=3D=20--dlpath=3D$(top_builddir)/src/test/regress=0A=20= ISOLATION=20=3D=20basic=20\=0A=20=09=20=20=20=20inplace=20\=0A=20=09=20=20= =20=20repack=20\=0A+=09=20=20=20=20repack_temporal=20\=0A+=09=20=20=20=20= repack_temporal_multirange=20\=0A=20=09=20=20=20=20repack_toast=20\=0A=20= =09=20=20=20=20syscache-update-pruned=20\=0A=20=09=20=20=20=20= heap_lock_update=0Adiff=20--git=20= a/src/test/modules/injection_points/expected/repack_temporal.out=20= b/src/test/modules/injection_points/expected/repack_temporal.out=0Anew=20= file=20mode=20100644=0Aindex=2000000000000..e6b06c00cec=0A---=20= /dev/null=0A+++=20= b/src/test/modules/injection_points/expected/repack_temporal.out=0A@@=20= -0,0=20+1,68=20@@=0A+Parsed=20test=20spec=20with=202=20sessions=0A+=0A= +starting=20permutation:=20wait_before_lock=20update_target=20= check_after_update=20wakeup_before_lock=20check_after_repack=0A= +injection_points_attach=0A+-----------------------=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=0A+(1=20row)=0A+=0A= +step=20wait_before_lock:=20=0A+=09REPACK=20(CONCURRENTLY)=20= repack_temporal=20USING=20INDEX=20repack_temporal_pkey;=0A+=20=0A+step=20update_target:=20=0A+=09UPDATE=20repack_temporal=0A+=09= SET=20label=20=3D=20'updated'=0A+=09WHERE=20id=20=3D=20'[2,3)'=20AND=20= valid_at=20=3D=20'[2000-01-10,2000-01-20)';=0A+=0A+step=20= check_after_update:=20=0A+=09INSERT=20INTO=20relfilenodes(node)=0A+=09= SELECT=20relfilenode=20FROM=20pg_class=20WHERE=20relname=20=3D=20= 'repack_temporal';=0A+=0A+=09--=20Expect=202=20rows=0A+=09SELECT=20id,=20= valid_at,=20label=0A+=09FROM=20repack_temporal=0A+=09ORDER=20BY=20id,=20= valid_at,=20label;=0A+=0A+id=20=20=20=20|valid_at=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|label=20=20=0A= +------+-----------------------+-------=0A= +[1,10)|[01-01-2000,02-01-2000)|other=20=20=0A+[2,3)=20= |[01-10-2000,01-20-2000)|updated=0A+(2=20rows)=0A+=0A+step=20= wakeup_before_lock:=20=0A+=09SELECT=20= injection_points_wakeup('repack-concurrently-before-lock');=0A+=0A= +injection_points_wakeup=0A+-----------------------=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=0A+(1=20row)=0A+=0A= +step=20wait_before_lock:=20<...=20completed>=0A+step=20= check_after_repack:=20=0A+=09INSERT=20INTO=20relfilenodes(node)=0A+=09= SELECT=20relfilenode=20FROM=20pg_class=20WHERE=20relname=20=3D=20= 'repack_temporal';=0A+=0A+=09--=20Expect=202,=20proving=20that=20repack=20= has=20rewritten=20the=20table=0A+=09SELECT=20count(DISTINCT=20node)=20= FROM=20relfilenodes;=0A+=0A+=09--=20Expect=202=20rows=0A+=09SELECT=20id,=20= valid_at,=20label=0A+=09FROM=20repack_temporal=0A+=09ORDER=20BY=20id,=20= valid_at,=20label;=0A+=0A+count=0A+-----=0A+=20=20=20=202=0A+(1=20row)=0A= +=0A+id=20=20=20=20|valid_at=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |label=20=20=0A+------+-----------------------+-------=0A= +[1,10)|[01-01-2000,02-01-2000)|other=20=20=0A+[2,3)=20= |[01-10-2000,01-20-2000)|updated=0A+(2=20rows)=0A+=0A= +injection_points_detach=0A+-----------------------=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=0A+(1=20row)=0A+=0A= diff=20--git=20= a/src/test/modules/injection_points/expected/repack_temporal_multirange.ou= t=20= b/src/test/modules/injection_points/expected/repack_temporal_multirange.ou= t=0Anew=20file=20mode=20100644=0Aindex=2000000000000..3f5ff8cfb0f=0A---=20= /dev/null=0A+++=20= b/src/test/modules/injection_points/expected/repack_temporal_multirange.ou= t=0A@@=20-0,0=20+1,74=20@@=0A+Parsed=20test=20spec=20with=202=20sessions=0A= +=0A+starting=20permutation:=20wait_before_lock=20update_target=20= check_after_update=20wakeup_before_lock=20final_check=0A= +injection_points_attach=0A+-----------------------=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=0A+(1=20row)=0A+=0A= +step=20wait_before_lock:=20=0A+=09REPACK=20(CONCURRENTLY)=20= repack_temporal_multirange=0A+=09=09USING=20INDEX=20= repack_temporal_multirange_pkey;=0A+=20=0A+step=20= update_target:=20=0A+=09UPDATE=20repack_temporal_multirange=0A+=09SET=20= label=20=3D=20'updated'=0A+=09WHERE=20id=20=3D=20= int4multirange(int4range(1,=207))=0A+=09=20=20AND=20valid_at=20=3D=20= datemultirange(daterange('2000-01-01',=20'2000-02-01'));=0A+=0A+step=20= check_after_update:=20=0A+=09INSERT=20INTO=20relfilenodes(node)=0A+=09= SELECT=20relfilenode=0A+=09FROM=20pg_class=0A+=09WHERE=20relname=20=3D=20= 'repack_temporal_multirange';=0A+=0A+=09--=20Expect=202=20rows=0A+=09= SELECT=20id,=20valid_at,=20label=0A+=09FROM=20repack_temporal_multirange=0A= +=09ORDER=20BY=20id,=20valid_at,=20label;=0A+=0A+id=20=20=20=20=20=20=20=20= =20=20=20|valid_at=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |label=20=20=0A+-------------+-------------------------+-------=0A= +{[1,3),[5,7)}|{[01-01-2000,02-01-2000)}|other=20=20=0A+{[1,7)}=20=20=20=20= =20=20|{[01-01-2000,02-01-2000)}|updated=0A+(2=20rows)=0A+=0A+step=20= wakeup_before_lock:=20=0A+=09SELECT=20= injection_points_wakeup('repack-concurrently-before-lock');=0A+=0A= +injection_points_wakeup=0A+-----------------------=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=0A+(1=20row)=0A+=0A= +step=20wait_before_lock:=20<...=20completed>=0A+step=20final_check:=20=0A= +=09INSERT=20INTO=20relfilenodes(node)=0A+=09SELECT=20relfilenode=0A+=09= FROM=20pg_class=0A+=09WHERE=20relname=20=3D=20= 'repack_temporal_multirange';=0A+=0A+=09--=20Expect=202,=20proving=20= that=20repack=20has=20rewritten=20the=20table=0A+=09SELECT=20= count(DISTINCT=20node)=20FROM=20relfilenodes;=0A+=0A+=09--=20Expect=202=20= rows=0A+=09SELECT=20id,=20valid_at,=20label=0A+=09FROM=20= repack_temporal_multirange=0A+=09ORDER=20BY=20id,=20valid_at,=20label;=0A= +=0A+count=0A+-----=0A+=20=20=20=202=0A+(1=20row)=0A+=0A+id=20=20=20=20=20= =20=20=20=20=20=20|valid_at=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|label=20=20=0A+-------------+-------------------------+-------=0A= +{[1,3),[5,7)}|{[01-01-2000,02-01-2000)}|other=20=20=0A+{[1,7)}=20=20=20=20= =20=20|{[01-01-2000,02-01-2000)}|updated=0A+(2=20rows)=0A+=0A= +injection_points_detach=0A+-----------------------=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=0A+(1=20row)=0A+=0A= diff=20--git=20a/src/test/modules/injection_points/meson.build=20= b/src/test/modules/injection_points/meson.build=0Aindex=20= fb1418e2caa..59dba1cb023=20100644=0A---=20= a/src/test/modules/injection_points/meson.build=0A+++=20= b/src/test/modules/injection_points/meson.build=0A@@=20-46,6=20+46,8=20= @@=20tests=20+=3D=20{=0A=20=20=20=20=20=20=20'basic',=0A=20=20=20=20=20=20= =20'inplace',=0A=20=20=20=20=20=20=20'repack',=0A+=20=20=20=20=20=20= 'repack_temporal',=0A+=20=20=20=20=20=20'repack_temporal_multirange',=0A=20= =20=20=20=20=20=20'repack_toast',=0A=20=20=20=20=20=20=20= 'syscache-update-pruned',=0A=20=20=20=20=20=20=20'heap_lock_update',=0A= diff=20--git=20= a/src/test/modules/injection_points/specs/repack_temporal.spec=20= b/src/test/modules/injection_points/specs/repack_temporal.spec=0Anew=20= file=20mode=20100644=0Aindex=2000000000000..9629d502ec1=0A---=20= /dev/null=0A+++=20= b/src/test/modules/injection_points/specs/repack_temporal.spec=0A@@=20= -0,0=20+1,90=20@@=0A+#=20REPACK=20(CONCURRENTLY)=20on=20a=20temporal=20= replica=20identity=20index.=0A+#=0A+#=20The=20table's=20replica=20= identity=20is=20a=20GiST=20index=20created=20by=20a=20temporal=20primary=0A= +#=20key.=20=20A=20concurrent=20UPDATE=20changes=20a=20non-key=20column=20= of=20one=20row,=20while=20another=0A+#=20row=20overlaps=20it=20on=20all=20= indexed=20columns.=20=20Replay=20must=20still=20find=20the=20exact=0A+#=20= target=20row.=0A+setup=0A+{=0A+=09CREATE=20EXTENSION=20injection_points;=0A= +=0A+=09CREATE=20TABLE=20repack_temporal=20(=0A+=09=09id=20int4range,=0A= +=09=09valid_at=20daterange,=0A+=09=09label=20text,=0A+=09=09PRIMARY=20= KEY=20(id,=20valid_at=20WITHOUT=20OVERLAPS)=0A+=09);=0A+=0A+=09ALTER=20= TABLE=20repack_temporal=20REPLICA=20IDENTITY=20USING=20INDEX=20= repack_temporal_pkey;=0A+=0A+=09INSERT=20INTO=20repack_temporal(id,=20= valid_at,=20label)=0A+=09VALUES=0A+=09=09('[1,10)',=20= '[2000-01-01,2000-02-01)',=20'other'),=0A+=09=09('[2,3)',=20=20= '[2000-01-10,2000-01-20)',=20'target');=0A+=0A+=09CREATE=20TABLE=20= relfilenodes(node=20oid);=0A+}=0A+=0A+teardown=0A+{=0A+=09DROP=20TABLE=20= repack_temporal;=0A+=09DROP=20EXTENSION=20injection_points;=0A+=09DROP=20= TABLE=20relfilenodes;=0A+}=0A+=0A+session=20s1=0A+setup=0A+{=0A+=09= SELECT=20injection_points_set_local();=0A+=09SELECT=20= injection_points_attach('repack-concurrently-before-lock',=20'wait');=0A= +}=0A+step=20wait_before_lock=0A+{=0A+=09REPACK=20(CONCURRENTLY)=20= repack_temporal=20USING=20INDEX=20repack_temporal_pkey;=0A+}=0A+step=20= check_after_repack=0A+{=0A+=09INSERT=20INTO=20relfilenodes(node)=0A+=09= SELECT=20relfilenode=20FROM=20pg_class=20WHERE=20relname=20=3D=20= 'repack_temporal';=0A+=0A+=09--=20Expect=202,=20proving=20that=20repack=20= has=20rewritten=20the=20table=0A+=09SELECT=20count(DISTINCT=20node)=20= FROM=20relfilenodes;=0A+=0A+=09--=20Expect=202=20rows=0A+=09SELECT=20id,=20= valid_at,=20label=0A+=09FROM=20repack_temporal=0A+=09ORDER=20BY=20id,=20= valid_at,=20label;=0A+}=0A+teardown=0A+{=0A+=09SELECT=20= injection_points_detach('repack-concurrently-before-lock');=0A+}=0A+=0A= +session=20s2=0A+step=20update_target=0A+{=0A+=09UPDATE=20= repack_temporal=0A+=09SET=20label=20=3D=20'updated'=0A+=09WHERE=20id=20=3D= =20'[2,3)'=20AND=20valid_at=20=3D=20'[2000-01-10,2000-01-20)';=0A+}=0A= +step=20check_after_update=0A+{=0A+=09INSERT=20INTO=20relfilenodes(node)=0A= +=09SELECT=20relfilenode=20FROM=20pg_class=20WHERE=20relname=20=3D=20= 'repack_temporal';=0A+=0A+=09--=20Expect=202=20rows=0A+=09SELECT=20id,=20= valid_at,=20label=0A+=09FROM=20repack_temporal=0A+=09ORDER=20BY=20id,=20= valid_at,=20label;=0A+}=0A+step=20wakeup_before_lock=0A+{=0A+=09SELECT=20= injection_points_wakeup('repack-concurrently-before-lock');=0A+}=0A+=0A= +permutation=0A+=09wait_before_lock=0A+=09update_target=0A+=09= check_after_update=0A+=09wakeup_before_lock=0A+=09check_after_repack=0A= diff=20--git=20= a/src/test/modules/injection_points/specs/repack_temporal_multirange.spec=20= b/src/test/modules/injection_points/specs/repack_temporal_multirange.spec=0A= new=20file=20mode=20100644=0Aindex=2000000000000..dfff1f2234d=0A---=20= /dev/null=0A+++=20= b/src/test/modules/injection_points/specs/repack_temporal_multirange.spec=0A= @@=20-0,0=20+1,102=20@@=0A+#=20REPACK=20(CONCURRENTLY)=20on=20a=20= temporal=20replica=20identity=20index=20with=20lossy=0A+#=20multirange=20= equality.=0A+#=0A+#=20The=20leading=20identity=20column=20is=20an=20= int4multirange.=20Two=20distinct=20rows=20have=0A+#=20different=20= multirange=20values=20but=20the=20same=20union=20range,=20so=20GiST=20= equality=20can=0A+#=20produce=20both=20as=20candidates=20and=20requires=20= exact=20recheck.=0A+setup=0A+{=0A+=09CREATE=20EXTENSION=20= injection_points;=0A+=0A+=09CREATE=20TABLE=20repack_temporal_multirange=20= (=0A+=09=09id=20int4multirange,=0A+=09=09valid_at=20datemultirange,=0A+=09= =09label=20text,=0A+=09=09PRIMARY=20KEY=20(id,=20valid_at=20WITHOUT=20= OVERLAPS)=0A+=09);=0A+=0A+=09ALTER=20TABLE=20repack_temporal_multirange=0A= +=09=09REPLICA=20IDENTITY=20USING=20INDEX=20= repack_temporal_multirange_pkey;=0A+=0A+=09--=20(1,3)+(5+7)=20is=20the=20= same=20uninon=20range=20of=20(1-7),=20but=20needs=20recheck=0A+=09INSERT=20= INTO=20repack_temporal_multirange(id,=20valid_at,=20label)=0A+=09VALUES=0A= +=09=09(int4multirange(int4range(1,=203),=20int4range(5,=207)),=0A+=09=09= =20datemultirange(daterange('2000-01-01',=20'2000-02-01')),=0A+=09=09=20= 'other'),=0A+=09=09(int4multirange(int4range(1,=207)),=0A+=09=09=20= datemultirange(daterange('2000-01-01',=20'2000-02-01')),=0A+=09=09=20= 'target');=0A+=0A+=09CREATE=20TABLE=20relfilenodes(node=20oid);=0A+}=0A+=0A= +teardown=0A+{=0A+=09DROP=20TABLE=20repack_temporal_multirange;=0A+=09= DROP=20EXTENSION=20injection_points;=0A+=09DROP=20TABLE=20relfilenodes;=0A= +}=0A+=0A+session=20s1=0A+setup=0A+{=0A+=09SELECT=20= injection_points_set_local();=0A+=09SELECT=20= injection_points_attach('repack-concurrently-before-lock',=20'wait');=0A= +}=0A+step=20wait_before_lock=0A+{=0A+=09REPACK=20(CONCURRENTLY)=20= repack_temporal_multirange=0A+=09=09USING=20INDEX=20= repack_temporal_multirange_pkey;=0A+}=0A+step=20final_check=0A+{=0A+=09= INSERT=20INTO=20relfilenodes(node)=0A+=09SELECT=20relfilenode=0A+=09FROM=20= pg_class=0A+=09WHERE=20relname=20=3D=20'repack_temporal_multirange';=0A+=0A= +=09--=20Expect=202,=20proving=20that=20repack=20has=20rewritten=20the=20= table=0A+=09SELECT=20count(DISTINCT=20node)=20FROM=20relfilenodes;=0A+=0A= +=09--=20Expect=202=20rows=0A+=09SELECT=20id,=20valid_at,=20label=0A+=09= FROM=20repack_temporal_multirange=0A+=09ORDER=20BY=20id,=20valid_at,=20= label;=0A+}=0A+teardown=0A+{=0A+=09SELECT=20= injection_points_detach('repack-concurrently-before-lock');=0A+}=0A+=0A= +session=20s2=0A+step=20update_target=0A+{=0A+=09UPDATE=20= repack_temporal_multirange=0A+=09SET=20label=20=3D=20'updated'=0A+=09= WHERE=20id=20=3D=20int4multirange(int4range(1,=207))=0A+=09=20=20AND=20= valid_at=20=3D=20datemultirange(daterange('2000-01-01',=20= '2000-02-01'));=0A+}=0A+step=20check_after_update=0A+{=0A+=09INSERT=20= INTO=20relfilenodes(node)=0A+=09SELECT=20relfilenode=0A+=09FROM=20= pg_class=0A+=09WHERE=20relname=20=3D=20'repack_temporal_multirange';=0A+=0A= +=09--=20Expect=202=20rows=0A+=09SELECT=20id,=20valid_at,=20label=0A+=09= FROM=20repack_temporal_multirange=0A+=09ORDER=20BY=20id,=20valid_at,=20= label;=0A+}=0A+step=20wakeup_before_lock=0A+{=0A+=09SELECT=20= injection_points_wakeup('repack-concurrently-before-lock');=0A+}=0A+=0A= +permutation=0A+=09wait_before_lock=0A+=09update_target=0A+=09= check_after_update=0A+=09wakeup_before_lock=0A+=09final_check=0A--=20=0A= 2.50.1=20(Apple=20Git-155)=0A=0A= --Apple-Mail=_E88C1AFE-7F58-4061-952B-970FA6B6584F--