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 1wKsoQ-001NOb-1o for pgsql-hackers@arkaria.postgresql.org; Thu, 07 May 2026 07:06:22 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wKsoO-002MDu-2a for pgsql-hackers@arkaria.postgresql.org; Thu, 07 May 2026 07:06:20 +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 1wKsoO-002MDm-1W for pgsql-hackers@lists.postgresql.org; Thu, 07 May 2026 07:06:20 +0000 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wKsoM-00000000xe9-0dnm for pgsql-hackers@lists.postgresql.org; Thu, 07 May 2026 07:06:20 +0000 Received: by mail-pj1-x1035.google.com with SMTP id 98e67ed59e1d1-3660daea6a5so140048a91.1 for ; Thu, 07 May 2026 00:06:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778137575; x=1778742375; 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=DAVgc9cX45/Vj+eT/TEv6yZ+0QtuJSf3Dnl5SggcIng=; b=nz0f4yNRWdDOYywjYWAtpxH8qZVyK8x94rtczMHPTNfZgNsOj8faxxLdJvbCRFnCXb c0K+z+Jj0oxu3O8dckXMv2NVLxTKJbc1VCQGqcnAPGBPgvp7EC+M8rMc0TtN7wXP0Sqq DNpmG0vY5Wp2g6eybGqENxLK1Ym6SZfBLzsax2o5hKjwCcr8nwg+j7U2YRNSJhGk/ITb OwVyy38zKkxh+8WzCXB+Rz19HHSekFuYKLHo2+ZZQmiy+HqZS9t5FN0qVO420N9MrnTy Vhv27hiZuiqKkLtoe0Mut9OQ/ZQS9r9j7UZpAXVjRIxEj5PHT+Q3GUr6kH3pIgyGlouE So1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778137575; x=1778742375; 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=DAVgc9cX45/Vj+eT/TEv6yZ+0QtuJSf3Dnl5SggcIng=; b=fl9t13PdKM39GsHi7lVih3eOHR85zVMQ1q1WSyCzMCyTTqirjeAlcMjCtwBt3f2aOQ 8C0QYDle/+hbsdFbjbEshOifR7PDjtxLMm3T1Ep9VAwbZQhGiBH1cEB5Ma5MIZh6KBw5 wAyCvzKWBsZf7Ie9c/qa6fDiDUFmuEov4XVijKE05ErKRV5RVoFsFuOd6b1jA2mDc3TN bAk1pcJKYMGXaM2Fo7687+rfEqooT8BQ8oFTtq3o1JqYszjtiBn/WGSJfN70wt+hF2KZ WMbJqGBAFO137RtMGnuQfXw+ZjPRtJ1ZanLV/GDZaUyUhMM6Bh7iKuMSuyAaByXCS4HF y6/Q== X-Forwarded-Encrypted: i=1; AFNElJ8e3BfoMqnK12T/FINGYYVWxtQNI+/1FsspkbidNJQS+TMD1LnCwi0OTVSvs8FP2yPFSyHkEvxqn660b7Hh@lists.postgresql.org X-Gm-Message-State: AOJu0YyDhKM1xxV58fBbu3/a+5k4XzcH2FkjFj2G9ON0zvd0gO8ZiuR5 6B/hqmLdpUpRgld7Uq5bZpvC/mLXV9RwkakO2t6eDh8W+z9TuBi3VvuA X-Gm-Gg: AeBDietcSXPNVBCzEvSWRo8cnNQ461UDiCwxJzM+BWW1s4GB5xS1/S12SpO3bD+Z0hI BVAb8e0/5s/svZVb3YjlivUYFqoL4b+Sr3aG7MbkoNufv41kqxisjwzs3d/Fi6eSXA+AghcdRL2 2OhKDKlKcjRHLiYzN5oqGbhaNdBUGirzkL15Nksrg+X6sY1OH+m1JKszfiN7x6hdxstrA6QY+Aa f1Xx7rjawsAW/5jGotSqsEkgoJ2sB5PicUnSWl59Pe7iIyr+l5etyAlWljLnRLcuVp6teL55vfx 7pLllkYPyHLG144Jkfz0Ru5y8noo9FqspSFokfN1LWNsvJzAF4++2meH5kIVDmjIJQTvmDX5Hft /tKFaMdrql4gU/xbVNdvUZMPYCRTEgkM9DYatSk3RC2Yrj33m3uWMUn1ehCxRDe14g+jsJ/7uWr +6bWqbSbxlbjCWnGKQfZ1tfAConhI2sNcqLzE5TuIX7g== X-Received: by 2002:a17:902:ebc1:b0:2b9:601e:da11 with SMTP id d9443c01a7336-2ba798d378cmr65812965ad.35.1778137575346; Thu, 07 May 2026 00:06:15 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2babb0e4c48sm13731635ad.75.2026.05.07.00.06.12 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 May 2026 00:06:14 -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: <66C1555B-CA54-4ED1-AB4F-0EE97D24A006@gmail.com> Date: Thu, 7 May 2026 15:05:34 +0800 Cc: Peter Eisentraut , jian he , SATYANARAYANA NARLAPURAM , PostgreSQL Hackers Content-Transfer-Encoding: quoted-printable Message-Id: <91B35E0F-5DC1-4417-A1B9-FAF4A3DCD2BD@gmail.com> References: <27BD5D23-19C9-4FD1-8935-9C788C3C9869@gmail.com> <66C1555B-CA54-4ED1-AB4F-0EE97D24A006@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 7, 2026, at 13:54, Chao Li wrote: >=20 >=20 >=20 >> On May 7, 2026, at 12:34, Chao Li wrote: >>=20 >>=20 >>=20 >>> On May 7, 2026, at 01:13, Paul A Jungwirth = wrote: >>>=20 >>> On Wed, May 6, 2026 at 4:39=E2=80=AFAM Peter Eisentraut = wrote: >>>>=20 >>>> On 05.05.26 23:50, Paul A Jungwirth wrote: >>>>> On Wed, Apr 22, 2026 at 11:03=E2=80=AFAM Paul A Jungwirth >>>>> wrote: >>>>>>=20 >>>>>> Good catch! I removed that line in v7 (attached). I also included = your >>>>>> test change to compute the range len by hand. Also a rebase was >>>>>> necessary after d3bba04154. >>>>>=20 >>>>> This needed a rebase. v8 attached. >>>>=20 >>>> This patch fails the injection_points/isolation test for me. It = looks >>>> like it causes a server crash. Check please. >>>=20 >>> Sorry, I didn't have injection_points enabled, but now I see it too. >>> The attached v9 fixes it. >>>=20 >>> Yours, >>>=20 >>> --=20 >>> Paul ~{:-) >>> pj@illuminatedcomputing.com >>> >>=20 >> Hi Paul, >>=20 >> I didn=E2=80=99t review this patch earlier because, from the subject, = I thought it was only about recomputing generated stored columns. I just = noticed that the patch also changes the inheritance-table path, and I = posted another patch for the inheritance-table bug. Please see [1]. >>=20 >> I tried applying the new tests from my patch on top of this patch, = and it looks like this patch still does not fix the multi-inheritance = case. >>=20 >> So I=E2=80=99d like to check with you how we should proceed. I think = there are two options: >>=20 >> 1. Keep this patch focused on the generated-column issue described in = the subject, and use my patch to fix the inheritance-table bug. >> 2. I can continue from this patch and extend it to fix the = multi-inheritance case as well. >>=20 >> Please let me know what you prefer. >>=20 >> [1] = https://www.postgresql.org/message-id/4245F94D-84F1-4E05-BF81-C458A6CF9901= %40gmail.com >>=20 >=20 > I just looked into v9 and made a fix in ExecInitForPortionOf() that = resolves the bug with multi-inheritance tables. I also added a test case = for that. >=20 > The inheritance-table bug affects not only UPDATE, but also DELETE, so = I added test cases for DELETE as well. Please see 0002 for my changes. >=20 > To make each commit self-contained, would you mind moving the code for = the inheritance-table fix to 0002? Then you can keep focusing on 0001, = and I can continue working on 0002. >=20 > PFA v10 - 0001 the same as v9. 0002 fixed a bug with multi-inheritance = tables. >=20 > (Note, in 0002, there is a comment format change around line 1496, = that was done by pgindent.) >=20 > Best regards, > -- > Chao Li (Evan) > HighGo Software Co., Ltd. > https://www.highgo.com/ >=20 >=20 >=20 >=20 > = A few comments for 0001: 1 - execUtils.c ``` + updatedCols =3D perminfo->updatedCols; + /* Map the columns to child's attribute numbers if needed. */ if (relinfo->ri_RootResultRelInfo) { TupleConversionMap *map =3D = ExecGetRootToChildMap(relinfo, estate); =20 if (map) - return execute_attr_map_cols(map->attrMap, = perminfo->updatedCols); + updatedCols =3D = execute_attr_map_cols(map->attrMap, updatedCols); + } + + /* + * For UPDATE ... FOR PORTION OF, the range column is being = modified + * (narrowed via intersection), but it is not included in = updatedCols + * because the user does not need UPDATE permission on it. Now = manualy + * add it to updatedCols. Since ri_forPortionOf->fp_rangeAttno = is already + * mapped for the child partition, we have to add it after the = mapping just + * above. Also that makes it unsafe to mutate perminfo. XXX: = Always add the + * unmapped attno instead (before mapping), and mutate perminfo, = to avoid + * repeated allocations? + */ + 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_add_member(updatedCols, + rangeAttno - = FirstLowInvalidHeapAttributeNumber); ``` 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. 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. 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); updatedCols =3D bms_add_member(updatedCols, rangeAttno - = FirstLowInvalidHeapAttributeNumber); ``` 2 - execUtils.c ``` + * because the user does not need UPDATE permission on it. Now manualy ``` Typo: manualy -> manually 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); + } ``` I think this comment is stale. It could be a partition child or an = inheritance child. 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); ``` I think the comment should say "each child relation" rather than "each = partition". Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/