LCOV - code coverage report
Current view: top level - src/backend/access/common - tupdesc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 345 366 94.3 %
Date: 2020-05-25 06:06:29 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-2020, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/access/common/tupdesc.c
      12             :  *
      13             :  * NOTES
      14             :  *    some of the executor utility code such as "ExecTypeFromTL" should be
      15             :  *    moved here.
      16             :  *
      17             :  *-------------------------------------------------------------------------
      18             :  */
      19             : 
      20             : #include "postgres.h"
      21             : 
      22             : #include "access/htup_details.h"
      23             : #include "access/tupdesc_details.h"
      24             : #include "catalog/pg_collation.h"
      25             : #include "catalog/pg_type.h"
      26             : #include "common/hashfn.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/resowner_private.h"
      33             : #include "utils/syscache.h"
      34             : 
      35             : 
      36             : /*
      37             :  * CreateTemplateTupleDesc
      38             :  *      This function allocates an empty tuple descriptor structure.
      39             :  *
      40             :  * Tuple type ID information is initially set for an anonymous record type;
      41             :  * caller can overwrite this if needed.
      42             :  */
      43             : TupleDesc
      44     7649852 : CreateTemplateTupleDesc(int natts)
      45             : {
      46             :     TupleDesc   desc;
      47             : 
      48             :     /*
      49             :      * sanity checks
      50             :      */
      51             :     AssertArg(natts >= 0);
      52             : 
      53             :     /*
      54             :      * Allocate enough memory for the tuple descriptor, including the
      55             :      * attribute rows.
      56             :      *
      57             :      * Note: the attribute array stride is sizeof(FormData_pg_attribute),
      58             :      * since we declare the array elements as FormData_pg_attribute for
      59             :      * notational convenience.  However, we only guarantee that the first
      60             :      * ATTRIBUTE_FIXED_PART_SIZE bytes of each entry are valid; most code that
      61             :      * copies tupdesc entries around copies just that much.  In principle that
      62             :      * could be less due to trailing padding, although with the current
      63             :      * definition of pg_attribute there probably isn't any padding.
      64             :      */
      65     7649852 :     desc = (TupleDesc) palloc(offsetof(struct TupleDescData, attrs) +
      66     7649852 :                               natts * sizeof(FormData_pg_attribute));
      67             : 
      68             :     /*
      69             :      * Initialize other fields of the tupdesc.
      70             :      */
      71     7649852 :     desc->natts = natts;
      72     7649852 :     desc->constr = NULL;
      73     7649852 :     desc->tdtypeid = RECORDOID;
      74     7649852 :     desc->tdtypmod = -1;
      75     7649852 :     desc->tdrefcount = -1;       /* assume not reference-counted */
      76             : 
      77     7649852 :     return desc;
      78             : }
      79             : 
      80             : /*
      81             :  * CreateTupleDesc
      82             :  *      This function allocates a new TupleDesc by copying a given
      83             :  *      Form_pg_attribute array.
      84             :  *
      85             :  * Tuple type ID information is initially set for an anonymous record type;
      86             :  * caller can overwrite this if needed.
      87             :  */
      88             : TupleDesc
      89     3391334 : CreateTupleDesc(int natts, Form_pg_attribute *attrs)
      90             : {
      91             :     TupleDesc   desc;
      92             :     int         i;
      93             : 
      94     3391334 :     desc = CreateTemplateTupleDesc(natts);
      95             : 
      96    53125410 :     for (i = 0; i < natts; ++i)
      97    49734076 :         memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
      98             : 
      99     3391334 :     return desc;
     100             : }
     101             : 
     102             : /*
     103             :  * CreateTupleDescCopy
     104             :  *      This function creates a new TupleDesc by copying from an existing
     105             :  *      TupleDesc.
     106             :  *
     107             :  * !!! Constraints and defaults are not copied !!!
     108             :  */
     109             : TupleDesc
     110      297950 : CreateTupleDescCopy(TupleDesc tupdesc)
     111             : {
     112             :     TupleDesc   desc;
     113             :     int         i;
     114             : 
     115      297950 :     desc = CreateTemplateTupleDesc(tupdesc->natts);
     116             : 
     117             :     /* Flat-copy the attribute array */
     118      595900 :     memcpy(TupleDescAttr(desc, 0),
     119      297950 :            TupleDescAttr(tupdesc, 0),
     120      297950 :            desc->natts * sizeof(FormData_pg_attribute));
     121             : 
     122             :     /*
     123             :      * Since we're not copying constraints and defaults, clear fields
     124             :      * associated with them.
     125             :      */
     126     1589294 :     for (i = 0; i < desc->natts; i++)
     127             :     {
     128     1291344 :         Form_pg_attribute att = TupleDescAttr(desc, i);
     129             : 
     130     1291344 :         att->attnotnull = false;
     131     1291344 :         att->atthasdef = false;
     132     1291344 :         att->atthasmissing = false;
     133     1291344 :         att->attidentity = '\0';
     134     1291344 :         att->attgenerated = '\0';
     135             :     }
     136             : 
     137             :     /* We can copy the tuple type identification, too */
     138      297950 :     desc->tdtypeid = tupdesc->tdtypeid;
     139      297950 :     desc->tdtypmod = tupdesc->tdtypmod;
     140             : 
     141      297950 :     return desc;
     142             : }
     143             : 
     144             : /*
     145             :  * CreateTupleDescCopyConstr
     146             :  *      This function creates a new TupleDesc by copying from an existing
     147             :  *      TupleDesc (including its constraints and defaults).
     148             :  */
     149             : TupleDesc
     150      298574 : CreateTupleDescCopyConstr(TupleDesc tupdesc)
     151             : {
     152             :     TupleDesc   desc;
     153      298574 :     TupleConstr *constr = tupdesc->constr;
     154             :     int         i;
     155             : 
     156      298574 :     desc = CreateTemplateTupleDesc(tupdesc->natts);
     157             : 
     158             :     /* Flat-copy the attribute array */
     159      597148 :     memcpy(TupleDescAttr(desc, 0),
     160      298574 :            TupleDescAttr(tupdesc, 0),
     161      298574 :            desc->natts * sizeof(FormData_pg_attribute));
     162             : 
     163             :     /* Copy the TupleConstr data structure, if any */
     164      298574 :     if (constr)
     165             :     {
     166      270018 :         TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
     167             : 
     168      270018 :         cpy->has_not_null = constr->has_not_null;
     169      270018 :         cpy->has_generated_stored = constr->has_generated_stored;
     170             : 
     171      270018 :         if ((cpy->num_defval = constr->num_defval) > 0)
     172             :         {
     173        1714 :             cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
     174        1714 :             memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
     175        4246 :             for (i = cpy->num_defval - 1; i >= 0; i--)
     176             :             {
     177        2532 :                 if (constr->defval[i].adbin)
     178        2532 :                     cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
     179             :             }
     180             :         }
     181             : 
     182      270018 :         if (constr->missing)
     183             :         {
     184         642 :             cpy->missing = (AttrMissing *) palloc(tupdesc->natts * sizeof(AttrMissing));
     185         642 :             memcpy(cpy->missing, constr->missing, tupdesc->natts * sizeof(AttrMissing));
     186        5474 :             for (i = tupdesc->natts - 1; i >= 0; i--)
     187             :             {
     188        4832 :                 if (constr->missing[i].am_present)
     189             :                 {
     190         974 :                     Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
     191             : 
     192         974 :                     cpy->missing[i].am_value = datumCopy(constr->missing[i].am_value,
     193         974 :                                                          attr->attbyval,
     194         974 :                                                          attr->attlen);
     195             :                 }
     196             :             }
     197             :         }
     198             : 
     199      270018 :         if ((cpy->num_check = constr->num_check) > 0)
     200             :         {
     201        1112 :             cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
     202        1112 :             memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
     203        2674 :             for (i = cpy->num_check - 1; i >= 0; i--)
     204             :             {
     205        1562 :                 if (constr->check[i].ccname)
     206        1562 :                     cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
     207        1562 :                 if (constr->check[i].ccbin)
     208        1562 :                     cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
     209        1562 :                 cpy->check[i].ccvalid = constr->check[i].ccvalid;
     210        1562 :                 cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
     211             :             }
     212             :         }
     213             : 
     214      270018 :         desc->constr = cpy;
     215             :     }
     216             : 
     217             :     /* We can copy the tuple type identification, too */
     218      298574 :     desc->tdtypeid = tupdesc->tdtypeid;
     219      298574 :     desc->tdtypmod = tupdesc->tdtypmod;
     220             : 
     221      298574 :     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       54378 : TupleDescCopy(TupleDesc dst, TupleDesc src)
     234             : {
     235             :     int         i;
     236             : 
     237             :     /* Flat-copy the header and attribute array */
     238       54378 :     memcpy(dst, src, TupleDescSize(src));
     239             : 
     240             :     /*
     241             :      * Since we're not copying constraints and defaults, clear fields
     242             :      * associated with them.
     243             :      */
     244      211626 :     for (i = 0; i < dst->natts; i++)
     245             :     {
     246      157248 :         Form_pg_attribute att = TupleDescAttr(dst, i);
     247             : 
     248      157248 :         att->attnotnull = false;
     249      157248 :         att->atthasdef = false;
     250      157248 :         att->atthasmissing = false;
     251      157248 :         att->attidentity = '\0';
     252      157248 :         att->attgenerated = '\0';
     253             :     }
     254       54378 :     dst->constr = NULL;
     255             : 
     256             :     /*
     257             :      * Also, assume the destination is not to be ref-counted.  (Copying the
     258             :      * source's refcount would be wrong in any case.)
     259             :      */
     260       54378 :     dst->tdrefcount = -1;
     261       54378 : }
     262             : 
     263             : /*
     264             :  * TupleDescCopyEntry
     265             :  *      This function copies a single attribute structure from one tuple
     266             :  *      descriptor to another.
     267             :  *
     268             :  * !!! Constraints and defaults are not copied !!!
     269             :  */
     270             : void
     271       13870 : TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
     272             :                    TupleDesc src, AttrNumber srcAttno)
     273             : {
     274       13870 :     Form_pg_attribute dstAtt = TupleDescAttr(dst, dstAttno - 1);
     275       13870 :     Form_pg_attribute srcAtt = TupleDescAttr(src, srcAttno - 1);
     276             : 
     277             :     /*
     278             :      * sanity checks
     279             :      */
     280             :     AssertArg(PointerIsValid(src));
     281             :     AssertArg(PointerIsValid(dst));
     282             :     AssertArg(srcAttno >= 1);
     283             :     AssertArg(srcAttno <= src->natts);
     284             :     AssertArg(dstAttno >= 1);
     285             :     AssertArg(dstAttno <= dst->natts);
     286             : 
     287       13870 :     memcpy(dstAtt, srcAtt, ATTRIBUTE_FIXED_PART_SIZE);
     288             : 
     289             :     /*
     290             :      * Aside from updating the attno, we'd better reset attcacheoff.
     291             :      *
     292             :      * XXX Actually, to be entirely safe we'd need to reset the attcacheoff of
     293             :      * all following columns in dst as well.  Current usage scenarios don't
     294             :      * require that though, because all following columns will get initialized
     295             :      * by other uses of this function or TupleDescInitEntry.  So we cheat a
     296             :      * bit to avoid a useless O(N^2) penalty.
     297             :      */
     298       13870 :     dstAtt->attnum = dstAttno;
     299       13870 :     dstAtt->attcacheoff = -1;
     300             : 
     301             :     /* since we're not copying constraints or defaults, clear these */
     302       13870 :     dstAtt->attnotnull = false;
     303       13870 :     dstAtt->atthasdef = false;
     304       13870 :     dstAtt->atthasmissing = false;
     305       13870 :     dstAtt->attidentity = '\0';
     306       13870 :     dstAtt->attgenerated = '\0';
     307       13870 : }
     308             : 
     309             : /*
     310             :  * Free a TupleDesc including all substructure
     311             :  */
     312             : void
     313     1358366 : FreeTupleDesc(TupleDesc tupdesc)
     314             : {
     315             :     int         i;
     316             : 
     317             :     /*
     318             :      * Possibly this should assert tdrefcount == 0, to disallow explicit
     319             :      * freeing of un-refcounted tupdescs?
     320             :      */
     321             :     Assert(tupdesc->tdrefcount <= 0);
     322             : 
     323     1358366 :     if (tupdesc->constr)
     324             :     {
     325      249308 :         if (tupdesc->constr->num_defval > 0)
     326             :         {
     327       12300 :             AttrDefault *attrdef = tupdesc->constr->defval;
     328             : 
     329       30346 :             for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
     330             :             {
     331       18046 :                 if (attrdef[i].adbin)
     332       18046 :                     pfree(attrdef[i].adbin);
     333             :             }
     334       12300 :             pfree(attrdef);
     335             :         }
     336      249308 :         if (tupdesc->constr->missing)
     337             :         {
     338        2592 :             AttrMissing *attrmiss = tupdesc->constr->missing;
     339             : 
     340       20362 :             for (i = tupdesc->natts - 1; i >= 0; i--)
     341             :             {
     342       17770 :                 if (attrmiss[i].am_present
     343        5114 :                     && !TupleDescAttr(tupdesc, i)->attbyval)
     344        1658 :                     pfree(DatumGetPointer(attrmiss[i].am_value));
     345             :             }
     346        2592 :             pfree(attrmiss);
     347             :         }
     348      249308 :         if (tupdesc->constr->num_check > 0)
     349             :         {
     350        4682 :             ConstrCheck *check = tupdesc->constr->check;
     351             : 
     352       10862 :             for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
     353             :             {
     354        6180 :                 if (check[i].ccname)
     355        6180 :                     pfree(check[i].ccname);
     356        6180 :                 if (check[i].ccbin)
     357        6180 :                     pfree(check[i].ccbin);
     358             :             }
     359        4682 :             pfree(check);
     360             :         }
     361      249308 :         pfree(tupdesc->constr);
     362             :     }
     363             : 
     364     1358366 :     pfree(tupdesc);
     365     1358366 : }
     366             : 
     367             : /*
     368             :  * Increment the reference count of a tupdesc, and log the reference in
     369             :  * CurrentResourceOwner.
     370             :  *
     371             :  * Do not apply this to tupdescs that are not being refcounted.  (Use the
     372             :  * macro PinTupleDesc for tupdescs of uncertain status.)
     373             :  */
     374             : void
     375    22378816 : IncrTupleDescRefCount(TupleDesc tupdesc)
     376             : {
     377             :     Assert(tupdesc->tdrefcount >= 0);
     378             : 
     379    22378816 :     ResourceOwnerEnlargeTupleDescs(CurrentResourceOwner);
     380    22378816 :     tupdesc->tdrefcount++;
     381    22378816 :     ResourceOwnerRememberTupleDesc(CurrentResourceOwner, tupdesc);
     382    22378816 : }
     383             : 
     384             : /*
     385             :  * Decrement the reference count of a tupdesc, remove the corresponding
     386             :  * reference from CurrentResourceOwner, and free the tupdesc if no more
     387             :  * references remain.
     388             :  *
     389             :  * Do not apply this to tupdescs that are not being refcounted.  (Use the
     390             :  * macro ReleaseTupleDesc for tupdescs of uncertain status.)
     391             :  */
     392             : void
     393    22378816 : DecrTupleDescRefCount(TupleDesc tupdesc)
     394             : {
     395             :     Assert(tupdesc->tdrefcount > 0);
     396             : 
     397    22378816 :     ResourceOwnerForgetTupleDesc(CurrentResourceOwner, tupdesc);
     398    22378816 :     if (--tupdesc->tdrefcount == 0)
     399         142 :         FreeTupleDesc(tupdesc);
     400    22378816 : }
     401             : 
     402             : /*
     403             :  * Compare two TupleDesc structures for logical equality
     404             :  *
     405             :  * Note: we deliberately do not check the attrelid and tdtypmod fields.
     406             :  * This allows typcache.c to use this routine to see if a cached record type
     407             :  * matches a requested type, and is harmless for relcache.c's uses.
     408             :  * We don't compare tdrefcount, either.
     409             :  */
     410             : bool
     411      400914 : equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
     412             : {
     413             :     int         i,
     414             :                 j,
     415             :                 n;
     416             : 
     417      400914 :     if (tupdesc1->natts != tupdesc2->natts)
     418        1728 :         return false;
     419      399186 :     if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
     420       18750 :         return false;
     421             : 
     422     3208840 :     for (i = 0; i < tupdesc1->natts; i++)
     423             :     {
     424     2839430 :         Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
     425     2839430 :         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     2839430 :         if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
     440        4910 :             return false;
     441     2834520 :         if (attr1->atttypid != attr2->atttypid)
     442         646 :             return false;
     443     2833874 :         if (attr1->attstattarget != attr2->attstattarget)
     444          34 :             return false;
     445     2833840 :         if (attr1->attlen != attr2->attlen)
     446          12 :             return false;
     447     2833828 :         if (attr1->attndims != attr2->attndims)
     448           0 :             return false;
     449     2833828 :         if (attr1->atttypmod != attr2->atttypmod)
     450          30 :             return false;
     451     2833798 :         if (attr1->attbyval != attr2->attbyval)
     452         152 :             return false;
     453     2833646 :         if (attr1->attstorage != attr2->attstorage)
     454         102 :             return false;
     455     2833544 :         if (attr1->attalign != attr2->attalign)
     456           0 :             return false;
     457     2833544 :         if (attr1->attnotnull != attr2->attnotnull)
     458         550 :             return false;
     459     2832994 :         if (attr1->atthasdef != attr2->atthasdef)
     460        2014 :             return false;
     461     2830980 :         if (attr1->attidentity != attr2->attidentity)
     462          84 :             return false;
     463     2830896 :         if (attr1->attgenerated != attr2->attgenerated)
     464          16 :             return false;
     465     2830880 :         if (attr1->attisdropped != attr2->attisdropped)
     466           0 :             return false;
     467     2830880 :         if (attr1->attislocal != attr2->attislocal)
     468        1978 :             return false;
     469     2828902 :         if (attr1->attinhcount != attr2->attinhcount)
     470         498 :             return false;
     471     2828404 :         if (attr1->attcollation != attr2->attcollation)
     472           0 :             return false;
     473             :         /* attacl, attoptions and attfdwoptions are not even present... */
     474             :     }
     475             : 
     476      369410 :     if (tupdesc1->constr != NULL)
     477             :     {
     478       87264 :         TupleConstr *constr1 = tupdesc1->constr;
     479       87264 :         TupleConstr *constr2 = tupdesc2->constr;
     480             : 
     481       87264 :         if (constr2 == NULL)
     482          90 :             return false;
     483       87174 :         if (constr1->has_not_null != constr2->has_not_null)
     484           0 :             return false;
     485       87174 :         if (constr1->has_generated_stored != constr2->has_generated_stored)
     486         190 :             return false;
     487       86984 :         n = constr1->num_defval;
     488       86984 :         if (n != (int) constr2->num_defval)
     489           0 :             return false;
     490       92374 :         for (i = 0; i < n; i++)
     491             :         {
     492        5390 :             AttrDefault *defval1 = constr1->defval + i;
     493        5390 :             AttrDefault *defval2 = constr2->defval;
     494             : 
     495             :             /*
     496             :              * We can't assume that the items are always read from the system
     497             :              * catalogs in the same order; so use the adnum field to identify
     498             :              * the matching item to compare.
     499             :              */
     500        7184 :             for (j = 0; j < n; defval2++, j++)
     501             :             {
     502        7184 :                 if (defval1->adnum == defval2->adnum)
     503        5390 :                     break;
     504             :             }
     505        5390 :             if (j >= n)
     506           0 :                 return false;
     507        5390 :             if (strcmp(defval1->adbin, defval2->adbin) != 0)
     508           0 :                 return false;
     509             :         }
     510       86984 :         if (constr1->missing)
     511             :         {
     512         314 :             if (!constr2->missing)
     513          44 :                 return false;
     514        1824 :             for (i = 0; i < tupdesc1->natts; i++)
     515             :             {
     516        1554 :                 AttrMissing *missval1 = constr1->missing + i;
     517        1554 :                 AttrMissing *missval2 = constr2->missing + i;
     518             : 
     519        1554 :                 if (missval1->am_present != missval2->am_present)
     520           0 :                     return false;
     521        1554 :                 if (missval1->am_present)
     522             :                 {
     523         322 :                     Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i);
     524             : 
     525         322 :                     if (!datumIsEqual(missval1->am_value, missval2->am_value,
     526         322 :                                       missatt1->attbyval, missatt1->attlen))
     527           0 :                         return false;
     528             :                 }
     529             :             }
     530             :         }
     531       86670 :         else if (constr2->missing)
     532           6 :             return false;
     533       86934 :         n = constr1->num_check;
     534       86934 :         if (n != (int) constr2->num_check)
     535         704 :             return false;
     536       87324 :         for (i = 0; i < n; i++)
     537             :         {
     538        1122 :             ConstrCheck *check1 = constr1->check + i;
     539        1122 :             ConstrCheck *check2 = constr2->check;
     540             : 
     541             :             /*
     542             :              * Similarly, don't assume that the checks are always read in the
     543             :              * same order; match them up by name and contents. (The name
     544             :              * *should* be unique, but...)
     545             :              */
     546        1468 :             for (j = 0; j < n; check2++, j++)
     547             :             {
     548        1440 :                 if (strcmp(check1->ccname, check2->ccname) == 0 &&
     549        1122 :                     strcmp(check1->ccbin, check2->ccbin) == 0 &&
     550        1122 :                     check1->ccvalid == check2->ccvalid &&
     551        1094 :                     check1->ccnoinherit == check2->ccnoinherit)
     552        1094 :                     break;
     553             :             }
     554        1122 :             if (j >= n)
     555          28 :                 return false;
     556             :         }
     557             :     }
     558      282146 :     else if (tupdesc2->constr != NULL)
     559         606 :         return false;
     560      367742 :     return true;
     561             : }
     562             : 
     563             : /*
     564             :  * hashTupleDesc
     565             :  *      Compute a hash value for a tuple descriptor.
     566             :  *
     567             :  * If two tuple descriptors would be considered equal by equalTupleDescs()
     568             :  * then their hash value will be equal according to this function.
     569             :  *
     570             :  * Note that currently contents of constraint are not hashed - it'd be a bit
     571             :  * painful to do so, and conflicts just due to constraints are unlikely.
     572             :  */
     573             : uint32
     574      108632 : hashTupleDesc(TupleDesc desc)
     575             : {
     576             :     uint32      s;
     577             :     int         i;
     578             : 
     579      108632 :     s = hash_combine(0, hash_uint32(desc->natts));
     580      108632 :     s = hash_combine(s, hash_uint32(desc->tdtypeid));
     581     1304634 :     for (i = 0; i < desc->natts; ++i)
     582     1196002 :         s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
     583             : 
     584      108632 :     return s;
     585             : }
     586             : 
     587             : /*
     588             :  * TupleDescInitEntry
     589             :  *      This function initializes a single attribute structure in
     590             :  *      a previously allocated tuple descriptor.
     591             :  *
     592             :  * If attributeName is NULL, the attname field is set to an empty string
     593             :  * (this is for cases where we don't know or need a name for the field).
     594             :  * Also, some callers use this function to change the datatype-related fields
     595             :  * in an existing tupdesc; they pass attributeName = NameStr(att->attname)
     596             :  * to indicate that the attname field shouldn't be modified.
     597             :  *
     598             :  * Note that attcollation is set to the default for the specified datatype.
     599             :  * If a nondefault collation is needed, insert it afterwards using
     600             :  * TupleDescInitEntryCollation.
     601             :  */
     602             : void
     603     5904330 : TupleDescInitEntry(TupleDesc desc,
     604             :                    AttrNumber attributeNumber,
     605             :                    const char *attributeName,
     606             :                    Oid oidtypeid,
     607             :                    int32 typmod,
     608             :                    int attdim)
     609             : {
     610             :     HeapTuple   tuple;
     611             :     Form_pg_type typeForm;
     612             :     Form_pg_attribute att;
     613             : 
     614             :     /*
     615             :      * sanity checks
     616             :      */
     617             :     AssertArg(PointerIsValid(desc));
     618             :     AssertArg(attributeNumber >= 1);
     619             :     AssertArg(attributeNumber <= desc->natts);
     620             : 
     621             :     /*
     622             :      * initialize the attribute fields
     623             :      */
     624     5904330 :     att = TupleDescAttr(desc, attributeNumber - 1);
     625             : 
     626     5904330 :     att->attrelid = 0;           /* dummy value */
     627             : 
     628             :     /*
     629             :      * Note: attributeName can be NULL, because the planner doesn't always
     630             :      * fill in valid resname values in targetlists, particularly for resjunk
     631             :      * attributes. Also, do nothing if caller wants to re-use the old attname.
     632             :      */
     633     5904330 :     if (attributeName == NULL)
     634     1985132 :         MemSet(NameStr(att->attname), 0, NAMEDATALEN);
     635     3919198 :     else if (attributeName != NameStr(att->attname))
     636     3911932 :         namestrcpy(&(att->attname), attributeName);
     637             : 
     638     5904330 :     att->attstattarget = -1;
     639     5904330 :     att->attcacheoff = -1;
     640     5904330 :     att->atttypmod = typmod;
     641             : 
     642     5904330 :     att->attnum = attributeNumber;
     643     5904330 :     att->attndims = attdim;
     644             : 
     645     5904330 :     att->attnotnull = false;
     646     5904330 :     att->atthasdef = false;
     647     5904330 :     att->atthasmissing = false;
     648     5904330 :     att->attidentity = '\0';
     649     5904330 :     att->attgenerated = '\0';
     650     5904330 :     att->attisdropped = false;
     651     5904330 :     att->attislocal = true;
     652     5904330 :     att->attinhcount = 0;
     653             :     /* attacl, attoptions and attfdwoptions are not present in tupledescs */
     654             : 
     655     5904330 :     tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
     656     5904330 :     if (!HeapTupleIsValid(tuple))
     657           0 :         elog(ERROR, "cache lookup failed for type %u", oidtypeid);
     658     5904330 :     typeForm = (Form_pg_type) GETSTRUCT(tuple);
     659             : 
     660     5904330 :     att->atttypid = oidtypeid;
     661     5904330 :     att->attlen = typeForm->typlen;
     662     5904330 :     att->attbyval = typeForm->typbyval;
     663     5904330 :     att->attalign = typeForm->typalign;
     664     5904330 :     att->attstorage = typeForm->typstorage;
     665     5904330 :     att->attcollation = typeForm->typcollation;
     666             : 
     667     5904330 :     ReleaseSysCache(tuple);
     668     5904330 : }
     669             : 
     670             : /*
     671             :  * TupleDescInitBuiltinEntry
     672             :  *      Initialize a tuple descriptor without catalog access.  Only
     673             :  *      a limited range of builtin types are supported.
     674             :  */
     675             : void
     676        3842 : TupleDescInitBuiltinEntry(TupleDesc desc,
     677             :                           AttrNumber attributeNumber,
     678             :                           const char *attributeName,
     679             :                           Oid oidtypeid,
     680             :                           int32 typmod,
     681             :                           int attdim)
     682             : {
     683             :     Form_pg_attribute att;
     684             : 
     685             :     /* sanity checks */
     686             :     AssertArg(PointerIsValid(desc));
     687             :     AssertArg(attributeNumber >= 1);
     688             :     AssertArg(attributeNumber <= desc->natts);
     689             : 
     690             :     /* initialize the attribute fields */
     691        3842 :     att = TupleDescAttr(desc, attributeNumber - 1);
     692        3842 :     att->attrelid = 0;           /* dummy value */
     693             : 
     694             :     /* unlike TupleDescInitEntry, we require an attribute name */
     695             :     Assert(attributeName != NULL);
     696        3842 :     namestrcpy(&(att->attname), attributeName);
     697             : 
     698        3842 :     att->attstattarget = -1;
     699        3842 :     att->attcacheoff = -1;
     700        3842 :     att->atttypmod = typmod;
     701             : 
     702        3842 :     att->attnum = attributeNumber;
     703        3842 :     att->attndims = attdim;
     704             : 
     705        3842 :     att->attnotnull = false;
     706        3842 :     att->atthasdef = false;
     707        3842 :     att->atthasmissing = false;
     708        3842 :     att->attidentity = '\0';
     709        3842 :     att->attgenerated = '\0';
     710        3842 :     att->attisdropped = false;
     711        3842 :     att->attislocal = true;
     712        3842 :     att->attinhcount = 0;
     713             :     /* attacl, attoptions and attfdwoptions are not present in tupledescs */
     714             : 
     715        3842 :     att->atttypid = oidtypeid;
     716             : 
     717             :     /*
     718             :      * Our goal here is to support just enough types to let basic builtin
     719             :      * commands work without catalog access - e.g. so that we can do certain
     720             :      * things even in processes that are not connected to a database.
     721             :      */
     722        3842 :     switch (oidtypeid)
     723             :     {
     724        3382 :         case TEXTOID:
     725             :         case TEXTARRAYOID:
     726        3382 :             att->attlen = -1;
     727        3382 :             att->attbyval = false;
     728        3382 :             att->attalign = TYPALIGN_INT;
     729        3382 :             att->attstorage = TYPSTORAGE_EXTENDED;
     730        3382 :             att->attcollation = DEFAULT_COLLATION_OID;
     731        3382 :             break;
     732             : 
     733           0 :         case BOOLOID:
     734           0 :             att->attlen = 1;
     735           0 :             att->attbyval = true;
     736           0 :             att->attalign = TYPALIGN_CHAR;
     737           0 :             att->attstorage = TYPSTORAGE_PLAIN;
     738           0 :             att->attcollation = InvalidOid;
     739           0 :             break;
     740             : 
     741         450 :         case INT4OID:
     742         450 :             att->attlen = 4;
     743         450 :             att->attbyval = true;
     744         450 :             att->attalign = TYPALIGN_INT;
     745         450 :             att->attstorage = TYPSTORAGE_PLAIN;
     746         450 :             att->attcollation = InvalidOid;
     747         450 :             break;
     748             : 
     749          10 :         case INT8OID:
     750          10 :             att->attlen = 8;
     751          10 :             att->attbyval = FLOAT8PASSBYVAL;
     752          10 :             att->attalign = TYPALIGN_DOUBLE;
     753          10 :             att->attstorage = TYPSTORAGE_PLAIN;
     754          10 :             att->attcollation = InvalidOid;
     755          10 :             break;
     756             : 
     757           0 :         default:
     758           0 :             elog(ERROR, "unsupported type %u", oidtypeid);
     759             :     }
     760        3842 : }
     761             : 
     762             : /*
     763             :  * TupleDescInitEntryCollation
     764             :  *
     765             :  * Assign a nondefault collation to a previously initialized tuple descriptor
     766             :  * entry.
     767             :  */
     768             : void
     769     3999420 : TupleDescInitEntryCollation(TupleDesc desc,
     770             :                             AttrNumber attributeNumber,
     771             :                             Oid collationid)
     772             : {
     773             :     /*
     774             :      * sanity checks
     775             :      */
     776             :     AssertArg(PointerIsValid(desc));
     777             :     AssertArg(attributeNumber >= 1);
     778             :     AssertArg(attributeNumber <= desc->natts);
     779             : 
     780     3999420 :     TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
     781     3999420 : }
     782             : 
     783             : 
     784             : /*
     785             :  * BuildDescForRelation
     786             :  *
     787             :  * Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
     788             :  *
     789             :  * Note: the default assumption is no OIDs; caller may modify the returned
     790             :  * TupleDesc if it wants OIDs.  Also, tdtypeid will need to be filled in
     791             :  * later on.
     792             :  */
     793             : TupleDesc
     794       70632 : BuildDescForRelation(List *schema)
     795             : {
     796             :     int         natts;
     797             :     AttrNumber  attnum;
     798             :     ListCell   *l;
     799             :     TupleDesc   desc;
     800             :     bool        has_not_null;
     801             :     char       *attname;
     802             :     Oid         atttypid;
     803             :     int32       atttypmod;
     804             :     Oid         attcollation;
     805             :     int         attdim;
     806             : 
     807             :     /*
     808             :      * allocate a new tuple descriptor
     809             :      */
     810       70632 :     natts = list_length(schema);
     811       70632 :     desc = CreateTemplateTupleDesc(natts);
     812       70632 :     has_not_null = false;
     813             : 
     814       70632 :     attnum = 0;
     815             : 
     816      591278 :     foreach(l, schema)
     817             :     {
     818      520662 :         ColumnDef  *entry = lfirst(l);
     819             :         AclResult   aclresult;
     820             :         Form_pg_attribute att;
     821             : 
     822             :         /*
     823             :          * for each entry in the list, get the name and type information from
     824             :          * the list and have TupleDescInitEntry fill in the attribute
     825             :          * information we need.
     826             :          */
     827      520662 :         attnum++;
     828             : 
     829      520662 :         attname = entry->colname;
     830      520662 :         typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
     831             : 
     832      520662 :         aclresult = pg_type_aclcheck(atttypid, GetUserId(), ACL_USAGE);
     833      520662 :         if (aclresult != ACLCHECK_OK)
     834          16 :             aclcheck_error_type(aclresult, atttypid);
     835             : 
     836      520646 :         attcollation = GetColumnDefCollation(NULL, entry, atttypid);
     837      520646 :         attdim = list_length(entry->typeName->arrayBounds);
     838             : 
     839      520646 :         if (entry->typeName->setof)
     840           0 :             ereport(ERROR,
     841             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
     842             :                      errmsg("column \"%s\" cannot be declared SETOF",
     843             :                             attname)));
     844             : 
     845      520646 :         TupleDescInitEntry(desc, attnum, attname,
     846             :                            atttypid, atttypmod, attdim);
     847      520646 :         att = TupleDescAttr(desc, attnum - 1);
     848             : 
     849             :         /* Override TupleDescInitEntry's settings as requested */
     850      520646 :         TupleDescInitEntryCollation(desc, attnum, attcollation);
     851      520646 :         if (entry->storage)
     852       10158 :             att->attstorage = entry->storage;
     853             : 
     854             :         /* Fill in additional stuff not handled by TupleDescInitEntry */
     855      520646 :         att->attnotnull = entry->is_not_null;
     856      520646 :         has_not_null |= entry->is_not_null;
     857      520646 :         att->attislocal = entry->is_local;
     858      520646 :         att->attinhcount = entry->inhcount;
     859             :     }
     860             : 
     861       70616 :     if (has_not_null)
     862             :     {
     863        6976 :         TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
     864             : 
     865        6976 :         constr->has_not_null = true;
     866        6976 :         constr->has_generated_stored = false;
     867        6976 :         constr->defval = NULL;
     868        6976 :         constr->missing = NULL;
     869        6976 :         constr->num_defval = 0;
     870        6976 :         constr->check = NULL;
     871        6976 :         constr->num_check = 0;
     872        6976 :         desc->constr = constr;
     873             :     }
     874             :     else
     875             :     {
     876       63640 :         desc->constr = NULL;
     877             :     }
     878             : 
     879       70616 :     return desc;
     880             : }
     881             : 
     882             : /*
     883             :  * BuildDescFromLists
     884             :  *
     885             :  * Build a TupleDesc given lists of column names (as String nodes),
     886             :  * column type OIDs, typmods, and collation OIDs.
     887             :  *
     888             :  * No constraints are generated.
     889             :  *
     890             :  * This is essentially a cut-down version of BuildDescForRelation for use
     891             :  * with functions returning RECORD.
     892             :  */
     893             : TupleDesc
     894         690 : BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
     895             : {
     896             :     int         natts;
     897             :     AttrNumber  attnum;
     898             :     ListCell   *l1;
     899             :     ListCell   *l2;
     900             :     ListCell   *l3;
     901             :     ListCell   *l4;
     902             :     TupleDesc   desc;
     903             : 
     904         690 :     natts = list_length(names);
     905             :     Assert(natts == list_length(types));
     906             :     Assert(natts == list_length(typmods));
     907             :     Assert(natts == list_length(collations));
     908             : 
     909             :     /*
     910             :      * allocate a new tuple descriptor
     911             :      */
     912         690 :     desc = CreateTemplateTupleDesc(natts);
     913             : 
     914         690 :     attnum = 0;
     915        2554 :     forfour(l1, names, l2, types, l3, typmods, l4, collations)
     916             :     {
     917        1864 :         char       *attname = strVal(lfirst(l1));
     918        1864 :         Oid         atttypid = lfirst_oid(l2);
     919        1864 :         int32       atttypmod = lfirst_int(l3);
     920        1864 :         Oid         attcollation = lfirst_oid(l4);
     921             : 
     922        1864 :         attnum++;
     923             : 
     924        1864 :         TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
     925        1864 :         TupleDescInitEntryCollation(desc, attnum, attcollation);
     926             :     }
     927             : 
     928         690 :     return desc;
     929             : }

Generated by: LCOV version 1.13