From 56066f836f389ca0efe169c1ea8d769f70aaa817 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Sat, 22 Jul 2023 14:53:49 -0700 Subject: [PATCH v3 1/4] move datum definitions to c.h --- src/include/c.h | 512 ++++++++++++++++++++++++++++++++++++++++ src/include/postgres.h | 519 +---------------------------------------- 2 files changed, 515 insertions(+), 516 deletions(-) diff --git a/src/include/c.h b/src/include/c.h index f69d739be5..daee2f50eb 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -35,6 +35,7 @@ * 7) widely useful macros * 8) random stuff * 9) system-specific hacks + * 10) Datum type + support functions * * NOTE: since this file is included by both frontend and backend modules, * it's usually wrong to put an "extern" declaration here, unless it's @@ -1374,4 +1375,515 @@ typedef intptr_t sigjmp_buf[5]; /* /port compatibility functions */ #include "port.h" +/* ---------------------------------------------------------------- + * Section 10: Datum type + support functions + * ---------------------------------------------------------------- + */ + +/* + * A Datum contains either a value of a pass-by-value type or a pointer to a + * value of a pass-by-reference type. Therefore, we require: + * + * sizeof(Datum) == sizeof(void *) == 4 or 8 + * + * The functions below and the analogous functions for other types should be used to + * convert between a Datum and the appropriate C type. + */ + +typedef uintptr_t Datum; + +/* + * A NullableDatum is used in places where both a Datum and its nullness needs + * to be stored. This can be more efficient than storing datums and nullness + * in separate arrays, due to better spatial locality, even if more space may + * be wasted due to padding. + */ +typedef struct NullableDatum +{ +#define FIELDNO_NULLABLE_DATUM_DATUM 0 + Datum value; +#define FIELDNO_NULLABLE_DATUM_ISNULL 1 + bool isnull; + /* due to alignment padding this could be used for flags for free */ +} NullableDatum; + +#define SIZEOF_DATUM SIZEOF_VOID_P + +/* + * DatumGetBool + * Returns boolean value of a datum. + * + * Note: any nonzero value will be considered true. + */ +static inline bool +DatumGetBool(Datum X) +{ + return (X != 0); +} + +/* + * BoolGetDatum + * Returns datum representation for a boolean. + * + * Note: any nonzero value will be considered true. + */ +static inline Datum +BoolGetDatum(bool X) +{ + return (Datum) (X ? 1 : 0); +} + +/* + * DatumGetChar + * Returns character value of a datum. + */ +static inline char +DatumGetChar(Datum X) +{ + return (char) X; +} + +/* + * CharGetDatum + * Returns datum representation for a character. + */ +static inline Datum +CharGetDatum(char X) +{ + return (Datum) X; +} + +/* + * Int8GetDatum + * Returns datum representation for an 8-bit integer. + */ +static inline Datum +Int8GetDatum(int8 X) +{ + return (Datum) X; +} + +/* + * DatumGetUInt8 + * Returns 8-bit unsigned integer value of a datum. + */ +static inline uint8 +DatumGetUInt8(Datum X) +{ + return (uint8) X; +} + +/* + * UInt8GetDatum + * Returns datum representation for an 8-bit unsigned integer. + */ +static inline Datum +UInt8GetDatum(uint8 X) +{ + return (Datum) X; +} + +/* + * DatumGetInt16 + * Returns 16-bit integer value of a datum. + */ +static inline int16 +DatumGetInt16(Datum X) +{ + return (int16) X; +} + +/* + * Int16GetDatum + * Returns datum representation for a 16-bit integer. + */ +static inline Datum +Int16GetDatum(int16 X) +{ + return (Datum) X; +} + +/* + * DatumGetUInt16 + * Returns 16-bit unsigned integer value of a datum. + */ +static inline uint16 +DatumGetUInt16(Datum X) +{ + return (uint16) X; +} + +/* + * UInt16GetDatum + * Returns datum representation for a 16-bit unsigned integer. + */ +static inline Datum +UInt16GetDatum(uint16 X) +{ + return (Datum) X; +} + +/* + * DatumGetInt32 + * Returns 32-bit integer value of a datum. + */ +static inline int32 +DatumGetInt32(Datum X) +{ + return (int32) X; +} + +/* + * Int32GetDatum + * Returns datum representation for a 32-bit integer. + */ +static inline Datum +Int32GetDatum(int32 X) +{ + return (Datum) X; +} + +/* + * DatumGetUInt32 + * Returns 32-bit unsigned integer value of a datum. + */ +static inline uint32 +DatumGetUInt32(Datum X) +{ + return (uint32) X; +} + +/* + * UInt32GetDatum + * Returns datum representation for a 32-bit unsigned integer. + */ +static inline Datum +UInt32GetDatum(uint32 X) +{ + return (Datum) X; +} + +/* + * DatumGetObjectId + * Returns object identifier value of a datum. + */ +static inline Oid +DatumGetObjectId(Datum X) +{ + return (Oid) X; +} + +/* + * ObjectIdGetDatum + * Returns datum representation for an object identifier. + */ +static inline Datum +ObjectIdGetDatum(Oid X) +{ + return (Datum) X; +} + +/* + * DatumGetTransactionId + * Returns transaction identifier value of a datum. + */ +static inline TransactionId +DatumGetTransactionId(Datum X) +{ + return (TransactionId) X; +} + +/* + * TransactionIdGetDatum + * Returns datum representation for a transaction identifier. + */ +static inline Datum +TransactionIdGetDatum(TransactionId X) +{ + return (Datum) X; +} + +/* + * MultiXactIdGetDatum + * Returns datum representation for a multixact identifier. + */ +static inline Datum +MultiXactIdGetDatum(MultiXactId X) +{ + return (Datum) X; +} + +/* + * DatumGetCommandId + * Returns command identifier value of a datum. + */ +static inline CommandId +DatumGetCommandId(Datum X) +{ + return (CommandId) X; +} + +/* + * CommandIdGetDatum + * Returns datum representation for a command identifier. + */ +static inline Datum +CommandIdGetDatum(CommandId X) +{ + return (Datum) X; +} + +/* + * DatumGetPointer + * Returns pointer value of a datum. + */ +static inline Pointer +DatumGetPointer(Datum X) +{ + return (Pointer) X; +} + +/* + * PointerGetDatum + * Returns datum representation for a pointer. + */ +static inline Datum +PointerGetDatum(const void *X) +{ + return (Datum) X; +} + +/* + * DatumGetCString + * Returns C string (null-terminated string) value of a datum. + * + * Note: C string is not a full-fledged Postgres type at present, + * but type input functions use this conversion for their inputs. + */ +static inline char * +DatumGetCString(Datum X) +{ + return (char *) DatumGetPointer(X); +} + +/* + * CStringGetDatum + * Returns datum representation for a C string (null-terminated string). + * + * Note: C string is not a full-fledged Postgres type at present, + * but type output functions use this conversion for their outputs. + * Note: CString is pass-by-reference; caller must ensure the pointed-to + * value has adequate lifetime. + */ +static inline Datum +CStringGetDatum(const char *X) +{ + return PointerGetDatum(X); +} + +/* + * DatumGetName + * Returns name value of a datum. + */ +static inline Name +DatumGetName(Datum X) +{ + return (Name) DatumGetPointer(X); +} + +/* + * NameGetDatum + * Returns datum representation for a name. + * + * Note: Name is pass-by-reference; caller must ensure the pointed-to + * value has adequate lifetime. + */ +static inline Datum +NameGetDatum(const NameData *X) +{ + return CStringGetDatum(NameStr(*X)); +} + +/* + * DatumGetInt64 + * Returns 64-bit integer value of a datum. + * + * Note: this function hides whether int64 is pass by value or by reference. + */ +static inline int64 +DatumGetInt64(Datum X) +{ +#ifdef USE_FLOAT8_BYVAL + return (int64) X; +#else + return *((int64 *) DatumGetPointer(X)); +#endif +} + +/* + * Int64GetDatum + * Returns datum representation for a 64-bit integer. + * + * Note: if int64 is pass by reference, this function returns a reference + * to palloc'd space. + */ +#ifdef USE_FLOAT8_BYVAL +static inline Datum +Int64GetDatum(int64 X) +{ + return (Datum) X; +} +#else +extern Datum Int64GetDatum(int64 X); +#endif + + +/* + * DatumGetUInt64 + * Returns 64-bit unsigned integer value of a datum. + * + * Note: this function hides whether int64 is pass by value or by reference. + */ +static inline uint64 +DatumGetUInt64(Datum X) +{ +#ifdef USE_FLOAT8_BYVAL + return (uint64) X; +#else + return *((uint64 *) DatumGetPointer(X)); +#endif +} + +/* + * UInt64GetDatum + * Returns datum representation for a 64-bit unsigned integer. + * + * Note: if int64 is pass by reference, this function returns a reference + * to palloc'd space. + */ +static inline Datum +UInt64GetDatum(uint64 X) +{ +#ifdef USE_FLOAT8_BYVAL + return (Datum) X; +#else + return Int64GetDatum((int64) X); +#endif +} + +/* + * Float <-> Datum conversions + * + * These have to be implemented as inline functions rather than macros, when + * passing by value, because many machines pass int and float function + * parameters/results differently; so we need to play weird games with unions. + */ + +/* + * DatumGetFloat4 + * Returns 4-byte floating point value of a datum. + */ +static inline float4 +DatumGetFloat4(Datum X) +{ + union + { + int32 value; + float4 retval; + } myunion; + + myunion.value = DatumGetInt32(X); + return myunion.retval; +} + +/* + * Float4GetDatum + * Returns datum representation for a 4-byte floating point number. + */ +static inline Datum +Float4GetDatum(float4 X) +{ + union + { + float4 value; + int32 retval; + } myunion; + + myunion.value = X; + return Int32GetDatum(myunion.retval); +} + +/* + * DatumGetFloat8 + * Returns 8-byte floating point value of a datum. + * + * Note: this function hides whether float8 is pass by value or by reference. + */ +static inline float8 +DatumGetFloat8(Datum X) +{ +#ifdef USE_FLOAT8_BYVAL + union + { + int64 value; + float8 retval; + } myunion; + + myunion.value = DatumGetInt64(X); + return myunion.retval; +#else + return *((float8 *) DatumGetPointer(X)); +#endif +} + +/* + * Float8GetDatum + * Returns datum representation for an 8-byte floating point number. + * + * Note: if float8 is pass by reference, this function returns a reference + * to palloc'd space. + */ +#ifdef USE_FLOAT8_BYVAL +static inline Datum +Float8GetDatum(float8 X) +{ + union + { + float8 value; + int64 retval; + } myunion; + + myunion.value = X; + return Int64GetDatum(myunion.retval); +} +#else +extern Datum Float8GetDatum(float8 X); +#endif + + +/* + * Int64GetDatumFast + * Float8GetDatumFast + * + * These macros are intended to allow writing code that does not depend on + * whether int64 and float8 are pass-by-reference types, while not + * sacrificing performance when they are. The argument must be a variable + * that will exist and have the same value for as long as the Datum is needed. + * In the pass-by-ref case, the address of the variable is taken to use as + * the Datum. In the pass-by-val case, these are the same as the non-Fast + * functions, except for asserting that the variable is of the correct type. + */ + +#ifdef USE_FLOAT8_BYVAL +#define Int64GetDatumFast(X) \ + (AssertVariableIsOfTypeMacro(X, int64), Int64GetDatum(X)) +#define Float8GetDatumFast(X) \ + (AssertVariableIsOfTypeMacro(X, double), Float8GetDatum(X)) +#else +#define Int64GetDatumFast(X) \ + (AssertVariableIsOfTypeMacro(X, int64), PointerGetDatum(&(X))) +#define Float8GetDatumFast(X) \ + (AssertVariableIsOfTypeMacro(X, double), PointerGetDatum(&(X))) +#endif + #endif /* C_H */ diff --git a/src/include/postgres.h b/src/include/postgres.h index 8a028ff789..4fcb207d0b 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -23,8 +23,7 @@ * * section description * ------- ------------------------------------------------ - * 1) Datum type + support functions - * 2) miscellaneous + * 1) miscellaneous * * NOTES * @@ -35,7 +34,7 @@ * postgres_fe.h. We do that since those type definitions are needed by * frontend modules that want to deal with binary data transmission to or * from the backend. Type definitions in this file should be for - * representations that never escape the backend, such as Datum. + * representations that never escape the backend. * *---------------------------------------------------------------- */ @@ -47,519 +46,7 @@ #include "utils/palloc.h" /* ---------------------------------------------------------------- - * Section 1: Datum type + support functions - * ---------------------------------------------------------------- - */ - -/* - * A Datum contains either a value of a pass-by-value type or a pointer to a - * value of a pass-by-reference type. Therefore, we require: - * - * sizeof(Datum) == sizeof(void *) == 4 or 8 - * - * The functions below and the analogous functions for other types should be used to - * convert between a Datum and the appropriate C type. - */ - -typedef uintptr_t Datum; - -/* - * A NullableDatum is used in places where both a Datum and its nullness needs - * to be stored. This can be more efficient than storing datums and nullness - * in separate arrays, due to better spatial locality, even if more space may - * be wasted due to padding. - */ -typedef struct NullableDatum -{ -#define FIELDNO_NULLABLE_DATUM_DATUM 0 - Datum value; -#define FIELDNO_NULLABLE_DATUM_ISNULL 1 - bool isnull; - /* due to alignment padding this could be used for flags for free */ -} NullableDatum; - -#define SIZEOF_DATUM SIZEOF_VOID_P - -/* - * DatumGetBool - * Returns boolean value of a datum. - * - * Note: any nonzero value will be considered true. - */ -static inline bool -DatumGetBool(Datum X) -{ - return (X != 0); -} - -/* - * BoolGetDatum - * Returns datum representation for a boolean. - * - * Note: any nonzero value will be considered true. - */ -static inline Datum -BoolGetDatum(bool X) -{ - return (Datum) (X ? 1 : 0); -} - -/* - * DatumGetChar - * Returns character value of a datum. - */ -static inline char -DatumGetChar(Datum X) -{ - return (char) X; -} - -/* - * CharGetDatum - * Returns datum representation for a character. - */ -static inline Datum -CharGetDatum(char X) -{ - return (Datum) X; -} - -/* - * Int8GetDatum - * Returns datum representation for an 8-bit integer. - */ -static inline Datum -Int8GetDatum(int8 X) -{ - return (Datum) X; -} - -/* - * DatumGetUInt8 - * Returns 8-bit unsigned integer value of a datum. - */ -static inline uint8 -DatumGetUInt8(Datum X) -{ - return (uint8) X; -} - -/* - * UInt8GetDatum - * Returns datum representation for an 8-bit unsigned integer. - */ -static inline Datum -UInt8GetDatum(uint8 X) -{ - return (Datum) X; -} - -/* - * DatumGetInt16 - * Returns 16-bit integer value of a datum. - */ -static inline int16 -DatumGetInt16(Datum X) -{ - return (int16) X; -} - -/* - * Int16GetDatum - * Returns datum representation for a 16-bit integer. - */ -static inline Datum -Int16GetDatum(int16 X) -{ - return (Datum) X; -} - -/* - * DatumGetUInt16 - * Returns 16-bit unsigned integer value of a datum. - */ -static inline uint16 -DatumGetUInt16(Datum X) -{ - return (uint16) X; -} - -/* - * UInt16GetDatum - * Returns datum representation for a 16-bit unsigned integer. - */ -static inline Datum -UInt16GetDatum(uint16 X) -{ - return (Datum) X; -} - -/* - * DatumGetInt32 - * Returns 32-bit integer value of a datum. - */ -static inline int32 -DatumGetInt32(Datum X) -{ - return (int32) X; -} - -/* - * Int32GetDatum - * Returns datum representation for a 32-bit integer. - */ -static inline Datum -Int32GetDatum(int32 X) -{ - return (Datum) X; -} - -/* - * DatumGetUInt32 - * Returns 32-bit unsigned integer value of a datum. - */ -static inline uint32 -DatumGetUInt32(Datum X) -{ - return (uint32) X; -} - -/* - * UInt32GetDatum - * Returns datum representation for a 32-bit unsigned integer. - */ -static inline Datum -UInt32GetDatum(uint32 X) -{ - return (Datum) X; -} - -/* - * DatumGetObjectId - * Returns object identifier value of a datum. - */ -static inline Oid -DatumGetObjectId(Datum X) -{ - return (Oid) X; -} - -/* - * ObjectIdGetDatum - * Returns datum representation for an object identifier. - */ -static inline Datum -ObjectIdGetDatum(Oid X) -{ - return (Datum) X; -} - -/* - * DatumGetTransactionId - * Returns transaction identifier value of a datum. - */ -static inline TransactionId -DatumGetTransactionId(Datum X) -{ - return (TransactionId) X; -} - -/* - * TransactionIdGetDatum - * Returns datum representation for a transaction identifier. - */ -static inline Datum -TransactionIdGetDatum(TransactionId X) -{ - return (Datum) X; -} - -/* - * MultiXactIdGetDatum - * Returns datum representation for a multixact identifier. - */ -static inline Datum -MultiXactIdGetDatum(MultiXactId X) -{ - return (Datum) X; -} - -/* - * DatumGetCommandId - * Returns command identifier value of a datum. - */ -static inline CommandId -DatumGetCommandId(Datum X) -{ - return (CommandId) X; -} - -/* - * CommandIdGetDatum - * Returns datum representation for a command identifier. - */ -static inline Datum -CommandIdGetDatum(CommandId X) -{ - return (Datum) X; -} - -/* - * DatumGetPointer - * Returns pointer value of a datum. - */ -static inline Pointer -DatumGetPointer(Datum X) -{ - return (Pointer) X; -} - -/* - * PointerGetDatum - * Returns datum representation for a pointer. - */ -static inline Datum -PointerGetDatum(const void *X) -{ - return (Datum) X; -} - -/* - * DatumGetCString - * Returns C string (null-terminated string) value of a datum. - * - * Note: C string is not a full-fledged Postgres type at present, - * but type input functions use this conversion for their inputs. - */ -static inline char * -DatumGetCString(Datum X) -{ - return (char *) DatumGetPointer(X); -} - -/* - * CStringGetDatum - * Returns datum representation for a C string (null-terminated string). - * - * Note: C string is not a full-fledged Postgres type at present, - * but type output functions use this conversion for their outputs. - * Note: CString is pass-by-reference; caller must ensure the pointed-to - * value has adequate lifetime. - */ -static inline Datum -CStringGetDatum(const char *X) -{ - return PointerGetDatum(X); -} - -/* - * DatumGetName - * Returns name value of a datum. - */ -static inline Name -DatumGetName(Datum X) -{ - return (Name) DatumGetPointer(X); -} - -/* - * NameGetDatum - * Returns datum representation for a name. - * - * Note: Name is pass-by-reference; caller must ensure the pointed-to - * value has adequate lifetime. - */ -static inline Datum -NameGetDatum(const NameData *X) -{ - return CStringGetDatum(NameStr(*X)); -} - -/* - * DatumGetInt64 - * Returns 64-bit integer value of a datum. - * - * Note: this function hides whether int64 is pass by value or by reference. - */ -static inline int64 -DatumGetInt64(Datum X) -{ -#ifdef USE_FLOAT8_BYVAL - return (int64) X; -#else - return *((int64 *) DatumGetPointer(X)); -#endif -} - -/* - * Int64GetDatum - * Returns datum representation for a 64-bit integer. - * - * Note: if int64 is pass by reference, this function returns a reference - * to palloc'd space. - */ -#ifdef USE_FLOAT8_BYVAL -static inline Datum -Int64GetDatum(int64 X) -{ - return (Datum) X; -} -#else -extern Datum Int64GetDatum(int64 X); -#endif - - -/* - * DatumGetUInt64 - * Returns 64-bit unsigned integer value of a datum. - * - * Note: this function hides whether int64 is pass by value or by reference. - */ -static inline uint64 -DatumGetUInt64(Datum X) -{ -#ifdef USE_FLOAT8_BYVAL - return (uint64) X; -#else - return *((uint64 *) DatumGetPointer(X)); -#endif -} - -/* - * UInt64GetDatum - * Returns datum representation for a 64-bit unsigned integer. - * - * Note: if int64 is pass by reference, this function returns a reference - * to palloc'd space. - */ -static inline Datum -UInt64GetDatum(uint64 X) -{ -#ifdef USE_FLOAT8_BYVAL - return (Datum) X; -#else - return Int64GetDatum((int64) X); -#endif -} - -/* - * Float <-> Datum conversions - * - * These have to be implemented as inline functions rather than macros, when - * passing by value, because many machines pass int and float function - * parameters/results differently; so we need to play weird games with unions. - */ - -/* - * DatumGetFloat4 - * Returns 4-byte floating point value of a datum. - */ -static inline float4 -DatumGetFloat4(Datum X) -{ - union - { - int32 value; - float4 retval; - } myunion; - - myunion.value = DatumGetInt32(X); - return myunion.retval; -} - -/* - * Float4GetDatum - * Returns datum representation for a 4-byte floating point number. - */ -static inline Datum -Float4GetDatum(float4 X) -{ - union - { - float4 value; - int32 retval; - } myunion; - - myunion.value = X; - return Int32GetDatum(myunion.retval); -} - -/* - * DatumGetFloat8 - * Returns 8-byte floating point value of a datum. - * - * Note: this function hides whether float8 is pass by value or by reference. - */ -static inline float8 -DatumGetFloat8(Datum X) -{ -#ifdef USE_FLOAT8_BYVAL - union - { - int64 value; - float8 retval; - } myunion; - - myunion.value = DatumGetInt64(X); - return myunion.retval; -#else - return *((float8 *) DatumGetPointer(X)); -#endif -} - -/* - * Float8GetDatum - * Returns datum representation for an 8-byte floating point number. - * - * Note: if float8 is pass by reference, this function returns a reference - * to palloc'd space. - */ -#ifdef USE_FLOAT8_BYVAL -static inline Datum -Float8GetDatum(float8 X) -{ - union - { - float8 value; - int64 retval; - } myunion; - - myunion.value = X; - return Int64GetDatum(myunion.retval); -} -#else -extern Datum Float8GetDatum(float8 X); -#endif - - -/* - * Int64GetDatumFast - * Float8GetDatumFast - * - * These macros are intended to allow writing code that does not depend on - * whether int64 and float8 are pass-by-reference types, while not - * sacrificing performance when they are. The argument must be a variable - * that will exist and have the same value for as long as the Datum is needed. - * In the pass-by-ref case, the address of the variable is taken to use as - * the Datum. In the pass-by-val case, these are the same as the non-Fast - * functions, except for asserting that the variable is of the correct type. - */ - -#ifdef USE_FLOAT8_BYVAL -#define Int64GetDatumFast(X) \ - (AssertVariableIsOfTypeMacro(X, int64), Int64GetDatum(X)) -#define Float8GetDatumFast(X) \ - (AssertVariableIsOfTypeMacro(X, double), Float8GetDatum(X)) -#else -#define Int64GetDatumFast(X) \ - (AssertVariableIsOfTypeMacro(X, int64), PointerGetDatum(&(X))) -#define Float8GetDatumFast(X) \ - (AssertVariableIsOfTypeMacro(X, double), PointerGetDatum(&(X))) -#endif - - -/* ---------------------------------------------------------------- - * Section 2: miscellaneous + * Section 1: miscellaneous * ---------------------------------------------------------------- */ -- 2.25.1