From 4225a4b2e51757f12d42459cd993dee674c04739 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 2 Jul 2026 18:11:10 -0400
Subject: [PATCH v3 5/5] Remove btree_gist's useless logic for encoding-aware
 truncation.

gbt_var_node_cp_len() contained logic to ensure that its choice of
a common prefix length didn't truncate away part of a multibyte
character.  However, that was really dead code, because we have not
allowed truncation of text-string data types since ef770cbb6, and
it seems unlikely that that behavior could ever get resurrected.
The code is still reachable via gbt_var_penalty, but for that
usage it hardly matters if we break in the middle of a multibyte
character: we're just calculating a small correction factor that
is arguably bunkum anyway in non-C locales.

Hence, delete said code.  That actually removes all need for
gbtree_vinfo.eml, which allows const-ification of the gbtree_vinfo
structs in which we were changing it, which removes one headache
for future attempts to thread-ify the backend.

(Curiously, all this infrastructure was itself added by ef770cbb6.
Not sure why Teodor didn't see the contradiction.)

Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/AH*AvQCYKhQGVvPWi1GiU4oY.8.1781609375063.Hmail.3020001251@tju.edu.cn
---
 contrib/btree_gist/btree_bit.c       |  1 -
 contrib/btree_gist/btree_bytea.c     |  1 -
 contrib/btree_gist/btree_numeric.c   |  1 -
 contrib/btree_gist/btree_text.c      | 21 ++--------------
 contrib/btree_gist/btree_utils_var.c | 36 +++++-----------------------
 contrib/btree_gist/btree_utils_var.h |  2 --
 6 files changed, 8 insertions(+), 54 deletions(-)

diff --git a/contrib/btree_gist/btree_bit.c b/contrib/btree_gist/btree_bit.c
index 8d8e9454268..5fb8c8b82f0 100644
--- a/contrib/btree_gist/btree_bit.c
+++ b/contrib/btree_gist/btree_bit.c
@@ -136,7 +136,6 @@ gbt_bit_l2n(GBT_VARKEY *leaf, FmgrInfo *flinfo)
 static const gbtree_vinfo tinfo =
 {
 	gbt_t_bit,
-	0,
 	true,						/* internal keys can be truncated */
 	gbt_bitgt,
 	gbt_bitge,
diff --git a/contrib/btree_gist/btree_bytea.c b/contrib/btree_gist/btree_bytea.c
index 8411598a99b..bcb469e8c86 100644
--- a/contrib/btree_gist/btree_bytea.c
+++ b/contrib/btree_gist/btree_bytea.c
@@ -73,7 +73,6 @@ gbt_byteacmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
 static const gbtree_vinfo tinfo =
 {
 	gbt_t_bytea,
-	0,
 	true,						/* internal keys can be truncated */
 	gbt_byteagt,
 	gbt_byteage,
diff --git a/contrib/btree_gist/btree_numeric.c b/contrib/btree_gist/btree_numeric.c
index 8a506865b17..7a75e2ed00d 100644
--- a/contrib/btree_gist/btree_numeric.c
+++ b/contrib/btree_gist/btree_numeric.c
@@ -83,7 +83,6 @@ gbt_numeric_cmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
 static const gbtree_vinfo tinfo =
 {
 	gbt_t_numeric,
-	0,
 	false,						/* no truncation permitted */
 	gbt_numeric_gt,
 	gbt_numeric_ge,
diff --git a/contrib/btree_gist/btree_text.c b/contrib/btree_gist/btree_text.c
index e7269ba3e7c..a8657fe461a 100644
--- a/contrib/btree_gist/btree_text.c
+++ b/contrib/btree_gist/btree_text.c
@@ -86,10 +86,9 @@ gbt_textcmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
  * more complicated than C.  The prefix-match hack used for simpler types
  * can't fix it, either.
  */
-static gbtree_vinfo tinfo =
+static const gbtree_vinfo tinfo =
 {
 	gbt_t_text,
-	0,
 	false,						/* no truncation permitted */
 	gbt_textgt,
 	gbt_textge,
@@ -156,10 +155,9 @@ gbt_bpcharcmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
 												 PointerGetDatum(b)));
 }
 
-static gbtree_vinfo bptinfo =
+static const gbtree_vinfo bptinfo =
 {
 	gbt_t_bpchar,
-	0,
 	false,						/* as above, no truncation permitted */
 	gbt_bpchargt,
 	gbt_bpcharge,
@@ -180,11 +178,6 @@ gbt_text_compress(PG_FUNCTION_ARGS)
 {
 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 
-	if (tinfo.eml == 0)
-	{
-		tinfo.eml = pg_database_encoding_max_length();
-	}
-
 	PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
 }
 
@@ -212,11 +205,6 @@ gbt_text_consistent(PG_FUNCTION_ARGS)
 	/* All cases served by this function are exact */
 	*recheck = false;
 
-	if (tinfo.eml == 0)
-	{
-		tinfo.eml = pg_database_encoding_max_length();
-	}
-
 	retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
 								GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
 
@@ -240,11 +228,6 @@ gbt_bpchar_consistent(PG_FUNCTION_ARGS)
 	/* All cases served by this function are exact */
 	*recheck = false;
 
-	if (bptinfo.eml == 0)
-	{
-		bptinfo.eml = pg_database_encoding_max_length();
-	}
-
 	retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
 								GIST_LEAF(entry), &bptinfo, fcinfo->flinfo);
 	PG_RETURN_BOOL(retval);
diff --git a/contrib/btree_gist/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c
index f1b13741630..60373aaf07c 100644
--- a/contrib/btree_gist/btree_utils_var.c
+++ b/contrib/btree_gist/btree_utils_var.c
@@ -126,56 +126,32 @@ gbt_var_leaf2node(GBT_VARKEY *leaf, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
 /*
  * returns the common prefix length of a node key
  *
- * If the underlying type is character data, the prefix length may point in
- * the middle of a multibyte character.
+ * This is not used for any cases where the underlying type is character data
+ * (except in gbt_var_penalty, where it doesn't matter since we're just making
+ * an estimated correction not constructing a truncated string).  If it were,
+ * we'd need to be careful not to truncate in the middle of a multibyte
+ * character.
  */
 static int32
 gbt_var_node_cp_len(const GBT_VARKEY *node, const gbtree_vinfo *tinfo)
 {
 	GBT_VARKEY_R r = gbt_var_key_readable(node);
 	int32		i = 0;
-	int32		l_left_to_match = 0;
-	int32		l_total = 0;
 	int32		t1len = VARSIZE(r.lower) - VARHDRSZ;
 	int32		t2len = VARSIZE(r.upper) - VARHDRSZ;
 	int32		ml = Min(t1len, t2len);
 	char	   *p1 = VARDATA(r.lower);
 	char	   *p2 = VARDATA(r.upper);
-	const char *end1 = p1 + t1len;
-	const char *end2 = p2 + t2len;
 
 	if (ml == 0)
 		return 0;
 
 	while (i < ml)
 	{
-		if (tinfo->eml > 1 && l_left_to_match == 0)
-		{
-			l_total = pg_mblen_range(p1, end1);
-			if (l_total != pg_mblen_range(p2, end2))
-			{
-				return i;
-			}
-			l_left_to_match = l_total;
-		}
 		if (*p1 != *p2)
-		{
-			if (tinfo->eml > 1)
-			{
-				int32		l_matched_subset = l_total - l_left_to_match;
-
-				/* end common prefix at final byte of last matching char */
-				return i - l_matched_subset;
-			}
-			else
-			{
-				return i;
-			}
-		}
-
+			return i;
 		p1++;
 		p2++;
-		l_left_to_match--;
 		i++;
 	}
 	return ml;					/* lower == upper */
diff --git a/contrib/btree_gist/btree_utils_var.h b/contrib/btree_gist/btree_utils_var.h
index c0ac77cb9ec..4750fc8361e 100644
--- a/contrib/btree_gist/btree_utils_var.h
+++ b/contrib/btree_gist/btree_utils_var.h
@@ -60,8 +60,6 @@ typedef struct
 	/* Attribs */
 
 	enum gbtree_type t;			/* data type */
-	int32		eml;			/* cached pg_database_encoding_max_length (0:
-								 * undefined) */
 	bool		trnc;			/* truncate (=compress) key */
 
 	/* Methods */
-- 
2.52.0

