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 1wMKXg-002OBS-0p for pgsql-hackers@arkaria.postgresql.org; Mon, 11 May 2026 06:55:04 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wMKXe-00GQdh-0D for pgsql-hackers@arkaria.postgresql.org; Mon, 11 May 2026 06:55:02 +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 1wMKXd-00GQdZ-1V for pgsql-hackers@lists.postgresql.org; Mon, 11 May 2026 06:55:01 +0000 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wMKXa-00000001Epx-2B22 for pgsql-hackers@postgresql.org; Mon, 11 May 2026 06:55:00 +0000 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-82f8893bff3so1728206b3a.2 for ; Sun, 10 May 2026 23:54:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778482498; x=1779087298; darn=postgresql.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=9Ve047SOlDpRKnfgWBVKaEoiGXuAjLMR/IDuXU/jcIg=; b=OiTBDXOjaey0vnbyiVzEmz+uKRU2FFupv4AzYSWOjuWVRpVFjRjQBu+8be7/7bcBQx StEwmrYztV6eg+Pvzu9OeHTbHplWVtNXai7SivWY83Qe3SDOtFhOT//KeOYsQIK76S+q 2SQcrsvXhTyh382E6dTezB04nCRJcZOeCDxIdAWd2jmrG3RT0nMFREBp6Ohgiomj98vD hZ47ueIbbOME/MfgLevwh5v/+jTn778SjQQgqPAU9Rp84BwVowDlrBmL8rQiERGz9qqP xzAm68GdgwN9wZflzO4x0HZZumI0os/sa+KJOAnTHbqwUzMq8Ymrh2zQ2sqQZ/KO/7qa LSqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778482498; x=1779087298; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=9Ve047SOlDpRKnfgWBVKaEoiGXuAjLMR/IDuXU/jcIg=; b=ppcf5t+Z5OLTmHu3wfBxMFsZKW/sLCPE5ecp5eipd/rq4l5bHbSYa15gPoNoSZNftX Rj9QY3dtduDBvfK4LCfL5jX2oYHdPElwlQTfN3WX+c60opVVdSnqkDl2wUcb9VKdXH0X VCyWGJ4Kx1NMVinPyEgHDeXAqwK6jJtQW7LPDLDytKUDnjS5+ig230TiSWPETvkPl9Vs 5VqfeftFyy2xHEoHNFmFXY+u3L3yu4bJtj1kYZcEVF1tdXPoVA8ZkxppZmZu5z+BNzSE 2ggE8ZF3vp51XWK5uMYIEwqZyW2yVoCtkPoBAJ4cff/mzq5y12bM+L0kISuS92oAn+h5 VR3g== X-Forwarded-Encrypted: i=1; AFNElJ/e3tuZDLa7w+4iKUnqpr2Z+kCAW+OWTDyhVFhFXzlMh/8hx12qMBI5EUZfM0Gfex/jI2DIA6HKvxl3uGoH@postgresql.org X-Gm-Message-State: AOJu0Yzn8TmTVxoqQpKKeYzK8zTnjXK0ScUVDPtLWWyGkcOgIZZZlHDO OvwIiVUu2Mbqfdwn0+2b+LmfH9uEiHyqB1P1DAwyN1drsyLlqL1DZ9Re X-Gm-Gg: Acq92OHYKCl5ig8fxBq5a9TVmMt8avZon3iKkPV8ZDkR7xhGcxssOCtPFLpSAWVZ5ol MgFih0akjZmfo7EwADFGQx/ObKvNPGR698rrvdlbTYxYJWMNFMYexzsqljvL29YOfiG3MCepqhN rdUVyTI/mdrHaTcWwhQBe7ADfYdP8+hc9SB7iS7h6psVLZBvj3bUkr/ZQWKWff7L0SZvt7Uv/yv S3g7iBTNBYkBRbNJ8DCvDzYanARjApAvzXz6wq85IWWBkV8rVihDVjJnZEX2Ve7F3ByCsm9Yr5Q yJtkk83EDQIfh6O3Np/mhD3qrX3BWyZfsWV1DubMGG/piUSm0LcYbmxsgZpxpjrtblkaY5g5IzO tfBm/zJfUXYymO8fzvAY7OdRLCKI4gfFRWy/FiYv9Ln9aQ0vK9Mw317fDyzi7Ro5//tyk8rnETt iiG1qweSQ70uRVK1HIt8BIZNrYjJWl0Rw= X-Received: by 2002:a05:6a00:3393:b0:82c:7767:5bb2 with SMTP id d2e1a72fcca58-83e3a032638mr8821795b3a.21.1778482498130; Sun, 10 May 2026 23:54:58 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-83965945c1bsm19920364b3a.15.2026.05.10.23.54.55 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 10 May 2026 23:54:57 -0700 (PDT) From: Chao Li Message-Id: <7DC152EA-F549-43D1-80ED-4ED2BB6F801E@gmail.com> Content-Type: multipart/mixed; boundary="Apple-Mail=_CC9623C8-35F8-44AE-A1FF-76FF606DB764" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.400.21\)) Subject: Re: Fix REPACK with WITHOUT OVERLAPS replica identity indexes Date: Mon, 11 May 2026 14:54:18 +0800 In-Reply-To: Cc: Kirill Reshke , PostgreSQL-development To: =?utf-8?Q?=C3=81lvaro_Herrera?= References: 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=_CC9623C8-35F8-44AE-A1FF-76FF606DB764 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On May 10, 2026, at 06:38, =C3=81lvaro Herrera = wrote: >=20 > On 2026-May-09, Chao Li wrote: >=20 >>> On May 9, 2026, at 01:47, Kirill Reshke = wrote: >>>=20 >>> On Fri, 8 May 2026 at 09:22, Chao Li wrote: >=20 >>>> 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. >=20 > Nice find, thanks for testing. >=20 >>>> 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. >=20 > Makes sense. >=20 > I think it would be a good idea to make identity_key_equal() not = deform > all attributes, but instead only up to the last one it needs for the = key > comparisons. >=20 That=E2=80=99s true. Please see v3. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ --Apple-Mail=_CC9623C8-35F8-44AE-A1FF-76FF606DB764 Content-Disposition: attachment; filename=v3-0001-Fix-REPACK-with-WITHOUT-OVERLAPS-replica-identity.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v3-0001-Fix-REPACK-with-WITHOUT-OVERLAPS-replica-identity.patch" Content-Transfer-Encoding: quoted-printable =46rom=20816c41624a7f6eff03aa7d499e3d84d501fb8352=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= v3]=20Fix=20REPACK=20with=20WITHOUT=20OVERLAPS=20replica=20identity=20= indexes=0AMIME-Version:=201.0=0AContent-Type:=20text/plain;=20= charset=3DUTF-8=0AContent-Transfer-Encoding:=208bit=0A=0AREPACK=20replay=20= builds=20scan=20keys=20for=20the=20replica=20identity=20index,=20but=20= it=0Ahard-coded=20BTEqualStrategyNumber=20when=20looking=20up=20the=20= equality=20operator.=0AThat=20is=20not=20correct=20for=20non-btree=20= identity=20indexes,=20such=20as=20the=20GiST=0Aindexes=20created=20for=20= WITHOUT=20OVERLAPS=20primary=20keys.=20=20In=20addition,=0A= find_target_tuple()=20accepted=20the=20first=20tuple=20returned=20by=20= the=20identity=0Aindex=20scan,=20which=20is=20unsafe=20for=20lossy=20= index=20scans=20because=20the=20index=20AM=20may=0Areturn=20false=20= positives=20with=20xs_recheck=20set.=0A=0AFix=20this=20by=20using=20= IndexAmTranslateCompareType()=20to=20translate=20COMPARE_EQ=0Ato=20the=20= equality=20strategy=20number=20for=20the=20index=20AM,=20and=20by=20= continuing=20the=0Ascan=20when=20recheck=20is=20required=20until=20a=20= candidate=20tuple=20matches=20the=20locator=0Atuple=20on=20all=20replica=20= identity=20key=20columns.=0A=0AThe=20recheck=20uses=20the=20same=20= equality=20operator=20functions=20as=20the=20identity=0Aindex=20scan=20= keys,=20preserving=20ScanKey=20argument=20ordering.=0A=0AAuthor:=20Chao=20= Li=20=0AReviewed-by:=20Kirill=20Reshke=20= =0AReviewed-by:=20=C3=81lvaro=20Herrera=20= =0ADiscussion:=20= https://postgr.es/m/7B0EC0EC-5461-41EF-9B31-F9BBE608DEA5@gmail.com=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=2075=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,=20409=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..d56f22069f5=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,69=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{=0A+=09=09=09CHECK_FOR_INTERRUPTS();=0A= +=09=09=09continue;=0A+=09=09}=0A+=0A+=09=09retval=20=3D=20true;=0A+=09=09= break;=0A+=09}=0A=20=09index_endscan(scan);=0A=20=0A=20=09return=20= retval;=0A=20}=0A=20=0A+/*=0A+=20*=20Check=20whether=20the=20candidate=20= tuple=20matches=20the=20locator=20tuple=20on=20all=20replica=0A+=20*=20= identity=20key=20columns,=20using=20the=20same=20equality=20operators=20= as=20the=20identity=0A+=20*=20index=20scan.=20=20This=20is=20needed=20to=20= filter=20lossy=20index=20matches,=20such=20as=20GiST=0A+=20*=20= multirange=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+=09= AttrNumber=09last_key_attno=20=3D=200;=0A+=0A+=09for=20(int=20i=20=3D=20= 0;=20i=20<=20chgcxt->cc_ident_key_nentries;=20i++)=0A+=09{=0A+=09=09= AttrNumber=09attno=20=3D=20idx->indkey.values[i];=0A+=0A+=09=09= Assert(attno=20>=200);=0A+=09=09last_key_attno=20=3D=20= Max(last_key_attno,=20attno);=0A+=09}=0A+=0A+=09= slot_getsomeattrs(locator,=20last_key_attno);=0A+=09= slot_getsomeattrs(candidate,=20last_key_attno);=0A+=0A+=09for=20(int=20i=20= =3D=200;=20i=20<=20chgcxt->cc_ident_key_nentries;=20i++)=0A+=09{=0A+=09=09= ScanKey=09=09entry=20=3D=20&chgcxt->cc_ident_key[i];=0A+=09=09AttrNumber=09= attno=20=3D=20idx->indkey.values[i];=0A+=0A+=09=09Assert(attno=20>=200);=0A= +=0A+=09=09if=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+3004,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+3027,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=_CC9623C8-35F8-44AE-A1FF-76FF606DB764--