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 1vdT6o-000vTe-1d for pgsql-general@arkaria.postgresql.org; Wed, 07 Jan 2026 12:57:55 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vdT6n-00E4PK-1Q for pgsql-general@arkaria.postgresql.org; Wed, 07 Jan 2026 12:57:54 +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 1vdT6n-00E4PC-07 for pgsql-general@lists.postgresql.org; Wed, 07 Jan 2026 12:57:53 +0000 Received: from mail-wr1-x430.google.com ([2a00:1450:4864:20::430]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vdT6l-00555m-0n for pgsql-general@postgresql.org; Wed, 07 Jan 2026 12:57:53 +0000 Received: by mail-wr1-x430.google.com with SMTP id ffacd0b85a97d-4327555464cso1144772f8f.1 for ; Wed, 07 Jan 2026 04:57:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cybertec.at; s=google; t=1767790670; x=1768395470; darn=postgresql.org; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:from:to:cc:subject:date :message-id:reply-to; bh=jFbyBIBhDR/Su7coB89QE8naXhGZwZY0zxnXYQoAI9E=; b=fYeaX1wrjFn8Rgt3X4wTC/+Av3lnK11yk6fkAm1K2DF475vyKTlAmpbmJ4EpbHnUEi FQZjbKEt8/nE2Jl0QiTOprzg/wz1Uq3ILGh0LgCTDw24gFiKw18mehXc8fJAfYDH9R25 5m0KvmLMvZt2zXey+k3wJVAaGp++bDM00nJSGXEHEJ8k8njCVwooE/TA7MjYgSQGxw2D yj+y6uDjvvZuUoiQk3VId+Yo6nFIVc7LyVtTASJE8TeakpM9RYBem4OEqjMcEdqkbHBQ gYSOtNNCsArhK6dXVSRPkis2TBKFTqR3kYjzbF+QCMUY6rgIFXA9rGp9SyA2Z6CgAeL0 CIkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767790670; x=1768395470; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=jFbyBIBhDR/Su7coB89QE8naXhGZwZY0zxnXYQoAI9E=; b=EtlmmwuQTdDzNXDFVuYmUeWZSJrhC+YO6uom8nwKv8Oq+wgYTSIzlhz/Vwhvw+lr0p g9rcZ2MvyoMb+w/YVaYb+tF9VZo/b9KvngIHcCe855JbUWIhzBikNwnGwYWjjJJTHs6K vR+lrOxF679f8ohiK6tnyT6BkaSn9PN1f/H8kToUrJvKJ0wt/3fWdeH8PS2mFOZPKlWM 9gardSwSB71O9DsTnytkdh83viDUHASePVs9WdFOf7DOpXCR5ZO+eSO04A8ceI6gBl/U gkW8zjzB47xAou+r9ByEf8Ad49kNQxLZy77AEX5zJaA71cArLxqnWYXIGvtytWMEO76+ kmNg== X-Forwarded-Encrypted: i=1; AJvYcCUl7ycwj8rdym8N7eoWReQq609QMG4FBbhaE21Te4Z3dOcVlybCnKl1VJqLwGDRcNTK2fwfgbAJu2WetRXV@postgresql.org X-Gm-Message-State: AOJu0YygEjWYRAKWY68W2g5rSDbNRLnHpRuH8RNHubxFHMYQaGXdnIN4 rb3cm2UIwLJ2tmvANNY443WvhZdTETPQ6b0qgmp/+887Wq9fXW6wJpeVR5+NwVwG9K4= X-Gm-Gg: AY/fxX4QNSLR7N30jsQUg8/HK04bcTAGp/LpRVPJfu9RKWrCkd19sOBFLR9KBtqWz6q JAr18V09dX+fHlFnGbY3DhFjPj1pNxiI3yhpoQxPNEt6c400FP5lubZPC9gBlILr8nf8+bShHWo gI2Kk4P7QKA4rgQIBxbGm2Ju6HmCfdXgjT0zR2odk2m+SBC5Mzv7nGh0vR6wnoQXSeMbGYtV3C9 DHmIlaLiX5R4vBfcy+ECnwkdrIr1pmeIOL7IaVJSpOnm5NFzj1nEtiU3HdGC/Mv8nweAfFglkKI 1ZyXjU75wod51Cfv5CAFrjpfvhzhbF01eAFBK2nGkiCrNUJFmLrEG/RDN8YYaruH2xsScQnkshU 77cKcD02dpIHTBJkyxTSXRdAPAbOzxaGwVvzJaZXTMMngECKmsKMeYLtQUdi00ZtACvB6q2rsqi MmsY5REHJglaKijgTZu4nZmOfGxg5eDmpRnjrES09bNrQ= X-Google-Smtp-Source: AGHT+IGI/T5PE7hn+X5sg3P+L12yqjdZqmfGp+ICGOxxXgQzl6kZuVSRDa6+GLQtcEilQXpN5X39/g== X-Received: by 2002:a05:6000:420a:b0:431:266:d132 with SMTP id ffacd0b85a97d-432c37a505bmr3368101f8f.46.1767790669879; Wed, 07 Jan 2026 04:57:49 -0800 (PST) Received: from laurenz.albe-K4N0CV00F97414D ([2001:871:270:4cd4:ad4e:e4e4:66cb:81ac]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-432bd5fe67csm9965655f8f.40.2026.01.07.04.57.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Jan 2026 04:57:49 -0800 (PST) Message-ID: <1fa24f41862f214b44bcf94556db51c9946d28bd.camel@cybertec.at> Subject: Re: Unexpected modification of check constraint definition From: Laurenz Albe To: Stuart Campbell , pgsql-general@postgresql.org Date: Wed, 07 Jan 2026 13:57:49 +0100 In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.58.2 (3.58.2-1.fc43) MIME-Version: 1.0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Wed, 2026-01-07 at 21:32 +1100, Stuart Campbell wrote: > I noticed that check constraint definitions are sometimes rewritten/norma= lized on input, and I was hoping to understand that a little better. >=20 > For instance, if I create this table with a check constraint: >=20 > create table foo ( > =C2=A0 val varchar, > =C2=A0 constraint val_valid check (val in ('a','b','c')) > ); >=20 > and then dump the schema with pg_dump, it looks more like this: >=20 > CREATE TABLE public.foo ( > =C2=A0 =C2=A0 val character varying, > =C2=A0 =C2=A0 CONSTRAINT val_valid CHECK (((val)::text =3D ANY ((ARRAY['a= '::character varying, 'b'::character varying, 'c'::character varying])::tex= t[]))) > ); >=20 > However, if I then recreate the schema from that dump, and then dump with= pg_dump a second time, it ends up different again: >=20 > CREATE TABLE public.foo ( > =C2=A0 =C2=A0 val character varying, > =C2=A0 =C2=A0 CONSTRAINT val_valid CHECK (((val)::text =3D ANY (ARRAY[('a= '::character varying)::text, ('b'::character varying)::text, ('c'::characte= r varying)::text]))) > ); >=20 > I'm working in a Ruby on Rails application where the schema is periodical= ly dumped to a structure.sql > file on disk. So, it would be convenient if the constraint definition was= "stable" (otherwise, there's > unnecessary noise in our version control history) >=20 > Is it expected that the second form is=C2=A0rewritten into the third form= ? It seems a bit odd to see all > the type casting going on, but maybe there is a good reason for that. (Ma= ybe this is an issue with > using varchar instead of text?) Yes, using "varchar" is definitely part of why it is so odd. There is no equality operator for "varchar", so you need an (implicit) cast= to "text". That implicit cast is made explicit when the parsed binary form of the cons= traint expression is reverse engineered to a string during "pg_dump". I'd say that the change you mention "just happened", but you can never rely= on these expressions being rendered in a fixed way - this can change any time. Look at this art= ificial example: CREATE TABLE test (col varchar CONSTRAINT con CHECK (col <> 'y')); SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname =3D 'co= n'; pg_get_constraintdef =20 =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90= =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95= =90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90= =E2=95=90=E2=95=90=E2=95=90 CHECK (((col)::text <> 'y'::text)) CREATE TYPE public.text AS enum ('x'); SET search_path =3D public, pg_catalog; SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname =3D 'co= n'; pg_get_constraintdef =20 =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90= =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95= =90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90= =E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2= =95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95= =90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90=E2=95=90 CHECK (((col)::pg_catalog.text <> 'y'::pg_catalog.text)) The proper solution is not to rely on the way that such expressions are ren= dered. Rather than relying on a tool like pg_dump to create your "structure.sql", = write it by hand an maintain in in a version control system. But perhaps it is good enoulh if you define the constraint by casting to "t= ext" early: CHECK (val::text IN ('a','b','c')) > This communication and any attachments may contain confidential informati= on and are intended to be > viewed only by the intended recipients. Got it, I won't forward your mail... err... Yours, Laurenz Albe