Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pZDoI-00009t-04 for pgsql-bugs@arkaria.postgresql.org; Mon, 06 Mar 2023 16:35:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pZDoG-00019V-Pr for pgsql-bugs@arkaria.postgresql.org; Mon, 06 Mar 2023 16:35:36 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pZDoG-00016F-GT for pgsql-bugs@lists.postgresql.org; Mon, 06 Mar 2023 16:35:36 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pZDoE-0002D0-8o for pgsql-bugs@lists.postgresql.org; Mon, 06 Mar 2023 16:35:36 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 326GZTwG3402994; Mon, 6 Mar 2023 11:35:30 -0500 From: Tom Lane To: hisahiro@freemind.co.jp cc: pgsql-bugs@lists.postgresql.org Subject: Re: BUG #17823: Generated columns not always updated correctly In-reply-to: <17823-b64909cf7d63de84@postgresql.org> References: <17823-b64909cf7d63de84@postgresql.org> Comments: In-reply-to PG Bug reporting form message dated "Mon, 06 Mar 2023 07:26:42 +0000" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <3402867.1678120442.0@sss.pgh.pa.us> Date: Mon, 06 Mar 2023 11:35:29 -0500 Message-ID: <3402993.1678120529@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <3402867.1678120442.1@sss.pgh.pa.us> PG Bug reporting form writes: > I found that the generated columns are sometimes not updated. Yeah. Looking into nodeModifyTable.c, we miss re-doing ExecComputeStoredGenerated when looping back after an EPQ update (which is what this case is). I see that we also fail to redo that after a cross-partition move, which is a bug since 8bf6ec3ba. The attached seems to be enough to fix it, but I want to also devise an isolation test for these cases ... regards, tom lane ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="fix-bug-17823-wip.patch"; charset="us-ascii" Content-ID: <3402867.1678120442.2@sss.pgh.pa.us> Content-Description: fix-bug-17823-wip.patch Content-Transfer-Encoding: quoted-printable diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor= /nodeModifyTable.c index 6f0543af83..6d9c0b0806 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -1910,9 +1910,10 @@ ExecUpdatePrologue(ModifyTableContext *context, Res= ultRelInfo *resultRelInfo, } = /* - * ExecUpdatePrepareSlot -- subroutine for ExecUpdate + * ExecUpdatePrepareSlot -- subroutine for ExecUpdateAct * * Apply the final modifications to the tuple slot before the update. + * (This is split out because we also need it in the foreign-table code p= ath.) */ static void ExecUpdatePrepareSlot(ResultRelInfo *resultRelInfo, @@ -1962,13 +1963,14 @@ ExecUpdateAct(ModifyTableContext *context, ResultR= elInfo *resultRelInfo, updateCxt->crossPartUpdate =3D false; = /* - * If we generate a new candidate tuple after EvalPlanQual testing, we - * must loop back here and recheck any RLS policies and constraints. (We - * don't need to redo triggers, however. If there are any BEFORE trigge= rs - * then trigger.c will have done table_tuple_lock to lock the correct - * tuple, so there's no need to do them again.) + * If we move the tuple to a new partition, we loop back here to recompu= te + * GENERATED values (which are allowed to be different across partitions= ) + * and recheck any RLS policies and constraints. We do not fire any + * BEFORE triggers of the new partition, however. */ lreplace: + /* Fill in GENERATEd columns */ + ExecUpdatePrepareSlot(resultRelInfo, slot, estate); = /* ensure slot is independent, consider e.g. EPQ */ ExecMaterializeSlot(slot); @@ -2268,6 +2270,7 @@ ExecUpdate(ModifyTableContext *context, ResultRelInf= o *resultRelInfo, } else if (resultRelInfo->ri_FdwRoutine) { + /* Fill in GENERATEd columns */ ExecUpdatePrepareSlot(resultRelInfo, slot, estate); = /* @@ -2290,9 +2293,13 @@ ExecUpdate(ModifyTableContext *context, ResultRelIn= fo *resultRelInfo, } else { - /* Fill in the slot appropriately */ - ExecUpdatePrepareSlot(resultRelInfo, slot, estate); - + /* + * If we generate a new candidate tuple after EvalPlanQual testing, we + * must loop back here to try again. (We don't need to redo triggers, + * however. If there are any BEFORE triggers then trigger.c will have + * done table_tuple_lock to lock the correct tuple, so there's no need + * to do them again.) + */ redo_act: result =3D ExecUpdateAct(context, resultRelInfo, tupleid, oldtuple, slo= t, canSetTag, &updateCxt); @@ -2876,7 +2883,6 @@ lmerge_matched: result =3D TM_Ok; break; } - ExecUpdatePrepareSlot(resultRelInfo, newslot, context->estate); result =3D ExecUpdateAct(context, resultRelInfo, tupleid, NULL, newslot, false, &updateCxt); if (result =3D=3D TM_Ok && updateCxt.updated) ------- =_aaaaaaaaaa0--