From: Jeff Davis Date: Wed, 22 Apr 2026 17:22:44 +0000 (-0700) Subject: catcache.c: use C_COLLATION_OID for texteqfast/texthashfast. X-Git-Url: http://git.ipfire.org/index.cgi?a=commitdiff_plain;ds=sidebyside;p=thirdparty%2Fpostgresql.git catcache.c: use C_COLLATION_OID for texteqfast/texthashfast. The problem report was about setting GUCs in the startup packet for a physical replication connection. Setting the GUC required an ACL check, which performed a lookup on pg_parameter_acl.parname. The catalog cache was hardwired to use DEFAULT_COLLATION_OID for texteqfast() and texthashfast(), but the database default collation was uninitialized because it's a physical walsender and never connects to a database. In versions 18 and later, this resulted in a NULL pointer dereference, while in version 17 it resulted in an ERROR. As the comments stated, using DEFAULT_COLLATION_OID was arbitrary anyway: if the collation actually mattered, it should have used the column's actual collation. (In the catalog, some text columns are the default collation and some are "C".) Fix by using C_COLLATION_OID, which doesn't require any initialization and is always available. When any deterministic collation will do, it's best to consistently use the simplest and fastest one, so this is a good idea anyway. Another problem was raised in the thread, which this commit doesn't fix (see second discussion link). Reported-by: Andrey Borodin Discussion: https://postgr.es/m/D18AD72A-5004-4EF8-AF80-10732AF677FA@yandex-team.ru Discussion: https://postgr.es/m/4524ed61a015d3496fc008644dcb999bb31916a7.camel%40j-davis.com Backpatch-through: 17 --- diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 87ed5506460..a8e7bf649d2 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -205,6 +205,10 @@ nameeqfast(Datum a, Datum b) char *ca = NameStr(*DatumGetName(a)); char *cb = NameStr(*DatumGetName(b)); + /* + * Catalogs only use deterministic collations, so ignore column collation + * and use fast path. + */ return strncmp(ca, cb, NAMEDATALEN) == 0; } @@ -213,6 +217,10 @@ namehashfast(Datum datum) { char *key = NameStr(*DatumGetName(datum)); + /* + * Catalogs only use deterministic collations, so ignore column collation + * and use fast path. + */ return hash_bytes((unsigned char *) key, strlen(key)); } @@ -244,17 +252,20 @@ static bool texteqfast(Datum a, Datum b) { /* - * The use of DEFAULT_COLLATION_OID is fairly arbitrary here. We just - * want to take the fast "deterministic" path in texteq(). + * Catalogs only use deterministic collations, so ignore column collation + * and use "C" locale for efficiency. */ - return DatumGetBool(DirectFunctionCall2Coll(texteq, DEFAULT_COLLATION_OID, a, b)); + return DatumGetBool(DirectFunctionCall2Coll(texteq, C_COLLATION_OID, a, b)); } static uint32 texthashfast(Datum datum) { - /* analogously here as in texteqfast() */ - return DatumGetInt32(DirectFunctionCall1Coll(hashtext, DEFAULT_COLLATION_OID, datum)); + /* + * Catalogs only use deterministic collations, so ignore column collation + * and use "C" locale for efficiency. + */ + return DatumGetInt32(DirectFunctionCall1Coll(hashtext, C_COLLATION_OID, datum)); } static bool