diff options
Diffstat (limited to 'contrib/pg_trgm')
-rw-r--r-- | contrib/pg_trgm/trgm.h | 5 | ||||
-rw-r--r-- | contrib/pg_trgm/trgm_op.c | 44 |
2 files changed, 45 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)==' ') ) diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c index d0833b3e4a1..94b9015fd67 100644 --- a/contrib/pg_trgm/trgm_op.c +++ b/contrib/pg_trgm/trgm_op.c @@ -42,6 +42,9 @@ PG_FUNCTION_INFO_V1(strict_word_similarity_commutator_op); PG_FUNCTION_INFO_V1(strict_word_similarity_dist_op); PG_FUNCTION_INFO_V1(strict_word_similarity_dist_commutator_op); +static int CMPTRGM_CHOOSE(const void *a, const void *b); +int (*CMPTRGM) (const void *a, const void *b) = CMPTRGM_CHOOSE; + /* Trigram with position */ typedef struct { @@ -107,6 +110,47 @@ _PG_init(void) MarkGUCPrefixReserved("pg_trgm"); } +#define CMPCHAR(a,b) ( ((a)==(b)) ? 0 : ( ((a)<(b)) ? -1 : 1 ) ) + +/* + * Functions for comparing two trgms while treating each char as "signed char" or + * "unsigned char". + */ +static inline int +CMPTRGM_SIGNED(const void *a, const void *b) +{ +#define CMPPCHAR_S(a,b,i) CMPCHAR( *(((const signed char*)(a))+i), *(((const signed char*)(b))+i) ) + + return CMPPCHAR_S(a, b, 0) ? CMPPCHAR_S(a, b, 0) + : (CMPPCHAR_S(a, b, 1) ? CMPPCHAR_S(a, b, 1) + : CMPPCHAR_S(a, b, 2)); +} + +static inline int +CMPTRGM_UNSIGNED(const void *a, const void *b) +{ +#define CMPPCHAR_UNS(a,b,i) CMPCHAR( *(((const unsigned char*)(a))+i), *(((const unsigned char*)(b))+i) ) + + return CMPPCHAR_UNS(a, b, 0) ? CMPPCHAR_UNS(a, b, 0) + : (CMPPCHAR_UNS(a, b, 1) ? CMPPCHAR_UNS(a, b, 1) + : CMPPCHAR_UNS(a, b, 2)); +} + +/* + * This gets called on the first call. It replaces the function pointer so + * that subsequent calls are routed directly to the chosen implementation. + */ +static int +CMPTRGM_CHOOSE(const void *a, const void *b) +{ + if (GetDefaultCharSignedness()) + CMPTRGM = CMPTRGM_SIGNED; + else + CMPTRGM = CMPTRGM_UNSIGNED; + + return CMPTRGM(a, b); +} + /* * Deprecated function. * Use "pg_trgm.similarity_threshold" GUC variable instead of this function. |