From 0f0047a9ba12eddbbd4385e8e89ec47b9d87905c Mon Sep 17 00:00:00 2001
From: Nikita Malakhov <n.malakhov@postgrespro.ru>
Date: Wed, 6 Dec 2023 12:13:32 +0300
Subject: [PATCH] Introducing custom TOAST pointer, with ability to store
 custom defined data inline as well as out-of-line, and custom metadata.

---
 src/backend/access/brin/brin_minmax_multi.c |  1 +
 src/include/varatt.h                        | 21 ++++-
 src/include/varatt_custom.h                 | 86 +++++++++++++++++++++
 3 files changed, 105 insertions(+), 3 deletions(-)
 create mode 100644 src/include/varatt_custom.h

diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c
index 9811451b54..e81ad5cba7 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -55,6 +55,7 @@
  *	  src/backend/access/brin/brin_minmax_multi.c
  */
 #include "postgres.h"
+#include "varatt_custom.h"
 
 /* needed for PGSQL_AF_INET */
 #include <sys/socket.h>
diff --git a/src/include/varatt.h b/src/include/varatt.h
index e34870526b..d84c9e96a5 100644
--- a/src/include/varatt.h
+++ b/src/include/varatt.h
@@ -86,17 +86,28 @@ typedef enum vartag_external
 	VARTAG_INDIRECT = 1,
 	VARTAG_EXPANDED_RO = 2,
 	VARTAG_EXPANDED_RW = 3,
-	VARTAG_ONDISK = 18
+	VARTAG_ONDISK = 18,
+	VARTAG_CUSTOM = 127
 } vartag_external;
 
+typedef enum ToastPtrSizeType
+{
+	TPTR_DATUM_SIZE,
+	TPTR_RAW_SIZE,
+	TPTR_STORAGE_SIZE
+} ToastPtrSizeType;
+
+extern Size toast_custom_datum_size(const void *ptr, ToastPtrSizeType sz_type);
+
 /* this test relies on the specific tag values above */
 #define VARTAG_IS_EXPANDED(tag) \
 	(((tag) & ~1) == VARTAG_EXPANDED_RO)
 
