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

Generated by: LCOV version 1.13