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