PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
tupdesc.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * tupdesc.c
4  * POSTGRES tuple descriptor support code
5  *
6  * Portions Copyright (c) 1996-2017, 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 "catalog/pg_collation.h"
24 #include "catalog/pg_type.h"
25 #include "miscadmin.h"
26 #include "parser/parse_type.h"
27 #include "utils/acl.h"
28 #include "utils/builtins.h"
29 #include "utils/resowner_private.h"
30 #include "utils/syscache.h"
31 
32 
33 /*
34  * CreateTemplateTupleDesc
35  * This function allocates an empty tuple descriptor structure.
36  *
37  * Tuple type ID information is initially set for an anonymous record type;
38  * caller can overwrite this if needed.
39  */
41 CreateTemplateTupleDesc(int natts, bool hasoid)
42 {
43  TupleDesc desc;
44  char *stg;
45  int attroffset;
46 
47  /*
48  * sanity checks
49  */
50  AssertArg(natts >= 0);
51 
52  /*
53  * Allocate enough memory for the tuple descriptor, including the
54  * attribute rows, and set up the attribute row pointers.
55  *
56  * Note: we assume that sizeof(struct tupleDesc) is a multiple of the
57  * struct pointer alignment requirement, and hence we don't need to insert
58  * alignment padding between the struct and the array of attribute row
59  * pointers.
60  *
61  * Note: Only the fixed part of pg_attribute rows is included in tuple
62  * descriptors, so we only need ATTRIBUTE_FIXED_PART_SIZE space per attr.
63  * That might need alignment padding, however.
64  */
65  attroffset = sizeof(struct tupleDesc) + natts * sizeof(Form_pg_attribute);
66  attroffset = MAXALIGN(attroffset);
67  stg = palloc(attroffset + natts * MAXALIGN(ATTRIBUTE_FIXED_PART_SIZE));
68  desc = (TupleDesc) stg;
69 
70  if (natts > 0)
71  {
73  int i;
74 
75  attrs = (Form_pg_attribute *) (stg + sizeof(struct tupleDesc));
76  desc->attrs = attrs;
77  stg += attroffset;
78  for (i = 0; i < natts; i++)
79  {
80  attrs[i] = (Form_pg_attribute) stg;
82  }
83  }
84  else
85  desc->attrs = NULL;
86 
87  /*
88  * Initialize other fields of the tupdesc.
89  */
90  desc->natts = natts;
91  desc->constr = NULL;
92  desc->tdtypeid = RECORDOID;
93  desc->tdtypmod = -1;
94  desc->tdhasoid = hasoid;
95  desc->tdrefcount = -1; /* assume not reference-counted */
96 
97  return desc;
98 }
99 
100 /*
101  * CreateTupleDesc
102  * This function allocates a new TupleDesc pointing to a given
103  * Form_pg_attribute array.
104  *
105  * Note: if the TupleDesc is ever freed, the Form_pg_attribute array
106  * will not be freed thereby.
107  *
108  * Tuple type ID information is initially set for an anonymous record type;
109  * caller can overwrite this if needed.
110  */
111 TupleDesc
113 {
114  TupleDesc desc;
115 
116  /*
117  * sanity checks
118  */
119  AssertArg(natts >= 0);
120 
121  desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
122  desc->attrs = attrs;
123  desc->natts = natts;
124  desc->constr = NULL;
125  desc->tdtypeid = RECORDOID;
126  desc->tdtypmod = -1;
127  desc->tdhasoid = hasoid;
128  desc->tdrefcount = -1; /* assume not reference-counted */
129 
130  return desc;
131 }
132 
133 /*
134  * CreateTupleDescCopy
135  * This function creates a new TupleDesc by copying from an existing
136  * TupleDesc.
137  *
138  * !!! Constraints and defaults are not copied !!!
139  */
140 TupleDesc
142 {
143  TupleDesc desc;
144  int i;
145 
146  desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
147 
148  for (i = 0; i < desc->natts; i++)
149  {
150  memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
151  desc->attrs[i]->attnotnull = false;
152  desc->attrs[i]->atthasdef = false;
153  desc->attrs[i]->attidentity = '\0';
154  }
155 
156  desc->tdtypeid = tupdesc->tdtypeid;
157  desc->tdtypmod = tupdesc->tdtypmod;
158 
159  return desc;
160 }
161 
162 /*
163  * CreateTupleDescCopyConstr
164  * This function creates a new TupleDesc by copying from an existing
165  * TupleDesc (including its constraints and defaults).
166  */
167 TupleDesc
169 {
170  TupleDesc desc;
171  TupleConstr *constr = tupdesc->constr;
172  int i;
173 
174  desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
175 
176  for (i = 0; i < desc->natts; i++)
177  {
178  memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
179  }
180 
181  if (constr)
182  {
183  TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
184 
185  cpy->has_not_null = constr->has_not_null;
186 
187  if ((cpy->num_defval = constr->num_defval) > 0)
188  {
189  cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
190  memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
191  for (i = cpy->num_defval - 1; i >= 0; i--)
192  {
193  if (constr->defval[i].adbin)
194  cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
195  }
196  }
197 
198  if ((cpy->num_check = constr->num_check) > 0)
199  {
200  cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
201  memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
202  for (i = cpy->num_check - 1; i >= 0; i--)
203  {
204  if (constr->check[i].ccname)
205  cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
206  if (constr->check[i].ccbin)
207  cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
208  cpy->check[i].ccvalid = constr->check[i].ccvalid;
209  cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
210  }
211  }
212 
213  desc->constr = cpy;
214  }
215 
216  desc->tdtypeid = tupdesc->tdtypeid;
217  desc->tdtypmod = tupdesc->tdtypmod;
218 
219  return desc;
220 }
221 
222 /*
223  * TupleDescCopyEntry
224  * This function copies a single attribute structure from one tuple
225  * descriptor to another.
226  *
227  * !!! Constraints and defaults are not copied !!!
228  */
229 void
231  TupleDesc src, AttrNumber srcAttno)
232 {
233  /*
234  * sanity checks
235  */
238  AssertArg(srcAttno >= 1);
239  AssertArg(srcAttno <= src->natts);
240  AssertArg(dstAttno >= 1);
241  AssertArg(dstAttno <= dst->natts);
242 
243  memcpy(dst->attrs[dstAttno - 1], src->attrs[srcAttno - 1],
245 
246  /*
247  * Aside from updating the attno, we'd better reset attcacheoff.
248  *
249  * XXX Actually, to be entirely safe we'd need to reset the attcacheoff of
250  * all following columns in dst as well. Current usage scenarios don't
251  * require that though, because all following columns will get initialized
252  * by other uses of this function or TupleDescInitEntry. So we cheat a
253  * bit to avoid a useless O(N^2) penalty.
254  */
255  dst->attrs[dstAttno - 1]->attnum = dstAttno;
256  dst->attrs[dstAttno - 1]->attcacheoff = -1;
257 
258  /* since we're not copying constraints or defaults, clear these */
259  dst->attrs[dstAttno - 1]->attnotnull = false;
260  dst->attrs[dstAttno - 1]->atthasdef = false;
261  dst->attrs[dstAttno - 1]->attidentity = '\0';
262 }
263 
264 /*
265  * Free a TupleDesc including all substructure
266  */
267 void
269 {
270  int i;
271 
272  /*
273  * Possibly this should assert tdrefcount == 0, to disallow explicit
274  * freeing of un-refcounted tupdescs?
275  */
276  Assert(tupdesc->tdrefcount <= 0);
277 
278  if (tupdesc->constr)
279  {
280  if (tupdesc->constr->num_defval > 0)
281  {
282  AttrDefault *attrdef = tupdesc->constr->defval;
283 
284  for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
285  {
286  if (attrdef[i].adbin)
287  pfree(attrdef[i].adbin);
288  }
289  pfree(attrdef);
290  }
291  if (tupdesc->constr->num_check > 0)
292  {
293  ConstrCheck *check = tupdesc->constr->check;
294 
295  for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
296  {
297  if (check[i].ccname)
298  pfree(check[i].ccname);
299  if (check[i].ccbin)
300  pfree(check[i].ccbin);
301  }
302  pfree(check);
303  }
304  pfree(tupdesc->constr);
305  }
306 
307  pfree(tupdesc);
308 }
309 
310 /*
311  * Increment the reference count of a tupdesc, and log the reference in
312  * CurrentResourceOwner.
313  *
314  * Do not apply this to tupdescs that are not being refcounted. (Use the
315  * macro PinTupleDesc for tupdescs of uncertain status.)
316  */
317 void
319 {
320  Assert(tupdesc->tdrefcount >= 0);
321 
323  tupdesc->tdrefcount++;
325 }
326 
327 /*
328  * Decrement the reference count of a tupdesc, remove the corresponding
329  * reference from CurrentResourceOwner, and free the tupdesc if no more
330  * references remain.
331  *
332  * Do not apply this to tupdescs that are not being refcounted. (Use the
333  * macro ReleaseTupleDesc for tupdescs of uncertain status.)
334  */
335 void
337 {
338  Assert(tupdesc->tdrefcount > 0);
339 
341  if (--tupdesc->tdrefcount == 0)
342  FreeTupleDesc(tupdesc);
343 }
344 
345 /*
346  * Compare two TupleDesc structures for logical equality
347  *
348  * Note: we deliberately do not check the attrelid and tdtypmod fields.
349  * This allows typcache.c to use this routine to see if a cached record type
350  * matches a requested type, and is harmless for relcache.c's uses.
351  * We don't compare tdrefcount, either.
352  */
353 bool
355 {
356  int i,
357  j,
358  n;
359 
360  if (tupdesc1->natts != tupdesc2->natts)
361  return false;
362  if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
363  return false;
364  if (tupdesc1->tdhasoid != tupdesc2->tdhasoid)
365  return false;
366 
367  for (i = 0; i < tupdesc1->natts; i++)
368  {
369  Form_pg_attribute attr1 = tupdesc1->attrs[i];
370  Form_pg_attribute attr2 = tupdesc2->attrs[i];
371 
372  /*
373  * We do not need to check every single field here: we can disregard
374  * attrelid and attnum (which were used to place the row in the attrs
375  * array in the first place). It might look like we could dispense
376  * with checking attlen/attbyval/attalign, since these are derived
377  * from atttypid; but in the case of dropped columns we must check
378  * them (since atttypid will be zero for all dropped columns) and in
379  * general it seems safer to check them always.
380  *
381  * attcacheoff must NOT be checked since it's possibly not set in both
382  * copies.
383  */
384  if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
385  return false;
386  if (attr1->atttypid != attr2->atttypid)
387  return false;
388  if (attr1->attstattarget != attr2->attstattarget)
389  return false;
390  if (attr1->attlen != attr2->attlen)
391  return false;
392  if (attr1->attndims != attr2->attndims)
393  return false;
394  if (attr1->atttypmod != attr2->atttypmod)
395  return false;
396  if (attr1->attbyval != attr2->attbyval)
397  return false;
398  if (attr1->attstorage != attr2->attstorage)
399  return false;
400  if (attr1->attalign != attr2->attalign)
401  return false;
402  if (attr1->attnotnull != attr2->attnotnull)
403  return false;
404  if (attr1->atthasdef != attr2->atthasdef)
405  return false;
406  if (attr1->attidentity != attr2->attidentity)
407  return false;
408  if (attr1->attisdropped != attr2->attisdropped)
409  return false;
410  if (attr1->attislocal != attr2->attislocal)
411  return false;
412  if (attr1->attinhcount != attr2->attinhcount)
413  return false;
414  if (attr1->attcollation != attr2->attcollation)
415  return false;
416  /* attacl, attoptions and attfdwoptions are not even present... */
417  }
418 
419  if (tupdesc1->constr != NULL)
420  {
421  TupleConstr *constr1 = tupdesc1->constr;
422  TupleConstr *constr2 = tupdesc2->constr;
423 
424  if (constr2 == NULL)
425  return false;
426  if (constr1->has_not_null != constr2->has_not_null)
427  return false;
428  n = constr1->num_defval;
429  if (n != (int) constr2->num_defval)
430  return false;
431  for (i = 0; i < n; i++)
432  {
433  AttrDefault *defval1 = constr1->defval + i;
434  AttrDefault *defval2 = constr2->defval;
435 
436  /*
437  * We can't assume that the items are always read from the system
438  * catalogs in the same order; so use the adnum field to identify
439  * the matching item to compare.
440  */
441  for (j = 0; j < n; defval2++, j++)
442  {
443  if (defval1->adnum == defval2->adnum)
444  break;
445  }
446  if (j >= n)
447  return false;
448  if (strcmp(defval1->adbin, defval2->adbin) != 0)
449  return false;
450  }
451  n = constr1->num_check;
452  if (n != (int) constr2->num_check)
453  return false;
454  for (i = 0; i < n; i++)
455  {
456  ConstrCheck *check1 = constr1->check + i;
457  ConstrCheck *check2 = constr2->check;
458 
459  /*
460  * Similarly, don't assume that the checks are always read in the
461  * same order; match them up by name and contents. (The name
462  * *should* be unique, but...)
463  */
464  for (j = 0; j < n; check2++, j++)
465  {
466  if (strcmp(check1->ccname, check2->ccname) == 0 &&
467  strcmp(check1->ccbin, check2->ccbin) == 0 &&
468  check1->ccvalid == check2->ccvalid &&
469  check1->ccnoinherit == check2->ccnoinherit)
470  break;
471  }
472  if (j >= n)
473  return false;
474  }
475  }
476  else if (tupdesc2->constr != NULL)
477  return false;
478  return true;
479 }
480 
481 /*
482  * TupleDescInitEntry
483  * This function initializes a single attribute structure in
484  * a previously allocated tuple descriptor.
485  *
486  * If attributeName is NULL, the attname field is set to an empty string
487  * (this is for cases where we don't know or need a name for the field).
488  * Also, some callers use this function to change the datatype-related fields
489  * in an existing tupdesc; they pass attributeName = NameStr(att->attname)
490  * to indicate that the attname field shouldn't be modified.
491  *
492  * Note that attcollation is set to the default for the specified datatype.
493  * If a nondefault collation is needed, insert it afterwards using
494  * TupleDescInitEntryCollation.
495  */
496 void
498  AttrNumber attributeNumber,
499  const char *attributeName,
500  Oid oidtypeid,
501  int32 typmod,
502  int attdim)
503 {
504  HeapTuple tuple;
505  Form_pg_type typeForm;
506  Form_pg_attribute att;
507 
508  /*
509  * sanity checks
510  */
511  AssertArg(PointerIsValid(desc));
512  AssertArg(attributeNumber >= 1);
513  AssertArg(attributeNumber <= desc->natts);
514 
515  /*
516  * initialize the attribute fields
517  */
518  att = desc->attrs[attributeNumber - 1];
519 
520  att->attrelid = 0; /* dummy value */
521 
522  /*
523  * Note: attributeName can be NULL, because the planner doesn't always
524  * fill in valid resname values in targetlists, particularly for resjunk
525  * attributes. Also, do nothing if caller wants to re-use the old attname.
526  */
527  if (attributeName == NULL)
528  MemSet(NameStr(att->attname), 0, NAMEDATALEN);
529  else if (attributeName != NameStr(att->attname))
530  namestrcpy(&(att->attname), attributeName);
531 
532  att->attstattarget = -1;
533  att->attcacheoff = -1;
534  att->atttypmod = typmod;
535 
536  att->attnum = attributeNumber;
537  att->attndims = attdim;
538 
539  att->attnotnull = false;
540  att->atthasdef = false;
541  att->attidentity = '\0';
542  att->attisdropped = false;
543  att->attislocal = true;
544  att->attinhcount = 0;
545  /* attacl, attoptions and attfdwoptions are not present in tupledescs */
546 
547  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
548  if (!HeapTupleIsValid(tuple))
549  elog(ERROR, "cache lookup failed for type %u", oidtypeid);
550  typeForm = (Form_pg_type) GETSTRUCT(tuple);
551 
552  att->atttypid = oidtypeid;
553  att->attlen = typeForm->typlen;
554  att->attbyval = typeForm->typbyval;
555  att->attalign = typeForm->typalign;
556  att->attstorage = typeForm->typstorage;
557  att->attcollation = typeForm->typcollation;
558 
559  ReleaseSysCache(tuple);
560 }
561 
562 /*
563  * TupleDescInitBuiltinEntry
564  * Initialize a tuple descriptor without catalog access. Only
565  * a limited range of builtin types are supported.
566  */
567 void
569  AttrNumber attributeNumber,
570  const char *attributeName,
571  Oid oidtypeid,
572  int32 typmod,
573  int attdim)
574 {
575  Form_pg_attribute att;
576 
577  /* sanity checks */
578  AssertArg(PointerIsValid(desc));
579  AssertArg(attributeNumber >= 1);
580  AssertArg(attributeNumber <= desc->natts);
581 
582  /* initialize the attribute fields */
583  att = desc->attrs[attributeNumber - 1];
584  att->attrelid = 0; /* dummy value */
585 
586  /* unlike TupleDescInitEntry, we require an attribute name */
587  Assert(attributeName != NULL);
588  namestrcpy(&(att->attname), attributeName);
589 
590  att->attstattarget = -1;
591  att->attcacheoff = -1;
592  att->atttypmod = typmod;
593 
594  att->attnum = attributeNumber;
595  att->attndims = attdim;
596 
597  att->attnotnull = false;
598  att->atthasdef = false;
599  att->attidentity = '\0';
600  att->attisdropped = false;
601  att->attislocal = true;
602  att->attinhcount = 0;
603  /* attacl, attoptions and attfdwoptions are not present in tupledescs */
604 
605  att->atttypid = oidtypeid;
606 
607  /*
608  * Our goal here is to support just enough types to let basic builtin
609  * commands work without catalog access - e.g. so that we can do certain
610  * things even in processes that are not connected to a database.
611  */
612  switch (oidtypeid)
613  {
614  case TEXTOID:
615  case TEXTARRAYOID:
616  att->attlen = -1;
617  att->attbyval = false;
618  att->attalign = 'i';
619  att->attstorage = 'x';
620  att->attcollation = DEFAULT_COLLATION_OID;
621  break;
622 
623  case BOOLOID:
624  att->attlen = 1;
625  att->attbyval = true;
626  att->attalign = 'c';
627  att->attstorage = 'p';
628  att->attcollation = InvalidOid;
629  break;
630 
631  case INT4OID:
632  att->attlen = 4;
633  att->attbyval = true;
634  att->attalign = 'i';
635  att->attstorage = 'p';
636  att->attcollation = InvalidOid;
637  break;
638 
639  case INT8OID:
640  att->attlen = 8;
641  att->attbyval = FLOAT8PASSBYVAL;
642  att->attalign = 'd';
643  att->attstorage = 'p';
644  att->attcollation = InvalidOid;
645  break;
646  }
647 }
648 
649 /*
650  * TupleDescInitEntryCollation
651  *
652  * Assign a nondefault collation to a previously initialized tuple descriptor
653  * entry.
654  */
655 void
657  AttrNumber attributeNumber,
658  Oid collationid)
659 {
660  /*
661  * sanity checks
662  */
663  AssertArg(PointerIsValid(desc));
664  AssertArg(attributeNumber >= 1);
665  AssertArg(attributeNumber <= desc->natts);
666 
667  desc->attrs[attributeNumber - 1]->attcollation = collationid;
668 }
669 
670 
671 /*
672  * BuildDescForRelation
673  *
674  * Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
675  *
676  * Note: the default assumption is no OIDs; caller may modify the returned
677  * TupleDesc if it wants OIDs. Also, tdtypeid will need to be filled in
678  * later on.
679  */
680 TupleDesc
682 {
683  int natts;
684  AttrNumber attnum;
685  ListCell *l;
686  TupleDesc desc;
687  bool has_not_null;
688  char *attname;
689  Oid atttypid;
690  int32 atttypmod;
691  Oid attcollation;
692  int attdim;
693 
694  /*
695  * allocate a new tuple descriptor
696  */
697  natts = list_length(schema);
698  desc = CreateTemplateTupleDesc(natts, false);
699  has_not_null = false;
700 
701  attnum = 0;
702 
703  foreach(l, schema)
704  {
705  ColumnDef *entry = lfirst(l);
706  AclResult aclresult;
707 
708  /*
709  * for each entry in the list, get the name and type information from
710  * the list and have TupleDescInitEntry fill in the attribute
711  * information we need.
712  */
713  attnum++;
714 
715  attname = entry->colname;
716  typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
717 
718  aclresult = pg_type_aclcheck(atttypid, GetUserId(), ACL_USAGE);
719  if (aclresult != ACLCHECK_OK)
720  aclcheck_error_type(aclresult, atttypid);
721 
722  attcollation = GetColumnDefCollation(NULL, entry, atttypid);
723  attdim = list_length(entry->typeName->arrayBounds);
724 
725  if (entry->typeName->setof)
726  ereport(ERROR,
727  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
728  errmsg("column \"%s\" cannot be declared SETOF",
729  attname)));
730 
731  TupleDescInitEntry(desc, attnum, attname,
732  atttypid, atttypmod, attdim);
733 
734  /* Override TupleDescInitEntry's settings as requested */
735  TupleDescInitEntryCollation(desc, attnum, attcollation);
736  if (entry->storage)
737  desc->attrs[attnum - 1]->attstorage = entry->storage;
738 
739  /* Fill in additional stuff not handled by TupleDescInitEntry */
740  desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
741  has_not_null |= entry->is_not_null;
742  desc->attrs[attnum - 1]->attislocal = entry->is_local;
743  desc->attrs[attnum - 1]->attinhcount = entry->inhcount;
744  }
745 
746  if (has_not_null)
747  {
749 
750  constr->has_not_null = true;
751  constr->defval = NULL;
752  constr->num_defval = 0;
753  constr->check = NULL;
754  constr->num_check = 0;
755  desc->constr = constr;
756  }
757  else
758  {
759  desc->constr = NULL;
760  }
761 
762  return desc;
763 }
764 
765 /*
766  * BuildDescFromLists
767  *
768  * Build a TupleDesc given lists of column names (as String nodes),
769  * column type OIDs, typmods, and collation OIDs.
770  *
771  * No constraints are generated.
772  *
773  * This is essentially a cut-down version of BuildDescForRelation for use
774  * with functions returning RECORD.
775  */
776 TupleDesc
777 BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
778 {
779  int natts;
780  AttrNumber attnum;
781  ListCell *l1;
782  ListCell *l2;
783  ListCell *l3;
784  ListCell *l4;
785  TupleDesc desc;
786 
787  natts = list_length(names);
788  Assert(natts == list_length(types));
789  Assert(natts == list_length(typmods));
790  Assert(natts == list_length(collations));
791 
792  /*
793  * allocate a new tuple descriptor
794  */
795  desc = CreateTemplateTupleDesc(natts, false);
796 
797  attnum = 0;
798 
799  l2 = list_head(types);
800  l3 = list_head(typmods);
801  l4 = list_head(collations);
802  foreach(l1, names)
803  {
804  char *attname = strVal(lfirst(l1));
805  Oid atttypid;
806  int32 atttypmod;
807  Oid attcollation;
808 
809  atttypid = lfirst_oid(l2);
810  l2 = lnext(l2);
811  atttypmod = lfirst_int(l3);
812  l3 = lnext(l3);
813  attcollation = lfirst_oid(l4);
814  l4 = lnext(l4);
815 
816  attnum++;
817 
818  TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
819  TupleDescInitEntryCollation(desc, attnum, attcollation);
820  }
821 
822  return desc;
823 }
void IncrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:318
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
Oid tdtypeid
Definition: tupdesc.h:77
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
char * ccname
Definition: tupdesc.h:30
bool tdhasoid
Definition: tupdesc.h:79
TupleDesc BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
Definition: tupdesc.c:777
char storage
Definition: parsenodes.h:646
struct typedefs * types
Definition: ecpg.c:29
bool is_local
Definition: parsenodes.h:642
bool ccnoinherit
Definition: tupdesc.h:33
Oid GetUserId(void)
Definition: miscinit.c:284
#define TEXTOID
Definition: pg_type.h:324
ConstrCheck * check
Definition: tupdesc.h:40
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
char * pstrdup(const char *in)
Definition: mcxt.c:1077
char * ccbin
Definition: tupdesc.h:31
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define INT4OID
Definition: pg_type.h:316
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:857
bool is_not_null
Definition: parsenodes.h:643
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
TupleDesc CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
Definition: tupdesc.c:112
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:216
int natts
Definition: tupdesc.h:73
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
void ResourceOwnerRememberTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: resowner.c:1108
int32 tdtypmod
Definition: tupdesc.h:78
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
signed int int32
Definition: c.h:256
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:950
AttrDefault * defval
Definition: tupdesc.h:39
#define TEXTARRAYOID
Definition: pg_type.h:470
void TupleDescInitBuiltinEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:568
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:107
void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno)
Definition: tupdesc.c:230
bool setof
Definition: parsenodes.h:210
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:656
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
AttrNumber adnum
Definition: tupdesc.h:24
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ACL_USAGE
Definition: parsenodes.h:80
char * adbin
Definition: tupdesc.h:25
#define RECORDOID
Definition: pg_type.h:680
void ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
Definition: resowner.c:1117
TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc)
Definition: tupdesc.c:168
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:497
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:179
#define lnext(lc)
Definition: pg_list.h:105
void ResourceOwnerEnlargeTupleDescs(ResourceOwner owner)
Definition: resowner.c:1097
#define ereport(elevel, rest)
Definition: elog.h:122
#define AssertArg(condition)
Definition: c.h:677
bool has_not_null
Definition: tupdesc.h:43
Oid GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
Definition: parse_type.c:521
void * palloc0(Size size)
Definition: mcxt.c:878
AclResult
Definition: acl.h:170
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition: parse_type.c:293
#define InvalidOid
Definition: postgres_ext.h:36
uint16 num_defval
Definition: tupdesc.h:41
struct tupleDesc * TupleDesc
#define INT8OID
Definition: pg_type.h:304
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
void DecrTupleDescRefCount(TupleDesc tupdesc)
Definition: tupdesc.c:336
TupleConstr * constr
Definition: tupdesc.h:76
static int list_length(const List *l)
Definition: pg_list.h:89
#define MAXALIGN(LEN)
Definition: c.h:588
TypeName * typeName
Definition: parsenodes.h:640
#define BOOLOID
Definition: pg_type.h:288
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:41
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:268
List * arrayBounds
Definition: parsenodes.h:214
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool ccvalid
Definition: tupdesc.h:32
int tdrefcount
Definition: tupdesc.h:80
int i
int inhcount
Definition: parsenodes.h:641
#define NameStr(name)
Definition: c.h:499
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:354
char * colname
Definition: parsenodes.h:639
uint16 num_check
Definition: tupdesc.h:42
#define elog
Definition: elog.h:219
TupleDesc BuildDescForRelation(List *schema)
Definition: tupdesc.c:681
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4534
Definition: pg_list.h:45
#define PointerIsValid(pointer)
Definition: c.h:526
int16 AttrNumber
Definition: attnum.h:21
#define lfirst_oid(lc)
Definition: pg_list.h:108