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 1w9vWJ-001tdM-26 for pgsql-hackers@arkaria.postgresql.org; Tue, 07 Apr 2026 01:46:23 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w9vWI-00DKVv-0b for pgsql-hackers@arkaria.postgresql.org; Tue, 07 Apr 2026 01:46:22 +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 1w9vWH-00DKVn-2q for pgsql-hackers@lists.postgresql.org; Tue, 07 Apr 2026 01:46:22 +0000 Received: from mail-pg1-x534.google.com ([2607:f8b0:4864:20::534]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w9vWF-000000010Sj-2mhr for pgsql-hackers@postgresql.org; Tue, 07 Apr 2026 01:46:22 +0000 Received: by mail-pg1-x534.google.com with SMTP id 41be03b00d2f7-b6ce6d1d3dcso1545509a12.3 for ; Mon, 06 Apr 2026 18:46:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775526378; x=1776131178; darn=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=tsJ7xQewU8tIb2CuB9WoASLDgAK80lFI0N+hF9goRR4=; b=DcyaW8/x3O1gGIGhvro2cih8in4sKA8Be3CzRP2i6Oyk8hOlSJJ6l5wdaqHgd3NVLQ bxvXWUY6aCpVv5hhKQj1oaWvipXjoAyJmAY4h5N1XTjX7+7E88R0sC8uWIG1rq6HKikm mXWGM5d8KKp0IkyZlR2O43auHaULN9p3/yPgNfmKtS1T6pTaGxWtd5W/idMsj4n0KN2D C96pI77V1kq3YL1XkTHk/c9+0LA/PaWJoPeKLd14F6OcXoxkduuHDYU59WmEUBDFS/lX RTT2TXZp9QliCNW+KzcuviowCOyH8b2mhkq6v+cbp0DwYpjqmokBh+LbjE0leRC4TVok FK1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775526378; x=1776131178; 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=tsJ7xQewU8tIb2CuB9WoASLDgAK80lFI0N+hF9goRR4=; b=h0a3ZmCWl38C7AxbL3c8dqj+ufCw6DdjudFiX3yOxuLUhxsoXv644bD+uYA6yWCGzO /by0Padn1FR9OFOAX0mehog47U5FKUsJ1hzy4XvuNbydNhVfhNfq6WBJdCmIivCtCavd MCBxPAB+ooKurm7szE00TSJEIydtxLaMM4ICN/XQmOUlUmS0aW+JQuSBg4+KTrudEFrF hKHk2mhi1vC6zjky+TKhe2xEBEfkVBsOzkGdKeXBh06eLI+GD2aLnmK3oQc7ISfFRQbF S0O77NtBTqVBG/FUPyK9S0GgCmwlChGMDQTQh5v38cCdpBCxE7m9PVFaxBq4uyhqLzeX EvVg== X-Forwarded-Encrypted: i=1; AJvYcCU0/Zc71RCpDG4LGega3pQTgquDiSJO4Dc2dg2AsjDEaDBEDx5/PSdgl4MdZHBXR1VNfM/+A89OH+8F8y7X@postgresql.org X-Gm-Message-State: AOJu0YyoVKbZ/U183I+zs2h4g+aPXTVR2DOhYZ8Fdpb9MMos2IQzagBv +la0PMDDbMdyVknPEPAYCKI49pdwp0VFDz5Vg3ZRD0b7X8VCQCGDSj0X X-Gm-Gg: AeBDievoh97J7hgf7lwMD87cahpWTihVAvJ2Or8psEJxYzfsWyeAc3I280zRgkMbiK6 /KRoPPhr3jtre5Yc2I37Ltut4yZGcE/4NPnaK+felo68SPz2hTi1v1ojJh2PgbvLix6mL0xQ4eV 8QI8NuUjAsG/P6JqNc3Hmib/qu/oEB+1+BMl2lGoOFEjFCe2qXUBOqtLNJc0mA5sZJT6l6QZcwR N+4xeQNYvRZZNnNsE3O/oPg1N4/SGkJWcvOUyfi34Y8FHPZvtb46xWBcHtca6y8XNBw4kF806Ea EdMbqtwiBJgWmDmtZTP+t7cHIXCu+54sAdBxYDwPU2R21COfB80q+lHXTCA6Dd8dcMfPIsnC4LL VEDuFzvOouMzfwVBSLWr1O5xYh1bXj6K3+3sGZEcqzwaqzMmNh8JmD3MXDDz5rgAXgo7icZxlBd hvvBvPewsdfQOXHirHg4EjTFzPWCNrUP4= X-Received: by 2002:a05:6a20:9152:b0:39f:2a91:5453 with SMTP id adf61e73a8af0-39f2ef7af44mr14718571637.3.1775526377947; Mon, 06 Apr 2026 18:46:17 -0700 (PDT) Received: from smtpclient.apple ([203.76.245.26]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c76c6492696sm13047268a12.12.2026.04.06.18.46.15 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 06 Apr 2026 18:46:17 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.400.21\)) Subject: Re: Eliminating SPI / SQL from some RI triggers - take 3 From: Chao Li In-Reply-To: Date: Tue, 7 Apr 2026 09:45:42 +0800 Cc: Junwang Zhao , Haibo Yan , Pavel Stehule , PostgreSQL-development , Tomas Vondra Content-Transfer-Encoding: quoted-printable Message-Id: <72AA2663-B642-4FB1-BDC2-5FAFF2D2DF15@gmail.com> References: <2BE661BA-D909-4093-BF78-DB9B0C099337@gmail.com> <77FA04FE-1F84-4DA1-8855-8BBFD8CC889A@gmail.com> To: Amit Langote 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 Apr 6, 2026, at 17:45, Amit Langote = wrote: >=20 > On Fri, Apr 3, 2026 at 6:39=E2=80=AFPM Amit Langote = wrote: >> On Fri, Apr 3, 2026 at 5:58=E2=80=AFPM Chao Li = wrote: >>>> On Apr 3, 2026, at 13:52, Amit Langote = wrote: >>>> On Thu, Apr 2, 2026 at 5:00=E2=80=AFPM Chao Li = wrote: >>>>> I plan to spend time testing and tracing this patch tomorrow. But = I don=E2=80=99t want to block your progress, if I find anything, I will = report to you. >>>>=20 >>>> Sure, I didn't want to leave committing this to the weekend or the = next week. >>>=20 >>> I spent several hours debugging this patch today, and I found a = problem where the batch mode doesn't seem to handle deferred RI = triggers, although the commit message suggests that it should. >>>=20 >>> I traced this scenario: >>> ``` >>> CREATE TABLE pk (a int primary key); >>> CREATE TABLE fk (a int references pk(a) DEFERRABLE INITIALLY = DEFERRED); >>> BEGIN; >>> INSERT INTO fk VALUES (1); >>> INSERT INTO pk VALUES (1); >>> COMMIT; >>> ``` >>>=20 >>> When COMMIT is executed, it reaches RI_FKey_check(), where = AfterTriggerIsActive() checks whether afterTriggers.query_depth >=3D 0. = But in the deferred case, afterTriggers.query_depth is -1. >>>=20 >>> =46rom the code: >>> ``` >>> if (ri_fastpath_is_applicable(riinfo)) >>> { >>> if (AfterTriggerIsActive()) >>> { >>> /* Batched path: buffer and probe in groups = */ >>> ri_FastPathBatchAdd(riinfo, fk_rel, newslot); >>> } >>> else >>> { >>> /* ALTER TABLE validation: per-row, no cache = */ >>> ri_FastPathCheck(riinfo, fk_rel, newslot); >>> } >>> return PointerGetDatum(NULL); >>> } >>> ``` >>>=20 >>> So this ends up falling back to the per-row path for deferred RI = checks at COMMIT, even though the intent here seems to be only to bypass = the ALTER TABLE validation case, where batch callbacks would never fire, = and MyTriggerDepth is 0. So, maybe we can just check MyTriggerDepth>0 in = AfterTriggerIsActive(). >>>=20 >>> I tried the attached fix. With it, deferred triggers go through the = batch mode, and all existing tests still pass. >>=20 >> I think you might be right. Thanks for the patch. It looks correct >> to me at a glance, but I will need to check it a bit more closely >> before committing. >=20 > Thinking about this some more, your fix is on the right track but > needs a bit more work -- MyTriggerDepth > 0 is too broad since it > fires for BEFORE triggers too. I have a revised version using a new > afterTriggerFiringDepth counter that I'll push shortly. >=20 > Added an open item for tracking in the meantime: > https://wiki.postgresql.org/wiki/PostgreSQL_19_Open_Items#Open_Issues >=20 > --=20 > Thanks, Amit Langote > V2 looks good to me. Besides the normal cases, I also traced an abnormal = case to verify that afterTriggerFiringDepth is always reset to 0: ``` evantest=3D# begin; BEGIN evantest=3D*# INSERT INTO fk VALUES (2); INSERT 0 1 evantest=3D*# commit; ERROR: insert or update on table "fk" violates foreign key constraint = "fk_a_fkey" DETAIL: Key (a)=3D(2) is not present in table "pk". ``` Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/