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 1x16x1-004z4S-1L for pgsql-hackers@arkaria.postgresql.org; Mon, 31 Aug 2026 18:41:47 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1x16x0-001nXr-1Q for pgsql-hackers@arkaria.postgresql.org; Mon, 31 Aug 2026 18:41:46 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x16wz-001nXi-2W for pgsql-hackers@lists.postgresql.org; Mon, 31 Aug 2026 18:41:46 +0000 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1x16wv-00000003LV1-1RuG for pgsql-hackers@postgresql.org; Mon, 31 Aug 2026 18:41:44 +0000 Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-49954b88fffso26962315e9.0 for ; Mon, 31 Aug 2026 11:41:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788201700; x=1788806500; darn=postgresql.org; h=in-reply-to:content-transfer-encoding:content-disposition :content-type:mime-version:references:message-id:subject:cc:to:from :date:from:to:cc:subject:date:message-id:reply-to:content-type; bh=HeVOTkG8zCovbbBjQqPETDt6qlNprQA+pTgAzTn0poU=; b=OiZJcBUaY73yajjxk3kBzw6j+KwskF3dXO1SgAg6lEwJEmvEBRw/mv+wi8fM/7q3sC i02wfMgZvs3NZigcgMLO8Q/Hwv0Zp4uoZNBq0wquGdCbeqvVDiNAk7og7ABirvw6Y0I6 zowiTtlprcPcDj4xmd/P+ExN09cdxZGiAJm102iLkcqmh6jtyGEZxDybpLUsbuxChz2N cqDP2epYsXqSfwxgBwwMoDnsibYqY/XGWat4vACcVXIEJeTSVies0Oz9AwhzS7RlesvC Oua3jxjOvnEI8c7TlXs0nDtyd1fQIPfSASL1FE6M2DTep1bP19bu2laO3i2XVMLy1Vrl XtaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788201700; x=1788806500; h=in-reply-to:content-transfer-encoding:content-disposition :content-type:mime-version:references:message-id:subject:cc:to:from :date:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=HeVOTkG8zCovbbBjQqPETDt6qlNprQA+pTgAzTn0poU=; b=XKI+YOl4hKD35yH8l1zPEJ+LVirLxL4Mb9XtxNf6Oi0Vap17XbKBx3HJZ7pfGmfqlf 7+n7UCugPS53QYcSEI289OdjT02j0Ddh76aqaFbvS3IyELfUw2CSnV8K0mNxEHrMzSHp 5b6yy7qW+owzFm5O04OmBrrPNU6Sub1YS2vkJIea7ar0JZo/hzX8LIFdwRAf+UGmXVLV +hl6qvtkPKFe9DUOSQpTTUy+QmAl7LbW0JqPVa95dT+363RHodunDTB+JUfJh/zl3hFx 0VUiSk/5hYo1h/+NuaJQofkviLSLJxd8lfNMf82PdF2nAsqy6jBAB5YXZZzCv4ZEfqEb 5wFA== X-Forwarded-Encrypted: i=1; AHgh+Rq8dVR4DD22Gh5P39CjrL/yW+whh6xiy2sWI+cAui59XJLfli6iGqdl4bZp+wUM/OnDGOpTj08FfJ4ciz18@postgresql.org X-Gm-Message-State: AFuF++nWKHHqjA+or6nWKBhtn7n5HuLa+yNTsjAOVKlyU5tcube2FTMK QGt/zFElpgaWx7UEls568tpT+aYA34QU5EJu+MfeQisiJOaE0AdcBOt5W7qkog== X-Gm-Gg: AR+sD1184XnHdPBAfPSNuL9E32V6Bhz1H/dlrrmrnPxJvY9keCj96l9NGLA8yXIIH1S FZR9RNT9TxEhcSYRNqGmKuA/Bwp1raJ5cOubmMC9AxbhrLVOXZJvBuABJOhPrRz/3vUxoCO5S3c zm39o2iGUCeqsoUGsGcZ/mx8vvSwlJq7hJh8TUlY1dcP9mNpxi0rgkgGYbpVuRVhx2bAe6nSsLI OtaEr7RRcfUzDyhIvH6S0dyWkVf20TWzk5FcY6qeT2T6rjpIrQGDizVrt2Z3WT18c+Fiz3mUDhk tV/lBQTwGaOPVy/JiqwrHnSnLUEEq3ywoAyUEknDpN7VTdYcwHAoC1hP50Un2qN5+vuvFBitmHI YY2iTsUMRKBdtTR298L/XmTSPHG6ciGPwVe7uaTXnnm2qQw3kSzOP7ZYXYED4fd6mOdQKgUAwQP Vk6bPlNKDX2GNRj89g6pqURL4BVpMrElARqq16QkytbSo4giZ2fn998ETsOAGt4n2pEyP5w8pi7 2lwQhHNVFU+3c8rH1UhN6LqW1Tw7OewoqWHhSd+lBK4b7n0InFiDp4= X-Received: by 2002:a05:600c:3549:b0:49b:5521:785d with SMTP id 5b1f17b1804b1-49b91c1e9d8mr415148355e9.4.1788201699579; Mon, 31 Aug 2026 11:41:39 -0700 (PDT) Received: from localhost (node-1secoahinaisz.sensational.ch. [2a02:168:9616:0:75a1:bbd8:703b:cb3]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49cdce164bcsm10208955e9.7.2026.08.31.11.41.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 31 Aug 2026 11:41:38 -0700 (PDT) Date: Mon, 31 Aug 2026 20:41:33 +0200 From: Alberto Piai To: Laurenz Albe , Alberto Piai , pgsql-hackers@postgresql.org Cc: =?utf-8?Q?=C3=81lvaro?= Herrera Subject: Re: Adding a stored generated column without long-lived locks Message-ID: X-Mailer: aerc 0.21.0 References: <6f5ea02f6e5205a96a9b3979190a4d7cb3c99414.camel@cybertec.at> <86a9336dc25d9a085916ad247a5791dc53d2ab13.camel@cybertec.at> <57bd5c0e2b532c07a1e6cd867520e899b1007622.camel@cybertec.at> <31fec16020bdf25d4a62cbbb4b8ea00af007e0d9.camel@cybertec.at> <82554bb40f6822bebbda7fcbc5ec1dc6a1823c0d.camel@cybertec.at> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="lthiybfwoezahbdk" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <82554bb40f6822bebbda7fcbc5ec1dc6a1823c0d.camel@cybertec.at> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --lthiybfwoezahbdk Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit Hi Laurenz, On Sat Aug 29, 2026 at 8:14 AM CEST, Laurenz Albe wrote: > On Fri, 2026-08-28 at 18:07 +0200, Alberto Piai wrote: >> Before this gets eventually picked up by a committer: I am having second >> thoughts about my choice to allow = in addition to IS NOT DISTINCT FROM. > > I think I see what you mean: this command exists exclusively so that users > can add a generated column to a bigger table without downtime. So they > will create the constraint specifically for this purpose, and it wouldn't > be a loss of functionality to force them to use IS NOT DISTINCT FROM. > Removing support for a constraint with = would simplify the code and the > documentation. > > I won't object to that, but I like the patch as it is now. > I can imagine a case where somebody uses a regular column with a check > constraint and at some later point decides to turn the column into a > generated column. That user might be annoyed if they had to create a > second check constraint, since there already is a perfectly good one. I liked the = form too (but: there is a "but" coming later :)), I always looked at this from the perspective of a user who is intentionally running through these steps to perform a very specific migration. Assuming they don't make mistakes (or the expression is not nullable, as in the simple case of "b = a + 1" where the referenced a is NOT NULL), = works fine. The problem is that it's relatively easy to make a mistake (or a malicious user could take advantage of it) whenever the expression is nullable. In that case, a row could be added to the table that still satisfies the constraint (since CHECK constraints are satisfied when the expression evaluates to NULL), the alter table would happily run through, and the db would be left in an inconsistent state. In the case above of "b = a + 1", if a is nullable, b is NOT NULL and a row (a, b) with values (null, 42) is inserted, rewriting operations like update ... set a = a, or pg_dump/pg_restore would fail. (This can easily be tested manually. I tried to trigger a run on the GitHub CI to show this, but the pg_upgrade test suite with PG_TEST_EXTRA=regress_dump_restore doesn't run there.) I also considered trying to prove non-nullability of the expression (there is for example expr_is_nonnullable() in clauses.c which does this), but the attempt failed on the realization that this would really require full static analysis of arbitrary functions in the expression. (The source column being NOT NULL is not sufficient, as a function used in the expression could still decide to return NULL in arbitrary cases.) So I think this is unfortunately a no-go, even if the form with = looks a lot more user-friendly. I have attached v10, which: - removes support for the = form of the constraints, adapting tests, documentation and error messages - removes an unnecessary ifdef I had around the injection points definitions - improves the detail message in the case where the constraint is found, but its shape doesn't match the expected form: alter table tgen.t1 add constraint chk_gen check (b = a * 2); alter table tgen.t1 alter column b add generated using constraint chk_gen stored; ERROR: cannot convert column "b" to generated -DETAIL: Could not find a valid constraint "chk_gen" CHECK ("b" IS NOT DISTINCT FROM expr). +DETAIL: The constraint "chk_gen" is not of the form CHECK ("b" IS NOT DISTINCT FROM expr). > I'd say that if you remove support for =, you might as well also remove > support for check constraints in the shape "(expression IS NOT DISTINCT > FROM column)". I left this in, as the extra code complexity is really tiny, so I thought it doesn't hurt much to have it there. I wish I'd have caught this sooner (especially after having been warned about this very problem in the first version of the patch) as it would have saved you some review effort. At least it's fixed before the next reviews :) Best regards, Alberto -- Alberto Piai Sensational AG Zürich, Switzerland --lthiybfwoezahbdk Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="v10-0001-Support-changing-a-column-into-a-stored-generate.patch"