-#define VARTAG_SIZE(tag) \
+#define VARTAG_SIZE(tag, ptr) \
 	((tag) == VARTAG_INDIRECT ? sizeof(varatt_indirect) : \
 	 VARTAG_IS_EXPANDED(tag) ? sizeof(varatt_expanded) : \
 	 (tag) == VARTAG_ONDISK ? sizeof(varatt_external) : \
+	 (tag) == VARTAG_CUSTOM ? toast_custom_datum_size((const void *)(ptr), TPTR_DATUM_SIZE) : \
 	 (AssertMacro(false), 0))
 
 /*
@@ -253,6 +264,7 @@ typedef struct
 #define VARHDRSZ_EXTERNAL		offsetof(varattrib_1b_e, va_data)
 #define VARHDRSZ_COMPRESSED		offsetof(varattrib_4b, va_compressed.va_data)
 #define VARHDRSZ_SHORT			offsetof(varattrib_1b, va_data)
+#define VARHDRSZ_CUSTOM			offsetof(varattrib_1b_e, va_data)
 
 #define VARATT_SHORT_MAX		0x7F
 #define VARATT_CAN_MAKE_SHORT(PTR) \
@@ -282,7 +294,7 @@ typedef struct
 #define VARDATA_SHORT(PTR)					VARDATA_1B(PTR)
 
 #define VARTAG_EXTERNAL(PTR)				VARTAG_1B_E(PTR)
-#define VARSIZE_EXTERNAL(PTR)				(VARHDRSZ_EXTERNAL + VARTAG_SIZE(VARTAG_EXTERNAL(PTR)))
+#define VARSIZE_EXTERNAL(PTR)				(VARHDRSZ_EXTERNAL + VARTAG_SIZE(VARTAG_EXTERNAL(PTR), (const void *)(PTR)))
 #define VARDATA_EXTERNAL(PTR)				VARDATA_1B_E(PTR)
 
 #define VARATT_IS_COMPRESSED(PTR)			VARATT_IS_4B_C(PTR)
@@ -302,6 +314,9 @@ typedef struct
 #define VARATT_IS_SHORT(PTR)				VARATT_IS_1B(PTR)
 #define VARATT_IS_EXTENDED(PTR)				(!VARATT_IS_4B_U(PTR))
 
+#define VARATT_IS_CUSTOM(PTR) \
+	(VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_CUSTOM)
+
 #define SET_VARSIZE(PTR, len)				SET_VARSIZE_4B(PTR, len)
 #define SET_VARSIZE_SHORT(PTR, len)			SET_VARSIZE_1B(PTR, len)
 #define SET_VARSIZE_COMPRESSED(PTR, len)	SET_VARSIZE_4B_C(PTR, len)
diff --git a/src/include/varatt_custom.h b/src/include/varatt_custom.h
new file mode 100644
index 0000000000..6a66383413
--- /dev/null
+++ b/src/include/varatt_custom.h
@@ -0,0 +1,86 @@
+/*-------------------------------------------------------------------------
+ *
+ * varatt_custom.h
+ *	  CUSTOM Toast Pointer definition and macros
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 2016-2023, Postgres Professional
+ *
+ * IDENTIFICATION
+ * contrib/toastapi/varatt_custom.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef VARATT_CUSTOM_H
+#define VARATT_CUSTOM_H
+
+#include "postgres.h"
+#include "varatt.h"
+
+typedef struct uint32align16
+{
+	uint16	hi;
+	uint16	lo;
+} uint32align16;
+
+#define set_uint32align16(p, v)	\
+	( \
+		(p)->hi = (v) >> 16, \
+		(p)->lo = (v) & 0xffff \
+	)
+
+#define get_uint32align16(p)	\
+	(((uint32)((p)->hi)) << 16 | ((uint32)((p)->lo)))
+
+/* varatt_custom uses 16bit aligment */
+typedef struct varatt_custom
+{
+	uint32align16	va_tptrdatalen;	/* total size of toast pointer, < BLCKSZ */
+	uint32align16	va_rawsize;		/* Original data size (includes header) */
+	char		va_tptrdata[FLEXIBLE_ARRAY_MEMBER];	/* Custom data */
+}			varatt_custom;
+
+/* Custom Toast pointer */
+#define VARATT_CUSTOM_GET_TOASTPOINTER(PTR) \
+	((varatt_custom *) VARDATA_EXTERNAL(PTR))
+
+#define VARATT_CUSTOM_GET_DATA_RAW_SIZE(PTR) \
+	(get_uint32align16(&VARATT_CUSTOM_GET_TOASTPOINTER(PTR)->va_rawsize))
+
+#define VARATT_CUSTOM_SET_DATA_RAW_SIZE(PTR, V) \
+	(set_uint32align16(&VARATT_CUSTOM_GET_TOASTPOINTER(PTR)->va_rawsize, (V)))
+
+#define VARATT_CUSTOM_GET_DATA_SIZE(PTR) \
+	(get_uint32align16(&VARATT_CUSTOM_GET_TOASTPOINTER(PTR)->va_tptrdatalen))
+
+#define VARATT_CUSTOM_SET_DATA_SIZE(PTR, V) \
+	(set_uint32align16(&VARATT_CUSTOM_GET_TOASTPOINTER(PTR)->va_tptrdatalen, (V)))
+
+#define VARATT_CUSTOM_GET_DATA(PTR) \
+	(VARATT_CUSTOM_GET_TOASTPOINTER(PTR)->va_tptrdata)
+
+#define VARATT_CUSTOM_SIZE(datalen) \
+	((Size) VARHDRSZ_EXTERNAL + offsetof(varatt_custom, va_tptrdata) + (datalen))
+
+#define VARATT_CUSTOM_MAX_DATA_SIZE \
+	(MaxAllocSize - VARATT_CUSTOM_SIZE(0))
+
+#define VARSIZE_CUSTOM(PTR)	VARATT_CUSTOM_SIZE(VARATT_CUSTOM_GET_DATA_SIZE(PTR))
+
+Size
+toast_custom_datum_size(const void *ptr, ToastPtrSizeType sz_type)
+{
+	if (sz_type == TPTR_DATUM_SIZE ||
+		sz_type == TPTR_STORAGE_SIZE)
+		return offsetof(varatt_custom, va_tptrdatalen) + VARATT_CUSTOM_GET_DATA_SIZE(ptr);
+	else if (sz_type == TPTR_RAW_SIZE)
+		return VARATT_CUSTOM_GET_DATA_RAW_SIZE(ptr);
+	else
+		elog(ERROR, "invalid toast_custom_datum_size() size type");
+
+	return 0; /* avoid warning */
+}
+
+#endif
-- 
2.25.1

