LCOV - code coverage report
Current view: top level - src/backend/access/common - tupdesc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 11beta1 Lines: 339 359 94.4 %
Date: 2018-06-18 00:19:56 Functions: 16 16 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * tupdesc.c
       4             :  *    POSTGRES tuple descriptor support code
       5             :  *
       6             :  * Portions Copyright (c) 1996-2018, 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/hash.h"
      23             : #include "access/htup_details.h"
      24             : #include "access/tupdesc_details.h"
      25             : #include "catalog/pg_collation.h"
      26             : #include "catalog/pg_type.h"
      27             : #include "miscadmin.h"
      28             : #include "parser/parse_type.h"
      29             : #include "utils/acl.h"
      30             : #include "utils/builtins.h"
      31             : #include "utils/datum.h"
      32             : #include "utils/hashutils.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     5024674 : CreateTemplateTupleDesc(int natts, bool hasoid)
      46             : {
      47             :     TupleDesc   desc;
      48             : 
      49             :     /*
      50             :      * sanity checks
      51             :      */
      52             :     AssertArg(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     5024674 :     desc = (TupleDesc) palloc(offsetof(struct tupleDesc, attrs) +
      67     5024674 :                               natts * sizeof(FormData_pg_attribute));
      68             : 
      69             :     /*
      70             :      * Initialize other fields of the tupdesc.
      71             :      */
      72     5024674 :     desc->natts = natts;
      73     5024674 :     desc->constr = NULL;
      74     5024674 :     desc->tdtypeid = RECORDOID;
      75     5024674 :     desc->tdtypmod = -1;
      76     5024674 :     desc->tdhasoid = hasoid;
      77     5024674 :     desc->tdrefcount = -1;       /* assume not reference-counted */
      78             : 
      79     5024674 :     return desc;
      80             : }
      81             : 
      82             : /*
      83             :  * CreateTupleDesc
      84             :  *      This function allocates a new TupleDesc by copying a given
      85             :  *      Form_pg_attribute array.
      86             :  *
      87             :  * Tuple type ID information is initially set for an anonymous record type;
      88             :  * caller can overwrite this if needed.
      89             :  */
      90             : TupleDesc
      91     1692576 : CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
      92             : {
      93             :     TupleDesc   desc;
      94             :     int         i;
      95             : 
      96     1692576 :     desc = CreateTemplateTupleDesc(natts, hasoid);
      97             : 
      98    34570656 :     for (i = 0; i < natts; ++i)
      99    32878080 :         memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
     100             : 
     101     1692576 :     return desc;
     102             : }
     103             : 
     104             : /*
     105             :  * CreateTupleDescCopy
     106             :  *      This function creates a new TupleDesc by copying from an existing
     107             :  *      TupleDesc.
     108             :  *
     109             :  * !!! Constraints and defaults are not copied !!!
     110             :  */
     111             : TupleDesc
     112      259644 : CreateTupleDescCopy(TupleDesc tupdesc)
     113             : {
     114             :     TupleDesc   desc;
     115             :     int         i;
     116             : 
     117      259644 :     desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
     118             : 
     119             :     /* Flat-copy the attribute array */
     120      519288 :     memcpy(TupleDescAttr(desc, 0),
     121      259644 :            TupleDescAttr(tupdesc, 0),
     122      259644 :            desc->natts * sizeof(FormData_pg_attribute));
     123             : 
     124             :     /*
     125             :      * Since we're not copying constraints and defaults, clear fields
     126             :      * associated with them.
     127             :      */
     128     1254352 :     for (i = 0; i < desc->natts; i++)
     129             :     {
     130      994708 :         Form_pg_attribute att = TupleDescAttr(desc, i);
     131             : 
     132      994708 :         att->attnotnull = false;
     133      994708 :         att->atthasdef = false;
     134      994708 :         att->atthasmissing = false;
     135      994708 :         att->attidentity = '\0';
     136             :     }
     137             : 
     138             :     /* We can copy the tuple type identification, too */
     139      259644 :     desc->tdtypeid = tupdesc->tdtypeid;
     140      259644 :     desc->tdtypmod = tupdesc->tdtypmod;
     141             : 
     142      259644 :     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      228284 : CreateTupleDescCopyConstr(TupleDesc tupdesc)
     152             : {
     153             :     TupleDesc   desc;
     154      228284 :     TupleConstr *constr = tupdesc->constr;
     155             :     int         i;
     156             : 
     157      228284 :     desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
     158             : 
     159             :     /* Flat-copy the attribute array */
     160      456568 :     memcpy(TupleDescAttr(desc, 0),
     161      228284 :            TupleDescAttr(tupdesc, 0),
     162      228284 :            desc->natts * sizeof(FormData_pg_attribute));
     163             : 
     164             :     /* Copy the TupleConstr data structure, if any */
     165      228284 :     if (constr)
     166             :     {
     167      203054 :         TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
     168             : 
     169      203054 :         cpy->has_not_null = constr->has_not_null;
     170             : 
     171      203054 :         if ((cpy->num_defval = constr->num_defval) > 0)
     172             :         {
     173        1156 :             cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
     174        1156 :             memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
     175        2938 :             for (i = cpy->num_defval - 1; i >= 0; i--)
     176             :             {
     177        1782 :                 if (constr->defval[i].adbin)
     178        1782 :                     cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
     179             :             }
     180             :         }
     181             : 
     182      203054 :         if (constr->missing)
     183             :         {
     184         536 :             cpy->missing = (AttrMissing *) palloc(tupdesc->natts * sizeof(AttrMissing));
     185         536 :             memcpy(cpy->missing, constr->missing, tupdesc->natts * sizeof(AttrMissing));
     186        5220 :             for (i = tupdesc->natts - 1; i >= 0; i--)
     187             :             {
     188        4684 :                 if (constr->missing[i].ammissingPresent)
     189             :                 {
     190         860 :                     Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
     191             : 
     192        2580 :                     cpy->missing[i].ammissing = datumCopy(constr->missing[i].ammissing,
     193         860 :                                                           attr->attbyval,
     194         860 :                                                           attr->attlen);
     195             :                 }
     196             :             }
     197             :         }
     198             : 
     199      203054 :         if ((cpy->num_check = constr->num_check) > 0)
     200             :         {
     201         942 :             cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
     202         942 :             memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
     203        2240 :             for (i = cpy->num_check - 1; i >= 0; i--)
     204             :             {
     205        1298 :                 if (constr->check[i].ccname)
     206        1298 :                     cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
     207        1298 :                 if (constr->check[i].ccbin)
     208        1298 :                     cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
     209        1298 :                 cpy->check[i].ccvalid = constr->check[i].ccvalid;
     210        1298 :                 cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
     211             :             }
     212             :         }
     213             : 
     214      203054 :         desc->constr = cpy;
     215             :     }
     216             : 
     217             :     /* We can copy the tuple type identification, too */
     218      228284 :     desc->tdtypeid = tupdesc->tdtypeid;
     219      228284 :     desc->tdtypmod = tupdesc->tdtypmod;
     220             : 
     221      228284 :     return desc;
     222             : }
     223             : 
     224             : /*
     225             :  * TupleDescCopy
     226             :  *      Copy a tuple descriptor into caller-supplied memory.
     227             :  *      The memory may be shared memory mapped at any address, and must
     228             :  *      be sufficient to hold TupleDescSize(src) bytes.
     229             :  *
     230             :  * !!! Constraints and defaults are not copied !!!
     231             :  */
     232             : void
     233        1632 : TupleDescCopy(TupleDesc dst, TupleDesc src)
     234             : {
     235             :     int         i;
     236             : 
     237             :     /* Flat-copy the header and attribute array */
     238        1632 :     memcpy(dst, src, TupleDescSize(src));
     239             : 
     240             :     /*
     241             :      * Since we're not copying constraints and defaults, clear fields
     242             :      * associated with them.
     243             :      */
     244        5040 :     for (i = 0; i < dst->natts; i++)
     245             :     {
     246        3408 :         Form_pg_attribute att = TupleDescAttr(dst, i);
     247             : 
     248        3408 :         att->attnotnull = false;
     249        3408 :         att->atthasdef = false;
     250        3408 :         att->atthasmissing = false;
     251        3408 :         att->attidentity = '\0';
     252             :     }
     253        1632 :     dst->constr = NULL;
     254             : 
     255             :     /*
     256             :      * Also, assume the destination is not to be ref-counted.  (Copying the
     257             :      * source's refcount would be wrong in any case.)
     258             :      */
     259        1632 :     dst->tdrefcount = -1;
     260        1632 : }
     261             : 
     262             : /*
     263             :  * TupleDescCopyEntry
     264             :  *      This function copies a single attribute structure from one tuple
     265             :  *      descriptor to another.
     266             :  *
     267             :  * !!! Constraints and defaults are not copied !!!
     268             :  */
     269             : void
     270       13766 : TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
     271             :                    TupleDesc src, AttrNumber srcAttno)
     272             : {
     273       13766 :     Form_pg_attribute dstAtt = TupleDescAttr(dst, dstAttno - 1);
     274       13766 :     Form_pg_attribute srcAtt = TupleDescAttr(src, srcAttno - 1);
     275             : 
     276             :     /*
     277             :      * sanity checks
     278             :      */
     279             :     AssertArg(PointerIsValid(src));
     280             :     AssertArg(PointerIsValid(dst));
     281             :     AssertArg(srcAttno >= 1);
     282             :     AssertArg(srcAttno <= src->natts);
     283             :     AssertArg(dstAttno >= 1);
     284             :     AssertArg(dstAttno <= dst->natts);
     285             : 
     286       13766 :     memcpy(dstAtt, srcAtt, ATTRIBUTE_FIXED_PART_SIZE);
     287             : 
     288             :     /*
     289             :      * Aside from updating the attno, we'd better reset attcacheoff.
     290             :      *
     291             :      * XXX Actually, to be entirely safe we'd need to reset the attcacheoff of
     292             :      * all following columns in dst as well.  Current usage scenarios don't
     293             :      * require that though, because all following columns will get initialized
     294             :      * by other uses of this function or TupleDescInitEntry.  So we cheat a
     295             :      * bit to avoid a useless O(N^2) penalty.
     296             :      */
     297       13766 :     dstAtt->attnum = dstAttno;
     298       13766 :     dstAtt->attcacheoff = -1;
     299             : 
     300             :     /* since we're not copying constraints or defaults, clear these */
     301       13766 :     dstAtt->attnotnull = false;
     302       13766 :     dstAtt->atthasdef = false;
     303       13766 :     dstAtt->atthasmissing = false;
     304       13766 :     dstAtt->attidentity = '\0';
     305       13766 : }
     306             : 
     307             : /*
     308             :  * Free a TupleDesc including all substructure
     309             :  */
     310             : void
     311     1065260 : FreeTupleDesc(TupleDesc tupdesc)
     312             : {
     313             :     int         i;
     314             : 
     315             :     /*
     316             :      * Possibly this should assert tdrefcount == 0, to disallow explicit
     317             :      * freeing of un-refcounted tupdescs?
     318             :      */
     319             :     Assert(tupdesc->tdrefcount <= 0);
     320             : 
     321     1065260 :     if (tupdesc->constr)
     322             :     {
     323      169670 :         if (tupdesc->constr->num_defval > 0)
     324             :         {
     325        6890 :             AttrDefault *attrdef = tupdesc->constr->defval;
     326             : 
     327       17854 :             for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
     328             :             {
     329       10964 :                 if (attrdef[i].adbin)
     330       10964 :                     pfree(attrdef[i].adbin);
     331             :             }
     332        6890 :             pfree(attrdef);
     333             :         }
     334      169670 :         if (tupdesc->constr->missing)
     335             :         {
     336        1844 :             AttrMissing *attrmiss = tupdesc->constr->missing;
     337             : 
     338       16776 :             for (i = tupdesc->natts - 1; i >= 0; i--)
     339             :             {
     340       14932 :                 if (attrmiss[i].ammissingPresent
     341        4250 :                     && !TupleDescAttr(tupdesc, i)->attbyval)
     342        1614 :                     pfree(DatumGetPointer(attrmiss[i].ammissing));
     343             :             }
     344        1844 :             pfree(attrmiss);
     345             :         }
     346      169670 :         if (tupdesc->constr->num_check > 0)
     347             :         {
     348        3962 :             ConstrCheck *check = tupdesc->constr->check;
     349             : 
     350        9168 :             for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
     351             :             {
     352        5206 :                 if (check[i].ccname)
     353        5206 :                     pfree(check[i].ccname);
     354        5206 :                 if (check[i].ccbin)
     355        5206 :                     pfree(check[i].ccbin);
     356             :             }
     357        3962 :             pfree(check);
     358             :         }
     359      169670 :         pfree(tupdesc->constr);
     360             :     }
     361             : 
     362     1065260 :     pfree(tupdesc);
     363     1065260 : }
     364             : 
     365             : /*
     366             :  * Increment the reference count of a tupdesc, and log the reference in
     367             :  * CurrentResourceOwner.
     368             :  *
     369             :  * Do not apply this to tupdescs that are not being refcounted.  (Use the
     370             :  * macro PinTupleDesc for tupdescs of uncertain status.)
     371             :  */
     372             : void
     373     2292446 : IncrTupleDescRefCount(TupleDesc tupdesc)
     374             : {
     375             :     Assert(tupdesc->tdrefcount >= 0);
     376             : 
     377     2292446 :     ResourceOwnerEnlargeTupleDescs(CurrentResourceOwner);
     378     2292446 :     tupdesc->tdrefcount++;
     379     2292446 :     ResourceOwnerRememberTupleDesc(CurrentResourceOwner, tupdesc);
     380     2292446 : }
     381             : 
     382             : /*
     383             :  * Decrement the reference count of a tupdesc, remove the corresponding
     384             :  * reference from CurrentResourceOwner, and free the tupdesc if no more
     385             :  * references remain.
     386             :  *
     387             :  * Do not apply this to tupdescs that are not being refcounted.  (Use the
     388             :  * macro ReleaseTupleDesc for tupdescs of uncertain status.)
     389             :  */
     390             : void
     391     2292446 : DecrTupleDescRefCount(TupleDesc tupdesc)
     392             : {
     393             :     Assert(tupdesc->tdrefcount > 0);
     394             : 
     395     2292446 :     ResourceOwnerForgetTupleDesc(CurrentResourceOwner, tupdesc);
     396     2292446 :     if (--tupdesc->tdrefcount == 0)
     397          96 :         FreeTupleDesc(tupdesc);
     398     2292446 : }
     399             : 
     400             : /*
     401             :  * Compare two TupleDesc structures for logical equality
     402             :  *
     403             :  * Note: we deliberately do not check the attrelid and tdtypmod fields.
     404             :  * This allows typcache.c to use this routine to see if a cached record type
     405             :  * matches a requested type, and is harmless for relcache.c's uses.
     406             :  * We don't compare tdrefcount, either.
     407             :  */
     408             : bool
     409      273330 : equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
     410             : {
     411             :     int         i,
     412             :                 j,
     413             :                 n;
     414             : 
     415      273330 :     if (tupdesc1->natts != tupdesc2->natts)
     416        1174 :         return false;
     417      272156 :     if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
     418       16188 :         return false;
     419      255968 :     if (tupdesc1->tdhasoid != tupdesc2->tdhasoid)
     420          82 :         return false;
     421             : 
     422     1910258 :     for (i = 0; i < tupdesc1->natts; i++)
     423             :     {
     424     1662866 :         Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
     425     1662866 :         Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i);
     426             : 
     427             :         /*
     428             :          * We do not need to check every single field here: we can disregard
     429             :          * attrelid and attnum (which were used to place the row in the attrs
     430             :          * array in the first place).  It might look like we could dispense
     431             :          * with checking attlen/attbyval/attalign, since these are derived
     432             :          * from atttypid; but in the case of dropped columns we must check
     433             :          * them (since atttypid will be zero for all dropped columns) and in
     434             :          * general it seems safer to check them always.
     435             :          *
     436             :          * attcacheoff must NOT be checked since it's possibly not set in both
     437             :          * copies.
     438             :          */
     439     1662866 :         if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
     440        4668 :             return false;
     441     1658198 :         if (attr1->atttypid != attr2->atttypid)
     442         366 :             return false;
     443     1657832 :         if (attr1->attstattarget != attr2->attstattarget)
     444          34 :             return false;
     445     1657798 :         if (attr1->attlen != attr2->attlen)
     446          10 :             return false;
     447     1657788 :         if (attr1->attndims != attr2->attndims)
     448           0 :             return false;
     449     1657788 :         if (attr1->atttypmod != attr2->atttypmod)
     450          10 :             return false;
     451     1657778 :         if (attr1->attbyval != attr2->attbyval)
     452          34 :             return false;
     453     1657744 :         if (attr1->attstorage != attr2->attstorage)
     454          82 :             return false;
     455     1657662 :         if (attr1->attalign != attr2->attalign)
     456           0 :             return false;
     457     1657662 :         if (attr1->attnotnull != attr2->attnotnull)
     458         338 :             return false;
     459     1657324 :         if (attr1->atthasdef != attr2->atthasdef)
     460        1262 :             return false;
     461     1656062 :         if (attr1->attidentity != attr2->attidentity)
     462          48 :             return false;
     463     1656014 :         if (attr1->attisdropped != attr2->attisdropped)
     464           0 :             return false;
     465     1656014 :         if (attr1->attislocal != attr2->attislocal)
     466        1280 :             return false;
     467     1654734 :         if (attr1->attinhcount != attr2->attinhcount)
     468         362 :             return false;
     469     1654372 :         if (attr1->attcollation != attr2->attcollation)
     470           0 :             return false;
     471             :         /* attacl, attoptions and attfdwoptions are not even present... */
     472             :     }
     473             : 
     474      247392 :     if (tupdesc1->constr != NULL)
     475             :     {
     476       34808 :         TupleConstr *constr1 = tupdesc1->constr;
     477       34808 :         TupleConstr *constr2 = tupdesc2->constr;
     478             : 
     479       34808 :         if (constr2 == NULL)
     480          76 :             return false;
     481       34732 :         if (constr1->has_not_null != constr2->has_not_null)
     482           0 :             return false;
     483       34732 :         n = constr1->num_defval;
     484       34732 :         if (n != (int) constr2->num_defval)
     485           0 :             return false;
     486       37076 :         for (i = 0; i < n; i++)
     487             :         {
     488        2344 :             AttrDefault *defval1 = constr1->defval + i;
     489        2344 :             AttrDefault *defval2 = constr2->defval;
     490             : 
     491             :             /*
     492             :              * We can't assume that the items are always read from the system
     493             :              * catalogs in the same order; so use the adnum field to identify
     494             :              * the matching item to compare.
     495             :              */
     496        3018 :             for (j = 0; j < n; defval2++, j++)
     497             :             {
     498        3018 :                 if (defval1->adnum == defval2->adnum)
     499        2344 :                     break;
     500             :             }
     501        2344 :             if (j >= n)
     502           0 :                 return false;
     503        2344 :             if (strcmp(defval1->adbin, defval2->adbin) != 0)
     504           0 :                 return false;
     505             :         }
     506       34732 :         if (constr1->missing)
     507             :         {
     508         148 :             if (!constr2->missing)
     509           0 :                 return false;
     510        1156 :             for (i = 0; i < tupdesc1->natts; i++)
     511             :             {
     512        1008 :                 AttrMissing *missval1 = constr1->missing + i;
     513        1008 :                 AttrMissing *missval2 = constr2->missing + i;
     514             : 
     515        1008 :                 if (missval1->ammissingPresent != missval2->ammissingPresent)
     516           0 :                     return false;
     517        1008 :                 if (missval1->ammissingPresent)
     518             :                 {
     519         188 :                     Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i);
     520             : 
     521         376 :                     if (!datumIsEqual(missval1->ammissing, missval2->ammissing,
     522         376 :                                       missatt1->attbyval, missatt1->attlen))
     523           0 :                         return false;
     524             :                 }
     525             :             }
     526             :         }
     527       34584 :         else if (constr2->missing)
     528           0 :             return false;
     529       34732 :         n = constr1->num_check;
     530       34732 :         if (n != (int) constr2->num_check)
     531         560 :             return false;
     532       34974 :         for (i = 0; i < n; i++)
     533             :         {
     534         830 :             ConstrCheck *check1 = constr1->check + i;
     535         830 :             ConstrCheck *check2 = constr2->check;
     536             : 
     537             :             /*
     538             :              * Similarly, don't assume that the checks are always read in the
     539             :              * same order; match them up by name and contents. (The name
     540             :              * *should* be unique, but...)
     541             :              */
     542        1066 :             for (j = 0; j < n; check2++, j++)
     543             :             {
     544        1868 :                 if (strcmp(check1->ccname, check2->ccname) == 0 &&
     545        1660 :                     strcmp(check1->ccbin, check2->ccbin) == 0 &&
     546        1632 :                     check1->ccvalid == check2->ccvalid &&
     547         802 :                     check1->ccnoinherit == check2->ccnoinherit)
     548         802 :                     break;
     549             :             }
     550         830 :             if (j >= n)
     551          28 :                 return false;
     552             :         }
     553             :     }
     554      212584 :     else if (tupdesc2->constr != NULL)
     555         432 :         return false;
     556      246296 :     return true;
     557             : }
     558             : 
     559             : /*
     560             :  * hashTupleDesc
     561             :  *      Compute a hash value for a tuple descriptor.
     562             :  *
     563             :  * If two tuple descriptors would be considered equal by equalTupleDescs()
     564             :  * then their hash value will be equal according to this function.
     565             :  *
     566             :  * Note that currently contents of constraint are not hashed - it'd be a bit
     567             :  * painful to do so, and conflicts just due to constraints are unlikely.
     568             :  */
     569             : uint32
     570      131290 : hashTupleDesc(TupleDesc desc)
     571             : {
     572             :     uint32      s;
     573             :     int         i;
     574             : 
     575      131290 :     s = hash_combine(0, hash_uint32(desc->natts));
     576      131290 :     s = hash_combine(s, hash_uint32(desc->tdtypeid));
     577      131290 :     s = hash_combine(s, hash_uint32(desc->tdhasoid));
     578     1172228 :     for (i = 0; i < desc->natts; ++i)
     579     1040938 :         s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
     580             : 
     581      131290 :     return s;
     582             : }
     583             : 
     584             : /*
     585             :  * TupleDescInitEntry
     586             :  *      This function initializes a single attribute structure in
     587             :  *      a previously allocated tuple descriptor.
     588             :  *
     589             :  * If attributeName is NULL, the attname field is set to an empty string
     590             :  * (this is for cases where we don't know or need a name for the field).
     591             :  * Also, some callers use this function to change the datatype-related fields
     592             :  * in an existing tupdesc; they pass attributeName = NameStr(att->attname)
     593             :  * to indicate that the attname field shouldn't be modified.
     594             :  *
     595             :  * Note that attcollation is set to the default for the specified datatype.
     596             :  * If a nondefault collation is needed, insert it afterwards using
     597             :  * TupleDescInitEntryCollation.
     598             :  */
     599             : void
     600     4186874 : TupleDescInitEntry(TupleDesc desc,
     601             :                    AttrNumber attributeNumber,
     602             :                    const char *attributeName,
     603             :                    Oid oidtypeid,
     604             :                    int32 typmod,
     605             :                    int attdim)
     606             : {
     607             :     HeapTuple   tuple;
     608             :     Form_pg_type typeForm;
     609             :     Form_pg_attribute att;
     610             : 
     611             :     /*
     612             :      * sanity checks
     613             :      */
     614             :     AssertArg(PointerIsValid(desc));
     615             :     AssertArg(attributeNumber >= 1);
     616             :     AssertArg(attributeNumber <= desc->natts);
     617             : 
     618             :     /*
     619             :      * initialize the attribute fields
     620             :      */
     621     4186874 :     att = TupleDescAttr(desc, attributeNumber - 1);
     622             : 
     623     4186874 :     att->attrelid = 0;           /* dummy value */
     624             : 
     625             :     /*
     626             :      * Note: attributeName can be NULL, because the planner doesn't always
     627             :      * fill in valid resname values in targetlists, particularly for resjunk
     628             :      * attributes. Also, do nothing if caller wants to re-use the old attname.
     629             :      */
     630     4186874 :     if (attributeName == NULL)
     631     1035500 :         MemSet(NameStr(att->attname), 0, NAMEDATALEN);
     632     3151374 :     else if (attributeName != NameStr(att->attname))
     633     3145750 :         namestrcpy(&(att->attname), attributeName);
     634             : 
     635     4186874 :     att->attstattarget = -1;
     636     4186874 :     att->attcacheoff = -1;
     637     4186874 :     att->atttypmod = typmod;
     638             : 
     639     4186874 :     att->attnum = attributeNumber;
     640     4186874 :     att->attndims = attdim;
     641             : 
     642     4186874 :     att->attnotnull = false;
     643     4186874 :     att->atthasdef = false;
     644     4186874 :     att->atthasmissing = false;
     645     4186874 :     att->attidentity = '\0';
     646     4186874 :     att->attisdropped = false;
     647     4186874 :     att->attislocal = true;
     648     4186874 :     att->attinhcount = 0;
     649             :     /* attacl, attoptions and attfdwoptions are not present in tupledescs */
     650             : 
     651     4186874 :     tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
     652     4186874 :     if (!HeapTupleIsValid(tuple))
     653           0 :         elog(ERROR, "cache lookup failed for type %u", oidtypeid);
     654     4186874 :     typeForm = (Form_pg_type) GETSTRUCT(tuple);
     655             : 
     656     4186874 :     att->atttypid = oidtypeid;
     657     4186874 :     att->attlen = typeForm->typlen;
     658     4186874 :     att->attbyval = typeForm->typbyval;
     659     4186874 :     att->attalign = typeForm->typalign;
     660     4186874 :     att->attstorage = typeForm->typstorage;
     661     4186874 :     att->attcollation = typeForm->typcollation;
     662             : 
     663     4186874 :     ReleaseSysCache(tuple);
     664     4186874 : }
     665             : 
     666             : /*
     667             :  * TupleDescInitBuiltinEntry
     668             :  *      Initialize a tuple descriptor without catalog access.  Only
     669             :  *      a limited range of builtin types are supported.
     670             :  */
     671             : void
     672        2748 : TupleDescInitBuiltinEntry(TupleDesc desc,
     673             :                           AttrNumber attributeNumber,
     674             :                           const char *attributeName,
     675             :                           Oid oidtypeid,
     676             :                           int32 typmod,
     677             :                           int attdim)
     678             : {
     679             :     Form_pg_attribute att;
     680             : 
     681             :     /* sanity checks */
     682             :     AssertArg(PointerIsValid(desc));
     683             :     AssertArg(attributeNumber >= 1);
     684             :     AssertArg(attributeNumber <= desc->natts);
     685             : 
     686             :     /* initialize the attribute fields */
     687        2748 :     att = TupleDescAttr(desc, attributeNumber - 1);
     688        2748 :     att->attrelid = 0;           /* dummy value */
     689             : 
     690             :     /* unlike TupleDescInitEntry, we require an attribute name */
     691             :     Assert(attributeName != NULL);
     692        2748 :     namestrcpy(&(att->attname), attributeName);
     693             : 
     694        2748 :     att->attstattarget = -1;
     695        2748 :     att->attcacheoff = -1;
     696        2748 :     att->atttypmod = typmod;
     697             : 
     698        2748 :     att->attnum = attributeNumber;
     699        2748 :     att->attndims = attdim;
     700             : 
     701        2748 :     att->attnotnull = false;
     702        2748 :     att->atthasdef = false;
     703        2748 :     att->atthasmissing = false;
     704        2748 :     att->attidentity = '\0';
     705        2748 :     att->attisdropped = false;
     706        2748 :     att->attislocal = true;
     707        2748 :     att->attinhcount = 0;
     708             :     /* attacl, attoptions and attfdwoptions are not present in tupledescs */
     709             : 
     710        2748 :     att->atttypid = oidtypeid;
     711             : 
     712             :     /*
     713             :      * Our goal here is to support just enough types to let basic builtin
     714             :      * commands work without catalog access - e.g. so that we can do certain
     715             :      * things even in processes that are not connected to a database.
     716             :      */
     717        2748 :     switch (oidtypeid)
     718             :     {
     719             :         case TEXTOID:
     720             :         case TEXTARRAYOID:
     721        2386 :             att->attlen = -1;
     722        2386 :             att->attbyval = false;
     723        2386 :             att->attalign = 'i';
     724        2386 :             att->attstorage = 'x';
     725        2386 :             att->attcollation = DEFAULT_COLLATION_OID;
     726        2386 :             break;
     727             : 
     728             :         case BOOLOID:
     729           0 :             att->attlen = 1;
     730           0 :             att->attbyval = true;
     731           0 :             att->attalign = 'c';
     732           0 :             att->attstorage = 'p';
     733           0 :             att->attcollation = InvalidOid;
     734           0 :             break;
     735             : 
     736             :         case INT4OID:
     737         348 :             att->attlen = 4;
     738         348 :             att->attbyval = true;
     739         348 :             att->attalign = 'i';
     740         348 :             att->attstorage = 'p';
     741         348 :             att->attcollation = InvalidOid;
     742         348 :             break;
     743             : 
     744             :         case INT8OID:
     745          14 :             att->attlen = 8;
     746          14 :             att->attbyval = FLOAT8PASSBYVAL;
     747          14 :             att->attalign = 'd';
     748          14 :             att->attstorage = 'p';
     749          14 :             att->attcollation = InvalidOid;
     750          14 :             break;
     751             :     }
     752        2748 : }
     753             : 
     754             : /*
     755             :  * TupleDescInitEntryCollation
     756             :  *
     757             :  * Assign a nondefault collation to a previously initialized tuple descriptor
     758             :  * entry.
     759             :  */
     760             : void
     761     2491020 : TupleDescInitEntryCollation(TupleDesc desc,
     762             :                             AttrNumber attributeNumber,
     763             :                             Oid collationid)
     764             : {
     765             :     /*
     766             :      * sanity checks
     767             :      */
     768             :     AssertArg(PointerIsValid(desc));
     769             :     AssertArg(attributeNumber >= 1);
     770             :     AssertArg(attributeNumber <= desc->natts);
     771             : 
     772     2491020 :     TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
     773     2491020 : }
     774             : 
     775             : 
     776             : /*
     777             :  * BuildDescForRelation
     778             :  *
     779             :  * Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
     780             :  *
     781             :  * Note: the default assumption is no OIDs; caller may modify the returned
     782             :  * TupleDesc if it wants OIDs.  Also, tdtypeid will need to be filled in
     783             :  * later on.
     784             :  */
     785             : TupleDesc
     786       54648 : BuildDescForRelation(List *schema)
     787             : {
     788             :     int         natts;
     789             :     AttrNumber  attnum;
     790             :     ListCell   *l;
     791             :     TupleDesc   desc;
     792             :     bool        has_not_null;
     793             :     char       *attname;
     794             :     Oid         atttypid;
     795             :     int32       atttypmod;
     796             :     Oid         attcollation;
     797             :     int         attdim;
     798             : 
     799             :     /*
     800             :      * allocate a new tuple descriptor
     801             :      */
     802       54648 :     natts = list_length(schema);
     803       54648 :     desc = CreateTemplateTupleDesc(natts, false);
     804       54648 :     has_not_null = false;
     805             : 
     806       54648 :     attnum = 0;
     807             : 
     808      445230 :     foreach(l, schema)
     809             :     {
     810      390598 :         ColumnDef  *entry = lfirst(l);
     811             :         AclResult   aclresult;
     812             :         Form_pg_attribute att;
     813             : 
     814             :         /*
     815             :          * for each entry in the list, get the name and type information from
     816             :          * the list and have TupleDescInitEntry fill in the attribute
     817             :          * information we need.
     818             :          */
     819      390598 :         attnum++;
     820             : 
     821      390598 :         attname = entry->colname;
     822      390598 :         typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
     823             : 
     824      390598 :         aclresult = pg_type_aclcheck(atttypid, GetUserId(), ACL_USAGE);
     825      390598 :         if (aclresult != ACLCHECK_OK)
     826          16 :             aclcheck_error_type(aclresult, atttypid);
     827             : 
     828      390582 :         attcollation = GetColumnDefCollation(NULL, entry, atttypid);
     829      390582 :         attdim = list_length(entry->typeName->arrayBounds);
     830             : 
     831      390582 :         if (entry->typeName->setof)
     832           0 :             ereport(ERROR,
     833             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
     834             :                      errmsg("column \"%s\" cannot be declared SETOF",
     835             :                             attname)));
     836             : 
     837      390582 :         TupleDescInitEntry(desc, attnum, attname,
     838             :                            atttypid, atttypmod, attdim);
     839      390582 :         att = TupleDescAttr(desc, attnum - 1);
     840             : 
     841             :         /* Override TupleDescInitEntry's settings as requested */
     842      390582 :         TupleDescInitEntryCollation(desc, attnum, attcollation);
     843      390582 :         if (entry->storage)
     844        5754 :             att->attstorage = entry->storage;
     845             : 
     846             :         /* Fill in additional stuff not handled by TupleDescInitEntry */
     847      390582 :         att->attnotnull = entry->is_not_null;
     848      390582 :         has_not_null |= entry->is_not_null;
     849      390582 :         att->attislocal = entry->is_local;
     850      390582 :         att->attinhcount = entry->inhcount;
     851             :     }
     852             : 
     853       54632 :     if (has_not_null)
     854             :     {
     855        5594 :         TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
     856             : 
     857        5594 :         constr->has_not_null = true;
     858        5594 :         constr->defval = NULL;
     859        5594 :         constr->missing = NULL;
     860        5594 :         constr->num_defval = 0;
     861        5594 :         constr->check = NULL;
     862        5594 :         constr->num_check = 0;
     863        5594 :         desc->constr = constr;
     864             :     }
     865             :     else
     866             :     {
     867       49038 :         desc->constr = NULL;
     868             :     }
     869             : 
     870       54632 :     return desc;
     871             : }
     872             : 
     873             : /*
     874             :  * BuildDescFromLists
     875             :  *
     876             :  * Build a TupleDesc given lists of column names (as String nodes),
     877             :  * column type OIDs, typmods, and collation OIDs.
     878             :  *
     879             :  * No constraints are generated.
     880             :  *
     881             :  * This is essentially a cut-down version of BuildDescForRelation for use
     882             :  * with functions returning RECORD.
     883             :  */
     884             : TupleDesc
     885         570 : BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
     886             : {
     887             :     int         natts;
     888             :     AttrNumber  attnum;
     889             :     ListCell   *l1;
     890             :     ListCell   *l2;
     891             :     ListCell   *l3;
     892             :     ListCell   *l4;
     893             :     TupleDesc   desc;
     894             : 
     895         570 :     natts = list_length(names);
     896             :     Assert(natts == list_length(types));
     897             :     Assert(natts == list_length(typmods));
     898             :     Assert(natts == list_length(collations));
     899             : 
     900             :     /*
     901             :      * allocate a new tuple descriptor
     902             :      */
     903         570 :     desc = CreateTemplateTupleDesc(natts, false);
     904             : 
     905         570 :     attnum = 0;
     906             : 
     907         570 :     l2 = list_head(types);
     908         570 :     l3 = list_head(typmods);
     909         570 :     l4 = list_head(collations);
     910        2226 :     foreach(l1, names)
     911             :     {
     912        1656 :         char       *attname = strVal(lfirst(l1));
     913             :         Oid         atttypid;
     914             :         int32       atttypmod;
     915             :         Oid         attcollation;
     916             : 
     917        1656 :         atttypid = lfirst_oid(l2);
     918        1656 :         l2 = lnext(l2);
     919        1656 :         atttypmod = lfirst_int(l3);
     920        1656 :         l3 = lnext(l3);
     921        1656 :         attcollation = lfirst_oid(l4);
     922        1656 :         l4 = lnext(l4);
     923             : 
     924        1656 :         attnum++;
     925             : 
     926        1656 :         TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
     927        1656 :         TupleDescInitEntryCollation(desc, attnum, attcollation);
     928             :     }
     929             : 
     930         570 :     return desc;
     931             : }

Generated by: LCOV version 1.13