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 1wfbqA-005XMw-2L for pgsql-hackers@arkaria.postgresql.org; Fri, 03 Jul 2026 11:13:51 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wfbpA-007DPP-1v for pgsql-hackers@arkaria.postgresql.org; Fri, 03 Jul 2026 11:12:48 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wfbpA-007DPG-04 for pgsql-hackers@lists.postgresql.org; Fri, 03 Jul 2026 11:12:48 +0000 Received: from fhigh-a8-smtp.messagingengine.com ([103.168.172.159]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wfbp7-00000001RpV-09LF for pgsql-hackers@lists.postgresql.org; Fri, 03 Jul 2026 11:12:47 +0000 Received: from phl-compute-10.internal (phl-compute-10.internal [10.202.2.50]) by mailfhigh.phl.internal (Postfix) with ESMTP id C6C541400077; Fri, 3 Jul 2026 07:12:42 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-10.internal (MEProxy); Fri, 03 Jul 2026 07:12:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kurilemu.de; h= cc:cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :reply-to:subject:subject:to:to; s=fm3; t=1783077162; x= 1783163562; bh=FxcTY3hr9k/+gh8sgn7puPi6rSg0P49t52lMMdWJohc=; b=1 BhMNpnCXKLsN532voLISKffP1kGcHxbMB/qjZ5r9Mwi0axc6U7KOVkuWP0pomPt2 /uByLxu4pGfSuICE1dk1qdAutAQq9PQILAc2r58vxouNZAO0vrE066AjCfISa1rB 6m/+x4L2drOGw81NneKRv3HtrBLTapxylrfA2PJNbsLzvGMZT+pXz4hN2DIq+gi9 g/XKQCqNM3QaJH3JqfwIH0ola+ooQQVebKNk3b3lPQ6XgVg8JfhC0bO7i3nI9KeX fIyU7WFCnSMMBXoNTmDxSEqTzit0mxIRcYwAnSyZRKgEZbJOdBaqOm63ZXH9Ghv2 yOcIziA3Q5514iwqXH0UQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm2; t=1783077162; x=1783163562; bh=F xcTY3hr9k/+gh8sgn7puPi6rSg0P49t52lMMdWJohc=; b=otP7LswlN5gw2l4fC gjtH2GxbYWtD/pSXunkxZLGUlehxLu6p8G1vq0wtzoP9IVqKgg+fYCAHlbW9PsFk Jt4OIy3ltN/IKexrWEtYHEK6e1e9UuORTxmJeFUEW3F2kA9YR4ZF/xoTR+hX4L0S /fCFKaJOI693Tp612oYlSgOqyEz3i6rChiMNXPqNvOs5CXsiTiT6zrMb1EdYAEAH O+Cftvo0F7WUUfTJS/e3tP8ReYk1BcS8tFr2kqqzHHN70CfOaM2N98ssChT/4W3i m3eSJxctJ9WoiLG34Iy18t5cObYWtVvg+s79JCPP7lDgF9esNGl6ays+jzgUCNSk zflKQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEHlHfQBc+D5Hw+ZNm/MCMJJx4meEDoe/roggp7hl+qdl+XHFEzGig8ValNfJdZcM t6G1yfXyEcMuJA7dMhtkEuvvsVhVyp1puF1+DPAJN2cFbFGrC1VjRTePnWvDSesRjXaJd1 fAch4xrWwQ/4ycRU8EKay65xU+x1R4EyyS/8VZMpXeDLu6n0X/U//tcK2HlD7UCxAPMRwK /3/DYEfNIPtnDPhaiwMB6/GbkQoQAdddqqNjF+u5tpMX/h7d0oZPorZqVnV7GfH1UhKXpZ VEKJIqYSLjpV4UgRe69iziO0TUL5uXAIXCkIVcIbZ0/LS3A6i95hm2NhfnPKDITe0MaceK 59GIcWD3AGUyvht2mhPPqYKt3IoTd4PPTeDc5hd8mXn51OyvSF8DbhCESvXlGn1p2ToHeE oqYlwjPNDQqjA8KoBXb+0ACWLHmbCnbuuQLrgzEX5FW4phGWefVIaJbKOV4BRn+Zvkss1b Tngt0Ohy/GImsOhSUjW3zbsGF9xZQmkmK8o1NWoKzo9mv7ng6uID7R5l80hPSLJOFIUJRj ZX2Td5gDUSgCAHApH9cyKCoReH3tAneDzcMWQATah6aTINtZ4sso3cLAWw8pVnW7LW3BsA 51nOg5wvuEixJcPFmlmFRLWS0dq79WqhSp8/arbcPOLNmPVpTQ9fMteh+MXA X-ME-Proxy: Feedback-ID: ie3de48e3:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 3 Jul 2026 07:12:42 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kurilemu.de; s=schmee; t=1783077159; bh=GzbMQr9sd+ld4gHUOFPWvSiuwHbXbeX+MNc3AmLdwcA=; h=Date:From:To:Cc:Subject:In-Reply-To:From; b=T2fbdpOcgku8W7GMe1NTParnDtfpvtJmjaUwwYpqMRgM7UOqayF8KUkmNn2h5KySn HVJFfjmTRIwXq91JeqZlk2r02p4QnbuSRl7Hj+Beyn8k2pzsMEF3AkxxiOUFkwJYnm tGzYByxD+gZex9wu7io9u5Jy0B6hsshV9kfZ0/DDp9p8fGAxWyldBaMmuS5DiE/yGv GrifbzRbaCroQ5IuHBwI1vj8Y6h3rtXRvZo4dk9IVc6EbIXBN6Yv7nCD/38Y8DbQk4 47ytKJnteSUBKoI/6C0c7yh4IqFOcndAlTCdcCUIIFSV4hZQiq1G1JfAkW+nX4BtB2 m5bOUNtkmdbNg== Received: by ida.kurilemu.internal (Postfix, from userid 1000) id C6ADAB006C1; Fri, 03 Jul 2026 13:12:39 +0200 (CEST) Date: Fri, 3 Jul 2026 13:12:39 +0200 From: Alvaro Herrera To: Ewan Young Cc: Antonin Houska , PostgreSQL Hackers , mihailnikalayeu@gmail.com Subject: Re: REPACK CONCURRENTLY fails on tables with generated columns Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="pi6rmivyoaehyqn6" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --pi6rmivyoaehyqn6 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit Hello, On 2026-Jun-22, Ewan Young wrote: > I applied the patch and ran it through an injection-point reproducer > (cassert). Without the fix the bug reproduces (ERROR: no generation > expression found for column number 3 ...); with it, REPACK CONCURRENTLY > succeeds under a concurrent non-HOT UPDATE for a STORED generated column, an > index directly on the generated column, and a VIRTUAL column, with correct > values afterwards. Your repack.spec change passes. > > The approach is right and I've confirmed it fixes the bug, so +1 from me in > this direction. Cool, thanks for reviewing -- I have pushed this fix, with some stylistic changes and one bigger change: these catalog rows are only needed in concurrent mode, so there was no reason to copy them in the other case. So I restricted the copying to that case. I've been looking at the other proposed change, and I agree with it. Here's it, again with some style changes, and only one other proposed change: for setting up updatedCols, ignore dropped columns. I don't think this should change anything in practice, but it just feels wrong to claim that a dropped column is being changed by an update. -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/ --pi6rmivyoaehyqn6 Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename=0001-REPACK-CONCURRENTLY-Initialize-the-range-table-more-.patch From 6d85052127d9f304a95034521567819a3f0b4f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Herrera?= Date: Fri, 3 Jul 2026 12:47:54 +0200 Subject: [PATCH] REPACK CONCURRENTLY: Initialize the range table more honestly We were skipping a bunch of things that are mostly unnecessary for REPACK. However, one thing that seems would be better to pass closer to truth, is the updatedCols bitmapset in the range table entry for the repacked table. Cons up an RTE and install it into the EState. This only has an effect on btree indexes, because certain operations are optimized in the case of unchanged columns; and even then, correctnesss is not being compromised. The values we pass after this commit are not fully trustworthy either, because we simply say "all columns were updated" for all insert/updates, regardless of whether their values were actually modified or not. However, this way we err to the side of caution rather than to the opposite direction as we were originally doing. This could be refined in the future, but there's a trade-off: determining whether the column was in fact updated could be expensive. Author: Antonin Houska Reviewed-by: Ewan Young Backpatch-through: 19 Discussion: https://postgr.es/m/18222.1782126731@localhost --- src/backend/commands/repack.c | 57 +++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 83a49afe7e1..faa07d1a118 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -63,6 +63,7 @@ #include "libpq/pqmq.h" #include "miscadmin.h" #include "optimizer/optimizer.h" +#include "parser/parse_relation.h" #include "pgstat.h" #include "replication/logicalrelation.h" #include "storage/bufmgr.h" @@ -3019,8 +3020,60 @@ initialize_change_context(ChangeContext *chgcxt, /* Only initialize fields needed by ExecInsertIndexTuples(). */ chgcxt->cc_estate = CreateExecutorState(); - chgcxt->cc_rri = (ResultRelInfo *) palloc(sizeof(ResultRelInfo)); - InitResultRelInfo(chgcxt->cc_rri, relation, 0, 0, 0); + /* + * Set up a range table for the executor, containing our repacked table as + * its only member. + */ + { + RangeTblEntry *rte; + TupleDesc desc = RelationGetDescr(relation); + List *perminfos = NIL; + Bitmapset *updatedCols = NULL; + RTEPermissionInfo *perminfo; + + /* + * For our use, the RTE only needs to have perminfoindex initialized, + * but there's no reason to not set the fields whose values we have at + * hand. + */ + rte = makeNode(RangeTblEntry); + rte->rtekind = RTE_RELATION; + rte->relid = RelationGetRelid(relation); + rte->relkind = RelationGetForm(relation)->relkind; + /* Create the RTEPermissionInfo instance (and set ->perminfoindex). */ + addRTEPermissionInfo(&perminfos, rte); + + /* + * Initialize updatedCols to show that all columns are updated. This + * is of course not necessarily true, and we cannot know this early; + * but this is only used by ExecInsertIndexTuples to flag index + * updates with no logical value changes, so if it's wrong, nothing + * terribly bad happens. We may want to improve this someday though. + * + * Don't claim that dropped columns are changed though. + */ + for (int i = 0; i < desc->natts; i++) + { + CompactAttribute *attr = TupleDescCompactAttr(desc, i); + + if (attr->attisdropped) + continue; + updatedCols = bms_add_member(updatedCols, + i + 1 - FirstLowInvalidHeapAttributeNumber); + } + + /* install updatedCols in the right place */ + perminfo = getRTEPermissionInfo(perminfos, rte); + perminfo->updatedCols = updatedCols; + + /* finally we can initialize the range table proper */ + ExecInitRangeTable(chgcxt->cc_estate, list_make1(rte), perminfos, + bms_make_singleton(1)); + } + + /* Set up our ResultRelInfo to use for index updates */ + chgcxt->cc_rri = makeNode(ResultRelInfo); + InitResultRelInfo(chgcxt->cc_rri, relation, 1, NULL, 0); ExecOpenIndices(chgcxt->cc_rri, false); /* -- 2.47.3 --pi6rmivyoaehyqn6--