poc_char_signedness.patch
application/octet-stream
Filename: poc_char_signedness.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| contrib/pg_trgm/trgm.h | 2 | 2 |
| contrib/pg_trgm/trgm_op.c | 42 | 0 |
| src/backend/access/transam/xlog.c | 23 | 0 |
| src/bin/pg_controldata/pg_controldata.c | 2 | 0 |
| src/include/access/xlog.h | 1 | 0 |
| src/include/catalog/pg_control.h | 6 | 0 |
diff --git a/contrib/pg_trgm/trgm.h b/contrib/pg_trgm/trgm.h
index afb0adb222..5534abe680 100644
--- a/contrib/pg_trgm/trgm.h
+++ b/contrib/pg_trgm/trgm.h
@@ -42,8 +42,6 @@
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); \
@@ -51,6 +49,8 @@ typedef char trgm[3];
*(((char*)(a))+2) = *(((char*)(b))+2); \
} while(0)
+extern int (*CMPTRGM) (const void *a, const void *b);
+
#ifdef KEEPONLYALNUM
#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 c509d15ee4..75e670edf6 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -40,6 +40,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 inline int CMPTRGM_CHOOSE(const void *a, const void *b);
+int (*CMPTRGM) (const void *a, const void *b) = CMPTRGM_CHOOSE;
+
/* Trigram with position */
typedef struct
{
@@ -105,6 +108,45 @@ _PG_init(void)
MarkGUCPrefixReserved("pg_trgm");
}
+/*
+ * 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 inline 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.
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index e96aa4d1cb..89a86009c3 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -42,6 +42,7 @@
#include <math.h>
#include <time.h>
#include <fcntl.h>
+#include <limits.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
@@ -4256,6 +4257,18 @@ WriteControlFile(void)
ControlFile->float8ByVal = FLOAT8PASSBYVAL;
+ /*
+ * The signedness of the char type is implementation-defined. For example
+ * on x86 architecture CPUs, the char data type is typically treated as
+ * signed by default whereas on aarch architecture CPUs it is typically
+ * treated as unsigned by default.
+ */
+#if CHAR_MIN != 0
+ ControlFile->signed_char = true;
+#else
+ ControlFile->signed_char = false;
+#endif
+
/* Contents are protected with a CRC */
INIT_CRC32C(ControlFile->crc);
COMP_CRC32C(ControlFile->crc,
@@ -4584,6 +4597,16 @@ DataChecksumsEnabled(void)
return (ControlFile->data_checksum_version > 0);
}
+/*
+ * Return true if the cluster was initialized on a platform where
+ * the default signedness of char is "signed".
+ */
+bool
+GetDefaultCharSignedness(void)
+{
+ return (ControlFile->signed_char);
+}
+
/*
* Returns a fake LSN for unlogged relations.
*
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index 93a05d80ca..769a9bfd98 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -323,6 +323,8 @@ main(int argc, char *argv[])
_("64-bit integers"));
printf(_("Float8 argument passing: %s\n"),
(ControlFile->float8ByVal ? _("by value") : _("by reference")));
+ printf(_("Default char data signedness: %s\n"),
+ (ControlFile->signed_char ? _("signed") : _("unsigned")));
printf(_("Data page checksum version: %u\n"),
ControlFile->data_checksum_version);
printf(_("Mock authentication nonce: %s\n"),
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 083810f5b4..ef64f67424 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -230,6 +230,7 @@ extern XLogRecPtr GetXLogWriteRecPtr(void);
extern uint64 GetSystemIdentifier(void);
extern char *GetMockAuthenticationNonce(void);
extern bool DataChecksumsEnabled(void);
+extern bool GetDefaultCharSignedness(void);
extern XLogRecPtr GetFakeLSNForUnloggedRel(void);
extern Size XLOGShmemSize(void);
extern void XLOGShmemInit(void);
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index e80ff8e414..7e79d147ce 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -221,6 +221,12 @@ typedef struct ControlFileData
/* Are data pages protected by checksums? Zero if no checksum version */
uint32 data_checksum_version;
+ /*
+ * True if the default signedness of char is "signed" on a platform where
+ * the control file is created.
+ */
+ bool signed_char;
+
/*
* Random nonce, used in authentication requests that need to proceed
* based on values that are cluster-unique, like a SASL exchange that