When commit 3e23b68dac006e8deb0afa327e855258df8de064 introduced single-byte
varlena headers, its fmgr.h changes presented PG_GETARG_TEXT_PP() and
PG_GETARG_TEXT_P() as equals.  Its postgres.h changes presented
PG_DETOAST_DATUM_PACKED() and VARDATA_ANY() as the exceptional case.  Let's
firmly recommend PG_GETARG_TEXT_PP() over PG_GETARG_TEXT_P(); likewise for
other ...PP() macros.  This shaves cycles and brings consistency of style.

If the attached policy-setting patch seems reasonable, I will follow it with a
mechanical patch adopting the recommended macros throughout the tree.  (If any
code does want the alignment it gets from an obsolecent macro, I will add a
comment to that code.)

diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 0878418..2ae0b64 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -243,13 +243,9 @@ extern struct varlena *pg_detoast_datum_packed(struct 
varlena * datum);
 /* and this if you can handle 1-byte-header datums: */
 /* DatumGetFoo macros for varlena types will typically look like this: */
-#define DatumGetByteaP(X)                      ((bytea *) PG_DETOAST_DATUM(X))
 #define DatumGetByteaPP(X)                     ((bytea *) 
-#define DatumGetTextP(X)                       ((text *) PG_DETOAST_DATUM(X))
 #define DatumGetTextPP(X)                      ((text *) 
-#define DatumGetBpCharP(X)                     ((BpChar *) PG_DETOAST_DATUM(X))
 #define DatumGetBpCharPP(X)                    ((BpChar *) 
-#define DatumGetVarCharP(X)                    ((VarChar *) 
 #define DatumGetVarCharPP(X)           ((VarChar *) PG_DETOAST_DATUM_PACKED(X))
 #define DatumGetHeapTupleHeader(X)     ((HeapTupleHeader) PG_DETOAST_DATUM(X))
 /* And we also offer variants that return an OK-to-write copy */
@@ -264,13 +260,9 @@ extern struct varlena *pg_detoast_datum_packed(struct 
varlena * datum);
 #define DatumGetBpCharPSlice(X,m,n) ((BpChar *) PG_DETOAST_DATUM_SLICE(X,m,n))
 #define DatumGetVarCharPSlice(X,m,n) ((VarChar *) 
 /* GETARG macros for varlena types will typically look like this: */
-#define PG_GETARG_BYTEA_P(n)           DatumGetByteaP(PG_GETARG_DATUM(n))
 #define PG_GETARG_BYTEA_PP(n)          DatumGetByteaPP(PG_GETARG_DATUM(n))
-#define PG_GETARG_TEXT_P(n)                    
 #define PG_GETARG_TEXT_PP(n)           DatumGetTextPP(PG_GETARG_DATUM(n))
-#define PG_GETARG_BPCHAR_P(n)          DatumGetBpCharP(PG_GETARG_DATUM(n))
 #define PG_GETARG_BPCHAR_PP(n)         DatumGetBpCharPP(PG_GETARG_DATUM(n))
-#define PG_GETARG_VARCHAR_P(n)         DatumGetVarCharP(PG_GETARG_DATUM(n))
 #define PG_GETARG_VARCHAR_PP(n)                
 /* And we also offer variants that return an OK-to-write copy */
@@ -284,6 +276,21 @@ extern struct varlena *pg_detoast_datum_packed(struct 
varlena * datum);
 #define PG_GETARG_TEXT_P_SLICE(n,a,b)  
 #define PG_GETARG_BPCHAR_P_SLICE(n,a,b) 
 #define PG_GETARG_VARCHAR_P_SLICE(n,a,b) 
+ * Obsolescent variants that guarantee INT alignment for the return value.
+ * Few operations on these particular types need alignment, mainly operations
+ * that cast the VARDATA pointer to a type like int16[].  Most code should use
+ * the ...PP(X) counterpart.  Nonetheless, these appear frequently in code
+ * predating the PostgreSQL 8.3 introduction of the ...PP(X) variants.
+ */
+#define DatumGetByteaP(X)                      ((bytea *) PG_DETOAST_DATUM(X))
+#define DatumGetTextP(X)                       ((text *) PG_DETOAST_DATUM(X))
+#define DatumGetBpCharP(X)                     ((BpChar *) PG_DETOAST_DATUM(X))
+#define DatumGetVarCharP(X)                    ((VarChar *) 
+#define PG_GETARG_BYTEA_P(n)           DatumGetByteaP(PG_GETARG_DATUM(n))
+#define PG_GETARG_TEXT_P(n)                    
+#define PG_GETARG_BPCHAR_P(n)          DatumGetBpCharP(PG_GETARG_DATUM(n))
+#define PG_GETARG_VARCHAR_P(n)         DatumGetVarCharP(PG_GETARG_DATUM(n))
 /* To return a NULL do this: */
 #define PG_RETURN_NULL()  \
diff --git a/src/include/postgres.h b/src/include/postgres.h
index be4d0d6..5844f78 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -287,20 +287,18 @@ typedef struct
 /* Externally visible macros */
- * VARDATA, VARSIZE, and SET_VARSIZE are the recommended API for most code
- * for varlena datatypes.  Note that they only work on untoasted,
- * 4-byte-header Datums!
- *
- * Code that wants to use 1-byte-header values without detoasting should
- * use VARSIZE_ANY/VARSIZE_ANY_EXHDR/VARDATA_ANY.  The other macros here
- * should usually be used only by tuple assembly/disassembly code and
- * code that specifically wants to work with still-toasted Datums.
- *
- * WARNING: It is only safe to use VARDATA_ANY() -- typically with
- * PG_DETOAST_DATUM_PACKED() -- if you really don't care about the alignment.
- * Either because you're working with something like text where the alignment
- * doesn't matter or because you're not going to access its constituent parts
- * and just use things like memcpy on it anyways.
+ * In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
+ * VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR().  Elsewhere, call
+ * PG_DETOAST_DATUM(), VARDATA() and VARSIZE().  Directly fetching an int16,
+ * int32 or wider field in the struct representing the datum layout requires
+ * aligned data.  memcpy() is alignment-oblivious, as are most operations on
+ * datatypes, such as text, whose layout struct contains only char fields.
+ *
+ * Code assembling a new datum should call VARDATA() and SET_VARSIZE().
+ * (Datums begin life untoasted.)
+ *
+ * Other macros here should usually be used only by tuple assembly/disassembly
+ * code and code that specifically wants to work with still-toasted Datums.
 #define VARDATA(PTR)                                           VARDATA_4B(PTR)
 #define VARSIZE(PTR)                                           VARSIZE_4B(PTR)
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:

Reply via email to