Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * tupdesc.h
4 : * POSTGRES tuple descriptor definitions.
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : * src/include/access/tupdesc.h
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 : #ifndef TUPDESC_H
15 : #define TUPDESC_H
16 :
17 : #include "access/attnum.h"
18 : #include "access/xlogdefs.h"
19 : #include "catalog/pg_attribute.h"
20 : #include "nodes/pg_list.h"
21 :
22 :
23 : typedef struct AttrDefault
24 : {
25 : AttrNumber adnum;
26 : char *adbin; /* nodeToString representation of expr */
27 : } AttrDefault;
28 :
29 : typedef struct ConstrCheck
30 : {
31 : char *ccname;
32 : char *ccbin; /* nodeToString representation of expr */
33 : bool ccenforced;
34 : bool ccvalid;
35 : bool ccnoinherit; /* this is a non-inheritable constraint */
36 : } ConstrCheck;
37 :
38 : /* This structure contains constraints of a tuple */
39 : typedef struct TupleConstr
40 : {
41 : AttrDefault *defval; /* array */
42 : ConstrCheck *check; /* array */
43 : struct AttrMissing *missing; /* missing attributes values, NULL if none */
44 : uint16 num_defval;
45 : uint16 num_check;
46 : bool has_not_null; /* any not-null, including not valid ones */
47 : bool has_generated_stored;
48 : bool has_generated_virtual;
49 : } TupleConstr;
50 :
51 : /*
52 : * CompactAttribute
53 : * Cut-down version of FormData_pg_attribute for faster access for tasks
54 : * such as tuple deformation. The fields of this struct are populated
55 : * using the populate_compact_attribute() function, which must be called
56 : * directly after the FormData_pg_attribute struct is populated or
57 : * altered in any way.
58 : *
59 : * Currently, this struct is 8 bytes. Any code changes which enlarge this
60 : * struct should be considered very carefully.
61 : *
62 : * Code which must access a TupleDesc's attribute data should always make use
63 : * the fields of this struct when required fields are available here. It's
64 : * more efficient to access the memory in CompactAttribute due to it being a
65 : * more compact representation of FormData_pg_attribute and also because
66 : * accessing the FormData_pg_attribute requires an additional calculations to
67 : * obtain the base address of the array within the TupleDesc.
68 : */
69 : typedef struct CompactAttribute
70 : {
71 : int16 attcacheoff; /* fixed offset into tuple, if known, or -1 */
72 : int16 attlen; /* attr len in bytes or -1 = varlen, -2 =
73 : * cstring */
74 : bool attbyval; /* as FormData_pg_attribute.attbyval */
75 : uint8 attalignby; /* alignment requirement in bytes */
76 : bool attispackable:1; /* FormData_pg_attribute.attstorage !=
77 : * TYPSTORAGE_PLAIN */
78 : bool atthasmissing:1; /* as FormData_pg_attribute.atthasmissing */
79 : bool attisdropped:1; /* as FormData_pg_attribute.attisdropped */
80 : bool attgenerated:1; /* FormData_pg_attribute.attgenerated != '\0' */
81 : char attnullability; /* status of not-null constraint, see below */
82 : } CompactAttribute;
83 :
84 : /* Valid values for CompactAttribute->attnullability */
85 : #define ATTNULLABLE_UNRESTRICTED 'f' /* No constraint exists */
86 : #define ATTNULLABLE_UNKNOWN 'u' /* constraint exists, validity unknown */
87 : #define ATTNULLABLE_VALID 'v' /* valid constraint exists */
88 : #define ATTNULLABLE_INVALID 'i' /* constraint exists, marked invalid */
89 :
90 : /*
91 : * This struct is passed around within the backend to describe the structure
92 : * of tuples. For tuples coming from on-disk relations, the information is
93 : * collected from the pg_attribute, pg_attrdef, and pg_constraint catalogs.
94 : * Transient row types (such as the result of a join query) have anonymous
95 : * TupleDesc structs that generally omit any constraint info; therefore the
96 : * structure is designed to let the constraints be omitted efficiently.
97 : *
98 : * Note that only user attributes, not system attributes, are mentioned in
99 : * TupleDesc.
100 : *
101 : * If the tupdesc is known to correspond to a named rowtype (such as a table's
102 : * rowtype) then tdtypeid identifies that type and tdtypmod is -1. Otherwise
103 : * tdtypeid is RECORDOID, and tdtypmod can be either -1 for a fully anonymous
104 : * row type, or a value >= 0 to allow the rowtype to be looked up in the
105 : * typcache.c type cache.
106 : *
107 : * Note that tdtypeid is never the OID of a domain over composite, even if
108 : * we are dealing with values that are known (at some higher level) to be of
109 : * a domain-over-composite type. This is because tdtypeid/tdtypmod need to
110 : * match up with the type labeling of composite Datums, and those are never
111 : * explicitly marked as being of a domain type, either.
112 : *
113 : * Tuple descriptors that live in caches (relcache or typcache, at present)
114 : * are reference-counted: they can be deleted when their reference count goes
115 : * to zero. Tuple descriptors created by the executor need no reference
116 : * counting, however: they are simply created in the appropriate memory
117 : * context and go away when the context is freed. We set the tdrefcount
118 : * field of such a descriptor to -1, while reference-counted descriptors
119 : * always have tdrefcount >= 0.
120 : *
121 : * Beyond the compact_attrs variable length array, the TupleDesc stores an
122 : * array of FormData_pg_attribute. The TupleDescAttr() function, as defined
123 : * below, takes care of calculating the address of the elements of the
124 : * FormData_pg_attribute array.
125 : *
126 : * The array of CompactAttribute is effectively an abbreviated version of the
127 : * array of FormData_pg_attribute. Because CompactAttribute is significantly
128 : * smaller than FormData_pg_attribute, code, especially performance-critical
129 : * code, should prioritize using the fields from the CompactAttribute over the
130 : * equivalent fields in FormData_pg_attribute.
131 : *
132 : * Any code making changes manually to and fields in the FormData_pg_attribute
133 : * array must subsequently call populate_compact_attribute() to flush the
134 : * changes out to the corresponding 'compact_attrs' element.
135 : *
136 : * firstNonCachedOffsetAttr stores the index into the compact_attrs array for
137 : * the first attribute that we don't have a known attcacheoff for.
138 : *
139 : * firstNonGuaranteedAttr stores the index to into the compact_attrs array for
140 : * the first attribute that is either NULLable, missing, or !attbyval. This
141 : * can be used in locations as a guarantee that attributes before this will
142 : * always exist in tuples. The !attbyval part isn't required for this, but
143 : * including this allows various tuple deforming routines to forego any checks
144 : * for !attbyval.
145 : *
146 : * Once a TupleDesc has been populated, before it is used for any purpose,
147 : * TupleDescFinalize() must be called on it.
148 : */
149 : typedef struct TupleDescData
150 : {
151 : int natts; /* number of attributes in the tuple */
152 : Oid tdtypeid; /* composite type ID for tuple type */
153 : int32 tdtypmod; /* typmod for tuple type */
154 : int tdrefcount; /* reference count, or -1 if not counting */
155 :
156 : /* ---
157 : * Version of the tuple descriptor in aggregate. Used to ensure we never
158 : * try to deform datum-style tuples with a different tupledesc than what
159 : * was used to form them. For !RECORDOID descriptors, this is equal to
160 : * TupleDescAttr(td, td->natts - 1)->attversion
161 : * but faster to access (due to the constant offset), except when natts=0,
162 : * in which case tdversion is 0. The descriptor-wide version is used when
163 : * forming tuples and as the fast-path when checking a datum tuple's
164 : * version (most of the time it will match, and no per-attribute version
165 : * checks are needed).
166 : *
167 : * See src/backend/catalog/README.attver.md.
168 : * ---
169 : */
170 : XLogRecPtr tdversion;
171 :
172 : int firstNonCachedOffsetAttr; /* index of first compact_attrs
173 : * element without an attcacheoff */
174 : int firstNonGuaranteedAttr; /* index of the first nullable,
175 : * missing, dropped, or !attbyval
176 : * compact_attrs element. */
177 : TupleConstr *constr; /* constraints, or NULL if none */
178 : /* compact_attrs[N] is the compact metadata of Attribute Number N+1 */
179 : pg_attribute_counted_by(natts) CompactAttribute compact_attrs[FLEXIBLE_ARRAY_MEMBER];
180 : } TupleDescData;
181 : typedef struct TupleDescData *TupleDesc;
182 :
183 : extern void populate_compact_attribute(TupleDesc tupdesc, int attnum);
184 :
185 : /*
186 : * Calculates the base address of the Form_pg_attribute at the end of the
187 : * TupleDescData struct.
188 : */
189 : #define TupleDescAttrAddress(desc) \
190 : (Form_pg_attribute) ((char *) (desc) + \
191 : (offsetof(struct TupleDescData, compact_attrs) + \
192 : (desc)->natts * sizeof(CompactAttribute)))
193 :
194 : /* Accessor for the i'th FormData_pg_attribute element of tupdesc. */
195 : static inline FormData_pg_attribute *
196 241209901 : TupleDescAttr(TupleDesc tupdesc, int i)
197 : {
198 241209901 : FormData_pg_attribute *attrs = TupleDescAttrAddress(tupdesc);
199 :
200 : Assert(i >= 0 && i < tupdesc->natts);
201 :
202 241209901 : return &attrs[i];
203 : }
204 :
205 : #undef TupleDescAttrAddress
206 :
207 : extern void verify_compact_attribute(TupleDesc, int attnum);
208 :
209 : /*
210 : * Accessor for the i'th CompactAttribute element of tupdesc.
211 : */
212 : static inline CompactAttribute *
213 1311777555 : TupleDescCompactAttr(TupleDesc tupdesc, int i)
214 : {
215 1311777555 : CompactAttribute *cattr = &tupdesc->compact_attrs[i];
216 :
217 : #ifdef USE_ASSERT_CHECKING
218 :
219 : /* Check that the CompactAttribute is correctly populated */
220 : verify_compact_attribute(tupdesc, i);
221 : #endif
222 :
223 1311777555 : return cattr;
224 : }
225 :
226 : extern TupleDesc CreateTemplateTupleDesc(int natts);
227 :
228 : extern TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs);
229 :
230 : extern TupleDesc CreateTupleDescCopy(TupleDesc tupdesc);
231 :
232 : extern TupleDesc CreateTupleDescTruncatedCopy(TupleDesc tupdesc, int natts);
233 :
234 : extern TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc);
235 :
236 : extern Size TupleDescCopySize(TupleDesc src);
237 : extern void TupleDescCopySized(TupleDesc dst, Size dstsize, TupleDesc src);
238 :
239 : extern void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
240 : TupleDesc src, AttrNumber srcAttno);
241 :
242 : extern void TupleDescFinalize(TupleDesc tupdesc);
243 : extern void FreeTupleDesc(TupleDesc tupdesc);
244 :
245 : extern void IncrTupleDescRefCount(TupleDesc tupdesc);
246 : extern void DecrTupleDescRefCount(TupleDesc tupdesc);
247 :
248 : extern XLogRecPtr TupleDescGetVersion(TupleDesc tupdesc);
249 : extern void TupleDescSetVersion(TupleDesc tupdesc, XLogRecPtr version);
250 : extern XLogRecPtr TupleDescGetAttrVersion(TupleDesc tupdesc, AttrNumber attnum);
251 :
252 : #define PinTupleDesc(tupdesc) \
253 : do { \
254 : if ((tupdesc)->tdrefcount >= 0) \
255 : IncrTupleDescRefCount(tupdesc); \
256 : } while (0)
257 :
258 : #define ReleaseTupleDesc(tupdesc) \
259 : do { \
260 : if ((tupdesc)->tdrefcount >= 0) \
261 : DecrTupleDescRefCount(tupdesc); \
262 : } while (0)
263 :
264 : extern bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
265 : extern bool equalRowTypes(TupleDesc tupdesc1, TupleDesc tupdesc2);
266 : extern uint32 hashRowType(TupleDesc desc);
267 :
268 : extern void TupleDescInitEntry(TupleDesc desc,
269 : AttrNumber attributeNumber,
270 : const char *attributeName,
271 : Oid oidtypeid,
272 : int32 typmod,
273 : int attdim);
274 :
275 : extern void TupleDescInitBuiltinEntry(TupleDesc desc,
276 : AttrNumber attributeNumber,
277 : const char *attributeName,
278 : Oid oidtypeid,
279 : int32 typmod,
280 : int attdim);
281 :
282 : extern void TupleDescInitEntryCollation(TupleDesc desc,
283 : AttrNumber attributeNumber,
284 : Oid collationid);
285 :
286 : extern TupleDesc BuildDescFromLists(const List *names, const List *types, const List *typmods, const List *collations);
287 :
288 : extern Node *TupleDescGetDefault(TupleDesc tupdesc, AttrNumber attnum);
289 :
290 : #endif /* TUPDESC_H */
|