summaryrefslogtreecommitdiff
path: root/contrib/pg_trgm/trgm.h
diff options
context:
space:
mode:
authorMasahiko Sawada2025-02-21 18:27:39 +0000
committerMasahiko Sawada2025-02-21 18:27:39 +0000
commitdfd8e6c73eeaa8a4d53851ba01e8d7b1c0bef0e3 (patch)
tree18c75e4e9e73d47e2bc6425e85b38f9b46ddb78f /contrib/pg_trgm/trgm.h
parent1aab6805919b84a2f2477132d96f2147ed36150e (diff)
Fix an issue with index scan using pg_trgm due to char signedness on different architectures.
GIN and GiST indexes utilizing pg_trgm's opclasses store sorted trigrams within index tuples. When comparing and sorting each trigram, pg_trgm treats each character as a 'char[3]' type in C. However, the char type in C can be interpreted as either signed char or unsigned char, depending on the platform, if the signedness is not explicitly specified. Consequently, during replication between different CPU architectures, there was an issue where index scans on standby servers could not locate matching index tuples due to the differing treatment of character signedness. This change introduces comparison functions for trgm that explicitly handle signed char and unsigned char. The appropriate comparison function will be dynamically selected based on the character signedness stored in the control file. Therefore, upgraded clusters can utilize the indexes without rebuilding, provided the cluster upgrade occurs on platforms with the same character signedness as the original cluster initialization. The default char signedness information was introduced in 44fe30fdab6, so no backpatch. Reviewed-by: Noah Misch <[email protected]> Discussion: https://postgr.es/m/CB11ADBC-0C3F-4FE0-A678-666EE80CBB07%40amazon.com
Diffstat (limited to 'contrib/pg_trgm/trgm.h')
-rw-r--r--contrib/pg_trgm/trgm.h5
1 files changed, 1 insertions, 4 deletions
diff --git a/contrib/pg_trgm/trgm.h b/contrib/pg_trgm/trgm.h
index 10827563694..ca017585369 100644
--- a/contrib/pg_trgm/trgm.h
+++ b/contrib/pg_trgm/trgm.h
@@ -40,15 +40,12 @@
typedef char trgm[3];
-#define CMPCHAR(a,b) ( ((a)==(b)) ? 0 : ( ((a)<(b)) ? -1 : 1 ) )
-#define CMPPCHAR(a,b,i) CMPCHAR( *(((const char*)(a))+i), *(((const char*)(b))+i) )
-#define CMPTRGM(a,b) ( CMPPCHAR(a,b,0) ? CMPPCHAR(a,b,0) : ( CMPPCHAR(a,b,1) ? CMPPCHAR(a,b,1) : CMPPCHAR(a,b,2) ) )
-
#define CPTRGM(a,b) do { \
*(((char*)(a))+0) = *(((char*)(b))+0); \
*(((char*)(a))+1) = *(((char*)(b))+1); \
*(((char*)(a))+2) = *(((char*)(b))+2); \
} while(0)
+extern int (*CMPTRGM) (const void *a, const void *b);
#define ISWORDCHR(c) (t_isalnum(c))
#define ISPRINTABLECHAR(a) ( isascii( *(unsigned char*)(a) ) && (isalnum( *(unsigned char*)(a) ) || *(unsigned char*)(a)==' ') )