LCOV - differential code coverage report
Current view: top level - src/backend/access/common - tupdesc.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 92.2 % 398 367 1 7 2 21 5 60 30 272 5 77 11
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 16 16 4 3 9 4
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * tupdesc.c
       4                 :  *    POSTGRES tuple descriptor support code
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, 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 CBC     7137282 : CreateTemplateTupleDesc(int natts)
      46                 : {
      47                 :     TupleDesc   desc;
      48                 : 
      49                 :     /*
      50                 :      * sanity checks
      51                 :      */
      52 GNC     7137282 :     Assert(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 CBC     7137282 :     desc = (TupleDesc) palloc(offsetof(struct TupleDescData, attrs) +
      67         7137282 :                               natts * sizeof(FormData_pg_attribute));
      68                 : 
      69                 :     /*
      70                 :      * Initialize other fields of the tupdesc.
      71                 :      */
      72         7137282 :     desc->natts = natts;
      73         7137282 :     desc->constr = NULL;
      74         7137282 :     desc->tdtypeid = RECORDOID;
      75         7137282 :     desc->tdtypmod = -1;
      76         7137282 :     desc->tdrefcount = -1;       /* assume not reference-counted */
      77                 : 
      78         7137282 :     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         3291810 : CreateTupleDesc(int natts, Form_pg_attribute *attrs)
      91                 : {
      92                 :     TupleDesc   desc;
      93                 :     int         i;
      94                 : 
      95         3291810 :     desc = CreateTemplateTupleDesc(natts);
      96                 : 
      97        51497225 :     for (i = 0; i < natts; ++i)
      98        48205415 :         memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
      99                 : 
     100         3291810 :     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          419124 : CreateTupleDescCopy(TupleDesc tupdesc)
     112                 : {
     113                 :     TupleDesc   desc;
     114                 :     int         i;
     115                 : 
     116          419124 :     desc = CreateTemplateTupleDesc(tupdesc->natts);
     117                 : 
     118                 :     /* Flat-copy the attribute array */
     119          419124 :     memcpy(TupleDescAttr(desc, 0),
     120          419124 :            TupleDescAttr(tupdesc, 0),
     121          419124 :            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         1907643 :     for (i = 0; i < desc->natts; i++)
     128                 :     {
     129         1488519 :         Form_pg_attribute att = TupleDescAttr(desc, i);
     130                 : 
     131         1488519 :         att->attnotnull = false;
     132         1488519 :         att->atthasdef = false;
     133         1488519 :         att->atthasmissing = false;
     134         1488519 :         att->attidentity = '\0';
     135         1488519 :         att->attgenerated = '\0';
     136                 :     }
     137                 : 
     138                 :     /* We can copy the tuple type identification, too */
     139          419124 :     desc->tdtypeid = tupdesc->tdtypeid;
     140          419124 :     desc->tdtypmod = tupdesc->tdtypmod;
     141                 : 
     142          419124 :     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          351050 : CreateTupleDescCopyConstr(TupleDesc tupdesc)
     152                 : {
     153                 :     TupleDesc   desc;
     154          351050 :     TupleConstr *constr = tupdesc->constr;
     155                 :     int         i;
     156                 : 
     157          351050 :     desc = CreateTemplateTupleDesc(tupdesc->natts);
     158                 : 
     159                 :     /* Flat-copy the attribute array */
     160          351050 :     memcpy(TupleDescAttr(desc, 0),
     161          351050 :            TupleDescAttr(tupdesc, 0),
     162          351050 :            desc->natts * sizeof(FormData_pg_attribute));
     163                 : 
     164                 :     /* Copy the TupleConstr data structure, if any */
     165          351050 :     if (constr)
     166                 :     {
     167          324155 :         TupleConstr *cpy = (TupleConstr *) palloc0(sizeof(TupleConstr));
     168                 : 
     169          324155 :         cpy->has_not_null = constr->has_not_null;
     170          324155 :         cpy->has_generated_stored = constr->has_generated_stored;
     171                 : 
     172          324155 :         if ((cpy->num_defval = constr->num_defval) > 0)
     173                 :         {
     174            1754 :             cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault));
     175            1754 :             memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault));
     176            4215 :             for (i = cpy->num_defval - 1; i >= 0; i--)
     177            2461 :                 cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin);
     178                 :         }
     179                 : 
     180          324155 :         if (constr->missing)
     181                 :         {
     182             273 :             cpy->missing = (AttrMissing *) palloc(tupdesc->natts * sizeof(AttrMissing));
     183             273 :             memcpy(cpy->missing, constr->missing, tupdesc->natts * sizeof(AttrMissing));
     184            2240 :             for (i = tupdesc->natts - 1; i >= 0; i--)
     185                 :             {
     186            1967 :                 if (constr->missing[i].am_present)
     187                 :                 {
     188             522 :                     Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
     189                 : 
     190             522 :                     cpy->missing[i].am_value = datumCopy(constr->missing[i].am_value,
     191             522 :                                                          attr->attbyval,
     192             522 :                                                          attr->attlen);
     193                 :                 }
     194                 :             }
     195                 :         }
     196                 : 
     197          324155 :         if ((cpy->num_check = constr->num_check) > 0)
     198                 :         {
     199             925 :             cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck));
     200             925 :             memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck));
     201            2209 :             for (i = cpy->num_check - 1; i >= 0; i--)
     202                 :             {
     203            1284 :                 cpy->check[i].ccname = pstrdup(constr->check[i].ccname);
     204            1284 :                 cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin);
     205            1284 :                 cpy->check[i].ccvalid = constr->check[i].ccvalid;
     206            1284 :                 cpy->check[i].ccnoinherit = constr->check[i].ccnoinherit;
     207                 :             }
     208                 :         }
     209                 : 
     210          324155 :         desc->constr = cpy;
     211                 :     }
     212                 : 
     213                 :     /* We can copy the tuple type identification, too */
     214          351050 :     desc->tdtypeid = tupdesc->tdtypeid;
     215          351050 :     desc->tdtypmod = tupdesc->tdtypmod;
     216                 : 
     217          351050 :     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           36116 : TupleDescCopy(TupleDesc dst, TupleDesc src)
     230                 : {
     231                 :     int         i;
     232                 : 
     233                 :     /* Flat-copy the header and attribute array */
     234           36116 :     memcpy(dst, src, TupleDescSize(src));
     235                 : 
     236                 :     /*
     237                 :      * Since we're not copying constraints and defaults, clear fields
     238                 :      * associated with them.
     239                 :      */
     240          140446 :     for (i = 0; i < dst->natts; i++)
     241                 :     {
     242          104330 :         Form_pg_attribute att = TupleDescAttr(dst, i);
     243                 : 
     244          104330 :         att->attnotnull = false;
     245          104330 :         att->atthasdef = false;
     246          104330 :         att->atthasmissing = false;
     247          104330 :         att->attidentity = '\0';
     248          104330 :         att->attgenerated = '\0';
     249                 :     }
     250           36116 :     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           36116 :     dst->tdrefcount = -1;
     257           36116 : }
     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            1652 : TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
     268                 :                    TupleDesc src, AttrNumber srcAttno)
     269                 : {
     270            1652 :     Form_pg_attribute dstAtt = TupleDescAttr(dst, dstAttno - 1);
     271            1652 :     Form_pg_attribute srcAtt = TupleDescAttr(src, srcAttno - 1);
     272                 : 
     273                 :     /*
     274                 :      * sanity checks
     275                 :      */
     276 GNC        1652 :     Assert(PointerIsValid(src));
     277            1652 :     Assert(PointerIsValid(dst));
     278            1652 :     Assert(srcAttno >= 1);
     279            1652 :     Assert(srcAttno <= src->natts);
     280            1652 :     Assert(dstAttno >= 1);
     281            1652 :     Assert(dstAttno <= dst->natts);
     282                 : 
     283 CBC        1652 :     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            1652 :     dstAtt->attnum = dstAttno;
     295            1652 :     dstAtt->attcacheoff = -1;
     296                 : 
     297                 :     /* since we're not copying constraints or defaults, clear these */
     298            1652 :     dstAtt->attnotnull = false;
     299            1652 :     dstAtt->atthasdef = false;
     300            1652 :     dstAtt->atthasmissing = false;
     301            1652 :     dstAtt->attidentity = '\0';
     302            1652 :     dstAtt->attgenerated = '\0';
     303            1652 : }
     304                 : 
     305                 : /*
     306                 :  * Free a TupleDesc including all substructure
     307                 :  */
     308                 : void
     309          829615 : 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          829615 :     Assert(tupdesc->tdrefcount <= 0);
     318                 : 
     319          829615 :     if (tupdesc->constr)
     320                 :     {
     321          250156 :         if (tupdesc->constr->num_defval > 0)
     322                 :         {
     323           10672 :             AttrDefault *attrdef = tupdesc->constr->defval;
     324                 : 
     325           26049 :             for (i = tupdesc->constr->num_defval - 1; i >= 0; i--)
     326           15377 :                 pfree(attrdef[i].adbin);
     327           10672 :             pfree(attrdef);
     328                 :         }
     329          250156 :         if (tupdesc->constr->missing)
     330                 :         {
     331            1569 :             AttrMissing *attrmiss = tupdesc->constr->missing;
     332                 : 
     333           11737 :             for (i = tupdesc->natts - 1; i >= 0; i--)
     334                 :             {
     335           10168 :                 if (attrmiss[i].am_present
     336            3471 :                     && !TupleDescAttr(tupdesc, i)->attbyval)
     337            1339 :                     pfree(DatumGetPointer(attrmiss[i].am_value));
     338                 :             }
     339            1569 :             pfree(attrmiss);
     340                 :         }
     341          250156 :         if (tupdesc->constr->num_check > 0)
     342                 :         {
     343            4305 :             ConstrCheck *check = tupdesc->constr->check;
     344                 : 
     345            9851 :             for (i = tupdesc->constr->num_check - 1; i >= 0; i--)
     346                 :             {
     347            5546 :                 pfree(check[i].ccname);
     348            5546 :                 pfree(check[i].ccbin);
     349                 :             }
     350            4305 :             pfree(check);
     351                 :         }
     352          250156 :         pfree(tupdesc->constr);
     353                 :     }
     354                 : 
     355          829615 :     pfree(tupdesc);
     356          829615 : }
     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        21210614 : IncrTupleDescRefCount(TupleDesc tupdesc)
     367                 : {
     368        21210614 :     Assert(tupdesc->tdrefcount >= 0);
     369                 : 
     370        21210614 :     ResourceOwnerEnlargeTupleDescs(CurrentResourceOwner);
     371        21210614 :     tupdesc->tdrefcount++;
     372        21210614 :     ResourceOwnerRememberTupleDesc(CurrentResourceOwner, tupdesc);
     373        21210614 : }
     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        21210614 : DecrTupleDescRefCount(TupleDesc tupdesc)
     385                 : {
     386        21210614 :     Assert(tupdesc->tdrefcount > 0);
     387                 : 
     388        21210614 :     ResourceOwnerForgetTupleDesc(CurrentResourceOwner, tupdesc);
     389        21210614 :     if (--tupdesc->tdrefcount == 0)
     390             141 :         FreeTupleDesc(tupdesc);
     391        21210614 : }
     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          524491 : equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
     403                 : {
     404                 :     int         i,
     405                 :                 n;
     406                 : 
     407          524491 :     if (tupdesc1->natts != tupdesc2->natts)
     408            1186 :         return false;
     409          523305 :     if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
     410             817 :         return false;
     411                 : 
     412         5604215 :     for (i = 0; i < tupdesc1->natts; i++)
     413                 :     {
     414         5091954 :         Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
     415         5091954 :         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         5091954 :         if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
     431            5255 :             return false;
     432         5086699 :         if (attr1->atttypid != attr2->atttypid)
     433             476 :             return false;
     434         5086223 :         if (attr1->attstattarget != attr2->attstattarget)
     435              28 :             return false;
     436         5086195 :         if (attr1->attlen != attr2->attlen)
     437               4 :             return false;
     438         5086191 :         if (attr1->attndims != attr2->attndims)
     439 UBC           0 :             return false;
     440 CBC     5086191 :         if (attr1->atttypmod != attr2->atttypmod)
     441              23 :             return false;
     442         5086168 :         if (attr1->attbyval != attr2->attbyval)
     443              76 :             return false;
     444         5086092 :         if (attr1->attalign != attr2->attalign)
     445 UBC           0 :             return false;
     446 CBC     5086092 :         if (attr1->attstorage != attr2->attstorage)
     447             102 :             return false;
     448         5085990 :         if (attr1->attcompression != attr2->attcompression)
     449              30 :             return false;
     450         5085960 :         if (attr1->attnotnull != attr2->attnotnull)
     451             588 :             return false;
     452         5085372 :         if (attr1->atthasdef != attr2->atthasdef)
     453            1748 :             return false;
     454         5083624 :         if (attr1->attidentity != attr2->attidentity)
     455              62 :             return false;
     456         5083562 :         if (attr1->attgenerated != attr2->attgenerated)
     457              10 :             return false;
     458         5083552 :         if (attr1->attisdropped != attr2->attisdropped)
     459 UBC           0 :             return false;
     460 CBC     5083552 :         if (attr1->attislocal != attr2->attislocal)
     461            1526 :             return false;
     462         5082026 :         if (attr1->attinhcount != attr2->attinhcount)
     463             299 :             return false;
     464         5081727 :         if (attr1->attcollation != attr2->attcollation)
     465 UBC           0 :             return false;
     466                 :         /* variable-length fields are not even present... */
     467                 :     }
     468                 : 
     469 CBC      512261 :     if (tupdesc1->constr != NULL)
     470                 :     {
     471           90540 :         TupleConstr *constr1 = tupdesc1->constr;
     472           90540 :         TupleConstr *constr2 = tupdesc2->constr;
     473                 : 
     474           90540 :         if (constr2 == NULL)
     475              67 :             return false;
     476           90473 :         if (constr1->has_not_null != constr2->has_not_null)
     477 UBC           0 :             return false;
     478 CBC       90473 :         if (constr1->has_generated_stored != constr2->has_generated_stored)
     479             206 :             return false;
     480           90267 :         n = constr1->num_defval;
     481           90267 :         if (n != (int) constr2->num_defval)
     482 UBC           0 :             return false;
     483                 :         /* We assume here that both AttrDefault arrays are in adnum order */
     484 CBC       95142 :         for (i = 0; i < n; i++)
     485                 :         {
     486            4875 :             AttrDefault *defval1 = constr1->defval + i;
     487            4875 :             AttrDefault *defval2 = constr2->defval + i;
     488                 : 
     489            4875 :             if (defval1->adnum != defval2->adnum)
     490 UBC           0 :                 return false;
     491 CBC        4875 :             if (strcmp(defval1->adbin, defval2->adbin) != 0)
     492 UBC           0 :                 return false;
     493                 :         }
     494 CBC       90267 :         if (constr1->missing)
     495                 :         {
     496             215 :             if (!constr2->missing)
     497              33 :                 return false;
     498            1096 :             for (i = 0; i < tupdesc1->natts; i++)
     499                 :             {
     500             914 :                 AttrMissing *missval1 = constr1->missing + i;
     501             914 :                 AttrMissing *missval2 = constr2->missing + i;
     502                 : 
     503             914 :                 if (missval1->am_present != missval2->am_present)
     504 UBC           0 :                     return false;
     505 CBC         914 :                 if (missval1->am_present)
     506                 :                 {
     507             235 :                     Form_pg_attribute missatt1 = TupleDescAttr(tupdesc1, i);
     508                 : 
     509             235 :                     if (!datumIsEqual(missval1->am_value, missval2->am_value,
     510             235 :                                       missatt1->attbyval, missatt1->attlen))
     511 UBC           0 :                         return false;
     512                 :                 }
     513                 :             }
     514                 :         }
     515 CBC       90052 :         else if (constr2->missing)
     516               2 :             return false;
     517           90232 :         n = constr1->num_check;
     518           90232 :         if (n != (int) constr2->num_check)
     519             587 :             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           90677 :         for (i = 0; i < n; i++)
     527                 :         {
     528            1071 :             ConstrCheck *check1 = constr1->check + i;
     529            1071 :             ConstrCheck *check2 = constr2->check + i;
     530                 : 
     531            1071 :             if (!(strcmp(check1->ccname, check2->ccname) == 0 &&
     532            1071 :                   strcmp(check1->ccbin, check2->ccbin) == 0 &&
     533            1071 :                   check1->ccvalid == check2->ccvalid &&
     534            1032 :                   check1->ccnoinherit == check2->ccnoinherit))
     535              39 :                 return false;
     536                 :         }
     537                 :     }
     538          421721 :     else if (tupdesc2->constr != NULL)
     539             663 :         return false;
     540          510664 :     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          271499 : hashTupleDesc(TupleDesc desc)
     555                 : {
     556                 :     uint32      s;
     557                 :     int         i;
     558                 : 
     559          271499 :     s = hash_combine(0, hash_uint32(desc->natts));
     560          271499 :     s = hash_combine(s, hash_uint32(desc->tdtypeid));
     561         3888426 :     for (i = 0; i < desc->natts; ++i)
     562         3616927 :         s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
     563                 : 
     564          271499 :     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         6458843 : 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 GNC     6458843 :     Assert(PointerIsValid(desc));
     598         6458843 :     Assert(attributeNumber >= 1);
     599         6458843 :     Assert(attributeNumber <= desc->natts);
     600         6458843 :     Assert(attdim >= 0);
     601         6458843 :     Assert(attdim <= PG_INT16_MAX);
     602 ECB             : 
     603                 :     /*
     604                 :      * initialize the attribute fields
     605                 :      */
     606 GIC     6458843 :     att = TupleDescAttr(desc, attributeNumber - 1);
     607                 : 
     608 CBC     6458843 :     att->attrelid = 0;           /* dummy value */
     609                 : 
     610 ECB             :     /*
     611                 :      * Note: attributeName can be NULL, because the planner doesn't always
     612                 :      * fill in valid resname values in targetlists, particularly for resjunk
     613                 :      * attributes. Also, do nothing if caller wants to re-use the old attname.
     614                 :      */
     615 GIC     6458843 :     if (attributeName == NULL)
     616         7089374 :         MemSet(NameStr(att->attname), 0, NAMEDATALEN);
     617 CBC     4939077 :     else if (attributeName != NameStr(att->attname))
     618         4932891 :         namestrcpy(&(att->attname), attributeName);
     619 ECB             : 
     620 CBC     6458843 :     att->attstattarget = -1;
     621 GIC     6458843 :     att->attcacheoff = -1;
     622 CBC     6458843 :     att->atttypmod = typmod;
     623 ECB             : 
     624 CBC     6458843 :     att->attnum = attributeNumber;
     625 GIC     6458843 :     att->attndims = attdim;
     626 ECB             : 
     627 CBC     6458843 :     att->attnotnull = false;
     628 GIC     6458843 :     att->atthasdef = false;
     629 CBC     6458843 :     att->atthasmissing = false;
     630         6458843 :     att->attidentity = '\0';
     631         6458843 :     att->attgenerated = '\0';
     632         6458843 :     att->attisdropped = false;
     633         6458843 :     att->attislocal = true;
     634         6458843 :     att->attinhcount = 0;
     635 ECB             :     /* variable-length fields are not present in tupledescs */
     636                 : 
     637 GIC     6458843 :     tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(oidtypeid));
     638         6458843 :     if (!HeapTupleIsValid(tuple))
     639 LBC           0 :         elog(ERROR, "cache lookup failed for type %u", oidtypeid);
     640 CBC     6458843 :     typeForm = (Form_pg_type) GETSTRUCT(tuple);
     641 EUB             : 
     642 CBC     6458843 :     att->atttypid = oidtypeid;
     643 GIC     6458843 :     att->attlen = typeForm->typlen;
     644 CBC     6458843 :     att->attbyval = typeForm->typbyval;
     645         6458843 :     att->attalign = typeForm->typalign;
     646         6458843 :     att->attstorage = typeForm->typstorage;
     647         6458843 :     att->attcompression = InvalidCompressionMethod;
     648         6458843 :     att->attcollation = typeForm->typcollation;
     649 ECB             : 
     650 CBC     6458843 :     ReleaseSysCache(tuple);
     651 GIC     6458843 : }
     652 ECB             : 
     653                 : /*
     654                 :  * TupleDescInitBuiltinEntry
     655                 :  *      Initialize a tuple descriptor without catalog access.  Only
     656                 :  *      a limited range of builtin types are supported.
     657                 :  */
     658                 : void
     659 GIC        5187 : TupleDescInitBuiltinEntry(TupleDesc desc,
     660                 :                           AttrNumber attributeNumber,
     661 ECB             :                           const char *attributeName,
     662                 :                           Oid oidtypeid,
     663                 :                           int32 typmod,
     664                 :                           int attdim)
     665                 : {
     666                 :     Form_pg_attribute att;
     667                 : 
     668                 :     /* sanity checks */
     669 GNC        5187 :     Assert(PointerIsValid(desc));
     670            5187 :     Assert(attributeNumber >= 1);
     671            5187 :     Assert(attributeNumber <= desc->natts);
     672            5187 :     Assert(attdim >= 0);
     673            5187 :     Assert(attdim <= PG_INT16_MAX);
     674 ECB             : 
     675                 :     /* initialize the attribute fields */
     676 CBC        5187 :     att = TupleDescAttr(desc, attributeNumber - 1);
     677            5187 :     att->attrelid = 0;           /* dummy value */
     678                 : 
     679                 :     /* unlike TupleDescInitEntry, we require an attribute name */
     680            5187 :     Assert(attributeName != NULL);
     681            5187 :     namestrcpy(&(att->attname), attributeName);
     682                 : 
     683 GIC        5187 :     att->attstattarget = -1;
     684 CBC        5187 :     att->attcacheoff = -1;
     685            5187 :     att->atttypmod = typmod;
     686                 : 
     687            5187 :     att->attnum = attributeNumber;
     688            5187 :     att->attndims = attdim;
     689 ECB             : 
     690 GIC        5187 :     att->attnotnull = false;
     691 CBC        5187 :     att->atthasdef = false;
     692            5187 :     att->atthasmissing = false;
     693 GIC        5187 :     att->attidentity = '\0';
     694 CBC        5187 :     att->attgenerated = '\0';
     695            5187 :     att->attisdropped = false;
     696            5187 :     att->attislocal = true;
     697            5187 :     att->attinhcount = 0;
     698 ECB             :     /* variable-length fields are not present in tupledescs */
     699                 : 
     700 CBC        5187 :     att->atttypid = oidtypeid;
     701 ECB             : 
     702                 :     /*
     703                 :      * Our goal here is to support just enough types to let basic builtin
     704                 :      * commands work without catalog access - e.g. so that we can do certain
     705                 :      * things even in processes that are not connected to a database.
     706                 :      */
     707 GIC        5187 :     switch (oidtypeid)
     708                 :     {
     709            4155 :         case TEXTOID:
     710                 :         case TEXTARRAYOID:
     711 CBC        4155 :             att->attlen = -1;
     712 GIC        4155 :             att->attbyval = false;
     713 CBC        4155 :             att->attalign = TYPALIGN_INT;
     714 GIC        4155 :             att->attstorage = TYPSTORAGE_EXTENDED;
     715 CBC        4155 :             att->attcompression = InvalidCompressionMethod;
     716            4155 :             att->attcollation = DEFAULT_COLLATION_OID;
     717            4155 :             break;
     718 ECB             : 
     719 LBC           0 :         case BOOLOID:
     720               0 :             att->attlen = 1;
     721               0 :             att->attbyval = true;
     722 UIC           0 :             att->attalign = TYPALIGN_CHAR;
     723 UBC           0 :             att->attstorage = TYPSTORAGE_PLAIN;
     724               0 :             att->attcompression = InvalidCompressionMethod;
     725               0 :             att->attcollation = InvalidOid;
     726               0 :             break;
     727 EUB             : 
     728 UBC           0 :         case INT4OID:
     729               0 :             att->attlen = 4;
     730               0 :             att->attbyval = true;
     731 UIC           0 :             att->attalign = TYPALIGN_INT;
     732 UBC           0 :             att->attstorage = TYPSTORAGE_PLAIN;
     733               0 :             att->attcompression = InvalidCompressionMethod;
     734               0 :             att->attcollation = InvalidOid;
     735               0 :             break;
     736 EUB             : 
     737 GBC         906 :         case INT8OID:
     738             906 :             att->attlen = 8;
     739             906 :             att->attbyval = FLOAT8PASSBYVAL;
     740 GIC         906 :             att->attalign = TYPALIGN_DOUBLE;
     741 CBC         906 :             att->attstorage = TYPSTORAGE_PLAIN;
     742             906 :             att->attcompression = InvalidCompressionMethod;
     743             906 :             att->attcollation = InvalidOid;
     744             906 :             break;
     745 ECB             : 
     746 GNC         126 :         case OIDOID:
     747             126 :             att->attlen = 4;
     748             126 :             att->attbyval = true;
     749             126 :             att->attalign = TYPALIGN_INT;
     750             126 :             att->attstorage = TYPSTORAGE_PLAIN;
     751             126 :             att->attcompression = InvalidCompressionMethod;
     752             126 :             att->attcollation = InvalidOid;
     753             126 :             break;
     754                 : 
     755 LBC           0 :         default:
     756               0 :             elog(ERROR, "unsupported type %u", oidtypeid);
     757 ECB             :     }
     758 GIC        5187 : }
     759 ECB             : 
     760                 : /*
     761                 :  * TupleDescInitEntryCollation
     762                 :  *
     763                 :  * Assign a nondefault collation to a previously initialized tuple descriptor
     764                 :  * entry.
     765                 :  */
     766                 : void
     767 GIC     2804782 : TupleDescInitEntryCollation(TupleDesc desc,
     768 EUB             :                             AttrNumber attributeNumber,
     769                 :                             Oid collationid)
     770                 : {
     771 ECB             :     /*
     772                 :      * sanity checks
     773                 :      */
     774 GNC     2804782 :     Assert(PointerIsValid(desc));
     775         2804782 :     Assert(attributeNumber >= 1);
     776         2804782 :     Assert(attributeNumber <= desc->natts);
     777                 : 
     778 GIC     2804782 :     TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid;
     779         2804782 : }
     780 ECB             : 
     781                 : 
     782                 : /*
     783                 :  * BuildDescForRelation
     784                 :  *
     785                 :  * Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
     786                 :  *
     787                 :  * Note: tdtypeid will need to be filled in later on.
     788                 :  */
     789                 : TupleDesc
     790 GIC       62881 : BuildDescForRelation(List *schema)
     791 ECB             : {
     792                 :     int         natts;
     793                 :     AttrNumber  attnum;
     794                 :     ListCell   *l;
     795                 :     TupleDesc   desc;
     796                 :     bool        has_not_null;
     797                 :     char       *attname;
     798                 :     Oid         atttypid;
     799                 :     int32       atttypmod;
     800                 :     Oid         attcollation;
     801                 :     int         attdim;
     802                 : 
     803                 :     /*
     804                 :      * allocate a new tuple descriptor
     805                 :      */
     806 GIC       62881 :     natts = list_length(schema);
     807           62881 :     desc = CreateTemplateTupleDesc(natts);
     808           62881 :     has_not_null = false;
     809                 : 
     810           62881 :     attnum = 0;
     811                 : 
     812          549933 :     foreach(l, schema)
     813                 :     {
     814          487064 :         ColumnDef  *entry = lfirst(l);
     815                 :         AclResult   aclresult;
     816                 :         Form_pg_attribute att;
     817                 : 
     818                 :         /*
     819 ECB             :          * for each entry in the list, get the name and type information from
     820                 :          * the list and have TupleDescInitEntry fill in the attribute
     821                 :          * information we need.
     822                 :          */
     823 CBC      487064 :         attnum++;
     824                 : 
     825          487064 :         attname = entry->colname;
     826 GIC      487064 :         typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
     827 ECB             : 
     828 GNC      487064 :         aclresult = object_aclcheck(TypeRelationId, atttypid, GetUserId(), ACL_USAGE);
     829 GIC      487064 :         if (aclresult != ACLCHECK_OK)
     830              12 :             aclcheck_error_type(aclresult, atttypid);
     831                 : 
     832          487052 :         attcollation = GetColumnDefCollation(NULL, entry, atttypid);
     833          487052 :         attdim = list_length(entry->typeName->arrayBounds);
     834 GNC      487052 :         if (attdim > PG_INT16_MAX)
     835 UNC           0 :             ereport(ERROR,
     836                 :                     errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     837                 :                     errmsg("too many array dimensions"));
     838                 : 
     839 GIC      487052 :         if (entry->typeName->setof)
     840 LBC           0 :             ereport(ERROR,
     841                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
     842 ECB             :                      errmsg("column \"%s\" cannot be declared SETOF",
     843                 :                             attname)));
     844                 : 
     845 CBC      487052 :         TupleDescInitEntry(desc, attnum, attname,
     846 ECB             :                            atttypid, atttypmod, attdim);
     847 CBC      487052 :         att = TupleDescAttr(desc, attnum - 1);
     848                 : 
     849 ECB             :         /* Override TupleDescInitEntry's settings as requested */
     850 CBC      487052 :         TupleDescInitEntryCollation(desc, attnum, attcollation);
     851          487052 :         if (entry->storage)
     852 GBC        8734 :             att->attstorage = entry->storage;
     853                 : 
     854                 :         /* Fill in additional stuff not handled by TupleDescInitEntry */
     855 GIC      487052 :         att->attnotnull = entry->is_not_null;
     856 CBC      487052 :         has_not_null |= entry->is_not_null;
     857 GBC      487052 :         att->attislocal = entry->is_local;
     858 GIC      487052 :         att->attinhcount = entry->inhcount;
     859                 :     }
     860                 : 
     861           62869 :     if (has_not_null)
     862 ECB             :     {
     863 GIC        5312 :         TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
     864 ECB             : 
     865 GIC        5312 :         constr->has_not_null = true;
     866            5312 :         constr->has_generated_stored = false;
     867 CBC        5312 :         constr->defval = NULL;
     868            5312 :         constr->missing = NULL;
     869            5312 :         constr->num_defval = 0;
     870 GIC        5312 :         constr->check = NULL;
     871            5312 :         constr->num_check = 0;
     872 CBC        5312 :         desc->constr = constr;
     873 ECB             :     }
     874                 :     else
     875                 :     {
     876 GIC       57557 :         desc->constr = NULL;
     877                 :     }
     878 ECB             : 
     879 GIC       62869 :     return desc;
     880 ECB             : }
     881                 : 
     882                 : /*
     883                 :  * BuildDescFromLists
     884                 :  *
     885                 :  * Build a TupleDesc given lists of column names (as String nodes),
     886                 :  * column type OIDs, typmods, and collation OIDs.
     887                 :  *
     888                 :  * No constraints are generated.
     889                 :  *
     890                 :  * This is essentially a cut-down version of BuildDescForRelation for use
     891                 :  * with functions returning RECORD.
     892                 :  */
     893                 : TupleDesc
     894 GIC         470 : BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
     895                 : {
     896 ECB             :     int         natts;
     897                 :     AttrNumber  attnum;
     898                 :     ListCell   *l1;
     899                 :     ListCell   *l2;
     900                 :     ListCell   *l3;
     901                 :     ListCell   *l4;
     902                 :     TupleDesc   desc;
     903                 : 
     904 GIC         470 :     natts = list_length(names);
     905             470 :     Assert(natts == list_length(types));
     906             470 :     Assert(natts == list_length(typmods));
     907             470 :     Assert(natts == list_length(collations));
     908                 : 
     909                 :     /*
     910                 :      * allocate a new tuple descriptor
     911 ECB             :      */
     912 GIC         470 :     desc = CreateTemplateTupleDesc(natts);
     913                 : 
     914             470 :     attnum = 0;
     915            1731 :     forfour(l1, names, l2, types, l3, typmods, l4, collations)
     916                 :     {
     917            1261 :         char       *attname = strVal(lfirst(l1));
     918            1261 :         Oid         atttypid = lfirst_oid(l2);
     919            1261 :         int32       atttypmod = lfirst_int(l3);
     920            1261 :         Oid         attcollation = lfirst_oid(l4);
     921 ECB             : 
     922 CBC        1261 :         attnum++;
     923 ECB             : 
     924 CBC        1261 :         TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
     925 GIC        1261 :         TupleDescInitEntryCollation(desc, attnum, attcollation);
     926                 :     }
     927                 : 
     928             470 :     return desc;
     929 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a