OSDN Git Service

66403a1b6b6043d199d9b5c8203141494353793f
[pg-rex/syncrep.git] / src / backend / access / common / tupdesc.c
1 /*-------------------------------------------------------------------------
2  *
3  * tupdesc.c
4  *        POSTGRES tuple descriptor support code
5  *
6  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.105 2004/08/29 04:12:17 momjian Exp $
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 "funcapi.h"
23 #include "access/heapam.h"
24 #include "catalog/namespace.h"
25 #include "catalog/pg_type.h"
26 #include "nodes/parsenodes.h"
27 #include "parser/parse_type.h"
28 #include "utils/builtins.h"
29 #include "utils/lsyscache.h"
30 #include "utils/syscache.h"
31 #include "utils/typcache.h"
32
33
34 /* ----------------------------------------------------------------
35  *              CreateTemplateTupleDesc
36  *
37  *              This function allocates and zeros a tuple descriptor structure.
38  *
39  * Tuple type ID information is initially set for an anonymous record type;
40  * caller can overwrite this if needed.
41  * ----------------------------------------------------------------
42  */
43 TupleDesc
44 CreateTemplateTupleDesc(int natts, bool hasoid)
45 {
46         TupleDesc       desc;
47
48         /*
49          * sanity checks
50          */
51         AssertArg(natts >= 0);
52
53         /*
54          * Allocate enough memory for the tuple descriptor, and zero the
55          * attrs[] array since TupleDescInitEntry assumes that the array
56          * is filled with NULL pointers.
57          */
58         desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
59
60         if (natts > 0)
61                 desc->attrs = (Form_pg_attribute *)
62                         palloc0(natts * sizeof(Form_pg_attribute));
63         else
64                 desc->attrs = NULL;
65
66         /*
67          * Initialize other fields of the tupdesc.
68          */
69         desc->natts = natts;
70         desc->constr = NULL;
71         desc->tdtypeid = RECORDOID;
72         desc->tdtypmod = -1;
73         desc->tdhasoid = hasoid;
74
75         return desc;
76 }
77
78 /* ----------------------------------------------------------------
79  *              CreateTupleDesc
80  *
81  *              This function allocates a new TupleDesc pointing to a given
82  *              Form_pg_attribute array
83  *
84  * Tuple type ID information is initially set for an anonymous record type;
85  * caller can overwrite this if needed.
86  * ----------------------------------------------------------------
87  */
88 TupleDesc
89 CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
90 {
91         TupleDesc       desc;
92
93         /*
94          * sanity checks
95          */
96         AssertArg(natts >= 0);
97
98         desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
99         desc->attrs = attrs;
100         desc->natts = natts;
101         desc->constr = NULL;
102         desc->tdtypeid = RECORDOID;
103         desc->tdtypmod = -1;
104         desc->tdhasoid = hasoid;
105
106         return desc;
107 }
108
109 /* ----------------------------------------------------------------
110  *              CreateTupleDescCopy
111  *
112  *              This function creates a new TupleDesc by copying from an existing
113  *              TupleDesc
114  *
115  *              !!! Constraints and defaults are not copied !!!
116  * ----------------------------------------------------------------
117  */
118 TupleDesc
119 CreateTupleDescCopy(TupleDesc tupdesc)
120 {
121         TupleDesc       desc;
122         int                     i;
123
124         desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
125         desc->natts = tupdesc->natts;
126         if (desc->natts > 0)
127         {
128                 desc->attrs = (Form_pg_attribute *)
129                         palloc(desc->natts * sizeof(Form_pg_attribute));
130                 for (i = 0; i < desc->natts; i++)
131                 {
132                         desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
133                         memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
134                         desc->attrs[i]->attnotnull = false;
135                         desc->attrs[i]->atthasdef = false;
136                 }
137         }
138         else
139                 desc->attrs = NULL;
140
141         desc->constr = NULL;
142
143         desc->tdtypeid = tupdesc->tdtypeid;
144         desc->tdtypmod = tupdesc->tdtypmod;
145         desc->tdhasoid = tupdesc->tdhasoid;
146
147         return desc;
148 }
149
150 /* ----------------------------------------------------------------
151  *              CreateTupleDescCopyConstr
152  *
153  *              This function creates a new TupleDesc by copying from an existing
154  *              TupleDesc (including its constraints and defaults)
155  * ----------------------------------------------------------------
156  */
157 TupleDesc
158 CreateTupleDescCopyConstr(TupleDesc tupdesc)
159 {
160         TupleDesc       desc;
161         TupleConstr *constr = tupdesc->constr;
162         int                     i;
163
164         desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
165         desc->natts = tupdesc->natts;
166         if (desc->natts > 0)
167         {
168                 desc->attrs = (Form_pg_attribute *)
169                         palloc(desc->natts * sizeof(Form_pg_attribute));
170                 for (i = 0; i < desc->natts; i++)
171                 {
172                         desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
173                         memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
174                 }
175         }
176         else
177                 desc->attrs = NULL;
178
179         if (constr)
180         {
181                 TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
182
183                 cpy->has_not_null = constr->has_not_null;
184
185                 if ((cpy->num_defval = constr->num_defval) > 0)
186                 {
187                         cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
188                         memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
189                         for (i = cpy->num_defval - 1; i >= 0; i--)
190                         {
191                                 if (constr->defval[i].adbin)
192                                         cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
193                         }
194                 }
195
196                 if ((cpy->num_check = constr->num_check) > 0)
197                 {
198                         cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
199                         memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
200                         for (i = cpy->num_check - 1; i >= 0; i--)
201                         {
202                                 if (constr->check[i].ccname)
203                                         cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
204                                 if (constr->check[i].ccbin)
205                                         cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
206                         }
207                 }
208
209                 desc->constr = cpy;
210         }
211         else
212                 desc->constr = NULL;
213
214         desc->tdtypeid = tupdesc->tdtypeid;
215         desc->tdtypmod = tupdesc->tdtypmod;
216         desc->tdhasoid = tupdesc->tdhasoid;
217
218         return desc;
219 }
220
221 /*
222  * Free a TupleDesc including all substructure
223  */
224 void
225 FreeTupleDesc(TupleDesc tupdesc)
226 {
227         int                     i;
228
229         for (i = 0; i < tupdesc->natts; i++)
230                 pfree(tupdesc->attrs[i]);
231         if (tupdesc->attrs)
232                 pfree(tupdesc->attrs);
233         if (tupdesc->constr)
234         {
235                 if (tupdesc->constr->num_defval > 0)
236                 {
237                         AttrDefault *attrdef = tupdesc->constr->defval;
238
239                         for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
240                         {
241                                 if (attrdef[i].adbin)
242                                         pfree(attrdef[i].adbin);
243                         }
244                         pfree(attrdef);
245                 }
246                 if (tupdesc->constr->num_check > 0)
247                 {
248                         ConstrCheck *check = tupdesc->constr->check;
249
250                         for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
251                         {
252                                 if (check[i].ccname)
253                                         pfree(check[i].ccname);
254                                 if (check[i].ccbin)
255                                         pfree(check[i].ccbin);
256                         }
257                         pfree(check);
258                 }
259                 pfree(tupdesc->constr);
260         }
261
262         pfree(tupdesc);
263 }
264
265 /*
266  * Compare two TupleDesc structures for logical equality
267  *
268  * Note: we deliberately do not check the attrelid and tdtypmod fields.
269  * This allows typcache.c to use this routine to see if a cached record type
270  * matches a requested type, and is harmless for relcache.c's uses.
271  */
272 bool
273 equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
274 {
275         int                     i,
276                                 j,
277                                 n;
278
279         if (tupdesc1->natts != tupdesc2->natts)
280                 return false;
281         if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
282                 return false;
283         if (tupdesc1->tdhasoid != tupdesc2->tdhasoid)
284                 return false;
285
286         for (i = 0; i < tupdesc1->natts; i++)
287         {
288                 Form_pg_attribute attr1 = tupdesc1->attrs[i];
289                 Form_pg_attribute attr2 = tupdesc2->attrs[i];
290
291                 /*
292                  * We do not need to check every single field here: we can
293                  * disregard attrelid, attnum (it was used to place the row in the
294                  * attrs array) and everything derived from the column datatype.
295                  * Also, attcacheoff must NOT be checked since it's possibly not
296                  * set in both copies.
297                  */
298                 if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
299                         return false;
300                 if (attr1->atttypid != attr2->atttypid)
301                         return false;
302                 if (attr1->attstattarget != attr2->attstattarget)
303                         return false;
304                 if (attr1->attndims != attr2->attndims)
305                         return false;
306                 if (attr1->atttypmod != attr2->atttypmod)
307                         return false;
308                 if (attr1->attstorage != attr2->attstorage)
309                         return false;
310                 if (attr1->attnotnull != attr2->attnotnull)
311                         return false;
312                 if (attr1->atthasdef != attr2->atthasdef)
313                         return false;
314                 if (attr1->attisdropped != attr2->attisdropped)
315                         return false;
316                 if (attr1->attislocal != attr2->attislocal)
317                         return false;
318                 if (attr1->attinhcount != attr2->attinhcount)
319                         return false;
320         }
321
322         if (tupdesc1->constr != NULL)
323         {
324                 TupleConstr *constr1 = tupdesc1->constr;
325                 TupleConstr *constr2 = tupdesc2->constr;
326
327                 if (constr2 == NULL)
328                         return false;
329                 if (constr1->has_not_null != constr2->has_not_null)
330                         return false;
331                 n = constr1->num_defval;
332                 if (n != (int) constr2->num_defval)
333                         return false;
334                 for (i = 0; i < n; i++)
335                 {
336                         AttrDefault *defval1 = constr1->defval + i;
337                         AttrDefault *defval2 = constr2->defval;
338
339                         /*
340                          * We can't assume that the items are always read from the
341                          * system catalogs in the same order; so use the adnum field
342                          * to identify the matching item to compare.
343                          */
344                         for (j = 0; j < n; defval2++, j++)
345                         {
346                                 if (defval1->adnum == defval2->adnum)
347                                         break;
348                         }
349                         if (j >= n)
350                                 return false;
351                         if (strcmp(defval1->adbin, defval2->adbin) != 0)
352                                 return false;
353                 }
354                 n = constr1->num_check;
355                 if (n != (int) constr2->num_check)
356                         return false;
357                 for (i = 0; i < n; i++)
358                 {
359                         ConstrCheck *check1 = constr1->check + i;
360                         ConstrCheck *check2 = constr2->check;
361
362                         /*
363                          * Similarly, don't assume that the checks are always read in
364                          * the same order; match them up by name and contents. (The
365                          * name *should* be unique, but...)
366                          */
367                         for (j = 0; j < n; check2++, j++)
368                         {
369                                 if (strcmp(check1->ccname, check2->ccname) == 0 &&
370                                         strcmp(check1->ccbin, check2->ccbin) == 0)
371                                         break;
372                         }
373                         if (j >= n)
374                                 return false;
375                 }
376         }
377         else if (tupdesc2->constr != NULL)
378                 return false;
379         return true;
380 }
381
382 /* ----------------------------------------------------------------
383  *              TupleDescInitEntry
384  *
385  *              This function initializes a single attribute structure in
386  *              a preallocated tuple descriptor.
387  * ----------------------------------------------------------------
388  */
389 void
390 TupleDescInitEntry(TupleDesc desc,
391                                    AttrNumber attributeNumber,
392                                    const char *attributeName,
393                                    Oid oidtypeid,
394                                    int32 typmod,
395                                    int attdim)
396 {
397         HeapTuple       tuple;
398         Form_pg_type typeForm;
399         Form_pg_attribute att;
400
401         /*
402          * sanity checks
403          */
404         AssertArg(PointerIsValid(desc));
405         AssertArg(attributeNumber >= 1);
406         AssertArg(attributeNumber <= desc->natts);
407         AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
408
409         /*
410          * allocate storage for this attribute
411          */
412
413         att = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
414         desc->attrs[attributeNumber - 1] = att;
415
416         /*
417          * initialize the attribute fields
418          */
419         att->attrelid = 0;                      /* dummy value */
420
421         /*
422          * Note: attributeName can be NULL, because the planner doesn't always
423          * fill in valid resname values in targetlists, particularly for resjunk
424          * attributes.
425          */
426         if (attributeName != NULL)
427                 namestrcpy(&(att->attname), attributeName);
428         else
429                 MemSet(NameStr(att->attname), 0, NAMEDATALEN);
430
431         att->attstattarget = -1;
432         att->attcacheoff = -1;
433         att->atttypmod = typmod;
434
435         att->attnum = attributeNumber;
436         att->attndims = attdim;
437
438         att->attnotnull = false;
439         att->atthasdef = false;
440         att->attisdropped = false;
441         att->attislocal = true;
442         att->attinhcount = 0;
443
444         tuple = SearchSysCache(TYPEOID,
445                                                    ObjectIdGetDatum(oidtypeid),
446                                                    0, 0, 0);
447         if (!HeapTupleIsValid(tuple))
448                 elog(ERROR, "cache lookup failed for type %u", oidtypeid);
449         typeForm = (Form_pg_type) GETSTRUCT(tuple);
450
451         att->atttypid = oidtypeid;
452         att->attlen = typeForm->typlen;
453         att->attbyval = typeForm->typbyval;
454         att->attalign = typeForm->typalign;
455         att->attstorage = typeForm->typstorage;
456
457         ReleaseSysCache(tuple);
458 }
459
460
461 /*
462  * BuildDescForRelation
463  *
464  * Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
465  *
466  * Note: the default assumption is no OIDs; caller may modify the returned
467  * TupleDesc if it wants OIDs.  Also, tdtypeid will need to be filled in
468  * later on.
469  */
470 TupleDesc
471 BuildDescForRelation(List *schema)
472 {
473         int                     natts;
474         AttrNumber      attnum;
475         ListCell   *l;
476         TupleDesc       desc;
477         AttrDefault *attrdef = NULL;
478         TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
479         char       *attname;
480         int32           atttypmod;
481         int                     attdim;
482         int                     ndef = 0;
483
484         /*
485          * allocate a new tuple descriptor
486          */
487         natts = list_length(schema);
488         desc = CreateTemplateTupleDesc(natts, false);
489         constr->has_not_null = false;
490
491         attnum = 0;
492
493         foreach(l, schema)
494         {
495                 ColumnDef  *entry = lfirst(l);
496
497                 /*
498                  * for each entry in the list, get the name and type information
499                  * from the list and have TupleDescInitEntry fill in the attribute
500                  * information we need.
501                  */
502                 attnum++;
503
504                 attname = entry->colname;
505                 atttypmod = entry->typename->typmod;
506                 attdim = list_length(entry->typename->arrayBounds);
507
508                 if (entry->typename->setof)
509                         ereport(ERROR,
510                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
511                                          errmsg("column \"%s\" cannot be declared SETOF",
512                                                         attname)));
513
514                 TupleDescInitEntry(desc, attnum, attname,
515                                                    typenameTypeId(entry->typename),
516                                                    atttypmod, attdim);
517
518                 /* Fill in additional stuff not handled by TupleDescInitEntry */
519                 if (entry->is_not_null)
520                         constr->has_not_null = true;
521                 desc->attrs[attnum - 1]->attnotnull = entry->is_not_null;
522
523                 /*
524                  * Note we copy only pre-cooked default expressions. Digestion of
525                  * raw ones is someone else's problem.
526                  */
527                 if (entry->cooked_default != NULL)
528                 {
529                         if (attrdef == NULL)
530                                 attrdef = (AttrDefault *) palloc(natts * sizeof(AttrDefault));
531                         attrdef[ndef].adnum = attnum;
532                         attrdef[ndef].adbin = pstrdup(entry->cooked_default);
533                         ndef++;
534                         desc->attrs[attnum - 1]->atthasdef = true;
535                 }
536
537                 desc->attrs[attnum - 1]->attislocal = entry->is_local;
538                 desc->attrs[attnum - 1]->attinhcount = entry->inhcount;
539         }
540
541         if (constr->has_not_null || ndef > 0)
542         {
543                 desc->constr = constr;
544
545                 if (ndef > 0)                   /* DEFAULTs */
546                 {
547                         if (ndef < natts)
548                                 constr->defval = (AttrDefault *)
549                                         repalloc(attrdef, ndef * sizeof(AttrDefault));
550                         else
551                                 constr->defval = attrdef;
552                         constr->num_defval = ndef;
553                 }
554                 else
555                 {
556                         constr->defval = NULL;
557                         constr->num_defval = 0;
558                 }
559                 constr->check = NULL;
560                 constr->num_check = 0;
561         }
562         else
563         {
564                 pfree(constr);
565                 desc->constr = NULL;
566         }
567
568         return desc;
569 }
570
571
572 /*
573  * RelationNameGetTupleDesc
574  *
575  * Given a (possibly qualified) relation name, build a TupleDesc.
576  */
577 TupleDesc
578 RelationNameGetTupleDesc(const char *relname)
579 {
580         RangeVar   *relvar;
581         Relation        rel;
582         TupleDesc       tupdesc;
583         List       *relname_list;
584
585         /* Open relation and copy the tuple description */
586         relname_list = stringToQualifiedNameList(relname, "RelationNameGetTupleDesc");
587         relvar = makeRangeVarFromNameList(relname_list);
588         rel = relation_openrv(relvar, AccessShareLock);
589         tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
590         relation_close(rel, AccessShareLock);
591
592         return tupdesc;
593 }
594
595 /*
596  * TypeGetTupleDesc
597  *
598  * Given a type Oid, build a TupleDesc.
599  *
600  * If the type is composite, *and* a colaliases List is provided, *and*
601  * the List is of natts length, use the aliases instead of the relation
602  * attnames.  (NB: this usage is deprecated since it may result in
603  * creation of unnecessary transient record types.)
604  *
605  * If the type is a base type, a single item alias List is required.
606  */
607 TupleDesc
608 TypeGetTupleDesc(Oid typeoid, List *colaliases)
609 {
610         char            functyptype = get_typtype(typeoid);
611         TupleDesc       tupdesc = NULL;
612
613         /*
614          * Build a suitable tupledesc representing the output rows
615          */
616         if (functyptype == 'c')
617         {
618                 /* Composite data type, e.g. a table's row type */
619                 tupdesc = CreateTupleDescCopy(lookup_rowtype_tupdesc(typeoid, -1));
620
621                 if (colaliases != NIL)
622                 {
623                         int                     natts = tupdesc->natts;
624                         int                     varattno;
625
626                         /* does the list length match the number of attributes? */
627                         if (list_length(colaliases) != natts)
628                                 ereport(ERROR,
629                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
630                                                  errmsg("number of aliases does not match number of columns")));
631
632                         /* OK, use the aliases instead */
633                         for (varattno = 0; varattno < natts; varattno++)
634                         {
635                                 char       *label = strVal(list_nth(colaliases, varattno));
636
637                                 if (label != NULL)
638                                         namestrcpy(&(tupdesc->attrs[varattno]->attname), label);
639                         }
640
641                         /* The tuple type is now an anonymous record type */
642                         tupdesc->tdtypeid = RECORDOID;
643                         tupdesc->tdtypmod = -1;
644                 }
645         }
646         else if (functyptype == 'b' || functyptype == 'd')
647         {
648                 /* Must be a base data type, i.e. scalar */
649                 char       *attname;
650
651                 /* the alias list is required for base types */
652                 if (colaliases == NIL)
653                         ereport(ERROR,
654                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
655                                          errmsg("no column alias was provided")));
656
657                 /* the alias list length must be 1 */
658                 if (list_length(colaliases) != 1)
659                         ereport(ERROR,
660                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
661                                          errmsg("number of aliases does not match number of columns")));
662
663                 /* OK, get the column alias */
664                 attname = strVal(linitial(colaliases));
665
666                 tupdesc = CreateTemplateTupleDesc(1, false);
667                 TupleDescInitEntry(tupdesc,
668                                                    (AttrNumber) 1,
669                                                    attname,
670                                                    typeoid,
671                                                    -1,
672                                                    0);
673         }
674         else if (typeoid == RECORDOID)
675         {
676                 /* XXX can't support this because typmod wasn't passed in ... */
677                 ereport(ERROR,
678                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
679                                  errmsg("could not determine row description for function returning record")));
680         }
681         else
682         {
683                 /* crummy error message, but parser should have caught this */
684                 elog(ERROR, "function in FROM has unsupported return type");
685         }
686
687         return tupdesc;
688 }