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 14361312 : CreateTemplateTupleDesc(int natts)
46 : {
47 : TupleDesc desc;
48 :
49 : /*
50 : * sanity checks
51 : */
52 : 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 14361312 : desc = (TupleDesc) palloc(offsetof(struct TupleDescData, attrs) +
67 14361312 : natts * sizeof(FormData_pg_attribute));
68 :
69 : /*
70 : * Initialize other fields of the tupdesc.
71 : */
72 14361312 : desc->natts = natts;
73 14361312 : desc->constr = NULL;
74 14361312 : desc->tdtypeid = RECORDOID;
75 14361312 : desc->tdtypmod = -1;
76 14361312 : desc->tdrefcount = -1; /* assume not reference-counted */
77 :
78 14361312 : 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 6531088 : CreateTupleDesc(int natts, Form_pg_attribute *attrs)
91 : {
92 : TupleDesc desc;
93 : int i;
94 :
95 6531088 : desc = CreateTemplateTupleDesc(natts);
96 :
97 102146326 : for (i = 0; i < natts; ++i)
98 95615238 : memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
99 :
100 6531088 : 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 835752 : CreateTupleDescCopy(TupleDesc tupdesc)
112 : {
113 : TupleDesc desc;
114 : int i;
115 :
116 835752 : desc = CreateTemplateTupleDesc(tupdesc->natts);
117 :
118 : /* Flat-copy the attribute array */
119 835752 : memcpy(TupleDescAttr(desc, 0),
120 835752 : TupleDescAttr(tupdesc, 0),
121 835752 : 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 3803880 : for (i = 0; i < desc->natts; i++)
128 : {
129 2968128 : Form_pg_attribute att = TupleDescAttr(desc, i);
130 :
131 2968128 : att->attnotnull = false;
132 2968128 : att->atthasdef = false;
133 2968128 : att->atthasmissing = false;
134 2968128 : att->attidentity = '\0';
135 2968128 : att->attgenerated = '\0';
136 : }
137 :
138 : /* We can copy the tuple type identification, too */
139 835752 : desc->tdtypeid = tupdesc->tdtypeid;
140 835752 : desc->tdtypmod = tupdesc->tdtypmod;
141 :
142 835752 : 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 701046 : CreateTupleDescCopyConstr(TupleDesc tupdesc)
152 : {
153 : TupleDesc desc;
154 701046 : TupleConstr *constr = tupdesc->constr;
155 : int i;
156 :
157 701046 : desc = CreateTemplateTupleDesc(tupdesc->natts);
158 :
159 : /* Flat-copy the attribute array */
160 701046 : memcpy(TupleDescAttr(desc, 0),
161 701046 : TupleDescAttr(tupdesc, 0),
162 701046 : desc->natts * sizeof(FormData_pg_attribute));
163 :
164 : /* Copy the TupleConstr data structure, if any */
165 701046 : if (constr)
166 : {
167 647564 : TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
168 :
169 647564 : cpy->has_not_null = constr->has_not_null;
170 647564 : cpy->has_generated_stored = constr->has_generated_stored;
171 :
172 647564 : if ((cpy->num_defval = constr->num_defval) > 0)
173 : {
174 2708 : cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
175 2708 : memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
176 6698 : for (i = cpy->num_defval - 1; i >= 0; i--)
177 3990 : cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
178 : }
179 :
180 647564 : if (constr->missing)
181 : {
182 558 : cpy->missing = (AttrMissing *) palloc(tupdesc->natts * sizeof(AttrMissing));
183 558 : memcpy(cpy->missing, constr->missing, tupdesc->natts * sizeof(AttrMissing));
184 4564 : for (i = tupdesc->natts - 1; i >= 0; i--)
185 : {
186 4006 : if (constr->missing[i].am_present)
187 : {
188 1056 : Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
189 :
190 1056 : cpy->missing[i].am_value = datumCopy(constr->missing[i].am_value,
191 1056 : attr->attbyval,
192 1056 : attr->attlen);
193 : }
194 : }
195 : }
196 :
197 647564 : if ((cpy->num_check = constr->num_check) > 0)
198 : {
199 1780 : cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
200 1780 : memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
201 4276 : for (i = cpy->num_check - 1; i >= 0; i--)
202 : {
203 2496 : cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
204 2496 : cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
205 2496 : cpy->check[i].ccvalid = constr->check[i].ccvalid;
206 2496 : cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
207 : }
208 : }
209 :
210 647564 : desc->constr = cpy;
211 : }
212 :
213 : /* We can copy the tuple type identification, too */
214 701046 : desc->tdtypeid = tupdesc->tdtypeid;
215 701046 : desc->tdtypmod = tupdesc->tdtypmod;
216 :
217 701046 : 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 68054 : TupleDescCopy(TupleDesc dst, TupleDesc src)
230 : {
231 : int i;
232 :
233 : /* Flat-copy the header and attribute array */
234 68054 : memcpy(dst, src, TupleDescSize(src));
235 :
236 : /*
237 : * Since we're not copying constraints and defaults, clear fields
238 : * associated with them.
239 : */
240 263652 : for (i = 0; i < dst->natts; i++)
241 : {
242 195598 : Form_pg_attribute att = TupleDescAttr(dst, i);
243 :
244 195598 : att->attnotnull = false;
245 195598 : att->atthasdef = false;
246 195598 : att->atthasmissing = false;
247 195598 : att->attidentity = '\0';
248 195598 : att->attgenerated = '\0';
249 : }
250 68054 : 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 68054 : dst->tdrefcount = -1;
257 68054 : }
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 3308 : TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
268 : TupleDesc src, AttrNumber srcAttno)
269 : {
270 3308 : Form_pg_attribute dstAtt = TupleDescAttr(dst, dstAttno - 1);
271 3308 : Form_pg_attribute srcAtt = TupleDescAttr(src, srcAttno - 1);
272 :
273 : /*
274 : * sanity checks
275 : */
276 : Assert(PointerIsValid(src));
277 : Assert(PointerIsValid(dst));
278 : Assert(srcAttno >= 1);
279 : Assert(srcAttno <= src->natts);
280 : Assert(dstAttno >= 1);
281 : Assert(dstAttno <= dst->natts);
282 :
283 3308 : 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 3308 : dstAtt->attnum = dstAttno;
295 3308 : dstAtt->attcacheoff = -1;
296 :
297 : /* since we're not copying constraints or defaults, clear these */
298 3308 : dstAtt->attnotnull = false;
299 3308 : dstAtt->atthasdef = false;
300 3308 : dstAtt->atthasmissing = false;
301 3308 : dstAtt->attidentity = '\0';
302 3308 : dstAtt->attgenerated = '\0';
303 3308 : }
304 :
305 : /*
306 : * Free a TupleDesc including all substructure
307 : */
308 : void
309 1658600 : 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 : Assert(tupdesc->tdrefcount <= 0);
318 :
319 1658600 : if (tupdesc->constr)
320 : {
321 500680 : if (tupdesc->constr->num_defval > 0)
322 : {
323 21304 : AttrDefault *attrdef = tupdesc->constr->defval;
324 :
325 51836 : for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
326 30532 : pfree(attrdef[i].adbin);
327 21304 : pfree(attrdef);
328 : }
329 500680 : if (tupdesc->constr->missing)
330 : {
331 3064 : AttrMissing *attrmiss = tupdesc->constr->missing;
332 :
333 22986 : for (i = tupdesc->natts - 1; i >= 0; i--)
334 : {
335 19922 : if (attrmiss[i].am_present
336 6840 : && !TupleDescAttr(tupdesc, i)->attbyval)
337 2668 : pfree(DatumGetPointer(attrmiss[i].am_value));
338 : }
339 3064 : pfree(attrmiss);
340 : }
341 500680 : if (tupdesc->constr->num_check > 0)
342 : {
343 8398 : ConstrCheck *check = tupdesc->constr->check;
344 :
345 19246 : for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
346 : {
347 10848 : pfree(check[i].ccname);
348 10848 : pfree(check[i].ccbin);
349 : }
350 8398 : pfree(check);
351 : }
352 500680 : pfree(tupdesc->constr);
353 : }
354 :
355 1658600 : pfree(tupdesc);
356 1658600 : }
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 40274928 : IncrTupleDescRefCount(TupleDesc tupdesc)
367 : {
368 : Assert(tupdesc->tdrefcount >= 0);
369 :
370 40274928 : ResourceOwnerEnlargeTupleDescs(CurrentResourceOwner);
371 40274928 : tupdesc->tdrefcount++;
372 40274928 : ResourceOwnerRememberTupleDesc(CurrentResourceOwner, tupdesc);
373 40274928 : }
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 40274928 : DecrTupleDescRefCount(TupleDesc tupdesc)
385 : {
386 : Assert(tupdesc->tdrefcount > 0);
387 :
388 40274928 : ResourceOwnerForgetTupleDesc(CurrentResourceOwner, tupdesc);
389 40274928 : if (--tupdesc->tdrefcount == 0)
390 290 : FreeTupleDesc(tupdesc);
391 40274928 : }
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 1047692 : equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
403 : {
404 : int i,
405 : n;
406 :
407 1047692 : if (tupdesc1->natts != tupdesc2->natts)
408 2352 : return false;
409 1045340 : if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
410 1636 : return false;
411 :
412 11370946 : for (i = 0; i < tupdesc1->natts; i++)
413 : {
414 10347466 : Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
415 10347466 : 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 10347466 : if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
431 10462 : return false;
432 10337004 : if (attr1->atttypid != attr2->atttypid)
433 956 : return false;
434 10336048 : if (attr1->attstattarget != attr2->attstattarget)
435 56 : return false;
436 10335992 : if (attr1->attlen != attr2->attlen)
437 8 : return false;
438 10335984 : if (attr1->attndims != attr2->attndims)
439 0 : return false;
440 10335984 : if (attr1->atttypmod != attr2->atttypmod)
441 46 : return false;
442 10335938 : if (attr1->attbyval != attr2->attbyval)
443 152 : return false;
444 10335786 : if (attr1->attalign != attr2->attalign)
445 0 : return false;
446 10335786 : if (attr1->attstorage != attr2->attstorage)
447 204 : return false;
448 10335582 : if (attr1->attcompression != attr2->attcompression)
449 60 : return false;
450 10335522 : if (attr1->attnotnull != attr2->attnotnull)
451 962 : return false;
452 10334560 : if (attr1->atthasdef != attr2->atthasdef)
453 3542 : return false;
454 10331018 : if (attr1->attidentity != attr2->attidentity)
455 124 : return false;
456 10330894 : if (attr1->attgenerated != attr2->attgenerated)
457 20 : return false;
458 10330874 : if (attr1->attisdropped != attr2->attisdropped)
459 0 : return false;
460 10330874 : if (attr1->attislocal != attr2->attislocal)
461 3052 : return false;
462 10327822 : if (attr1->attinhcount != attr2->attinhcount)
463 580 : return false;
464 10327242 : if (attr1->attcollation != attr2->attcollation)
465 0 : return false;
466 : /* variable-length fields are not even present... */
467 : }
468 :
469 1023480 : if (tupdesc1->constr != NULL)
470 : {
471 179990 : TupleConstr *constr1 = tupdesc1->constr;
472 179990 : TupleConstr *constr2 = tupdesc2->constr;
473 :
474 179990 : if (constr2 == NULL)
475 134 : return false;
476 179856 : if (constr1->has_not_null != constr2->has_not_null)
477 0 : return false;
478 179856 : if (constr1->has_generated_stored != constr2->has_generated_stored)
479 446 : return false;
480 179410 : n = constr1->num_defval;
481 179410 : if (n != (int) constr2->num_defval)
482 0 : return false;
483 : /* We assume here that both AttrDefault arrays are in adnum order */
484 188902 : for (i = 0; i < n; i++)
485 : {
486 9492 : AttrDefault *defval1 = constr1->defval + i;
487 9492 : AttrDefault *defval2 = constr2->defval + i;
488 :
489 9492 : if (defval1->adnum != defval2->adnum)
490 0 : return false;
491 9492 : if (strcmp(defval1->adbin, defval2->adbin) != 0)
492 0 : return false;
493 : }
494 179410 : if (constr1->missing)
495 : {
496 320 : if (!constr2->missing)
497 66 : return false;
498 1476 : for (i = 0; i < tupdesc1->natts; i++)
499 : {
500 1222 : AttrMissing *missval1 = constr1->missing + i;
501 1222 : AttrMissing *missval2 = constr2->missing + i;
502 :
503 1222 : if (missval1->am_present != missval2->am_present)
504 0 : return false;
505 1222 : if (missval1->am_present)
506 : {
507 332 : Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i);
508 :
509 332 : if (!datumIsEqual(missval1->am_value, missval2->am_value,
510 332 : missatt1->attbyval, missatt1->attlen))
511 0 : return false;
512 : }
513 : }
514 : }
515 179090 : else if (constr2->missing)
516 4 : return false;
517 179340 : n = constr1->num_check;
518 179340 : if (n != (int) constr2->num_check)
519 1170 : 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 180138 : for (i = 0; i < n; i++)
527 : {
528 2046 : ConstrCheck *check1 = constr1->check + i;
529 2046 : ConstrCheck *check2 = constr2->check + i;
530 :
531 2046 : if (!(strcmp(check1->ccname, check2->ccname) == 0 &&
532 2046 : strcmp(check1->ccbin, check2->ccbin) == 0 &&
533 2046 : check1->ccvalid == check2->ccvalid &&
534 1968 : check1->ccnoinherit == check2->ccnoinherit))
535 78 : return false;
536 : }
537 : }
538 843490 : else if (tupdesc2->constr != NULL)
539 1312 : return false;
540 1020270 : 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 543832 : hashTupleDesc(TupleDesc desc)
555 : {
556 : uint32 s;
557 : int i;
558 :
559 543832 : s = hash_combine(0, hash_uint32(desc->natts));
560 543832 : s = hash_combine(s, hash_uint32(desc->tdtypeid));
561 7960212 : for (i = 0; i < desc->natts; ++i)
562 7416380 : s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
563 :
564 543832 : 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 13015272 : 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 : Assert(PointerIsValid(desc));
598 : Assert(attributeNumber >= 1);
599 : Assert(attributeNumber <= desc->natts);
600 : Assert(attdim >= 0);
601 : Assert(attdim <= PG_INT16_MAX);
602 :
603 : /*
604 : * initialize the attribute fields
605 : */
606 13015272 : att = TupleDescAttr(desc, attributeNumber - 1);
607 :
608 13015272 : att->attrelid = 0; /* dummy value */
609 :
610 : /*
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 13015272 : if (attributeName == NULL)
616 13872624 : MemSet(NameStr(att->attname), 0, NAMEDATALEN);
617 10040472 : else if (attributeName != NameStr(att->attname))
618 10028176 : namestrcpy(&(att->attname), attributeName);
619 :
620 13015272 : att->attstattarget = -1;
621 13015272 : att->attcacheoff = -1;
622 13015272 : att->atttypmod = typmod;
623 :
624 13015272 : att->attnum = attributeNumber;
625 13015272 : att->attndims = attdim;
626 :
627 13015272 : att->attnotnull = false;
628 13015272 : att->atthasdef = false;
629 13015272 : att->atthasmissing = false;
630 13015272 : att->attidentity = '\0';
631 13015272 : att->attgenerated = '\0';
632 13015272 : att->attisdropped = false;
633 13015272 : att->attislocal = true;
634 13015272 : att->attinhcount = 0;
635 : /* variable-length fields are not present in tupledescs */
636 :
637 13015272 : tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
638 13015272 : if (!HeapTupleIsValid(tuple))
639 0 : elog(ERROR, "cache lookup failed for type %u", oidtypeid);
640 13015272 : typeForm = (Form_pg_type) GETSTRUCT(tuple);
641 :
642 13015272 : att->atttypid = oidtypeid;
643 13015272 : att->attlen = typeForm->typlen;
644 13015272 : att->attbyval = typeForm->typbyval;
645 13015272 : att->attalign = typeForm->typalign;
646 13015272 : att->attstorage = typeForm->typstorage;
647 13015272 : att->attcompression = InvalidCompressionMethod;
648 13015272 : att->attcollation = typeForm->typcollation;
649 :
650 13015272 : ReleaseSysCache(tuple);
651 13015272 : }
652 :
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 10246 : TupleDescInitBuiltinEntry(TupleDesc desc,
660 : AttrNumber attributeNumber,
661 : const char *attributeName,
662 : Oid oidtypeid,
663 : int32 typmod,
664 : int attdim)
665 : {
666 : Form_pg_attribute att;
667 :
668 : /* sanity checks */
669 : Assert(PointerIsValid(desc));
670 : Assert(attributeNumber >= 1);
671 : Assert(attributeNumber <= desc->natts);
672 : Assert(attdim >= 0);
673 : Assert(attdim <= PG_INT16_MAX);
674 :
675 : /* initialize the attribute fields */
676 10246 : att = TupleDescAttr(desc, attributeNumber - 1);
677 10246 : att->attrelid = 0; /* dummy value */
678 :
679 : /* unlike TupleDescInitEntry, we require an attribute name */
680 : Assert(attributeName != NULL);
681 10246 : namestrcpy(&(att->attname), attributeName);
682 :
683 10246 : att->attstattarget = -1;
684 10246 : att->attcacheoff = -1;
685 10246 : att->atttypmod = typmod;
686 :
687 10246 : att->attnum = attributeNumber;
688 10246 : att->attndims = attdim;
689 :
690 10246 : att->attnotnull = false;
691 10246 : att->atthasdef = false;
692 10246 : att->atthasmissing = false;
693 10246 : att->attidentity = '\0';
694 10246 : att->attgenerated = '\0';
695 10246 : att->attisdropped = false;
696 10246 : att->attislocal = true;
697 10246 : att->attinhcount = 0;
698 : /* variable-length fields are not present in tupledescs */
699 :
700 10246 : att->atttypid = oidtypeid;
701 :
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 10246 : switch (oidtypeid)
708 : {
709 8250 : case TEXTOID:
710 : case TEXTARRAYOID:
711 8250 : att->attlen = -1;
712 8250 : att->attbyval = false;
713 8250 : att->attalign = TYPALIGN_INT;
714 8250 : att->attstorage = TYPSTORAGE_EXTENDED;
715 8250 : att->attcompression = InvalidCompressionMethod;
716 8250 : att->attcollation = DEFAULT_COLLATION_OID;
717 8250 : break;
718 :
719 0 : case BOOLOID:
720 0 : att->attlen = 1;
721 0 : att->attbyval = true;
722 0 : att->attalign = TYPALIGN_CHAR;
723 0 : att->attstorage = TYPSTORAGE_PLAIN;
724 0 : att->attcompression = InvalidCompressionMethod;
725 0 : att->attcollation = InvalidOid;
726 0 : break;
727 :
728 0 : case INT4OID:
729 0 : att->attlen = 4;
730 0 : att->attbyval = true;
731 0 : att->attalign = TYPALIGN_INT;
732 0 : att->attstorage = TYPSTORAGE_PLAIN;
733 0 : att->attcompression = InvalidCompressionMethod;
734 0 : att->attcollation = InvalidOid;
735 0 : break;
736 :
737 1760 : case INT8OID:
738 1760 : att->attlen = 8;
739 1760 : att->attbyval = FLOAT8PASSBYVAL;
740 1760 : att->attalign = TYPALIGN_DOUBLE;
741 1760 : att->attstorage = TYPSTORAGE_PLAIN;
742 1760 : att->attcompression = InvalidCompressionMethod;
743 1760 : att->attcollation = InvalidOid;
744 1760 : break;
745 :
746 236 : case OIDOID:
747 236 : att->attlen = 4;
748 236 : att->attbyval = true;
749 236 : att->attalign = TYPALIGN_INT;
750 236 : att->attstorage = TYPSTORAGE_PLAIN;
751 236 : att->attcompression = InvalidCompressionMethod;
752 236 : att->attcollation = InvalidOid;
753 236 : break;
754 :
755 0 : default:
756 0 : elog(ERROR, "unsupported type %u", oidtypeid);
757 : }
758 10246 : }
759 :
760 : /*
761 : * TupleDescInitEntryCollation
762 : *
763 : * Assign a nondefault collation to a previously initialized tuple descriptor
764 : * entry.
765 : */
766 : void
767 5526018 : TupleDescInitEntryCollation(TupleDesc desc,
768 : AttrNumber attributeNumber,
769 : Oid collationid)
770 : {
771 : /*
772 : * sanity checks
773 : */
774 : Assert(PointerIsValid(desc));
775 : Assert(attributeNumber >= 1);
776 : Assert(attributeNumber <= desc->natts);
777 :
778 5526018 : TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
779 5526018 : }
780 :
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 125188 : BuildDescForRelation(List *schema)
791 : {
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 125188 : natts = list_length(schema);
807 125188 : desc = CreateTemplateTupleDesc(natts);
808 125188 : has_not_null = false;
809 :
810 125188 : attnum = 0;
811 :
812 1095542 : foreach(l, schema)
813 : {
814 970378 : ColumnDef *entry = lfirst(l);
815 : AclResult aclresult;
816 : Form_pg_attribute att;
817 :
818 : /*
819 : * 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 970378 : attnum++;
824 :
825 970378 : attname = entry->colname;
826 970378 : typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
827 :
828 970378 : aclresult = object_aclcheck(TypeRelationId, atttypid, GetUserId(), ACL_USAGE);
829 970378 : if (aclresult != ACLCHECK_OK)
830 24 : aclcheck_error_type(aclresult, atttypid);
831 :
832 970354 : attcollation = GetColumnDefCollation(NULL, entry, atttypid);
833 970354 : attdim = list_length(entry->typeName->arrayBounds);
834 970354 : if (attdim > PG_INT16_MAX)
835 0 : ereport(ERROR,
836 : errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
837 : errmsg("too many array dimensions"));
838 :
839 970354 : if (entry->typeName->setof)
840 0 : ereport(ERROR,
841 : (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
842 : errmsg("column \"%s\" cannot be declared SETOF",
843 : attname)));
844 :
845 970354 : TupleDescInitEntry(desc, attnum, attname,
846 : atttypid, atttypmod, attdim);
847 970354 : att = TupleDescAttr(desc, attnum - 1);
848 :
849 : /* Override TupleDescInitEntry's settings as requested */
850 970354 : TupleDescInitEntryCollation(desc, attnum, attcollation);
851 970354 : if (entry->storage)
852 17514 : att->attstorage = entry->storage;
853 :
854 : /* Fill in additional stuff not handled by TupleDescInitEntry */
855 970354 : att->attnotnull = entry->is_not_null;
856 970354 : has_not_null |= entry->is_not_null;
857 970354 : att->attislocal = entry->is_local;
858 970354 : att->attinhcount = entry->inhcount;
859 : }
860 :
861 125164 : if (has_not_null)
862 : {
863 10702 : TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
864 :
865 10702 : constr->has_not_null = true;
866 10702 : constr->has_generated_stored = false;
867 10702 : constr->defval = NULL;
868 10702 : constr->missing = NULL;
869 10702 : constr->num_defval = 0;
870 10702 : constr->check = NULL;
871 10702 : constr->num_check = 0;
872 10702 : desc->constr = constr;
873 : }
874 : else
875 : {
876 114462 : desc->constr = NULL;
877 : }
878 :
879 125164 : return desc;
880 : }
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 940 : BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
895 : {
896 : int natts;
897 : AttrNumber attnum;
898 : ListCell *l1;
899 : ListCell *l2;
900 : ListCell *l3;
901 : ListCell *l4;
902 : TupleDesc desc;
903 :
904 940 : natts = list_length(names);
905 : Assert(natts == list_length(types));
906 : Assert(natts == list_length(typmods));
907 : Assert(natts == list_length(collations));
908 :
909 : /*
910 : * allocate a new tuple descriptor
911 : */
912 940 : desc = CreateTemplateTupleDesc(natts);
913 :
914 940 : attnum = 0;
915 3462 : forfour(l1, names, l2, types, l3, typmods, l4, collations)
916 : {
917 2522 : char *attname = strVal(lfirst(l1));
918 2522 : Oid atttypid = lfirst_oid(l2);
919 2522 : int32 atttypmod = lfirst_int(l3);
920 2522 : Oid attcollation = lfirst_oid(l4);
921 :
922 2522 : attnum++;
923 :
924 2522 : TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
925 2522 : TupleDescInitEntryCollation(desc, attnum, attcollation);
926 : }
927 :
928 940 : return desc;
929 : }
|