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.94.2) (envelope-from ) id 1rvCrb-00ARnS-Ex for pgsql-hackers@arkaria.postgresql.org; Fri, 12 Apr 2024 09:06:27 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rvCrY-00BoKw-Ii for pgsql-hackers@arkaria.postgresql.org; Fri, 12 Apr 2024 09:06:24 +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.94.2) (envelope-from ) id 1rvCrY-00BoKo-96 for pgsql-hackers@lists.postgresql.org; Fri, 12 Apr 2024 09:06:24 +0000 Received: from mail-vs1-xe2d.google.com ([2607:f8b0:4864:20::e2d]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rvCrR-000Wa0-8W for pgsql-hackers@lists.postgresql.org; Fri, 12 Apr 2024 09:06:23 +0000 Received: by mail-vs1-xe2d.google.com with SMTP id ada2fe7eead31-479c8f43ca5so307279137.0 for ; Fri, 12 Apr 2024 02:06:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1712912775; x=1713517575; darn=lists.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=+wjlWBPOnUP8P0Swr0BgC/1jfLkp6oeZ7iwxasmWN2U=; b=jz91E9vAjoQbmZ8fdDhjn9Qmp2C5/dMPmkbJfGtMihDCJTTnB6xCbD0TOcPpdMBmZ1 33RSP9J/UMAwxf1oPfkDAPkhX3Cw7/XXjZVOKP2DkiOhLL7R13Kpj80xC3SecKNJlv2K Y6axhZ3b4vKPUC8Bu461u3R3zeuKebSr33sUPO/4N2acaOkQUcBZ72N7/yYmbvW0tx8A pRE3Dzk2VQHPt/nMWl8vHOG7smVrIRcFqZctyvpm1CDolX2Gwu7NOHXOat/YpZbSYjqI mvAmzGX12fQWcCKe6n6iGDUGs+oO9+lFABd4NkCJ6pGgtHNQmJSeP0gmSLt8ggBN/Szu 8eUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712912775; x=1713517575; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+wjlWBPOnUP8P0Swr0BgC/1jfLkp6oeZ7iwxasmWN2U=; b=nJEjrG4kKceiURIhW9XkbCg9RtXYikukJH3aoWPalbtG1BJCuKi+gvQggNpG7bye/f 0CaWarmy7vGnI1SfhBbNsBk8c6VPaNskboUMSRvvyIhqiStIYgNs6D086fXI/TLeze05 2aZ7UJ86xEv6h4tLYFcMEFLSHXBk6I0nEaIInKxxdtuFs5pKgYmwuQKWdUVICxNmeMR7 Y86DBLfuohkVKjUL0voav2XIkzzLRDF3X2qayl/lqCR6P3FrBl/LS9UYMI9gAB+ULCNl TCMOd+E1oahnHdWV45s4hh6IOBC6a+qSg4QA4kMEBMVg70zG3FABfKvMGWbT9T794szr H+YQ== X-Gm-Message-State: AOJu0Yx003pLoF8ybNNW+IHiSDRNrD5LJZesQfzuI8utKpnF3hGTlhn6 ITpID605TO4ns5hNZLCfpkVlCt865l5ylqYXKX8sqEC6/VrQXpcv+c9hTj7nhkt1UuJBv4MuWF8 19Lx0db66wTHBiuS8wPghtP8s3g8HuMolc7g= X-Google-Smtp-Source: AGHT+IEx7LgFqGoPIdwjMeDwbdM6c2dmD2e7b284YkFvdC89pUszHbn7E1QSJ27u4TsgaH9K53H+TWNdMVBH3yuN84k= X-Received: by 2002:a05:6102:6c8:b0:47a:2c9c:9da with SMTP id m8-20020a05610206c800b0047a2c9c09damr2440132vsg.22.1712912775276; Fri, 12 Apr 2024 02:06:15 -0700 (PDT) MIME-Version: 1.0 References: <78d824e0-b21e-480d-a252-e4b84bc2c24b@illuminatedcomputing.com> <69f0a887-a4ed-49cf-9d63-923891006658@illuminatedcomputing.com> In-Reply-To: From: jian he Date: Fri, 12 Apr 2024 17:06:04 +0800 Message-ID: Subject: Re: altering a column's collation leaves an invalid foreign key To: Paul Jungwirth Cc: PostgreSQL Hackers 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 Tue, Mar 26, 2024 at 1:00=E2=80=AFPM jian he wrote: > > On Mon, Mar 25, 2024 at 2:47=E2=80=AFPM Paul Jungwirth > wrote: > > > > On 3/23/24 10:04, Paul Jungwirth wrote: > > > Perhaps if the previous collation was nondeterministic we should forc= e a re-check. > > > > Here is a patch implementing this. It was a bit more fuss than I expect= ed, so maybe someone has a > > better way. > > > > + /* test follows the one in ri_FetchConstraintInfo() */ > + if (ARR_NDIM(arr) !=3D 1 || > + ARR_HASNULL(arr) || > + ARR_ELEMTYPE(arr) !=3D INT2OID) > + elog(ERROR, "conkey is not a 1-D smallint array"); > + attarr =3D (AttrNumber *) ARR_DATA_PTR(arr); > + > + /* stash a List of the collation Oids in our Constraint node */ > + for (i =3D 0; i < numkeys; i++) > + con->old_collations =3D lappend_oid(con->old_collations, > + list_nth_oid(changedCollationOids, attarr[i] - 1)); > > I don't understand the "ri_FetchConstraintInfo" comment. I still don't understand this comment. > > +static void > +RememberCollationForRebuilding(AttrNumber attnum, AlteredTableInfo *tab) > +{ > + Oid typid; > + int32 typmod; > + Oid collid; > + ListCell *lc; > + > + /* Fill in the list with InvalidOid if this is our first visit */ > + if (tab->changedCollationOids =3D=3D NIL) > + { > + int len =3D RelationGetNumberOfAttributes(tab->rel); > + int i; > + > + for (i =3D 0; i < len; i++) > + tab->changedCollationOids =3D lappend_oid(tab->changedCollationOids, > + InvalidOid); > + } > + > + get_atttypetypmodcoll(RelationGetRelid(tab->rel), attnum, > + &typid, &typmod, &collid); > + > + lc =3D list_nth_cell(tab->changedCollationOids, attnum - 1); > + lfirst_oid(lc) =3D collid; > +} > > do we need to check if `collid` is a valid collation? > like: > > if (!OidIsValid(collid)) > { > lc =3D list_nth_cell(tab->changedCollationOids, attnum - 1); > lfirst_oid(lc) =3D collid; > } now I think RememberCollationForRebuilding is fine. no need further change. in ATAddForeignKeyConstraint. if (old_check_ok) { /* * When a pfeqop changes, revalidate the constraint. We could * permit intra-opfamily changes, but that adds subtle complexity * without any concrete benefit for core types. We need not * assess ppeqop or ffeqop, which RI_Initial_Check() does not use. */ old_check_ok =3D (pfeqop =3D=3D lfirst_oid(old_pfeqop_item)); old_pfeqop_item =3D lnext(fkconstraint->old_conpfeqop, old_pfeqop_item); } maybe we can do the logic right below it. like: if (old_check_ok) { * All deterministic collations use bitwise equality to resolve * ties, but if the previous collation was nondeterministic, * we must re-check the foreign key, because some references * that use to be "equal" may not be anymore. If we have * InvalidOid here, either there was no collation or the * attribute didn't change. old_check_ok =3D (old_collation =3D=3D InvalidOid || get_collation_isdeterministic(old_collation)); } then we don't need to cram it with the other `if (old_check_ok){}`. do we need to add an entry in https://wiki.postgresql.org/wiki/PostgreSQL_17_Open_Items#Open_Issues ?