LCOV - code coverage report
Current view: top level - src/backend/access/common - tupdesc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 11devel Lines: 306 322 95.0 %
Date: 2018-02-20 09:20:13 Functions: 16 16 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 127 153 83.0 %

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

Generated by: LCOV version 1.13