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

Generated by: LCOV version 1.14