PostgreSQL Source Code  git master
expandeddatum.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * expandeddatum.h
4  * Declarations for access to "expanded" value representations.
5  *
6  * Complex data types, particularly container types such as arrays and
7  * records, usually have on-disk representations that are compact but not
8  * especially convenient to modify. What's more, when we do modify them,
9  * having to recopy all the rest of the value can be extremely inefficient.
10  * Therefore, we provide a notion of an "expanded" representation that is used
11  * only in memory and is optimized more for computation than storage.
12  * The format appearing on disk is called the data type's "flattened"
13  * representation, since it is required to be a contiguous blob of bytes --
14  * but the type can have an expanded representation that is not. Data types
15  * must provide means to translate an expanded representation back to
16  * flattened form.
17  *
18  * An expanded object is meant to survive across multiple operations, but
19  * not to be enormously long-lived; for example it might be a local variable
20  * in a PL/pgSQL procedure. So its extra bulk compared to the on-disk format
21  * is a worthwhile trade-off.
22  *
23  * References to expanded objects are a type of TOAST pointer.
24  * Because of longstanding conventions in Postgres, this means that the
25  * flattened form of such an object must always be a varlena object.
26  * Fortunately that's no restriction in practice.
27  *
28  * There are actually two kinds of TOAST pointers for expanded objects:
29  * read-only and read-write pointers. Possession of one of the latter
30  * authorizes a function to modify the value in-place rather than copying it
31  * as would normally be required. Functions should always return a read-write
32  * pointer to any new expanded object they create. Functions that modify an
33  * argument value in-place must take care that they do not corrupt the old
34  * value if they fail partway through.
35  *
36  *
37  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
38  * Portions Copyright (c) 1994, Regents of the University of California
39  *
40  * src/include/utils/expandeddatum.h
41  *
42  *-------------------------------------------------------------------------
43  */
44 #ifndef EXPANDEDDATUM_H
45 #define EXPANDEDDATUM_H
46 
47 #include "varatt.h"
48 
49 /* Size of an EXTERNAL datum that contains a pointer to an expanded object */
50 #define EXPANDED_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(varatt_expanded))
51 
52 /*
53  * "Methods" that must be provided for any expanded object.
54  *
55  * get_flat_size: compute space needed for flattened representation (total,
56  * including header).
57  *
58  * flatten_into: construct flattened representation in the caller-allocated
59  * space at *result, of size allocated_size (which will always be the result
60  * of a preceding get_flat_size call; it's passed for cross-checking).
61  *
62  * The flattened representation must be a valid in-line, non-compressed,
63  * 4-byte-header varlena object.
64  *
65  * Note: construction of a heap tuple from an expanded datum calls
66  * get_flat_size twice, so it's worthwhile to make sure that that doesn't
67  * incur too much overhead.
68  */
71  void *result, Size allocated_size);
72 
73 /* Struct of function pointers for an expanded object's methods */
74 typedef struct ExpandedObjectMethods
75 {
79 
80 /*
81  * Every expanded object must contain this header; typically the header
82  * is embedded in some larger struct that adds type-specific fields.
83  *
84  * It is presumed that the header object and all subsidiary data are stored
85  * in eoh_context, so that the object can be freed by deleting that context,
86  * or its storage lifespan can be altered by reparenting the context.
87  * (In principle the object could own additional resources, such as malloc'd
88  * storage, and use a memory context reset callback to free them upon reset or
89  * deletion of eoh_context.)
90  *
91  * We set up two TOAST pointers within the standard header, one read-write
92  * and one read-only. This allows functions to return either kind of pointer
93  * without making an additional allocation, and in particular without worrying
94  * whether a separately palloc'd object would have sufficient lifespan.
95  * But note that these pointers are just a convenience; a pointer object
96  * appearing somewhere else would still be legal.
97  *
98  * The typedef declaration for this appears in postgres.h.
99  */
101 {
102  /* Phony varlena header */
103  int32 vl_len_; /* always EOH_HEADER_MAGIC, see below */
104 
105  /* Pointer to methods required for object type */
107 
108  /* Memory context containing this header and subsidiary data */
110 
111  /* Standard R/W TOAST pointer for this object is kept here */
113 
114  /* Standard R/O TOAST pointer for this object is kept here */
116 };
117 
118 /*
119  * Particularly for read-only functions, it is handy to be able to work with
120  * either regular "flat" varlena inputs or expanded inputs of the same data
121  * type. To allow determining which case an argument-fetching function has
122  * returned, the first int32 of an ExpandedObjectHeader always contains -1
123  * (EOH_HEADER_MAGIC to the code). This works since no 4-byte-header varlena
124  * could have that as its first 4 bytes. Caution: we could not reliably tell
125  * the difference between an ExpandedObjectHeader and a short-header object
126  * with this trick. However, it works fine if the argument fetching code
127  * always returns either a 4-byte-header flat object or an expanded object.
128  */
129 #define EOH_HEADER_MAGIC (-1)
130 #define VARATT_IS_EXPANDED_HEADER(PTR) \
131  (((varattrib_4b *) (PTR))->va_4byte.va_header == (uint32) EOH_HEADER_MAGIC)
132 
133 /*
134  * Generic support functions for expanded objects.
135  * (More of these might be worth inlining later.)
136  */
137 
138 static inline Datum
140 {
141  return PointerGetDatum(eohptr->eoh_rw_ptr);
142 }
143 
144 static inline Datum
146 {
147  return PointerGetDatum(eohptr->eoh_ro_ptr);
148 }
149 
150 /* Does the Datum represent a writable expanded object? */
151 #define DatumIsReadWriteExpandedObject(d, isnull, typlen) \
152  (((isnull) || (typlen) != -1) ? false : \
153  VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)))
154 
155 #define MakeExpandedObjectReadOnly(d, isnull, typlen) \
156  (((isnull) || (typlen) != -1) ? (d) : \
157  MakeExpandedObjectReadOnlyInternal(d))
158 
160 extern void EOH_init_header(ExpandedObjectHeader *eohptr,
161  const ExpandedObjectMethods *methods,
162  MemoryContext obj_context);
164 extern void EOH_flatten_into(ExpandedObjectHeader *eohptr,
165  void *result, Size allocated_size);
167 extern Datum TransferExpandedObject(Datum d, MemoryContext new_parent);
168 extern void DeleteExpandedObject(Datum d);
169 
170 #endif /* EXPANDEDDATUM_H */
signed int int32
Definition: c.h:494
size_t Size
Definition: c.h:605
#define EXPANDED_POINTER_SIZE
Definition: expandeddatum.h:50
static Datum EOHPGetRWDatum(const struct ExpandedObjectHeader *eohptr)
void(* EOM_flatten_into_method)(ExpandedObjectHeader *eohptr, void *result, Size allocated_size)
Definition: expandeddatum.h:70
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
Size(* EOM_get_flat_size_method)(ExpandedObjectHeader *eohptr)
Definition: expandeddatum.h:69
void EOH_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size)
Definition: expandeddatum.c:81
struct ExpandedObjectMethods ExpandedObjectMethods
void EOH_init_header(ExpandedObjectHeader *eohptr, const ExpandedObjectMethods *methods, MemoryContext obj_context)
Definition: expandeddatum.c:48
void DeleteExpandedObject(Datum d)
Datum TransferExpandedObject(Datum d, MemoryContext new_parent)
Datum MakeExpandedObjectReadOnlyInternal(Datum d)
Definition: expandeddatum.c:95
static Datum EOHPGetRODatum(const struct ExpandedObjectHeader *eohptr)
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
Definition: expandeddatum.c:75
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
char eoh_rw_ptr[EXPANDED_POINTER_SIZE]
MemoryContext eoh_context
const ExpandedObjectMethods * eoh_methods
char eoh_ro_ptr[EXPANDED_POINTER_SIZE]
EOM_get_flat_size_method get_flat_size
Definition: expandeddatum.h:76
EOM_flatten_into_method flatten_into
Definition: expandeddatum.h:77