Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * tupdesc.c
4 : * POSTGRES tuple descriptor support code
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/access/common/tupdesc.c
12 : *
13 : * NOTES
14 : * some of the executor utility code such as "ExecTypeFromTL" should be
15 : * moved here.
16 : *
17 : *-------------------------------------------------------------------------
18 : */
19 :
20 : #include "postgres.h"
21 :
22 : #include "access/htup_details.h"
23 : #include "access/toast_compression.h"
24 : #include "access/tupdesc_details.h"
25 : #include "catalog/pg_collation.h"
26 : #include "catalog/pg_type.h"
27 : #include "common/hashfn.h"
28 : #include "miscadmin.h"
29 : #include "parser/parse_type.h"
30 : #include "utils/acl.h"
31 : #include "utils/builtins.h"
32 : #include "utils/datum.h"
33 : #include "utils/resowner_private.h"
34 : #include "utils/syscache.h"
35 :
36 :
37 : /*
38 : * CreateTemplateTupleDesc
39 : * This function allocates an empty tuple descriptor structure.
40 : *
41 : * Tuple type ID information is initially set for an anonymous record type;
42 : * caller can overwrite this if needed.
43 : */
44 : TupleDesc
1601 andres 45 CBC 7137282 : CreateTemplateTupleDesc(int natts)
46 : {
47 : TupleDesc desc;
48 :
49 : /*
50 : * sanity checks
51 : */
163 peter 52 GNC 7137282 : Assert(natts >= 0);
53 :
54 : /*
55 : * Allocate enough memory for the tuple descriptor, including the
56 : * attribute rows.
57 : *
58 : * Note: the attribute array stride is sizeof(FormData_pg_attribute),
59 : * since we declare the array elements as FormData_pg_attribute for
60 : * notational convenience. However, we only guarantee that the first
61 : * ATTRIBUTE_FIXED_PART_SIZE bytes of each entry are valid; most code that
62 : * copies tupdesc entries around copies just that much. In principle that
63 : * could be less due to trailing padding, although with the current
64 : * definition of pg_attribute there probably isn't any padding.
65 : */
1546 andres 66 CBC 7137282 : desc = (TupleDesc) palloc(offsetof(struct TupleDescData, attrs) +
2058 67 7137282 : natts * sizeof(FormData_pg_attribute));
68 :
69 : /*
70 : * Initialize other fields of the tupdesc.
71 : */
6947 tgl 72 7137282 : desc->natts = natts;
7498 73 7137282 : desc->constr = NULL;
6947 74 7137282 : desc->tdtypeid = RECORDOID;
75 7137282 : desc->tdtypmod = -1;
6141 76 7137282 : desc->tdrefcount = -1; /* assume not reference-counted */
77 :
8986 bruce 78 7137282 : return desc;
79 : }
80 :
81 : /*
82 : * CreateTupleDesc
83 : * This function allocates a new TupleDesc by copying a given
84 : * Form_pg_attribute array.
85 : *
86 : * Tuple type ID information is initially set for an anonymous record type;
87 : * caller can overwrite this if needed.
88 : */
89 : TupleDesc
1601 andres 90 3291810 : CreateTupleDesc(int natts, Form_pg_attribute *attrs)
91 : {
92 : TupleDesc desc;
93 : int i;
94 :
95 3291810 : desc = CreateTemplateTupleDesc(natts);
96 :
2058 97 51497225 : for (i = 0; i < natts; ++i)
98 48205415 : memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
99 :
8986 bruce 100 3291810 : return desc;
101 : }
102 :
103 : /*
104 : * CreateTupleDescCopy
105 : * This function creates a new TupleDesc by copying from an existing
106 : * TupleDesc.
107 : *
108 : * !!! Constraints and defaults are not copied !!!
109 : */
110 : TupleDesc
9770 scrappy 111 419124 : CreateTupleDescCopy(TupleDesc tupdesc)
112 : {
113 : TupleDesc desc;
114 : int i;
115 :
1601 andres 116 419124 : desc = CreateTemplateTupleDesc(tupdesc->natts);
117 :
118 : /* Flat-copy the attribute array */
1922 tgl 119 419124 : memcpy(TupleDescAttr(desc, 0),
120 419124 : TupleDescAttr(tupdesc, 0),
121 419124 : desc->natts * sizeof(FormData_pg_attribute));
122 :
123 : /*
124 : * Since we're not copying constraints and defaults, clear fields
125 : * associated with them.
126 : */
6607 127 1907643 : for (i = 0; i < desc->natts; i++)
128 : {
2058 andres 129 1488519 : Form_pg_attribute att = TupleDescAttr(desc, i);
130 :
131 1488519 : att->attnotnull = false;
132 1488519 : att->atthasdef = false;
1838 andrew 133 1488519 : att->atthasmissing = false;
2058 andres 134 1488519 : att->attidentity = '\0';
1471 peter 135 1488519 : att->attgenerated = '\0';
136 : }
137 :
138 : /* We can copy the tuple type identification, too */
6947 tgl 139 419124 : desc->tdtypeid = tupdesc->tdtypeid;
140 419124 : desc->tdtypmod = tupdesc->tdtypmod;
141 :
9345 bruce 142 419124 : return desc;
143 : }
144 :
145 : /*
146 : * CreateTupleDescCopyConstr
147 : * This function creates a new TupleDesc by copying from an existing
148 : * TupleDesc (including its constraints and defaults).
149 : */
150 : TupleDesc
9361 vadim4o 151 351050 : CreateTupleDescCopyConstr(TupleDesc tupdesc)
152 : {
153 : TupleDesc desc;
9344 bruce 154 351050 : TupleConstr *constr = tupdesc->constr;
155 : int i;
156 :
1601 andres 157 351050 : desc = CreateTemplateTupleDesc(tupdesc->natts);
158 :
159 : /* Flat-copy the attribute array */
1922 tgl 160 351050 : memcpy(TupleDescAttr(desc, 0),
161 351050 : TupleDescAttr(tupdesc, 0),
162 351050 : desc->natts * sizeof(FormData_pg_attribute));
163 :
164 : /* Copy the TupleConstr data structure, if any */
9345 bruce 165 351050 : if (constr)
166 : {
6947 tgl 167 324155 : TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
168 :
9345 bruce 169 324155 : cpy->has_not_null = constr->has_not_null;
1471 peter 170 324155 : cpy->has_generated_stored = constr->has_generated_stored;
171 :
9345 bruce 172 324155 : if ((cpy->num_defval = constr->num_defval) > 0)
173 : {
174 1754 : cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
175 1754 : memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
176 4215 : for (i = cpy->num_defval - 1; i >= 0; i--)
733 tgl 177 2461 : cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
178 : }
179 :
1838 andrew 180 324155 : if (constr->missing)
181 : {
182 273 : cpy->missing = (AttrMissing *) palloc(tupdesc->natts * sizeof(AttrMissing));
183 273 : memcpy(cpy->missing, constr->missing, tupdesc->natts * sizeof(AttrMissing));
184 2240 : for (i = tupdesc->natts - 1; i >= 0; i--)
185 : {
1747 akapila 186 1967 : if (constr->missing[i].am_present)
187 : {
1838 andrew 188 522 : Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
189 :
1747 akapila 190 522 : cpy->missing[i].am_value = datumCopy(constr->missing[i].am_value,
191 522 : attr->attbyval,
192 522 : attr->attlen);
193 : }
194 : }
195 : }
196 :
9345 bruce 197 324155 : if ((cpy->num_check = constr->num_check) > 0)
198 : {
199 925 : cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
200 925 : memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
201 2209 : for (i = cpy->num_check - 1; i >= 0; i--)
202 : {
733 tgl 203 1284 : cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
204 1284 : cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
4330 alvherre 205 1284 : cpy->check[i].ccvalid = constr->check[i].ccvalid;
3304 noah 206 1284 : cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
207 : }
208 : }
209 :
9345 bruce 210 324155 : desc->constr = cpy;
211 : }
212 :
213 : /* We can copy the tuple type identification, too */
6947 tgl 214 351050 : desc->tdtypeid = tupdesc->tdtypeid;
215 351050 : desc->tdtypmod = tupdesc->tdtypmod;
216 :
9345 bruce 217 351050 : return desc;
218 : }
219 :
220 : /*
221 : * TupleDescCopy
222 : * Copy a tuple descriptor into caller-supplied memory.
223 : * The memory may be shared memory mapped at any address, and must
224 : * be sufficient to hold TupleDescSize(src) bytes.
225 : *
226 : * !!! Constraints and defaults are not copied !!!
227 : */
228 : void
2033 andres 229 36116 : TupleDescCopy(TupleDesc dst, TupleDesc src)
230 : {
231 : int i;
232 :
233 : /* Flat-copy the header and attribute array */
234 36116 : memcpy(dst, src, TupleDescSize(src));
235 :
236 : /*
237 : * Since we're not copying constraints and defaults, clear fields
238 : * associated with them.
239 : */
1922 tgl 240 140446 : for (i = 0; i < dst->natts; i++)
241 : {
242 104330 : Form_pg_attribute att = TupleDescAttr(dst, i);
243 :
244 104330 : att->attnotnull = false;
245 104330 : att->atthasdef = false;
1838 andrew 246 104330 : att->atthasmissing = false;
1922 tgl 247 104330 : att->attidentity = '\0';
1471 peter 248 104330 : att->attgenerated = '\0';
249 : }
2033 andres 250 36116 : dst->constr = NULL;
251 :
252 : /*
253 : * Also, assume the destination is not to be ref-counted. (Copying the
254 : * source's refcount would be wrong in any case.)
255 : */
256 36116 : dst->tdrefcount = -1;
257 36116 : }
258 :
259 : /*
260 : * TupleDescCopyEntry
261 : * This function copies a single attribute structure from one tuple
262 : * descriptor to another.
263 : *
264 : * !!! Constraints and defaults are not copied !!!
265 : */
266 : void
3426 tgl 267 1652 : TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
268 : TupleDesc src, AttrNumber srcAttno)
269 : {
2058 andres 270 1652 : Form_pg_attribute dstAtt = TupleDescAttr(dst, dstAttno - 1);
271 1652 : Form_pg_attribute srcAtt = TupleDescAttr(src, srcAttno - 1);
272 :
273 : /*
274 : * sanity checks
275 : */
163 peter 276 GNC 1652 : Assert(PointerIsValid(src));
277 1652 : Assert(PointerIsValid(dst));
278 1652 : Assert(srcAttno >= 1);
279 1652 : Assert(srcAttno <= src->natts);
280 1652 : Assert(dstAttno >= 1);
281 1652 : Assert(dstAttno <= dst->natts);
282 :
2058 andres 283 CBC 1652 : memcpy(dstAtt, srcAtt, ATTRIBUTE_FIXED_PART_SIZE);
284 :
285 : /*
286 : * Aside from updating the attno, we'd better reset attcacheoff.
287 : *
288 : * XXX Actually, to be entirely safe we'd need to reset the attcacheoff of
289 : * all following columns in dst as well. Current usage scenarios don't
290 : * require that though, because all following columns will get initialized
291 : * by other uses of this function or TupleDescInitEntry. So we cheat a
292 : * bit to avoid a useless O(N^2) penalty.
293 : */
294 1652 : dstAtt->attnum = dstAttno;
295 1652 : dstAtt->attcacheoff = -1;
296 :
297 : /* since we're not copying constraints or defaults, clear these */
298 1652 : dstAtt->attnotnull = false;
299 1652 : dstAtt->atthasdef = false;
1838 andrew 300 1652 : dstAtt->atthasmissing = false;
2058 andres 301 1652 : dstAtt->attidentity = '\0';
1471 peter 302 1652 : dstAtt->attgenerated = '\0';
3426 tgl 303 1652 : }
304 :
305 : /*
306 : * Free a TupleDesc including all substructure
307 : */
308 : void
9345 bruce 309 829615 : FreeTupleDesc(TupleDesc tupdesc)
310 : {
311 : int i;
312 :
313 : /*
314 : * Possibly this should assert tdrefcount == 0, to disallow explicit
315 : * freeing of un-refcounted tupdescs?
316 : */
6141 tgl 317 829615 : Assert(tupdesc->tdrefcount <= 0);
318 :
9345 bruce 319 829615 : if (tupdesc->constr)
320 : {
321 250156 : if (tupdesc->constr->num_defval > 0)
322 : {
9344 323 10672 : AttrDefault *attrdef = tupdesc->constr->defval;
324 :
9345 325 26049 : for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
733 tgl 326 15377 : pfree(attrdef[i].adbin);
9345 bruce 327 10672 : pfree(attrdef);
328 : }
1838 andrew 329 250156 : if (tupdesc->constr->missing)
330 : {
331 1569 : AttrMissing *attrmiss = tupdesc->constr->missing;
332 :
333 11737 : for (i = tupdesc->natts - 1; i >= 0; i--)
334 : {
1747 akapila 335 10168 : if (attrmiss[i].am_present
1838 andrew 336 3471 : && !TupleDescAttr(tupdesc, i)->attbyval)
1747 akapila 337 1339 : pfree(DatumGetPointer(attrmiss[i].am_value));
338 : }
1838 andrew 339 1569 : pfree(attrmiss);
340 : }
9345 bruce 341 250156 : if (tupdesc->constr->num_check > 0)
342 : {
9344 343 4305 : ConstrCheck *check = tupdesc->constr->check;
344 :
9345 345 9851 : for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
346 : {
733 tgl 347 5546 : pfree(check[i].ccname);
348 5546 : pfree(check[i].ccbin);
349 : }
9345 bruce 350 4305 : pfree(check);
351 : }
352 250156 : pfree(tupdesc->constr);
353 : }
354 :
355 829615 : pfree(tupdesc);
9361 vadim4o 356 829615 : }
357 :
358 : /*
359 : * Increment the reference count of a tupdesc, and log the reference in
360 : * CurrentResourceOwner.
361 : *
362 : * Do not apply this to tupdescs that are not being refcounted. (Use the
363 : * macro PinTupleDesc for tupdescs of uncertain status.)
364 : */
365 : void
6141 tgl 366 21210614 : IncrTupleDescRefCount(TupleDesc tupdesc)
367 : {
368 21210614 : Assert(tupdesc->tdrefcount >= 0);
369 :
370 21210614 : ResourceOwnerEnlargeTupleDescs(CurrentResourceOwner);
371 21210614 : tupdesc->tdrefcount++;
372 21210614 : ResourceOwnerRememberTupleDesc(CurrentResourceOwner, tupdesc);
373 21210614 : }
374 :
375 : /*
376 : * Decrement the reference count of a tupdesc, remove the corresponding
377 : * reference from CurrentResourceOwner, and free the tupdesc if no more
378 : * references remain.
379 : *
380 : * Do not apply this to tupdescs that are not being refcounted. (Use the
381 : * macro ReleaseTupleDesc for tupdescs of uncertain status.)
382 : */
383 : void
384 21210614 : DecrTupleDescRefCount(TupleDesc tupdesc)
385 : {
386 21210614 : Assert(tupdesc->tdrefcount > 0);
387 :
388 21210614 : ResourceOwnerForgetTupleDesc(CurrentResourceOwner, tupdesc);
389 21210614 : if (--tupdesc->tdrefcount == 0)
390 141 : FreeTupleDesc(tupdesc);
391 21210614 : }
392 :
393 : /*
394 : * Compare two TupleDesc structures for logical equality
395 : *
396 : * Note: we deliberately do not check the attrelid and tdtypmod fields.
397 : * This allows typcache.c to use this routine to see if a cached record type
398 : * matches a requested type, and is harmless for relcache.c's uses.
399 : * We don't compare tdrefcount, either.
400 : */
401 : bool
8469 402 524491 : equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
403 : {
404 : int i,
405 : n;
406 :
407 524491 : if (tupdesc1->natts != tupdesc2->natts)
408 1186 : return false;
6947 409 523305 : if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
410 817 : return false;
411 :
8469 412 5604215 : for (i = 0; i < tupdesc1->natts; i++)
413 : {
2058 andres 414 5091954 : Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
415 5091954 : Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i);
416 :
417 : /*
418 : * We do not need to check every single field here: we can disregard
419 : * attrelid and attnum (which were used to place the row in the attrs
420 : * array in the first place). It might look like we could dispense
421 : * with checking attlen/attbyval/attalign, since these are derived
422 : * from atttypid; but in the case of dropped columns we must check
423 : * them (since atttypid will be zero for all dropped columns) and in
424 : * general it seems safer to check them always.
425 : *
426 : * attcacheoff must NOT be checked since it's possibly not set in both
427 : * copies. We also intentionally ignore atthasmissing, since that's
428 : * not very relevant in tupdescs, which lack the attmissingval field.
429 : */
8469 tgl 430 5091954 : if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
431 5255 : return false;
432 5086699 : if (attr1->atttypid != attr2->atttypid)
433 476 : return false;
8007 434 5086223 : if (attr1->attstattarget != attr2->attstattarget)
435 28 : return false;
6569 436 5086195 : if (attr1->attlen != attr2->attlen)
437 4 : return false;
6947 438 5086191 : if (attr1->attndims != attr2->attndims)
6947 tgl 439 UBC 0 : return false;
8469 tgl 440 CBC 5086191 : if (attr1->atttypmod != attr2->atttypmod)
441 23 : return false;
6569 442 5086168 : if (attr1->attbyval != attr2->attbyval)
443 76 : return false;
686 444 5086092 : if (attr1->attalign != attr2->attalign)
686 tgl 445 UBC 0 : return false;
8469 tgl 446 CBC 5086092 : if (attr1->attstorage != attr2->attstorage)
447 102 : return false;
686 448 5085990 : if (attr1->attcompression != attr2->attcompression)
6569 449 30 : return false;
8469 450 5085960 : if (attr1->attnotnull != attr2->attnotnull)
451 588 : return false;
7527 452 5085372 : if (attr1->atthasdef != attr2->atthasdef)
453 1748 : return false;
2194 peter_e 454 5083624 : if (attr1->attidentity != attr2->attidentity)
455 62 : return false;
1471 peter 456 5083562 : if (attr1->attgenerated != attr2->attgenerated)
457 10 : return false;
7555 tgl 458 5083552 : if (attr1->attisdropped != attr2->attisdropped)
7555 tgl 459 UBC 0 : return false;
7504 tgl 460 CBC 5083552 : if (attr1->attislocal != attr2->attislocal)
461 1526 : return false;
462 5082026 : if (attr1->attinhcount != attr2->attinhcount)
7527 463 299 : return false;
4370 464 5081727 : if (attr1->attcollation != attr2->attcollation)
4370 tgl 465 UBC 0 : return false;
466 : /* variable-length fields are not even present... */
467 : }
468 :
8469 tgl 469 CBC 512261 : if (tupdesc1->constr != NULL)
470 : {
8397 bruce 471 90540 : TupleConstr *constr1 = tupdesc1->constr;
472 90540 : TupleConstr *constr2 = tupdesc2->constr;
473 :
8469 tgl 474 90540 : if (constr2 == NULL)
475 67 : return false;
8187 476 90473 : if (constr1->has_not_null != constr2->has_not_null)
8187 tgl 477 UBC 0 : return false;
1471 peter 478 CBC 90473 : if (constr1->has_generated_stored != constr2->has_generated_stored)
479 206 : return false;
8187 tgl 480 90267 : n = constr1->num_defval;
481 90267 : if (n != (int) constr2->num_defval)
8469 tgl 482 UBC 0 : return false;
483 : /* We assume here that both AttrDefault arrays are in adnum order */
8187 tgl 484 CBC 95142 : for (i = 0; i < n; i++)
485 : {
8397 bruce 486 4875 : AttrDefault *defval1 = constr1->defval + i;
733 tgl 487 4875 : AttrDefault *defval2 = constr2->defval + i;
488 :
489 4875 : if (defval1->adnum != defval2->adnum)
8469 tgl 490 UBC 0 : return false;
8469 tgl 491 CBC 4875 : if (strcmp(defval1->adbin, defval2->adbin) != 0)
8469 tgl 492 UBC 0 : return false;
493 : }
1838 andrew 494 CBC 90267 : if (constr1->missing)
495 : {
496 215 : if (!constr2->missing)
497 33 : return false;
498 1096 : for (i = 0; i < tupdesc1->natts; i++)
499 : {
500 914 : AttrMissing *missval1 = constr1->missing + i;
501 914 : AttrMissing *missval2 = constr2->missing + i;
502 :
1747 akapila 503 914 : if (missval1->am_present != missval2->am_present)
1838 andrew 504 UBC 0 : return false;
1747 akapila 505 CBC 914 : if (missval1->am_present)
506 : {
1838 andrew 507 235 : Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i);
508 :
1747 akapila 509 235 : if (!datumIsEqual(missval1->am_value, missval2->am_value,
1838 andrew 510 235 : missatt1->attbyval, missatt1->attlen))
1838 andrew 511 UBC 0 : return false;
512 : }
513 : }
514 : }
1838 andrew 515 CBC 90052 : else if (constr2->missing)
516 2 : return false;
8187 tgl 517 90232 : n = constr1->num_check;
518 90232 : if (n != (int) constr2->num_check)
8469 519 587 : return false;
520 :
521 : /*
522 : * Similarly, we rely here on the ConstrCheck entries being sorted by
523 : * name. If there are duplicate names, the outcome of the comparison
524 : * is uncertain, but that should not happen.
525 : */
8187 526 90677 : for (i = 0; i < n; i++)
527 : {
8397 bruce 528 1071 : ConstrCheck *check1 = constr1->check + i;
733 tgl 529 1071 : ConstrCheck *check2 = constr2->check + i;
530 :
531 1071 : if (!(strcmp(check1->ccname, check2->ccname) == 0 &&
532 1071 : strcmp(check1->ccbin, check2->ccbin) == 0 &&
533 1071 : check1->ccvalid == check2->ccvalid &&
534 1032 : check1->ccnoinherit == check2->ccnoinherit))
8469 535 39 : return false;
536 : }
537 : }
538 421721 : else if (tupdesc2->constr != NULL)
539 663 : return false;
540 510664 : return true;
541 : }
542 :
543 : /*
544 : * hashTupleDesc
545 : * Compute a hash value for a tuple descriptor.
546 : *
547 : * If two tuple descriptors would be considered equal by equalTupleDescs()
548 : * then their hash value will be equal according to this function.
549 : *
550 : * Note that currently contents of constraint are not hashed - it'd be a bit
551 : * painful to do so, and conflicts just due to constraints are unlikely.
552 : */
553 : uint32
2056 andres 554 271499 : hashTupleDesc(TupleDesc desc)
555 : {
556 : uint32 s;
557 : int i;
558 :
559 271499 : s = hash_combine(0, hash_uint32(desc->natts));
560 271499 : s = hash_combine(s, hash_uint32(desc->tdtypeid));
561 3888426 : for (i = 0; i < desc->natts; ++i)
562 3616927 : s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
563 :
564 271499 : return s;
565 : }
566 :
567 : /*
568 : * TupleDescInitEntry
569 : * This function initializes a single attribute structure in
570 : * a previously allocated tuple descriptor.
571 : *
572 : * If attributeName is NULL, the attname field is set to an empty string
573 : * (this is for cases where we don't know or need a name for the field).
574 : * Also, some callers use this function to change the datatype-related fields
575 : * in an existing tupdesc; they pass attributeName = NameStr(att->attname)
576 : * to indicate that the attname field shouldn't be modified.
577 : *
578 : * Note that attcollation is set to the default for the specified datatype.
579 : * If a nondefault collation is needed, insert it afterwards using
580 : * TupleDescInitEntryCollation.
581 : */
582 : void
9770 scrappy 583 6458843 : TupleDescInitEntry(TupleDesc desc,
584 : AttrNumber attributeNumber,
585 : const char *attributeName,
586 : Oid oidtypeid,
587 : int32 typmod,
588 : int attdim)
589 : {
590 : HeapTuple tuple;
591 : Form_pg_type typeForm;
592 : Form_pg_attribute att;
593 :
594 : /*
595 : * sanity checks
596 : */
163 peter 597 GNC 6458843 : Assert(PointerIsValid(desc));
598 6458843 : Assert(attributeNumber >= 1);
599 6458843 : Assert(attributeNumber <= desc->natts);
12 600 6458843 : Assert(attdim >= 0);
601 6458843 : Assert(attdim <= PG_INT16_MAX);
9345 bruce 602 ECB :
8053 603 : /*
604 : * initialize the attribute fields
605 : */
2058 andres 606 GIC 6458843 : att = TupleDescAttr(desc, attributeNumber - 1);
607 :
9345 bruce 608 CBC 6458843 : att->attrelid = 0; /* dummy value */
609 :
7181 tgl 610 ECB : /*
611 : * Note: attributeName can be NULL, because the planner doesn't always
612 : * fill in valid resname values in targetlists, particularly for resjunk
613 : * attributes. Also, do nothing if caller wants to re-use the old attname.
614 : */
3450 tgl 615 GIC 6458843 : if (attributeName == NULL)
8554 bruce 616 7089374 : MemSet(NameStr(att->attname), 0, NAMEDATALEN);
3450 tgl 617 CBC 4939077 : else if (attributeName != NameStr(att->attname))
618 4932891 : namestrcpy(&(att->attname), attributeName);
9345 bruce 619 ECB :
7557 tgl 620 CBC 6458843 : att->attstattarget = -1;
9345 bruce 621 GIC 6458843 : att->attcacheoff = -1;
9189 bruce 622 CBC 6458843 : att->atttypmod = typmod;
9345 bruce 623 ECB :
9345 bruce 624 CBC 6458843 : att->attnum = attributeNumber;
8007 tgl 625 GIC 6458843 : att->attndims = attdim;
9173 bruce 626 ECB :
9345 bruce 627 CBC 6458843 : att->attnotnull = false;
9345 bruce 628 GIC 6458843 : att->atthasdef = false;
1838 andrew 629 CBC 6458843 : att->atthasmissing = false;
2194 peter_e 630 6458843 : att->attidentity = '\0';
1471 peter 631 6458843 : att->attgenerated = '\0';
7555 tgl 632 6458843 : att->attisdropped = false;
7504 633 6458843 : att->attislocal = true;
634 6458843 : att->attinhcount = 0;
499 peter 635 ECB : /* variable-length fields are not present in tupledescs */
9345 bruce 636 :
4802 rhaas 637 GIC 6458843 : tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
9345 bruce 638 6458843 : if (!HeapTupleIsValid(tuple))
7202 tgl 639 LBC 0 : elog(ERROR, "cache lookup failed for type %u", oidtypeid);
8986 bruce 640 CBC 6458843 : typeForm = (Form_pg_type) GETSTRUCT(tuple);
9345 bruce 641 EUB :
6947 tgl 642 CBC 6458843 : att->atttypid = oidtypeid;
6947 tgl 643 GIC 6458843 : att->attlen = typeForm->typlen;
6947 tgl 644 CBC 6458843 : att->attbyval = typeForm->typbyval;
645 6458843 : att->attalign = typeForm->typalign;
646 6458843 : att->attstorage = typeForm->typstorage;
682 647 6458843 : att->attcompression = InvalidCompressionMethod;
686 648 6458843 : att->attcollation = typeForm->typcollation;
751 rhaas 649 ECB :
8179 tgl 650 CBC 6458843 : ReleaseSysCache(tuple);
9770 scrappy 651 GIC 6458843 : }
9770 scrappy 652 ECB :
2266 rhaas 653 : /*
654 : * TupleDescInitBuiltinEntry
655 : * Initialize a tuple descriptor without catalog access. Only
656 : * a limited range of builtin types are supported.
657 : */
658 : void
2266 rhaas 659 GIC 5187 : TupleDescInitBuiltinEntry(TupleDesc desc,
660 : AttrNumber attributeNumber,
2266 rhaas 661 ECB : const char *attributeName,
662 : Oid oidtypeid,
663 : int32 typmod,
664 : int attdim)
665 : {
666 : Form_pg_attribute att;
667 :
668 : /* sanity checks */
163 peter 669 GNC 5187 : Assert(PointerIsValid(desc));
670 5187 : Assert(attributeNumber >= 1);
671 5187 : Assert(attributeNumber <= desc->natts);
12 672 5187 : Assert(attdim >= 0);
673 5187 : Assert(attdim <= PG_INT16_MAX);
2266 rhaas 674 ECB :
675 : /* initialize the attribute fields */
2058 andres 676 CBC 5187 : att = TupleDescAttr(desc, attributeNumber - 1);
2266 rhaas 677 5187 : att->attrelid = 0; /* dummy value */
678 :
679 : /* unlike TupleDescInitEntry, we require an attribute name */
680 5187 : Assert(attributeName != NULL);
681 5187 : namestrcpy(&(att->attname), attributeName);
682 :
2266 rhaas 683 GIC 5187 : att->attstattarget = -1;
2266 rhaas 684 CBC 5187 : att->attcacheoff = -1;
685 5187 : att->atttypmod = typmod;
686 :
687 5187 : att->attnum = attributeNumber;
688 5187 : att->attndims = attdim;
2266 rhaas 689 ECB :
2266 rhaas 690 GIC 5187 : att->attnotnull = false;
2266 rhaas 691 CBC 5187 : att->atthasdef = false;
1838 andrew 692 5187 : att->atthasmissing = false;
2194 peter_e 693 GIC 5187 : att->attidentity = '\0';
1471 peter 694 CBC 5187 : att->attgenerated = '\0';
2266 rhaas 695 5187 : att->attisdropped = false;
696 5187 : att->attislocal = true;
697 5187 : att->attinhcount = 0;
499 peter 698 ECB : /* variable-length fields are not present in tupledescs */
2266 rhaas 699 :
2266 rhaas 700 CBC 5187 : att->atttypid = oidtypeid;
2266 rhaas 701 ECB :
702 : /*
703 : * Our goal here is to support just enough types to let basic builtin
704 : * commands work without catalog access - e.g. so that we can do certain
705 : * things even in processes that are not connected to a database.
706 : */
2266 rhaas 707 GIC 5187 : switch (oidtypeid)
708 : {
709 4155 : case TEXTOID:
710 : case TEXTARRAYOID:
2266 rhaas 711 CBC 4155 : att->attlen = -1;
2266 rhaas 712 GIC 4155 : att->attbyval = false;
1131 tgl 713 CBC 4155 : att->attalign = TYPALIGN_INT;
1131 tgl 714 GIC 4155 : att->attstorage = TYPSTORAGE_EXTENDED;
682 tgl 715 CBC 4155 : att->attcompression = InvalidCompressionMethod;
2266 rhaas 716 4155 : att->attcollation = DEFAULT_COLLATION_OID;
717 4155 : break;
2266 rhaas 718 ECB :
2266 rhaas 719 LBC 0 : case BOOLOID:
720 0 : att->attlen = 1;
721 0 : att->attbyval = true;
1131 tgl 722 UIC 0 : att->attalign = TYPALIGN_CHAR;
1131 tgl 723 UBC 0 : att->attstorage = TYPSTORAGE_PLAIN;
686 724 0 : att->attcompression = InvalidCompressionMethod;
2266 rhaas 725 0 : att->attcollation = InvalidOid;
726 0 : break;
2266 rhaas 727 EUB :
2266 rhaas 728 UBC 0 : case INT4OID:
729 0 : att->attlen = 4;
730 0 : att->attbyval = true;
1131 tgl 731 UIC 0 : att->attalign = TYPALIGN_INT;
1131 tgl 732 UBC 0 : att->attstorage = TYPSTORAGE_PLAIN;
686 733 0 : att->attcompression = InvalidCompressionMethod;
2266 rhaas 734 0 : att->attcollation = InvalidOid;
2258 735 0 : break;
2258 rhaas 736 EUB :
2258 rhaas 737 GBC 906 : case INT8OID:
738 906 : att->attlen = 8;
739 906 : att->attbyval = FLOAT8PASSBYVAL;
1131 tgl 740 GIC 906 : att->attalign = TYPALIGN_DOUBLE;
1131 tgl 741 CBC 906 : att->attstorage = TYPSTORAGE_PLAIN;
686 742 906 : att->attcompression = InvalidCompressionMethod;
2258 rhaas 743 906 : att->attcollation = InvalidOid;
2266 744 906 : break;
1581 tgl 745 ECB :
279 peter 746 GNC 126 : case OIDOID:
747 126 : att->attlen = 4;
748 126 : att->attbyval = true;
749 126 : att->attalign = TYPALIGN_INT;
750 126 : att->attstorage = TYPSTORAGE_PLAIN;
751 126 : att->attcompression = InvalidCompressionMethod;
752 126 : att->attcollation = InvalidOid;
753 126 : break;
754 :
1581 tgl 755 LBC 0 : default:
756 0 : elog(ERROR, "unsupported type %u", oidtypeid);
2266 rhaas 757 ECB : }
2266 rhaas 758 GIC 5187 : }
2266 rhaas 759 ECB :
4443 peter_e 760 : /*
761 : * TupleDescInitEntryCollation
762 : *
4397 tgl 763 : * Assign a nondefault collation to a previously initialized tuple descriptor
764 : * entry.
4443 peter_e 765 : */
766 : void
4443 peter_e 767 GIC 2804782 : TupleDescInitEntryCollation(TupleDesc desc,
4443 peter_e 768 EUB : AttrNumber attributeNumber,
769 : Oid collationid)
770 : {
4443 peter_e 771 ECB : /*
772 : * sanity checks
773 : */
163 peter 774 GNC 2804782 : Assert(PointerIsValid(desc));
775 2804782 : Assert(attributeNumber >= 1);
776 2804782 : Assert(attributeNumber <= desc->natts);
777 :
2058 andres 778 GIC 2804782 : TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
4443 peter_e 779 2804782 : }
4443 peter_e 780 ECB :
781 :
782 : /*
783 : * BuildDescForRelation
784 : *
785 : * Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
786 : *
1028 michael 787 : * Note: tdtypeid will need to be filled in later on.
9770 scrappy 788 : */
789 : TupleDesc
7681 tgl 790 GIC 62881 : BuildDescForRelation(List *schema)
9770 scrappy 791 ECB : {
9344 bruce 792 : int natts;
793 : AttrNumber attnum;
794 : ListCell *l;
795 : TupleDesc desc;
796 : bool has_not_null;
797 : char *attname;
798 : Oid atttypid;
799 : int32 atttypmod;
800 : Oid attcollation;
801 : int attdim;
802 :
8053 803 : /*
804 : * allocate a new tuple descriptor
805 : */
6888 neilc 806 GIC 62881 : natts = list_length(schema);
1601 andres 807 62881 : desc = CreateTemplateTupleDesc(natts);
5448 tgl 808 62881 : has_not_null = false;
809 :
9345 bruce 810 62881 : attnum = 0;
811 :
6892 neilc 812 549933 : foreach(l, schema)
813 : {
814 487064 : ColumnDef *entry = lfirst(l);
815 : AclResult aclresult;
816 : Form_pg_attribute att;
817 :
818 : /*
6385 bruce 819 ECB : * for each entry in the list, get the name and type information from
820 : * the list and have TupleDescInitEntry fill in the attribute
8053 821 : * information we need.
822 : */
9345 bruce 823 CBC 487064 : attnum++;
824 :
825 487064 : attname = entry->colname;
4414 tgl 826 GIC 487064 : typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
4128 peter_e 827 ECB :
147 peter 828 GNC 487064 : aclresult = object_aclcheck(TypeRelationId, atttypid, GetUserId(), ACL_USAGE);
4128 peter_e 829 GIC 487064 : if (aclresult != ACLCHECK_OK)
3950 830 12 : aclcheck_error_type(aclresult, atttypid);
831 :
4414 tgl 832 487052 : attcollation = GetColumnDefCollation(NULL, entry, atttypid);
5015 peter_e 833 487052 : attdim = list_length(entry->typeName->arrayBounds);
12 peter 834 GNC 487052 : if (attdim > PG_INT16_MAX)
12 peter 835 UNC 0 : ereport(ERROR,
836 : errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
837 : errmsg("too many array dimensions"));
838 :
5015 peter_e 839 GIC 487052 : if (entry->typeName->setof)
6947 tgl 840 LBC 0 : ereport(ERROR,
841 : (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6947 tgl 842 ECB : errmsg("column \"%s\" cannot be declared SETOF",
843 : attname)));
844 :
7681 tgl 845 CBC 487052 : TupleDescInitEntry(desc, attnum, attname,
5944 tgl 846 ECB : atttypid, atttypmod, attdim);
2058 andres 847 CBC 487052 : att = TupleDescAttr(desc, attnum - 1);
848 :
4926 tgl 849 ECB : /* Override TupleDescInitEntry's settings as requested */
4397 tgl 850 CBC 487052 : TupleDescInitEntryCollation(desc, attnum, attcollation);
4926 851 487052 : if (entry->storage)
2058 andres 852 GBC 8734 : att->attstorage = entry->storage;
853 :
854 : /* Fill in additional stuff not handled by TupleDescInitEntry */
2058 andres 855 GIC 487052 : att->attnotnull = entry->is_not_null;
5448 tgl 856 CBC 487052 : has_not_null |= entry->is_not_null;
2058 andres 857 GBC 487052 : att->attislocal = entry->is_local;
2058 andres 858 GIC 487052 : att->attinhcount = entry->inhcount;
859 : }
860 :
5448 tgl 861 62869 : if (has_not_null)
9345 bruce 862 ECB : {
5448 tgl 863 GIC 5312 : TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
9364 vadim4o 864 ECB :
5448 tgl 865 GIC 5312 : constr->has_not_null = true;
1471 peter 866 5312 : constr->has_generated_stored = false;
5448 tgl 867 CBC 5312 : constr->defval = NULL;
1838 andrew 868 5312 : constr->missing = NULL;
5448 tgl 869 5312 : constr->num_defval = 0;
8589 tgl 870 GIC 5312 : constr->check = NULL;
9345 bruce 871 5312 : constr->num_check = 0;
5448 tgl 872 CBC 5312 : desc->constr = constr;
9345 bruce 873 ECB : }
874 : else
875 : {
9345 bruce 876 GIC 57557 : desc->constr = NULL;
877 : }
6947 tgl 878 ECB :
9345 bruce 879 GIC 62869 : return desc;
9770 scrappy 880 ECB : }
881 :
6233 tgl 882 : /*
883 : * BuildDescFromLists
884 : *
885 : * Build a TupleDesc given lists of column names (as String nodes),
4370 886 : * column type OIDs, typmods, and collation OIDs.
887 : *
888 : * No constraints are generated.
6233 889 : *
890 : * This is essentially a cut-down version of BuildDescForRelation for use
891 : * with functions returning RECORD.
892 : */
893 : TupleDesc
4443 peter_e 894 GIC 470 : BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
895 : {
6233 tgl 896 ECB : int natts;
897 : AttrNumber attnum;
898 : ListCell *l1;
899 : ListCell *l2;
900 : ListCell *l3;
901 : ListCell *l4;
902 : TupleDesc desc;
903 :
6233 tgl 904 GIC 470 : natts = list_length(names);
905 470 : Assert(natts == list_length(types));
906 470 : Assert(natts == list_length(typmods));
4443 peter_e 907 470 : Assert(natts == list_length(collations));
908 :
909 : /*
910 : * allocate a new tuple descriptor
6233 tgl 911 ECB : */
1601 andres 912 GIC 470 : desc = CreateTemplateTupleDesc(natts);
913 :
6233 tgl 914 470 : attnum = 0;
1501 915 1731 : forfour(l1, names, l2, types, l3, typmods, l4, collations)
916 : {
6233 917 1261 : char *attname = strVal(lfirst(l1));
1501 918 1261 : Oid atttypid = lfirst_oid(l2);
919 1261 : int32 atttypmod = lfirst_int(l3);
920 1261 : Oid attcollation = lfirst_oid(l4);
6233 tgl 921 ECB :
6233 tgl 922 CBC 1261 : attnum++;
6233 tgl 923 ECB :
6233 tgl 924 CBC 1261 : TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
4443 peter_e 925 GIC 1261 : TupleDescInitEntryCollation(desc, attnum, attcollation);
926 : }
927 :
6233 tgl 928 470 : return desc;
6233 tgl 929 ECB : }
|