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 1w4vHK-002hFn-0m for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Mar 2026 06:30:14 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w4vHI-004dRS-1g for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Mar 2026 06:30:12 +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 1w4vHI-004dRH-0m for pgsql-hackers@lists.postgresql.org; Tue, 24 Mar 2026 06:30:12 +0000 Received: from mail-ot1-x335.google.com ([2607:f8b0:4864:20::335]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w4vHG-00000000pRQ-0PXx for pgsql-hackers@postgresql.org; Tue, 24 Mar 2026 06:30:12 +0000 Received: by mail-ot1-x335.google.com with SMTP id 46e09a7af769-7d7447778b9so1813606a34.2 for ; Mon, 23 Mar 2026 23:30:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1774333809; cv=none; d=google.com; s=arc-20240605; b=S1cMiDz9cOpI0PXWAsKHG7/eZvTlV15Qv966LwDI+5GNzapctt51TE8wsihYKl21y5 SJ6nGrffWAKNE81lae8xPNDooCy1RyLt/vg3lW2bqT6FsuCLf4oGNKENnjU/z7cmbzs8 zOt4XvkI7qi2T5eJgIQ43kR8z7MI7aWB4wwHK4tYKnlVlMSaCTWzNBBSq71Zowl2pRQf s/ENrsQ7TdNF1F/cmBd4CrhlFB9a/7hyYOn3B1vrSTuooyHgzSfaGyjj6b3Q1dKaJ+9G dHvYgFetBTZ59A+IfFY8wRzMis+4BHpmMMFmDpWNKejncgPmTDv+RK8lmhS2izk99xVJ dY9Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=eMLSrvgq6jTOiLvl0AYj2iI4Yd5fhtnrMmeYPKzqgnQ=; fh=eLlHHukhOAkV6fRvA+QHempXrf+afsViNG2YcCtsl8U=; b=N/FpyTFAm3KLRgVMvfbWAhjdnxq0ADTl0tXfQgl8NtOkevVLV22lrK2h1cY6c/FxO5 nNsCbXhlOPBWP5yJcCGhsYmsoomBqDca1R7mFMTVbz0PjQCSNQxQe90AEMDU4bbIxdOV gCHS0/2wXyWTaWXdCCFCbIkgokvvZsLeufSqUqmkKpJfxxowqgVoIXqTDs7//Kg+eTDw RgEDlTIbGsUrDPSNHE9LrpRmE5qPGGZLhq3ENYuTxcAdAMlLwXFTKNZSnCYBloknrjP4 NlIdk6O8Zl8Ha+1/fpqZRrZUgx5VXbZcpMyjK4cL8cMsM+pwo3nu2CfqpY5aUR2mGTdk fnhg==; darn=postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774333809; x=1774938609; darn=postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=eMLSrvgq6jTOiLvl0AYj2iI4Yd5fhtnrMmeYPKzqgnQ=; b=RjK9N/V+kTpmfpseSd9Urn9lBHrQv11/JGP7J14zjpxw5yCcDr7P1d7r+bCzFRU+0Y tfRhZ3LBv21Opw76lJ7VeRZV1NRPSmqCjV5YyROUB27LLQWxgm9xmnTFXjF/4xkWu2a3 XqkKqAjnt3Q/g7uy9cq8cgiV0EcY6drnc/N9MfSrZmFh9omWQmVsPhmpU0fhMdNlrwgo iEHoJgu9WBqZi9w+j3G35h62zZMofH/GiQjGGkYVIbPKD7gcN2oxb6fTOGsG0nQhEv11 lYmmv9xVwSJdn/0PQD86m7fB2KDBIDe19vd6r13uS0FCx6m4O+kyMHGH4wa3eCALEtT0 3KhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774333809; x=1774938609; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=eMLSrvgq6jTOiLvl0AYj2iI4Yd5fhtnrMmeYPKzqgnQ=; b=Kc7JVFoI+BkZp/xnDsFdQZfR/HUaSp9ze/gwKDxeXCZREgzavQ8rnCHb8p8prvNjHK 5l9cFHnbFaRUFsR600qN/8xFvjuw1VjdW9d05g1xnCXCrTXanoVoMxpN8U70mSubz+3o wefiEal/qAh8yNEBRBvWh4P8gZS0BDxXxUy7f9fZJUgTbggjrhWZls7w+0cqhwVdu2wi Snm7iLLMFx0zNSBBE+qe2u5ylKoHkJJ/qS5ZWyLwfJfodZkV2mD1b/oXTE1F2WS9dzqI PgxKkGPL2RZuyWYhiCZ/a/isxwdtoIon1tqmj1ntHROZRRuae9lgMkzzpCkHToxVUmWC r54Q== X-Gm-Message-State: AOJu0YwkToHoNHJPN+U/9/JHz1xXEBfVW2Wb6kVuGAw1yVce55qurV/F euLBpDF17vv9gnUtVoSlY2cVt9wBxL5a2VQGmWfPvWVPnzMvbD8+I5dPzeZxVZHZfHvbJSdnhUU e/euAosYcHT9Pp82CjexNDuFcc20hHKU= X-Gm-Gg: ATEYQzw49AYXC59rDCpCEIMvcpLe5L6bN4/rGHiAoT/2H+DRgUeghz+S13YEwY1NtYe 6QPssR/BV4/Jn4Iz7v81D4cfkgvNqIchMQIcHhJtyZnA/KbVpddbDQvHAzewYYD4QQiGz3Ybi70 6wyElg/Ya+PJ/yc9DHIGLSLcaJz0oO3D4jlYSKWR1Hs0a0+VJDQyzwghc5Op45PXZjw/i3U3JnB WaiOc82s1R7mp8HamJZPqVf0avSfL3KS5DUacg4L6MVhc/ODdAI0zks8bykX7H2K+dn6sh6S1UA Jr+AkYAlAifPgSIRJlf1D8DlW3wDYIrlQ/gwIB0= X-Received: by 2002:a05:6820:c8e:b0:67b:f1c8:edd6 with SMTP id 006d021491bc7-67c22faa4ffmr10937689eaf.55.1774333808334; Mon, 23 Mar 2026 23:30:08 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Fujii Masao Date: Tue, 24 Mar 2026 15:29:55 +0900 X-Gm-Features: AQROBzBg4aNRC2TxotFrDAaWCJpeoyff9lnEbazm8tGQst3wa-zQQvwG5SRm1C0 Message-ID: Subject: Re: [PATCH] Fix unexpected loss of DEFERRABLE property after toggling NOT ENFORCED / ENFORCED To: Yasuo Honda Cc: PostgreSQL-development Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Fri, Feb 27, 2026 at 6:51=E2=80=AFPM Yasuo Honda = wrote: > > Hi, > > I have encountered an unexpected behavior where the DEFERRABLE and > INITIALLY DEFERRED properties of foreign keys are lost after toggling > them from NOT ENFORCED to ENFORCED. > > Background > > In the Ruby on Rails framework, there is a built-in mechanism to > temporarily bypass foreign key checks while loading test data. > Currently, this is implemented using: ALTER TABLE ... DISABLE TRIGGER > ALL; ALTER TABLE ... ENABLE TRIGGER ALL; > > However, this requires superuser privileges. With the newly introduced > support for "NOT ENFORCED" foreign keys in PostgreSQL 18, I am > interested in switching to: ALTER TABLE ... ALTER CONSTRAINT ... NOT > ENFORCED; ALTER TABLE ... ALTER CONSTRAINT ... ENFORCED; > > This would allow the operation to be performed by the table owner > without superuser rights. However, I discovered that switching the > state back to ENFORCED unexpectedly strips away the DEFERRABLE > property. > > Problem > > When re-enforcing a constraint, there is a discrepancy between the > constraint definition and its underlying triggers. > While the flags in pg_constraint remain correct, the corresponding > triggers in pg_trigger (tgdeferrable and tginitdeferred) are reset to > defaults ('f') when they are reconstructed during the ENFORCED > operation. > > I have attached a reproduction SQL script that demonstrates this by > comparing the values in pg_constraint and pg_trigger. In the current > PostgreSQL 18.3, you can see that the triggers lose their > deferrability even though the constraint itself is still defined as > DEFERRABLE. This causes "SET CONSTRAINTS ... DEFERRED" to fail. > > After Patch > > * The tgdeferrable and tginitdeferred flags in pg_trigger are > correctly preserved to match pg_constraint after the toggle, and > deferred execution works as expected. > > I've attached the reproduction SQL script and a patch to fix this in > src/backend/commands/tablecmds.c. The patch and reproduction SQL > script were developed with the assistance of Claude Code. I have > reviewed and verified the code myself. > > Any feedback is appreciated. Thanks for reporting the issue and providing a patch! I was able to reproduce the issue on the master. The patch looks good overall, but since I'm not very familiar with this are= a, I'd like to spend a bit more time reviewing the changes in detail. Regarding the regression test, would it be better to verify not only catalo= g state (e.g., pg_trigger) but also the actual behavior? For example, we coul= d check that a foreign key violation is not raised immediately on INSERT, but instead at COMMIT even after ALTER CONSTRAINT ENFORCED: ALTER TABLE ... ALTER CONSTRAINT ... NOT ENFORCED; ALTER TABLE ... ALTER CONSTRAINT ... ENFORCED; BEGIN; INSERT INTO t VALUES (1); COMMIT; In this case, the foreign key violation should be reported at COMMIT, even after ALTER CONSTRAINT ... ENFORCED. Regards, --=20 Fujii Masao