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
45 CBC 7137282 : CreateTemplateTupleDesc(int natts)
46 : {
47 : TupleDesc desc;
48 :
49 : /*
50 : * sanity checks
51 : */
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 : */
66 CBC 7137282 : desc = (TupleDesc) palloc(offsetof(struct TupleDescData, attrs) +
67 7137282 : natts * sizeof(FormData_pg_attribute));
68 :
69 : /*
70 : * Initialize other fields of the tupdesc.
71 : */
72 7137282 : desc->natts = natts;
73 7137282 : desc->constr = NULL;
74 7137282 : desc->tdtypeid = RECORDOID;
75 7137282 : desc->tdtypmod = -1;
76 7137282 : desc->tdrefcount = -1; /* assume not reference-counted */
77 :
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
90 3291810 : CreateTupleDesc(int natts, Form_pg_attribute *attrs)
91 : {
92 : TupleDesc desc;
93 : int i;
94 :
95 3291810 : desc = CreateTemplateTupleDesc(natts);
96 :
97 51497225 : for (i = 0; i < natts; ++i)
98 48205415 : memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
99 :
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
111 419124 : CreateTupleDescCopy(TupleDesc tupdesc)
112 : {
113 : TupleDesc desc;
114 : int i;
115 :
116 419124 : desc = CreateTemplateTupleDesc(tupdesc->natts);
117 :
118 : /* Flat-copy the attribute array */
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 : */
127 1907643 : for (i = 0; i < desc->natts; i++)
128 : {
129 1488519 : Form_pg_attribute att = TupleDescAttr(desc, i);
130 :
131 1488519 : att->attnotnull = false;
132 1488519 : att->atthasdef = false;
133 1488519 : att->atthasmissing = false;
134 1488519 : att->attidentity = '\0';
135 1488519 : att->attgenerated = '\0';
136 : }
137 :
138 : /* We can copy the tuple type identification, too */
139 419124 : desc->tdtypeid = tupdesc->tdtypeid;
140 419124 : desc->tdtypmod = tupdesc->tdtypmod;
141 :
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
151 351050 : CreateTupleDescCopyConstr(TupleDesc tupdesc)
152 : {
153 : TupleDesc desc;
154 351050 : TupleConstr *constr = tupdesc->constr;
155 : int i;
156 :
157 351050 : desc = CreateTemplateTupleDesc(tupdesc->natts);
158 :
159 : /* Flat-copy the attribute array */
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 */
165 351050 : if (constr)
166 : {
167 324155 : TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
168 :
169 324155 : cpy->has_not_null = constr->has_not_null;
170 324155 : cpy->has_generated_stored = constr->has_generated_stored;
171 :
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--)
177 2461 : cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
178 : }
179 :
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 : {
186 1967 : if (constr->missing[i].am_present)
187 : {
188 522 : Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
189 :
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 :
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 : {
203 1284 : cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
204 1284 : cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
205 1284 : cpy->check[i].ccvalid = constr->check[i].ccvalid;
206 1284 : cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
207 : }
208 : }
209 :
210 324155 : desc->constr = cpy;
211 : }
212 :
213 : /* We can copy the tuple type identification, too */
214 351050 : desc->tdtypeid = tupdesc->tdtypeid;
215 351050 : desc->tdtypmod = tupdesc->tdtypmod;
216 :
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
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 : */
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;
246 104330 : att->atthasmissing = false;
247 104330 : att->attidentity = '\0';
248 104330 : att->attgenerated = '\0';
249 : }
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
267 1652 : TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
268 : TupleDesc src, AttrNumber srcAttno)
269 : {
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 : */
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 :
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;
300 1652 : dstAtt->atthasmissing = false;
301 1652 : dstAtt->attidentity = '\0';
302 1652 : dstAtt->attgenerated = '\0';
303 1652 : }
304 :
305 : /*
306 : * Free a TupleDesc including all substructure
307 : */
308 : void
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 : */
317 829615 : Assert(tupdesc->tdrefcount <= 0);
318 :
319 829615 : if (tupdesc->constr)
320 : {
321 250156 : if (tupdesc->constr->num_defval > 0)
322 : {
323 10672 : AttrDefault *attrdef = tupdesc->constr->defval;
324 :
325 26049 : for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
326 15377 : pfree(attrdef[i].adbin);
327 10672 : pfree(attrdef);
328 : }
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 : {
335 10168 : if (attrmiss[i].am_present
336 3471 : && !TupleDescAttr(tupdesc, i)->attbyval)
337 1339 : pfree(DatumGetPointer(attrmiss[i].am_value));
338 : }
339 1569 : pfree(attrmiss);
340 : }
341 250156 : if (tupdesc->constr->num_check > 0)
342 : {
343 4305 : ConstrCheck *check = tupdesc->constr->check;
344 :
345 9851 : for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
346 : {
347 5546 : pfree(check[i].ccname);
348 5546 : pfree(check[i].ccbin);
349 : }
350 4305 : pfree(check);
351 : }
352 250156 : pfree(tupdesc->constr);
353 : }
354 :
355 829615 : pfree(tupdesc);
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
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
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;
409 523305 : if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
410 817 : return false;
411 :
412 5604215 : for (i = 0; i < tupdesc1->natts; i++)
413 : {
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 : */
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;
434 5086223 : if (attr1->attstattarget != attr2->attstattarget)
435 28 : return false;
436 5086195 : if (attr1->attlen != attr2->attlen)
437 4 : return false;
438 5086191 : if (attr1->attndims != attr2->attndims)
439 UBC 0 : return false;
440 CBC 5086191 : if (attr1->atttypmod != attr2->atttypmod)
441 23 : return false;
442 5086168 : if (attr1->attbyval != attr2->attbyval)
443 76 : return false;
444 5086092 : if (attr1->attalign != attr2->attalign)
445 UBC 0 : return false;
446 CBC 5086092 : if (attr1->attstorage != attr2->attstorage)
447 102 : return false;
448 5085990 : if (attr1->attcompression != attr2->attcompression)
449 30 : return false;
450 5085960 : if (attr1->attnotnull != attr2->attnotnull)
451 588 : return false;
452 5085372 : if (attr1->atthasdef != attr2->atthasdef)
453 1748 : return false;
454 5083624 : if (attr1->attidentity != attr2->attidentity)
455 62 : return false;
456 5083562 : if (attr1->attgenerated != attr2->attgenerated)
457 10 : return false;
458 5083552 : if (attr1->attisdropped != attr2->attisdropped)
459 UBC 0 : return false;
460 CBC 5083552 : if (attr1->attislocal != attr2->attislocal)
461 1526 : return false;
462 5082026 : if (attr1->attinhcount != attr2->attinhcount)
463 299 : return false;
464 5081727 : if (attr1->attcollation != attr2->attcollation)
465 UBC 0 : return false;
466 : /* variable-length fields are not even present... */
467 : }
468 :
469 CBC 512261 : if (tupdesc1->constr != NULL)
470 : {
471 90540 : TupleConstr *constr1 = tupdesc1->constr;
472 90540 : TupleConstr *constr2 = tupdesc2->constr;
473 :
474 90540 : if (constr2 == NULL)
475 67 : return false;
476 90473 : if (constr1->has_not_null != constr2->has_not_null)
477 UBC 0 : return false;
478 CBC 90473 : if (constr1->has_generated_stored != constr2->has_generated_stored)
479 206 : return false;
480 90267 : n = constr1->num_defval;
481 90267 : if (n != (int) constr2->num_defval)
482 UBC 0 : return false;
483 : /* We assume here that both AttrDefault arrays are in adnum order */
484 CBC 95142 : for (i = 0; i < n; i++)
485 : {
486 4875 : AttrDefault *defval1 = constr1->defval + i;
487 4875 : AttrDefault *defval2 = constr2->defval + i;
488 :
489 4875 : if (defval1->adnum != defval2->adnum)
490 UBC 0 : return false;
491 CBC 4875 : if (strcmp(defval1->adbin, defval2->adbin) != 0)
492 UBC 0 : return false;
493 : }
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 :
503 914 : if (missval1->am_present != missval2->am_present)
504 UBC 0 : return false;
505 CBC 914 : if (missval1->am_present)
506 : {
507 235 : Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i);
508 :
509 235 : if (!datumIsEqual(missval1->am_value, missval2->am_value,
510 235 : missatt1->attbyval, missatt1->attlen))
511 UBC 0 : return false;
512 : }
513 : }
514 : }
515 CBC 90052 : else if (constr2->missing)
516 2 : return false;
517 90232 : n = constr1->num_check;
518 90232 : if (n != (int) constr2->num_check)
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 : */
526 90677 : for (i = 0; i < n; i++)
527 : {
528 1071 : ConstrCheck *check1 = constr1->check + i;
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))
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
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
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 : */
597 GNC 6458843 : Assert(PointerIsValid(desc));
598 6458843 : Assert(attributeNumber >= 1);
599 6458843 : Assert(attributeNumber <= desc->natts);
600 6458843 : Assert(attdim >= 0);
601 6458843 : Assert(attdim <= PG_INT16_MAX);
602 ECB :
603 : /*
604 : * initialize the attribute fields
605 : */
606 GIC 6458843 : att = TupleDescAttr(desc, attributeNumber - 1);
607 :
608 CBC 6458843 : att->attrelid = 0; /* dummy value */
609 :
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 : */
615 GIC 6458843 : if (attributeName == NULL)
616 7089374 : MemSet(NameStr(att->attname), 0, NAMEDATALEN);
617 CBC 4939077 : else if (attributeName != NameStr(att->attname))
618 4932891 : namestrcpy(&(att->attname), attributeName);
619 ECB :
620 CBC 6458843 : att->attstattarget = -1;
621 GIC 6458843 : att->attcacheoff = -1;
622 CBC 6458843 : att->atttypmod = typmod;
623 ECB :
624 CBC 6458843 : att->attnum = attributeNumber;
625 GIC 6458843 : att->attndims = attdim;
626 ECB :
627 CBC 6458843 : att->attnotnull = false;
628 GIC 6458843 : att->atthasdef = false;
629 CBC 6458843 : att->atthasmissing = false;
630 6458843 : att->attidentity = '\0';
631 6458843 : att->attgenerated = '\0';
632 6458843 : att->attisdropped = false;
633 6458843 : att->attislocal = true;
634 6458843 : att->attinhcount = 0;
635 ECB : /* variable-length fields are not present in tupledescs */
636 :
637 GIC 6458843 : tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
638 6458843 : if (!HeapTupleIsValid(tuple))
639 LBC 0 : elog(ERROR, "cache lookup failed for type %u", oidtypeid);
640 CBC 6458843 : typeForm = (Form_pg_type) GETSTRUCT(tuple);
641 EUB :
642 CBC 6458843 : att->atttypid = oidtypeid;
643 GIC 6458843 : att->attlen = typeForm->typlen;
644 CBC 6458843 : att->attbyval = typeForm->typbyval;
645 6458843 : att->attalign = typeForm->typalign;
646 6458843 : att->attstorage = typeForm->typstorage;
647 6458843 : att->attcompression = InvalidCompressionMethod;
648 6458843 : att->attcollation = typeForm->typcollation;
649 ECB :
650 CBC 6458843 : ReleaseSysCache(tuple);
651 GIC 6458843 : }
652 ECB :
653 : /*
654 : * TupleDescInitBuiltinEntry
655 : * Initialize a tuple descriptor without catalog access. Only
656 : * a limited range of builtin types are supported.
657 : */
658 : void
659 GIC 5187 : TupleDescInitBuiltinEntry(TupleDesc desc,
660 : AttrNumber attributeNumber,
661 ECB : const char *attributeName,
662 : Oid oidtypeid,
663 : int32 typmod,
664 : int attdim)
665 : {
666 : Form_pg_attribute att;
667 :
668 : /* sanity checks */
669 GNC 5187 : Assert(PointerIsValid(desc));
670 5187 : Assert(attributeNumber >= 1);
671 5187 : Assert(attributeNumber <= desc->natts);
672 5187 : Assert(attdim >= 0);
673 5187 : Assert(attdim <= PG_INT16_MAX);
674 ECB :
675 : /* initialize the attribute fields */
676 CBC 5187 : att = TupleDescAttr(desc, attributeNumber - 1);
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 :
683 GIC 5187 : att->attstattarget = -1;
684 CBC 5187 : att->attcacheoff = -1;
685 5187 : att->atttypmod = typmod;
686 :
687 5187 : att->attnum = attributeNumber;
688 5187 : att->attndims = attdim;
689 ECB :
690 GIC 5187 : att->attnotnull = false;
691 CBC 5187 : att->atthasdef = false;
692 5187 : att->atthasmissing = false;
693 GIC 5187 : att->attidentity = '\0';
694 CBC 5187 : att->attgenerated = '\0';
695 5187 : att->attisdropped = false;
696 5187 : att->attislocal = true;
697 5187 : att->attinhcount = 0;
698 ECB : /* variable-length fields are not present in tupledescs */
699 :
700 CBC 5187 : att->atttypid = oidtypeid;
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 : */
707 GIC 5187 : switch (oidtypeid)
708 : {
709 4155 : case TEXTOID:
710 : case TEXTARRAYOID:
711 CBC 4155 : att->attlen = -1;
712 GIC 4155 : att->attbyval = false;
713 CBC 4155 : att->attalign = TYPALIGN_INT;
714 GIC 4155 : att->attstorage = TYPSTORAGE_EXTENDED;
715 CBC 4155 : att->attcompression = InvalidCompressionMethod;
716 4155 : att->attcollation = DEFAULT_COLLATION_OID;
717 4155 : break;
718 ECB :
719 LBC 0 : case BOOLOID:
720 0 : att->attlen = 1;
721 0 : att->attbyval = true;
722 UIC 0 : att->attalign = TYPALIGN_CHAR;
723 UBC 0 : att->attstorage = TYPSTORAGE_PLAIN;
724 0 : att->attcompression = InvalidCompressionMethod;
725 0 : att->attcollation = InvalidOid;
726 0 : break;
727 EUB :
728 UBC 0 : case INT4OID:
729 0 : att->attlen = 4;
730 0 : att->attbyval = true;
731 UIC 0 : att->attalign = TYPALIGN_INT;
732 UBC 0 : att->attstorage = TYPSTORAGE_PLAIN;
733 0 : att->attcompression = InvalidCompressionMethod;
734 0 : att->attcollation = InvalidOid;
735 0 : break;
736 EUB :
737 GBC 906 : case INT8OID:
738 906 : att->attlen = 8;
739 906 : att->attbyval = FLOAT8PASSBYVAL;
740 GIC 906 : att->attalign = TYPALIGN_DOUBLE;
741 CBC 906 : att->attstorage = TYPSTORAGE_PLAIN;
742 906 : att->attcompression = InvalidCompressionMethod;
743 906 : att->attcollation = InvalidOid;
744 906 : break;
745 ECB :
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 :
755 LBC 0 : default:
756 0 : elog(ERROR, "unsupported type %u", oidtypeid);
757 ECB : }
758 GIC 5187 : }
759 ECB :
760 : /*
761 : * TupleDescInitEntryCollation
762 : *
763 : * Assign a nondefault collation to a previously initialized tuple descriptor
764 : * entry.
765 : */
766 : void
767 GIC 2804782 : TupleDescInitEntryCollation(TupleDesc desc,
768 EUB : AttrNumber attributeNumber,
769 : Oid collationid)
770 : {
771 ECB : /*
772 : * sanity checks
773 : */
774 GNC 2804782 : Assert(PointerIsValid(desc));
775 2804782 : Assert(attributeNumber >= 1);
776 2804782 : Assert(attributeNumber <= desc->natts);
777 :
778 GIC 2804782 : TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
779 2804782 : }
780 ECB :
781 :
782 : /*
783 : * BuildDescForRelation
784 : *
785 : * Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
786 : *
787 : * Note: tdtypeid will need to be filled in later on.
788 : */
789 : TupleDesc
790 GIC 62881 : BuildDescForRelation(List *schema)
791 ECB : {
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 :
803 : /*
804 : * allocate a new tuple descriptor
805 : */
806 GIC 62881 : natts = list_length(schema);
807 62881 : desc = CreateTemplateTupleDesc(natts);
808 62881 : has_not_null = false;
809 :
810 62881 : attnum = 0;
811 :
812 549933 : foreach(l, schema)
813 : {
814 487064 : ColumnDef *entry = lfirst(l);
815 : AclResult aclresult;
816 : Form_pg_attribute att;
817 :
818 : /*
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
821 : * information we need.
822 : */
823 CBC 487064 : attnum++;
824 :
825 487064 : attname = entry->colname;
826 GIC 487064 : typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
827 ECB :
828 GNC 487064 : aclresult = object_aclcheck(TypeRelationId, atttypid, GetUserId(), ACL_USAGE);
829 GIC 487064 : if (aclresult != ACLCHECK_OK)
830 12 : aclcheck_error_type(aclresult, atttypid);
831 :
832 487052 : attcollation = GetColumnDefCollation(NULL, entry, atttypid);
833 487052 : attdim = list_length(entry->typeName->arrayBounds);
834 GNC 487052 : if (attdim > PG_INT16_MAX)
835 UNC 0 : ereport(ERROR,
836 : errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
837 : errmsg("too many array dimensions"));
838 :
839 GIC 487052 : if (entry->typeName->setof)
840 LBC 0 : ereport(ERROR,
841 : (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
842 ECB : errmsg("column \"%s\" cannot be declared SETOF",
843 : attname)));
844 :
845 CBC 487052 : TupleDescInitEntry(desc, attnum, attname,
846 ECB : atttypid, atttypmod, attdim);
847 CBC 487052 : att = TupleDescAttr(desc, attnum - 1);
848 :
849 ECB : /* Override TupleDescInitEntry's settings as requested */
850 CBC 487052 : TupleDescInitEntryCollation(desc, attnum, attcollation);
851 487052 : if (entry->storage)
852 GBC 8734 : att->attstorage = entry->storage;
853 :
854 : /* Fill in additional stuff not handled by TupleDescInitEntry */
855 GIC 487052 : att->attnotnull = entry->is_not_null;
856 CBC 487052 : has_not_null |= entry->is_not_null;
857 GBC 487052 : att->attislocal = entry->is_local;
858 GIC 487052 : att->attinhcount = entry->inhcount;
859 : }
860 :
861 62869 : if (has_not_null)
862 ECB : {
863 GIC 5312 : TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
864 ECB :
865 GIC 5312 : constr->has_not_null = true;
866 5312 : constr->has_generated_stored = false;
867 CBC 5312 : constr->defval = NULL;
868 5312 : constr->missing = NULL;
869 5312 : constr->num_defval = 0;
870 GIC 5312 : constr->check = NULL;
871 5312 : constr->num_check = 0;
872 CBC 5312 : desc->constr = constr;
873 ECB : }
874 : else
875 : {
876 GIC 57557 : desc->constr = NULL;
877 : }
878 ECB :
879 GIC 62869 : return desc;
880 ECB : }
881 :
882 : /*
883 : * BuildDescFromLists
884 : *
885 : * Build a TupleDesc given lists of column names (as String nodes),
886 : * column type OIDs, typmods, and collation OIDs.
887 : *
888 : * No constraints are generated.
889 : *
890 : * This is essentially a cut-down version of BuildDescForRelation for use
891 : * with functions returning RECORD.
892 : */
893 : TupleDesc
894 GIC 470 : BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
895 : {
896 ECB : int natts;
897 : AttrNumber attnum;
898 : ListCell *l1;
899 : ListCell *l2;
900 : ListCell *l3;
901 : ListCell *l4;
902 : TupleDesc desc;
903 :
904 GIC 470 : natts = list_length(names);
905 470 : Assert(natts == list_length(types));
906 470 : Assert(natts == list_length(typmods));
907 470 : Assert(natts == list_length(collations));
908 :
909 : /*
910 : * allocate a new tuple descriptor
911 ECB : */
912 GIC 470 : desc = CreateTemplateTupleDesc(natts);
913 :
914 470 : attnum = 0;
915 1731 : forfour(l1, names, l2, types, l3, typmods, l4, collations)
916 : {
917 1261 : char *attname = strVal(lfirst(l1));
918 1261 : Oid atttypid = lfirst_oid(l2);
919 1261 : int32 atttypmod = lfirst_int(l3);
920 1261 : Oid attcollation = lfirst_oid(l4);
921 ECB :
922 CBC 1261 : attnum++;
923 ECB :
924 CBC 1261 : TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
925 GIC 1261 : TupleDescInitEntryCollation(desc, attnum, attcollation);
926 : }
927 :
928 470 : return desc;
929 ECB : }
|