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 1wLFLz-001eN0-27 for pgsql-hackers@arkaria.postgresql.org; Fri, 08 May 2026 07:10:31 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wLFLy-008R70-1n for pgsql-hackers@arkaria.postgresql.org; Fri, 08 May 2026 07:10:30 +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 1wLFLy-008R6r-0Z for pgsql-hackers@lists.postgresql.org; Fri, 08 May 2026 07:10:30 +0000 Received: from mail-pl1-x62f.google.com ([2607:f8b0:4864:20::62f]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wLFLv-00000001AMV-3Ssj for pgsql-hackers@lists.postgresql.org; Fri, 08 May 2026 07:10:29 +0000 Received: by mail-pl1-x62f.google.com with SMTP id d9443c01a7336-2ba0714574fso9916895ad.2 for ; Fri, 08 May 2026 00:10:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778224225; x=1778829025; darn=lists.postgresql.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=DjnzjudW7qnLkChtJ9zkz5UvuGGWAI0hl2gbQtERHTg=; b=Ui/EtuMNCi29SkmBEE6jWMi9F4GEIvYc5e/Z9dxJFBFB7meEFLhYA/Y2vlHX2hyY++ s37yHYpmE81LejGemX6IHaMsP7cCLsMWyrJNh8wH++SY4GhLy5l7XsDw8XX2dXP7msBE 7AbfAHRMbJEDv5K7w/R4CDge2kTfzOVPC2iG+aycUFNX0BfxziGhF2mDWuu/8MtwlSzL pKfSswFa5VKWXvxn9YUZ7RQNwc3UMn6lqK866RZn2O/haKjMq0SkUCHr/g/kjO/zFYB/ lTbdeU8pfRQvOew7C9gueung9StCsoasYHXt6SqOEJcxQx3WdPQjLALDcYQzBQzOKwcj 0SjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778224225; x=1778829025; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-gg:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=DjnzjudW7qnLkChtJ9zkz5UvuGGWAI0hl2gbQtERHTg=; b=A9CYcBqxKUxM0BJvLBVSEOoeVRIvroADm5YS6QzYGsMR6YBJ15SlZbNESCL6bMfIwq IxlougJCHbErtgNBRgG/JTJ+Qi9+XTtm0SLW0znvvouZr8axGrSk3XSZy1OEZeK0BqNQ rhsWoM1i0inJfwhY5mRlRthozVaYLFB2KYdqi1KDpAhytUh9kRZHwTvLi3rwzdf7Q+dI wsbwsQocT2CEgs2oaGm86mgXgO1LbW7TrtMrmw1anWDdR8DCsEiyO6kH4vNxGAoWaFJH 6wMKxSN3Ja8sPJ77uY1FGcBbbvDiQI08riKr1TUSujQQddfx6c7XnUz66B+PPyEZz8eN /oHw== X-Forwarded-Encrypted: i=1; AFNElJ88I85VXjq8FSX2htB/mHsX+qEF5SaK4JjOPYWj9y8RhlrtvLBBmIhe29Mexn0pksX8WKm1TnEzNf5rjLgX@lists.postgresql.org X-Gm-Message-State: AOJu0YwEvuFBCAGDent7tXWrENkk6FDWvOWMTwwu11lyZjAkLUfShqxd gK3s0rgkc4n+UxpjbBH61YSPiyheAYl/hrpQBzGy1/WWouR7VDhrMaaM X-Gm-Gg: Acq92OEtzUqDS8bITVk1mQFRYIAH6Lin3M+NDotaGgHxoSxTqaFGyWWLSiURixeK2p9 jk+fTv2LsdwQ9AnW7iXsPX6Qp5tNajk5iwDgAd4QZStvbuV2+v9HtiisJ+ZKtGY4jLtXMXHQAef 9AGhuuFZmrtqI53sNwGCw8j4HuaXLc7cHhUYVdTYsXzR9HmH/iuJpBFdgvbfBASBXL6qgxeugmh UuAF/wlhhE+9uywkCLVJM5FK7aAXSv75j8Zil901WuloMWkLXkEQzFxDk/0p5nWH392Z4OEndKj 1bb9rc57XUK4OHgqCtNBHk/DOUwVplGakgLvqCPdQPOyKgKWyBYqOsQfyYUY/CRZFDQOgqJ2azf ucrqZU+e9MXfDdyFAK46zmO0tlMOBen32QtcP1Z8fRwpGoSfOQjBmV9iQj7qqWITrTqbXIURgID nB4ICwv28jD8xNf8Xv4k7GgWZSFBpgIcczZrKqysTudQ== X-Received: by 2002:a17:903:b46:b0:2b2:eb9d:1648 with SMTP id d9443c01a7336-2ba79c25ad9mr117803245ad.37.1778224225229; Fri, 08 May 2026 00:10:25 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2baf1e36c65sm10575245ad.40.2026.05.08.00.10.22 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 08 May 2026 00:10:24 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.400.21\)) Subject: Re: FOR PORTION OF does not recompute GENERATED STORED columns that depend on the range column From: Chao Li In-Reply-To: Date: Fri, 8 May 2026 15:09:46 +0800 Cc: Peter Eisentraut , jian he , SATYANARAYANA NARLAPURAM , PostgreSQL Hackers Content-Transfer-Encoding: quoted-printable Message-Id: <74C1863C-2C2A-423A-BDE7-0228889F1D80@gmail.com> References: <27BD5D23-19C9-4FD1-8935-9C788C3C9869@gmail.com> <66C1555B-CA54-4ED1-AB4F-0EE97D24A006@gmail.com> <91B35E0F-5DC1-4417-A1B9-FAF4A3DCD2BD@gmail.com> To: Paul A Jungwirth X-Mailer: Apple Mail (2.3864.400.21) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk > On May 8, 2026, at 07:47, Paul A Jungwirth = wrote: >=20 > On Thu, May 7, 2026 at 12:06=E2=80=AFAM Chao Li = wrote: >>> = >>=20 >> A few comments for 0001: >>=20 >> 1 - execUtils.c >> The comment explicitly says that it is unsafe to mutate perminfo, but = bms_add_member() does not always allocate a new bitmapset. So if = updatedCols still points to perminfo->updatedCols, then bms_add_member() = may mutate perminfo->updatedCols. >>=20 >> To verify that, I added Assert(updatedCols !=3D = perminfo->updatedCols); right after the bms_add_member(), then ran "make = check". A lot of tests failed, which seems to confirm that = perminfo->updatedCols was being mutated. >>=20 >> So, I think we should make a copy the bitmapset before bms_add_member = when needed, to make sure perminfo is not mutated, something like: >> ``` >> if (updatedCols =3D=3D perminfo->updatedCols) >> updatedCols =3D bms_copy(updatedCols); >>=20 >> updatedCols =3D >> bms_add_member(updatedCols, >> rangeAttno = - FirstLowInvalidHeapAttributeNumber); >> ``` >=20 > Ah, thanks for catching this! Fixed. >=20 >> 2 - execUtils.c >> ``` >> + * because the user does not need UPDATE permission on it. Now = manualy >> ``` >>=20 >> Typo: manualy -> manually >=20 > Fixed. >=20 >> 3 - nodeModifyTable.c >> ``` >> + /* >> + * If we don't have a ForPortionOfState yet, we must = be a partition >> + * child being hit for the first time. Make a copy = from the root, with >> + * our own TupleTableSlot. We do this lazily so that = we don't pay the >> + * price of unused partitions. >> + */ >> + if ((((ModifyTable *) = context.mtstate->ps.plan)->forPortionOf) && >> + !resultRelInfo->ri_forPortionOf) >> + { >> + ExecInitForPortionOf(context.mtstate, estate, = resultRelInfo); >> + } >> ``` >>=20 >> I think this comment is stale. It could be a partition child or an = inheritance child. >=20 > Okay. >=20 >> 4 - nodeModifyTable.c >> ``` >> + /* Each partition needs a slot matching its tuple descriptor = */ >> + leafState->fp_Existing =3D >> + table_slot_create(resultRelInfo->ri_RelationDesc, >> + = &mtstate->ps.state->es_tupleTable); >> ``` >>=20 >> I think the comment should say "each child relation" rather than = "each partition". >=20 > Okay. >=20 > In these v11 patches I've tried to separate (1) the fix for GENERATED > STORED columns and UPDATE OF triggers (2) fixing inheritance and (and > partitions too, for the bugs in #1). I understand why jian he combined > these into one patch: there is some overlap. If you don't like my > separation, let me know. >=20 > Yours, >=20 > --=20 > Paul ~{:-) > pj@illuminatedcomputing.com > = Thanks for updating the patch and making the separation. After reading = v11, I still have a few comments for 0001. ``` + if (relinfo->ri_forPortionOf) + { + AttrNumber rangeAttno =3D = relinfo->ri_forPortionOf->fp_rangeAttno; + + if (!bms_is_member(rangeAttno - = FirstLowInvalidHeapAttributeNumber, + updatedCols)) + { + MemoryContext oldContext; + + oldContext =3D = MemoryContextSwitchTo(estate->es_query_cxt); + + updatedCols =3D bms_copy(updatedCols); + updatedCols =3D + bms_add_member(updatedCols, + rangeAttno - = FirstLowInvalidHeapAttributeNumber); + + MemoryContextSwitchTo(oldContext); + } } ``` 1. I don=E2=80=99t think we should unconditionally do bms_copy, only if = (updatedCols =3D=3D perminfo->updatedCols), we need to make the copy. 2. I doubt if we need to switch to estate->es_query_cxt. Because = ExecGetUpdatedCols() is called by ExecGetAllUpdatedCols(), and its = header comment says the function runs in per-tuple memory context: ``` /* * Return columns being updated, including generated columns * * The bitmap is allocated in per-tuple memory context. It's up to the = caller to * copy it into a different context with the appropriate lifespan, if = needed. */ Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate) ``` So I think bms_copy and bms_add_member should be just done in the = current memory context. 3. "rangeAttno - FirstLowInvalidHeapAttributeNumber=E2=80=9D appears = twice, maybe add a local variable to avoid the duplication. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/