LCOV - differential code coverage report
Current view: top level - src/backend/catalog - pg_type.c (source / functions) Coverage Total Hit UBC CBC
Current: ba12a202ce1b5581dc0ed149cf3f637d7897ad5d vs 2866d8c7dbfc9d882a7d80fef93fbbe763709932 Lines: 93.6 % 283 265 18 265
Current Date: 2026-08-27 14:31:44 +0300 Functions: 100.0 % 7 7 7
Baseline: lcov-20260827-baseline Branches: 68.7 % 198 136 62 136
Baseline Date: 2026-08-27 14:31:58 +0300 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 1 1 1
(360..) days: 93.6 % 282 264 18 264
Function coverage date bins:
(360..) days: 100.0 % 7 7 7
Branch coverage date bins:
(30,360] days: 50.0 % 2 1 1 1
(360..) days: 68.9 % 196 135 61 135

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * pg_type.c
                                  4                 :                :  *    routines to support manipulation of the pg_type relation
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/catalog/pg_type.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : #include "postgres.h"
                                 16                 :                : 
                                 17                 :                : #include "access/htup_details.h"
                                 18                 :                : #include "access/table.h"
                                 19                 :                : #include "access/xact.h"
                                 20                 :                : #include "catalog/binary_upgrade.h"
                                 21                 :                : #include "catalog/catalog.h"
                                 22                 :                : #include "catalog/dependency.h"
                                 23                 :                : #include "catalog/indexing.h"
                                 24                 :                : #include "catalog/objectaccess.h"
                                 25                 :                : #include "catalog/pg_collation.h"
                                 26                 :                : #include "catalog/pg_namespace.h"
                                 27                 :                : #include "catalog/pg_proc.h"
                                 28                 :                : #include "catalog/pg_type.h"
                                 29                 :                : #include "commands/defrem.h"
                                 30                 :                : #include "commands/typecmds.h"
                                 31                 :                : #include "mb/pg_wchar.h"
                                 32                 :                : #include "miscadmin.h"
                                 33                 :                : #include "utils/acl.h"
                                 34                 :                : #include "utils/builtins.h"
                                 35                 :                : #include "utils/fmgroids.h"
                                 36                 :                : #include "utils/lsyscache.h"
                                 37                 :                : #include "utils/rel.h"
                                 38                 :                : #include "utils/syscache.h"
                                 39                 :                : 
                                 40                 :                : /* Potentially set by pg_upgrade_support functions */
                                 41                 :                : Oid         binary_upgrade_next_pg_type_oid = InvalidOid;
                                 42                 :                : 
                                 43                 :                : /* ----------------------------------------------------------------
                                 44                 :                :  *      TypeShellMake
                                 45                 :                :  *
                                 46                 :                :  *      This procedure inserts a "shell" tuple into the pg_type relation.
                                 47                 :                :  *      The type tuple inserted has valid but dummy values, and its
                                 48                 :                :  *      "typisdefined" field is false indicating it's not really defined.
                                 49                 :                :  *
                                 50                 :                :  *      This is used so that a tuple exists in the catalogs.  The I/O
                                 51                 :                :  *      functions for the type will link to this tuple.  When the full
                                 52                 :                :  *      CREATE TYPE command is issued, the bogus values will be replaced
                                 53                 :                :  *      with correct ones, and "typisdefined" will be set to true.
                                 54                 :                :  * ----------------------------------------------------------------
                                 55                 :                :  */
                                 56                 :                : ObjectAddress
 6393 tgl@sss.pgh.pa.us          57                 :CBC         150 : TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
                                 58                 :                : {
                                 59                 :                :     Relation    pg_type_desc;
                                 60                 :                :     TupleDesc   tupDesc;
                                 61                 :                :     int         i;
                                 62                 :                :     HeapTuple   tup;
                                 63                 :                :     Datum       values[Natts_pg_type];
                                 64                 :                :     bool        nulls[Natts_pg_type];
                                 65                 :                :     Oid         typoid;
                                 66                 :                :     NameData    name;
                                 67                 :                :     ObjectAddress address;
                                 68                 :                : 
  337 peter@eisentraut.org       69         [ -  + ]:            150 :     Assert(typeName);
                                 70                 :                : 
                                 71                 :                :     /*
                                 72                 :                :      * open pg_type
                                 73                 :                :      */
 2775 andres@anarazel.de         74                 :            150 :     pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
 8917 tgl@sss.pgh.pa.us          75                 :            150 :     tupDesc = pg_type_desc->rd_att;
                                 76                 :                : 
                                 77                 :                :     /*
                                 78                 :                :      * initialize our *nulls and *values arrays
                                 79                 :                :      */
10581 bruce@momjian.us           80         [ +  + ]:           4950 :     for (i = 0; i < Natts_pg_type; ++i)
                                 81                 :                :     {
 6507 tgl@sss.pgh.pa.us          82                 :           4800 :         nulls[i] = false;
  384                            83                 :           4800 :         values[i] = (Datum) 0;  /* redundant, but safe */
                                 84                 :                :     }
                                 85                 :                : 
                                 86                 :                :     /*
                                 87                 :                :      * initialize *values with the type name and dummy values
                                 88                 :                :      *
                                 89                 :                :      * The representational details are the same as int4 ... it doesn't really
                                 90                 :                :      * matter what they are so long as they are consistent.  Also note that we
                                 91                 :                :      * give it typtype = TYPTYPE_PSEUDO as extra insurance that it won't be
                                 92                 :                :      * mistaken for a usable type.
                                 93                 :                :      */
10375 scrappy@hub.org            94                 :            150 :     namestrcpy(&name, typeName);
 5551 tgl@sss.pgh.pa.us          95                 :            150 :     values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
                                 96                 :            150 :     values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
                                 97                 :            150 :     values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
 5176 peter_e@gmx.net            98                 :            150 :     values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32));
 5551 tgl@sss.pgh.pa.us          99                 :            150 :     values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true);
                                100                 :            150 :     values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO);
                                101                 :            150 :     values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE);
                                102                 :            150 :     values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false);
                                103                 :            150 :     values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false);
                                104                 :            150 :     values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM);
                                105                 :            150 :     values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid);
 2087                           106                 :            150 :     values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(InvalidOid);
 5551                           107                 :            150 :     values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid);
                                108                 :            150 :     values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid);
                                109                 :            150 :     values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN);
                                110                 :            150 :     values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT);
                                111                 :            150 :     values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid);
                                112                 :            150 :     values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid);
                                113                 :            150 :     values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid);
                                114                 :            150 :     values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid);
                                115                 :            150 :     values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid);
 2367                           116                 :            150 :     values[Anum_pg_type_typalign - 1] = CharGetDatum(TYPALIGN_INT);
                                117                 :            150 :     values[Anum_pg_type_typstorage - 1] = CharGetDatum(TYPSTORAGE_PLAIN);
 5551                           118                 :            150 :     values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false);
                                119                 :            150 :     values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid);
                                120                 :            150 :     values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1);
                                121                 :            150 :     values[Anum_pg_type_typndims - 1] = Int32GetDatum(0);
                                122                 :            150 :     values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid);
                                123                 :            150 :     nulls[Anum_pg_type_typdefaultbin - 1] = true;
                                124                 :            150 :     nulls[Anum_pg_type_typdefault - 1] = true;
 5364 peter_e@gmx.net           125                 :            150 :     nulls[Anum_pg_type_typacl - 1] = true;
                                126                 :                : 
                                127                 :                :     /* Use binary-upgrade override for pg_type.oid? */
 4385 bruce@momjian.us          128         [ +  + ]:            150 :     if (IsBinaryUpgrade)
                                129                 :                :     {
                                130         [ -  + ]:              8 :         if (!OidIsValid(binary_upgrade_next_pg_type_oid))
 4385 bruce@momjian.us          131         [ #  # ]:UBC           0 :             ereport(ERROR,
                                132                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                133                 :                :                      errmsg("pg_type OID value not set when in binary upgrade mode")));
                                134                 :                : 
 2837 andres@anarazel.de        135                 :CBC           8 :         typoid = binary_upgrade_next_pg_type_oid;
 6090 bruce@momjian.us          136                 :              8 :         binary_upgrade_next_pg_type_oid = InvalidOid;
                                137                 :                :     }
                                138                 :                :     else
                                139                 :                :     {
 2837 andres@anarazel.de        140                 :            142 :         typoid = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId,
                                141                 :                :                                     Anum_pg_type_oid);
                                142                 :                :     }
                                143                 :                : 
                                144                 :            150 :     values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typoid);
                                145                 :                : 
                                146                 :                :     /*
                                147                 :                :      * create a new type tuple
                                148                 :                :      */
                                149                 :            150 :     tup = heap_form_tuple(tupDesc, values, nulls);
                                150                 :                : 
                                151                 :                :     /*
                                152                 :                :      * insert the tuple in the relation and get the tuple's oid.
                                153                 :                :      */
                                154                 :            150 :     CatalogTupleInsert(pg_type_desc, tup);
                                155                 :                : 
                                156                 :                :     /*
                                157                 :                :      * Create dependencies.  We can/must skip this in bootstrap mode.
                                158                 :                :      */
 8632 tgl@sss.pgh.pa.us         159         [ +  - ]:            150 :     if (!IsBootstrapProcessingMode())
 2365                           160                 :            150 :         GenerateTypeDependencies(tup,
                                161                 :                :                                  pg_type_desc,
                                162                 :                :                                  NULL,
                                163                 :                :                                  NULL,
                                164                 :                :                                  0,
                                165                 :                :                                  false,
                                166                 :                :                                  false,
                                167                 :                :                                  true,  /* make extension dependency */
                                168                 :                :                                  false);
                                169                 :                : 
                                170                 :                :     /* Post creation hook for new shell type */
 4922 rhaas@postgresql.org      171         [ -  + ]:            150 :     InvokeObjectPostCreateHook(TypeRelationId, typoid, 0);
                                172                 :                : 
 4195 alvherre@alvh.no-ip.      173                 :            150 :     ObjectAddressSet(address, TypeRelationId, typoid);
                                174                 :                : 
                                175                 :                :     /*
                                176                 :                :      * clean up and return the type-oid
                                177                 :                :      */
 9751 JanWieck@Yahoo.com        178                 :            150 :     heap_freetuple(tup);
 2775 andres@anarazel.de        179                 :            150 :     table_close(pg_type_desc, RowExclusiveLock);
                                180                 :                : 
 4195 alvherre@alvh.no-ip.      181                 :            150 :     return address;
                                182                 :                : }
                                183                 :                : 
                                184                 :                : /* ----------------------------------------------------------------
                                185                 :                :  *      TypeCreate
                                186                 :                :  *
                                187                 :                :  *      This does all the necessary work needed to define a new type.
                                188                 :                :  *
                                189                 :                :  *      Returns the ObjectAddress assigned to the new type.
                                190                 :                :  *      If newTypeOid is zero (the normal case), a new OID is created;
                                191                 :                :  *      otherwise we use exactly that OID.
                                192                 :                :  *
                                193                 :                :  *      NB: Caller is responsible for ensuring the user has USAGE
                                194                 :                :  *      on all types defaultTypeBin depends on.
                                195                 :                :  * ----------------------------------------------------------------
                                196                 :                :  */
                                197                 :                : ObjectAddress
 7048 tgl@sss.pgh.pa.us         198                 :          92494 : TypeCreate(Oid newTypeOid,
                                199                 :                :            const char *typeName,
                                200                 :                :            Oid typeNamespace,
                                201                 :                :            Oid relationOid,     /* only for relation rowtypes */
                                202                 :                :            char relationKind,   /* ditto */
                                203                 :                :            Oid ownerId,
                                204                 :                :            int16 internalSize,
                                205                 :                :            char typeType,
                                206                 :                :            char typeCategory,
                                207                 :                :            bool typePreferred,
                                208                 :                :            char typDelim,
                                209                 :                :            Oid inputProcedure,
                                210                 :                :            Oid outputProcedure,
                                211                 :                :            Oid receiveProcedure,
                                212                 :                :            Oid sendProcedure,
                                213                 :                :            Oid typmodinProcedure,
                                214                 :                :            Oid typmodoutProcedure,
                                215                 :                :            Oid analyzeProcedure,
                                216                 :                :            Oid subscriptProcedure,
                                217                 :                :            Oid elementType,
                                218                 :                :            bool isImplicitArray,
                                219                 :                :            Oid arrayType,
                                220                 :                :            Oid baseType,
                                221                 :                :            const char *defaultTypeValue,    /* human-readable rep */
                                222                 :                :            char *defaultTypeBin,    /* cooked rep */
                                223                 :                :            bool passedByValue,
                                224                 :                :            char alignment,
                                225                 :                :            char storage,
                                226                 :                :            int32 typeMod,
                                227                 :                :            int32 typNDims,      /* Array dimensions for baseType */
                                228                 :                :            bool typeNotNull,
                                229                 :                :            Oid typeCollation)
                                230                 :                : {
                                231                 :                :     Relation    pg_type_desc;
                                232                 :                :     Oid         typeObjectId;
                                233                 :                :     bool        isDependentType;
 8632                           234                 :          92494 :     bool        rebuildDeps = false;
                                235                 :                :     Acl        *typacl;
                                236                 :                :     HeapTuple   tup;
                                237                 :                :     bool        nulls[Natts_pg_type];
                                238                 :                :     bool        replaces[Natts_pg_type];
                                239                 :                :     Datum       values[Natts_pg_type];
                                240                 :                :     NameData    name;
                                241                 :                :     int         i;
                                242                 :                :     ObjectAddress address;
                                243                 :                : 
                                244                 :                :     /*
                                245                 :                :      * We assume that the caller validated the arguments individually, but did
                                246                 :                :      * not check for bad combinations.
                                247                 :                :      *
                                248                 :                :      * Validate size specifications: either positive (fixed-length) or -1
                                249                 :                :      * (varlena) or -2 (cstring).
                                250                 :                :      */
 8769                           251   [ +  +  -  +  :          92494 :     if (!(internalSize > 0 ||
                                              -  - ]
                                252                 :                :           internalSize == -1 ||
                                253                 :                :           internalSize == -2))
 8438 tgl@sss.pgh.pa.us         254         [ #  # ]:UBC           0 :         ereport(ERROR,
                                255                 :                :                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                256                 :                :                  errmsg("invalid type internal size %d",
                                257                 :                :                         internalSize)));
                                258                 :                : 
 6598 tgl@sss.pgh.pa.us         259         [ +  + ]:CBC       92494 :     if (passedByValue)
                                260                 :                :     {
                                261                 :                :         /*
                                262                 :                :          * Pass-by-value types must have a fixed length that is one of the
                                263                 :                :          * values supported by fetch_att() and store_att_byval(); and the
                                264                 :                :          * alignment had better agree, too.  All this code must match
                                265                 :                :          * access/tupmacs.h!
                                266                 :                :          */
                                267         [ +  + ]:            748 :         if (internalSize == (int16) sizeof(char))
                                268                 :                :         {
 2367                           269         [ -  + ]:              7 :             if (alignment != TYPALIGN_CHAR)
 6598 tgl@sss.pgh.pa.us         270         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                271                 :                :                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                272                 :                :                          errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
                                273                 :                :                                 alignment, internalSize)));
                                274                 :                :         }
 6598 tgl@sss.pgh.pa.us         275         [ +  + ]:CBC         741 :         else if (internalSize == (int16) sizeof(int16))
                                276                 :                :         {
 2367                           277         [ -  + ]:              2 :             if (alignment != TYPALIGN_SHORT)
 6598 tgl@sss.pgh.pa.us         278         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                279                 :                :                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                280                 :                :                          errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
                                281                 :                :                                 alignment, internalSize)));
                                282                 :                :         }
 6598 tgl@sss.pgh.pa.us         283         [ +  + ]:CBC         739 :         else if (internalSize == (int16) sizeof(int32))
                                284                 :                :         {
 2367                           285         [ -  + ]:            650 :             if (alignment != TYPALIGN_INT)
 6598 tgl@sss.pgh.pa.us         286         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                287                 :                :                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                288                 :                :                          errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
                                289                 :                :                                 alignment, internalSize)));
                                290                 :                :         }
  379 tgl@sss.pgh.pa.us         291         [ +  - ]:CBC          89 :         else if (internalSize == (int16) sizeof(int64))
                                292                 :                :         {
 2367                           293         [ -  + ]:             89 :             if (alignment != TYPALIGN_DOUBLE)
 6598 tgl@sss.pgh.pa.us         294         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                295                 :                :                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                296                 :                :                          errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
                                297                 :                :                                 alignment, internalSize)));
                                298                 :                :         }
                                299                 :                :         else
                                300         [ #  # ]:              0 :             ereport(ERROR,
                                301                 :                :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                302                 :                :                      errmsg("internal size %d is invalid for passed-by-value type",
                                303                 :                :                             internalSize)));
                                304                 :                :     }
                                305                 :                :     else
                                306                 :                :     {
                                307                 :                :         /* varlena types must have int align or better */
 2367 tgl@sss.pgh.pa.us         308   [ +  +  +  + ]:CBC       91746 :         if (internalSize == -1 &&
                                309         [ -  + ]:          89596 :             !(alignment == TYPALIGN_INT || alignment == TYPALIGN_DOUBLE))
 6598 tgl@sss.pgh.pa.us         310         [ #  # ]:UBC           0 :             ereport(ERROR,
                                311                 :                :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                312                 :                :                      errmsg("alignment \"%c\" is invalid for variable-length type",
                                313                 :                :                             alignment)));
                                314                 :                :         /* cstring must have char alignment */
 2367 tgl@sss.pgh.pa.us         315   [ -  +  -  - ]:CBC       91746 :         if (internalSize == -2 && !(alignment == TYPALIGN_CHAR))
 6598 tgl@sss.pgh.pa.us         316         [ #  # ]:UBC           0 :             ereport(ERROR,
                                317                 :                :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                318                 :                :                      errmsg("alignment \"%c\" is invalid for variable-length type",
                                319                 :                :                             alignment)));
                                320                 :                :     }
                                321                 :                : 
                                322                 :                :     /* Only varlena types can be toasted */
 2367 tgl@sss.pgh.pa.us         323   [ +  +  -  + ]:CBC       92494 :     if (storage != TYPSTORAGE_PLAIN && internalSize != -1)
 8438 tgl@sss.pgh.pa.us         324         [ #  # ]:UBC           0 :         ereport(ERROR,
                                325                 :                :                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                326                 :                :                  errmsg("fixed-size types must have storage PLAIN")));
                                327                 :                : 
                                328                 :                :     /*
                                329                 :                :      * This is a dependent type if it's an implicitly-created array type or
                                330                 :                :      * multirange type, or if it's a relation rowtype that's not a composite
                                331                 :                :      * type.  For such types we'll leave the ACL empty, and we'll skip
                                332                 :                :      * creating some dependency records because there will be a dependency
                                333                 :                :      * already through the depended-on type or relation.  (Caution: this is
                                334                 :                :      * closely intertwined with some behavior in GenerateTypeDependencies.)
                                335                 :                :      */
 2848 tgl@sss.pgh.pa.us         336         [ +  + ]:CBC       46256 :     isDependentType = isImplicitArray ||
  925                           337   [ +  +  +  + ]:         183379 :         typeType == TYPTYPE_MULTIRANGE ||
 2848                           338         [ +  + ]:          44629 :         (OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE);
                                339                 :                : 
                                340                 :                :     /*
                                341                 :                :      * initialize arrays needed for heap_form_tuple or heap_modify_tuple
                                342                 :                :      */
10581 bruce@momjian.us          343         [ +  + ]:        3052302 :     for (i = 0; i < Natts_pg_type; ++i)
                                344                 :                :     {
 6507 tgl@sss.pgh.pa.us         345                 :        2959808 :         nulls[i] = false;
                                346                 :        2959808 :         replaces[i] = true;
 9121                           347                 :        2959808 :         values[i] = (Datum) 0;
                                348                 :                :     }
                                349                 :                : 
                                350                 :                :     /*
                                351                 :                :      * insert data values
                                352                 :                :      */
10222 bruce@momjian.us          353                 :          92494 :     namestrcpy(&name, typeName);
 5551 tgl@sss.pgh.pa.us         354                 :          92494 :     values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
                                355                 :          92494 :     values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
                                356                 :          92494 :     values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
                                357                 :          92494 :     values[Anum_pg_type_typlen - 1] = Int16GetDatum(internalSize);
                                358                 :          92494 :     values[Anum_pg_type_typbyval - 1] = BoolGetDatum(passedByValue);
                                359                 :          92494 :     values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType);
                                360                 :          92494 :     values[Anum_pg_type_typcategory - 1] = CharGetDatum(typeCategory);
                                361                 :          92494 :     values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(typePreferred);
                                362                 :          92494 :     values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(true);
                                363                 :          92494 :     values[Anum_pg_type_typdelim - 1] = CharGetDatum(typDelim);
                                364                 :          92494 :     values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(relationOid);
 2087                           365                 :          92494 :     values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(subscriptProcedure);
 5551                           366                 :          92494 :     values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(elementType);
                                367                 :          92494 :     values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(arrayType);
                                368                 :          92494 :     values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(inputProcedure);
                                369                 :          92494 :     values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(outputProcedure);
                                370                 :          92494 :     values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(receiveProcedure);
                                371                 :          92494 :     values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(sendProcedure);
                                372                 :          92494 :     values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(typmodinProcedure);
                                373                 :          92494 :     values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(typmodoutProcedure);
                                374                 :          92494 :     values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(analyzeProcedure);
                                375                 :          92494 :     values[Anum_pg_type_typalign - 1] = CharGetDatum(alignment);
                                376                 :          92494 :     values[Anum_pg_type_typstorage - 1] = CharGetDatum(storage);
                                377                 :          92494 :     values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(typeNotNull);
                                378                 :          92494 :     values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(baseType);
                                379                 :          92494 :     values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(typeMod);
                                380                 :          92494 :     values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims);
                                381                 :          92494 :     values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation);
                                382                 :                : 
                                383                 :                :     /*
                                384                 :                :      * initialize the default binary value for this type.  Check for nulls of
                                385                 :                :      * course.
                                386                 :                :      */
 8927 bruce@momjian.us          387         [ +  + ]:          92494 :     if (defaultTypeBin)
 5551 tgl@sss.pgh.pa.us         388                 :             96 :         values[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(defaultTypeBin);
                                389                 :                :     else
                                390                 :          92398 :         nulls[Anum_pg_type_typdefaultbin - 1] = true;
                                391                 :                : 
                                392                 :                :     /*
                                393                 :                :      * initialize the default value for this type.
                                394                 :                :      */
 9121                           395         [ +  + ]:          92494 :     if (defaultTypeValue)
 5551                           396                 :            107 :         values[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultTypeValue);
                                397                 :                :     else
                                398                 :          92387 :         nulls[Anum_pg_type_typdefault - 1] = true;
                                399                 :                : 
                                400                 :                :     /*
                                401                 :                :      * Initialize the type's ACL, too.  But dependent types don't get one.
                                402                 :                :      */
 2848                           403         [ +  + ]:          92494 :     if (isDependentType)
                                404                 :          88624 :         typacl = NULL;
                                405                 :                :     else
                                406                 :           3870 :         typacl = get_user_default_acl(OBJECT_TYPE, ownerId,
                                407                 :                :                                       typeNamespace);
 5364 peter_e@gmx.net           408         [ +  + ]:          92494 :     if (typacl != NULL)
                                409                 :              4 :         values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl);
                                410                 :                :     else
                                411                 :          92490 :         nulls[Anum_pg_type_typacl - 1] = true;
                                412                 :                : 
                                413                 :                :     /*
                                414                 :                :      * open pg_type and prepare to insert or update a row.
                                415                 :                :      *
                                416                 :                :      * NOTE: updating will not work correctly in bootstrap mode; but we don't
                                417                 :                :      * expect to be overwriting any shell types in bootstrap mode.
                                418                 :                :      */
 2775 andres@anarazel.de        419                 :          92494 :     pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
                                420                 :                : 
 6038 rhaas@postgresql.org      421                 :          92494 :     tup = SearchSysCacheCopy2(TYPENAMENSP,
                                422                 :                :                               CStringGetDatum(typeName),
                                423                 :                :                               ObjectIdGetDatum(typeNamespace));
10581 bruce@momjian.us          424         [ +  + ]:          92494 :     if (HeapTupleIsValid(tup))
                                425                 :                :     {
 2837 andres@anarazel.de        426                 :            134 :         Form_pg_type typform = (Form_pg_type) GETSTRUCT(tup);
                                427                 :                : 
                                428                 :                :         /*
                                429                 :                :          * check that the type is not already defined.  It may exist as a
                                430                 :                :          * shell type, however.
                                431                 :                :          */
                                432         [ -  + ]:            134 :         if (typform->typisdefined)
 8438 tgl@sss.pgh.pa.us         433         [ #  # ]:UBC           0 :             ereport(ERROR,
                                434                 :                :                     (errcode(ERRCODE_DUPLICATE_OBJECT),
                                435                 :                :                      errmsg("type \"%s\" already exists", typeName)));
                                436                 :                : 
                                437                 :                :         /*
                                438                 :                :          * shell type must have been created by same owner
                                439                 :                :          */
 2837 andres@anarazel.de        440         [ -  + ]:CBC         134 :         if (typform->typowner != ownerId)
 3190 peter_e@gmx.net           441                 :UBC           0 :             aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TYPE, typeName);
                                442                 :                : 
                                443                 :                :         /* trouble if caller wanted to force the OID */
 7048 tgl@sss.pgh.pa.us         444         [ -  + ]:CBC         134 :         if (OidIsValid(newTypeOid))
 7048 tgl@sss.pgh.pa.us         445         [ #  # ]:UBC           0 :             elog(ERROR, "cannot assign new OID to existing shell type");
                                446                 :                : 
 2837 andres@anarazel.de        447                 :CBC         134 :         replaces[Anum_pg_type_oid - 1] = false;
                                448                 :                : 
                                449                 :                :         /*
                                450                 :                :          * Okay to update existing shell type tuple
                                451                 :                :          */
 6507 tgl@sss.pgh.pa.us         452                 :            134 :         tup = heap_modify_tuple(tup,
                                453                 :                :                                 RelationGetDescr(pg_type_desc),
                                454                 :                :                                 values,
                                455                 :                :                                 nulls,
                                456                 :                :                                 replaces);
                                457                 :                : 
 3495 alvherre@alvh.no-ip.      458                 :            134 :         CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup);
                                459                 :                : 
 2837 andres@anarazel.de        460                 :            134 :         typeObjectId = typform->oid;
                                461                 :                : 
 8632 tgl@sss.pgh.pa.us         462                 :            134 :         rebuildDeps = true;     /* get rid of shell type's dependencies */
                                463                 :                :     }
                                464                 :                :     else
                                465                 :                :     {
                                466                 :                :         /* Force the OID if requested by caller */
 7048                           467         [ +  + ]:          92360 :         if (OidIsValid(newTypeOid))
 2837 andres@anarazel.de        468                 :          46701 :             typeObjectId = newTypeOid;
                                469                 :                :         /* Use binary-upgrade override for pg_type.oid, if supplied. */
 4385 bruce@momjian.us          470         [ +  + ]:          45659 :         else if (IsBinaryUpgrade)
                                471                 :                :         {
                                472         [ -  + ]:            931 :             if (!OidIsValid(binary_upgrade_next_pg_type_oid))
 4385 bruce@momjian.us          473         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                474                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                475                 :                :                          errmsg("pg_type OID value not set when in binary upgrade mode")));
                                476                 :                : 
 2837 andres@anarazel.de        477                 :CBC         931 :             typeObjectId = binary_upgrade_next_pg_type_oid;
 6090 bruce@momjian.us          478                 :            931 :             binary_upgrade_next_pg_type_oid = InvalidOid;
                                479                 :                :         }
                                480                 :                :         else
                                481                 :                :         {
 2837 andres@anarazel.de        482                 :          44728 :             typeObjectId = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId,
                                483                 :                :                                               Anum_pg_type_oid);
                                484                 :                :         }
                                485                 :                : 
                                486                 :          92360 :         values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typeObjectId);
                                487                 :                : 
                                488                 :          92360 :         tup = heap_form_tuple(RelationGetDescr(pg_type_desc),
                                489                 :                :                               values, nulls);
                                490                 :                : 
                                491                 :          92360 :         CatalogTupleInsert(pg_type_desc, tup);
                                492                 :                :     }
                                493                 :                : 
                                494                 :                :     /*
                                495                 :                :      * Create dependencies.  We can/must skip this in bootstrap mode.
                                496                 :                :      */
 8806 tgl@sss.pgh.pa.us         497         [ +  + ]:          92494 :     if (!IsBootstrapProcessingMode())
 2365                           498         [ +  + ]:          85440 :         GenerateTypeDependencies(tup,
                                499                 :                :                                  pg_type_desc,
                                500                 :                :                                  (defaultTypeBin ?
 8632                           501                 :             96 :                                   stringToNode(defaultTypeBin) :
                                502                 :                :                                   NULL),
                                503                 :                :                                  typacl,
                                504                 :                :                                  relationKind,
                                505                 :                :                                  isImplicitArray,
                                506                 :                :                                  isDependentType,
                                507                 :                :                                  true,  /* make extension dependency */
                                508                 :                :                                  rebuildDeps);
                                509                 :                : 
                                510                 :                :     /* Post creation hook for new type */
 4922 rhaas@postgresql.org      511         [ +  + ]:          92492 :     InvokeObjectPostCreateHook(TypeRelationId, typeObjectId, 0);
                                512                 :                : 
 4195 alvherre@alvh.no-ip.      513                 :          92492 :     ObjectAddressSet(address, TypeRelationId, typeObjectId);
                                514                 :                : 
                                515                 :                :     /*
                                516                 :                :      * finish up
                                517                 :                :      */
 2775 andres@anarazel.de        518                 :          92492 :     table_close(pg_type_desc, RowExclusiveLock);
                                519                 :                : 
 4195 alvherre@alvh.no-ip.      520                 :          92492 :     return address;
                                521                 :                : }
                                522                 :                : 
                                523                 :                : /*
                                524                 :                :  * GenerateTypeDependencies: build the dependencies needed for a type
                                525                 :                :  *
                                526                 :                :  * Most of what this function needs to know about the type is passed as the
                                527                 :                :  * new pg_type row, typeTuple.  We make callers pass the pg_type Relation
                                528                 :                :  * as well, so that we have easy access to a tuple descriptor for the row.
                                529                 :                :  *
                                530                 :                :  * While this is able to extract the defaultExpr and typacl from the tuple,
                                531                 :                :  * doing so is relatively expensive, and callers may have those values at
                                532                 :                :  * hand already.  Pass those if handy, otherwise pass NULL.  (typacl is really
                                533                 :                :  * "Acl *", but we declare it "void *" to avoid including acl.h in pg_type.h.)
                                534                 :                :  *
                                535                 :                :  * relationKind and isImplicitArray are likewise somewhat expensive to deduce
                                536                 :                :  * from the tuple, so we make callers pass those (they're not optional).
                                537                 :                :  *
                                538                 :                :  * isDependentType is true if this is an implicit array, multirange, or
                                539                 :                :  * relation rowtype; that means it doesn't need its own dependencies on owner
                                540                 :                :  * etc.
                                541                 :                :  *
                                542                 :                :  * We make an extension-membership dependency if we're in an extension
                                543                 :                :  * script and makeExtensionDep is true.
                                544                 :                :  * makeExtensionDep should be true when creating a new type or replacing a
                                545                 :                :  * shell type, but not for ALTER TYPE on an existing type.  Passing false
                                546                 :                :  * causes the type's extension membership to be left alone.
                                547                 :                :  *
                                548                 :                :  * rebuild should be true if this is a pre-existing type.  We will remove
                                549                 :                :  * existing dependencies and rebuild them from scratch.  This is needed for
                                550                 :                :  * ALTER TYPE, and also when replacing a shell type.  We don't remove any
                                551                 :                :  * existing extension dependency, though; hence, if makeExtensionDep is also
                                552                 :                :  * true and we're in an extension script, an error will occur unless the
                                553                 :                :  * type already belongs to the current extension.  That's the behavior we
                                554                 :                :  * want when replacing a shell type, which is the only case where both flags
                                555                 :                :  * are true.
                                556                 :                :  *
                                557                 :                :  * NB: Caller is responsible for ensuring the user has USAGE on all types
                                558                 :                :  * defaultExpr depends on.
                                559                 :                :  */
                                560                 :                : void
 2365 tgl@sss.pgh.pa.us         561                 :          85543 : GenerateTypeDependencies(HeapTuple typeTuple,
                                562                 :                :                          Relation typeCatalog,
                                563                 :                :                          Node *defaultExpr,
                                564                 :                :                          void *typacl,
                                565                 :                :                          char relationKind, /* only for relation rowtypes */
                                566                 :                :                          bool isImplicitArray,
                                567                 :                :                          bool isDependentType,
                                568                 :                :                          bool makeExtensionDep,
                                569                 :                :                          bool rebuild)
                                570                 :                : {
                                571                 :          85543 :     Form_pg_type typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
                                572                 :          85543 :     Oid         typeObjectId = typeForm->oid;
                                573                 :                :     Datum       datum;
                                574                 :                :     bool        isNull;
                                575                 :                :     ObjectAddress myself,
                                576                 :                :                 referenced;
                                577                 :                :     ObjectAddresses *addrs_normal;
                                578                 :                : 
                                579                 :                :     /* Extract defaultExpr if caller didn't pass it */
                                580         [ +  + ]:          85543 :     if (defaultExpr == NULL)
                                581                 :                :     {
                                582                 :          85442 :         datum = heap_getattr(typeTuple, Anum_pg_type_typdefaultbin,
                                583                 :                :                              RelationGetDescr(typeCatalog), &isNull);
                                584         [ -  + ]:          85442 :         if (!isNull)
 2365 tgl@sss.pgh.pa.us         585                 :UBC           0 :             defaultExpr = stringToNode(TextDatumGetCString(datum));
                                586                 :                :     }
                                587                 :                :     /* Extract typacl if caller didn't pass it */
 2365 tgl@sss.pgh.pa.us         588         [ +  + ]:CBC       85543 :     if (typacl == NULL)
                                589                 :                :     {
                                590                 :          85539 :         datum = heap_getattr(typeTuple, Anum_pg_type_typacl,
                                591                 :                :                              RelationGetDescr(typeCatalog), &isNull);
                                592         [ -  + ]:          85539 :         if (!isNull)
 2365 tgl@sss.pgh.pa.us         593                 :UBC           0 :             typacl = DatumGetAclPCopy(datum);
                                594                 :                :     }
                                595                 :                : 
                                596                 :                :     /* If rebuild, first flush old dependencies, except extension deps */
 8665 bruce@momjian.us          597         [ +  + ]:CBC       85543 :     if (rebuild)
                                598                 :                :     {
 5679 tgl@sss.pgh.pa.us         599                 :            183 :         deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
 6426                           600                 :            183 :         deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
                                601                 :                :     }
                                602                 :                : 
 2250 michael@paquier.xyz       603                 :          85543 :     ObjectAddressSet(myself, TypeRelationId, typeObjectId);
                                604                 :                : 
                                605                 :                :     /*
                                606                 :                :      * Make dependencies on namespace, owner, ACL.
                                607                 :                :      *
                                608                 :                :      * Skip these for a dependent type, since it will have such dependencies
                                609                 :                :      * indirectly through its depended-on type or relation.  An exception is
                                610                 :                :      * that multiranges need their own namespace dependency, since we don't
                                611                 :                :      * force them to be in the same schema as their range type.
                                612                 :                :      */
                                613                 :                : 
                                614                 :                :     /* collects normal dependencies for bulk recording */
 2182                           615                 :          85543 :     addrs_normal = new_object_addresses();
                                616                 :                : 
  925 tgl@sss.pgh.pa.us         617   [ +  +  +  + ]:          85543 :     if (!isDependentType || typeForm->typtype == TYPTYPE_MULTIRANGE)
                                618                 :                :     {
 2250 michael@paquier.xyz       619                 :           4198 :         ObjectAddressSet(referenced, NamespaceRelationId,
                                620                 :                :                          typeForm->typnamespace);
  925 tgl@sss.pgh.pa.us         621                 :           4198 :         add_exact_object_address(&referenced, addrs_normal);
                                622                 :                :     }
                                623                 :                : 
                                624         [ +  + ]:          85543 :     if (!isDependentType)
                                625                 :                :     {
 2848                           626                 :           4065 :         recordDependencyOnOwner(TypeRelationId, typeObjectId,
                                627                 :                :                                 typeForm->typowner);
                                628                 :                : 
                                629                 :           4065 :         recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
                                630                 :                :                                  typeForm->typowner, typacl);
                                631                 :                :     }
                                632                 :                : 
                                633                 :                :     /*
                                634                 :                :      * Make extension dependency if requested.
                                635                 :                :      *
                                636                 :                :      * We used to skip this for dependent types, but it seems better to record
                                637                 :                :      * their extension membership explicitly; otherwise code such as
                                638                 :                :      * postgres_fdw's shippability test will be fooled.
                                639                 :                :      */
  906                           640         [ +  + ]:          85543 :     if (makeExtensionDep)
                                641                 :          85494 :         recordDependencyOnCurrentExtension(&myself, rebuild);
                                642                 :                : 
                                643                 :                :     /* Normal dependencies on the I/O and support functions */
 2848                           644         [ +  - ]:          85542 :     if (OidIsValid(typeForm->typinput))
                                645                 :                :     {
 2250 michael@paquier.xyz       646                 :          85542 :         ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typinput);
 2182                           647                 :          85542 :         add_exact_object_address(&referenced, addrs_normal);
                                648                 :                :     }
                                649                 :                : 
 2848 tgl@sss.pgh.pa.us         650         [ +  - ]:          85542 :     if (OidIsValid(typeForm->typoutput))
                                651                 :                :     {
 2250 michael@paquier.xyz       652                 :          85542 :         ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typoutput);
 2182                           653                 :          85542 :         add_exact_object_address(&referenced, addrs_normal);
                                654                 :                :     }
                                655                 :                : 
 2848 tgl@sss.pgh.pa.us         656         [ +  + ]:          85542 :     if (OidIsValid(typeForm->typreceive))
                                657                 :                :     {
 2250 michael@paquier.xyz       658                 :          85262 :         ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typreceive);
 2182                           659                 :          85262 :         add_exact_object_address(&referenced, addrs_normal);
                                660                 :                :     }
                                661                 :                : 
 2848 tgl@sss.pgh.pa.us         662         [ +  + ]:          85542 :     if (OidIsValid(typeForm->typsend))
                                663                 :                :     {
 2250 michael@paquier.xyz       664                 :          85254 :         ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsend);
 2182                           665                 :          85254 :         add_exact_object_address(&referenced, addrs_normal);
                                666                 :                :     }
                                667                 :                : 
 2848 tgl@sss.pgh.pa.us         668         [ +  + ]:          85542 :     if (OidIsValid(typeForm->typmodin))
                                669                 :                :     {
 2250 michael@paquier.xyz       670                 :             18 :         ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodin);
 2182                           671                 :             18 :         add_exact_object_address(&referenced, addrs_normal);
                                672                 :                :     }
                                673                 :                : 
 2848 tgl@sss.pgh.pa.us         674         [ +  + ]:          85542 :     if (OidIsValid(typeForm->typmodout))
                                675                 :                :     {
 2250 michael@paquier.xyz       676                 :             18 :         ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodout);
 2182                           677                 :             18 :         add_exact_object_address(&referenced, addrs_normal);
                                678                 :                :     }
                                679                 :                : 
 2848 tgl@sss.pgh.pa.us         680         [ +  + ]:          85542 :     if (OidIsValid(typeForm->typanalyze))
                                681                 :                :     {
 2250 michael@paquier.xyz       682                 :          43065 :         ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typanalyze);
 2182                           683                 :          43065 :         add_exact_object_address(&referenced, addrs_normal);
                                684                 :                :     }
                                685                 :                : 
 2087 tgl@sss.pgh.pa.us         686         [ +  + ]:          85542 :     if (OidIsValid(typeForm->typsubscript))
                                687                 :                :     {
                                688                 :          42683 :         ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsubscript);
                                689                 :          42683 :         add_exact_object_address(&referenced, addrs_normal);
                                690                 :                :     }
                                691                 :                : 
                                692                 :                :     /* Normal dependency from a domain to its base type. */
 2182 michael@paquier.xyz       693         [ +  + ]:          85542 :     if (OidIsValid(typeForm->typbasetype))
                                694                 :                :     {
                                695                 :            948 :         ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
                                696                 :            948 :         add_exact_object_address(&referenced, addrs_normal);
                                697                 :                :     }
                                698                 :                : 
                                699                 :                :     /*
                                700                 :                :      * Normal dependency from a domain to its collation.  We know the default
                                701                 :                :      * collation is pinned, so don't bother recording it.
                                702                 :                :      */
                                703         [ +  + ]:          85542 :     if (OidIsValid(typeForm->typcollation) &&
                                704         [ +  + ]:            652 :         typeForm->typcollation != DEFAULT_COLLATION_OID)
                                705                 :                :     {
                                706                 :            360 :         ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
                                707                 :            360 :         add_exact_object_address(&referenced, addrs_normal);
                                708                 :                :     }
                                709                 :                : 
                                710                 :          85542 :     record_object_address_dependencies(&myself, addrs_normal, DEPENDENCY_NORMAL);
                                711                 :          85541 :     free_object_addresses(addrs_normal);
                                712                 :                : 
                                713                 :                :     /* Normal dependency on the default expression. */
                                714         [ +  + ]:          85541 :     if (defaultExpr)
                                715                 :            101 :         recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
                                716                 :                : 
                                717                 :                :     /*
                                718                 :                :      * If the type is a rowtype for a relation, mark it as internally
                                719                 :                :      * dependent on the relation, *unless* it is a stand-alone composite type
                                720                 :                :      * relation. For the latter case, we have to reverse the dependency.
                                721                 :                :      *
                                722                 :                :      * In the former case, this allows the type to be auto-dropped when the
                                723                 :                :      * relation is, and not otherwise. And in the latter, of course we get the
                                724                 :                :      * opposite effect.
                                725                 :                :      */
 2848 tgl@sss.pgh.pa.us         726         [ +  + ]:          85541 :     if (OidIsValid(typeForm->typrelid))
                                727                 :                :     {
 2250 michael@paquier.xyz       728                 :          41054 :         ObjectAddressSet(referenced, RelationRelationId, typeForm->typrelid);
                                729                 :                : 
 8665 bruce@momjian.us          730         [ +  + ]:          41054 :         if (relationKind != RELKIND_COMPOSITE_TYPE)
                                731                 :          38678 :             recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
                                732                 :                :         else
                                733                 :           2376 :             recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
                                734                 :                :     }
                                735                 :                : 
                                736                 :                :     /*
                                737                 :                :      * If the type is an implicitly-created array type, mark it as internally
                                738                 :                :      * dependent on the element type.  Otherwise, if it has an element type,
                                739                 :                :      * the dependency is a normal one.
                                740                 :                :      */
 2848 tgl@sss.pgh.pa.us         741         [ +  + ]:          85541 :     if (OidIsValid(typeForm->typelem))
                                742                 :                :     {
 2250 michael@paquier.xyz       743                 :          42672 :         ObjectAddressSet(referenced, TypeRelationId, typeForm->typelem);
 7048 tgl@sss.pgh.pa.us         744         [ +  + ]:          42672 :         recordDependencyOn(&myself, &referenced,
                                745                 :                :                            isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
                                746                 :                :     }
                                747                 :                : 
                                748                 :                :     /*
                                749                 :                :      * Note: you might expect that we should record an internal dependency of
                                750                 :                :      * a multirange on its range type here, by analogy with the cases above.
                                751                 :                :      * But instead, that is done by RangeCreate(), which also handles
                                752                 :                :      * recording of other range-type-specific dependencies.  That's pretty
                                753                 :                :      * bogus.  It's okay for now, because there are no cases where we need to
                                754                 :                :      * regenerate the dependencies of a range or multirange type.  But someday
                                755                 :                :      * we might need to move that logic here to allow such regeneration.
                                756                 :                :      */
11006 scrappy@hub.org           757                 :          85541 : }
                                758                 :                : 
                                759                 :                : /*
                                760                 :                :  * RenameTypeInternal
                                761                 :                :  *      This renames a type, as well as any associated array type.
                                762                 :                :  *
                                763                 :                :  * Caller must have already checked privileges.
                                764                 :                :  *
                                765                 :                :  * Currently this is used for renaming table rowtypes and for
                                766                 :                :  * ALTER TYPE RENAME TO command.
                                767                 :                :  */
                                768                 :                : void
 6735 tgl@sss.pgh.pa.us         769                 :            225 : RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
                                770                 :                : {
                                771                 :                :     Relation    pg_type_desc;
                                772                 :                :     HeapTuple   tuple;
                                773                 :                :     Form_pg_type typ;
                                774                 :                :     Oid         arrayOid;
                                775                 :                :     Oid         oldTypeOid;
                                776                 :                : 
 2775 andres@anarazel.de        777                 :            225 :     pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
                                778                 :                : 
 6038 rhaas@postgresql.org      779                 :            225 :     tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
 9415 tgl@sss.pgh.pa.us         780         [ -  + ]:            225 :     if (!HeapTupleIsValid(tuple))
 7047 tgl@sss.pgh.pa.us         781         [ #  # ]:UBC           0 :         elog(ERROR, "cache lookup failed for type %u", typeOid);
 7047 tgl@sss.pgh.pa.us         782                 :CBC         225 :     typ = (Form_pg_type) GETSTRUCT(tuple);
                                783                 :                : 
                                784                 :                :     /* We are not supposed to be changing schemas here */
                                785         [ -  + ]:            225 :     Assert(typeNamespace == typ->typnamespace);
                                786                 :                : 
                                787                 :            225 :     arrayOid = typ->typarray;
                                788                 :                : 
                                789                 :                :     /* Check for a conflicting type name. */
 2837 andres@anarazel.de        790                 :            225 :     oldTypeOid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
                                791                 :                :                                  CStringGetDatum(newTypeName),
                                792                 :                :                                  ObjectIdGetDatum(typeNamespace));
                                793                 :                : 
                                794                 :                :     /*
                                795                 :                :      * If there is one, see if it's an autogenerated array type, and if so
                                796                 :                :      * rename it out of the way.  (But we must skip that for a shell type
                                797                 :                :      * because moveArrayTypeName will do the wrong thing in that case.)
                                798                 :                :      * Otherwise, we can at least give a more friendly error than unique-index
                                799                 :                :      * violation.
                                800                 :                :      */
 3380 tgl@sss.pgh.pa.us         801         [ +  + ]:            225 :     if (OidIsValid(oldTypeOid))
                                802                 :                :     {
                                803   [ +  -  +  - ]:             16 :         if (get_typisdefined(oldTypeOid) &&
                                804                 :              8 :             moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
                                805                 :                :              /* successfully dodged the problem */ ;
                                806                 :                :         else
 3380 tgl@sss.pgh.pa.us         807         [ #  # ]:UBC           0 :             ereport(ERROR,
                                808                 :                :                     (errcode(ERRCODE_DUPLICATE_OBJECT),
                                809                 :                :                      errmsg("type \"%s\" already exists", newTypeName)));
                                810                 :                :     }
                                811                 :                : 
                                812                 :                :     /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
 7047 tgl@sss.pgh.pa.us         813                 :CBC         225 :     namestrcpy(&(typ->typname), newTypeName);
                                814                 :                : 
 3495 alvherre@alvh.no-ip.      815                 :            225 :     CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
                                816                 :                : 
 4911 rhaas@postgresql.org      817         [ -  + ]:            225 :     InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
                                818                 :                : 
 9415 tgl@sss.pgh.pa.us         819                 :            225 :     heap_freetuple(tuple);
 2775 andres@anarazel.de        820                 :            225 :     table_close(pg_type_desc, RowExclusiveLock);
                                821                 :                : 
                                822                 :                :     /*
                                823                 :                :      * If the type has an array type, recurse to handle that.  But we don't
                                824                 :                :      * need to do anything more if we already renamed that array type above
                                825                 :                :      * (which would happen when, eg, renaming "foo" to "_foo").
                                826                 :                :      */
 3380 tgl@sss.pgh.pa.us         827   [ +  +  +  + ]:            225 :     if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
                                828                 :                :     {
 6860 bruce@momjian.us          829                 :            102 :         char       *arrname = makeArrayTypeName(newTypeName, typeNamespace);
                                830                 :                : 
 6735 tgl@sss.pgh.pa.us         831                 :            102 :         RenameTypeInternal(arrayOid, arrname, typeNamespace);
 7047                           832                 :            102 :         pfree(arrname);
                                833                 :                :     }
11006 scrappy@hub.org           834                 :            225 : }
                                835                 :                : 
                                836                 :                : 
                                837                 :                : /*
                                838                 :                :  * makeArrayTypeName
                                839                 :                :  *    - given a base type name, make an array type name for it
                                840                 :                :  *
                                841                 :                :  * the caller is responsible for pfreeing the result
                                842                 :                :  */
                                843                 :                : char *
 7048 tgl@sss.pgh.pa.us         844                 :          46357 : makeArrayTypeName(const char *typeName, Oid typeNamespace)
                                845                 :                : {
                                846                 :                :     char       *arr_name;
 1493                           847                 :          46357 :     int         pass = 0;
                                848                 :                :     char        suffix[NAMEDATALEN];
                                849                 :                : 
                                850                 :                :     /*
                                851                 :                :      * Per ancient Postgres tradition, array type names are made by prepending
                                852                 :                :      * an underscore to the base type name.  Much client code knows that
                                853                 :                :      * convention, so don't muck with it.  However, the tradition is less
                                854                 :                :      * clear about what to do in the corner cases where the resulting name is
                                855                 :                :      * too long or conflicts with an existing name.  Our current rules are (1)
                                856                 :                :      * truncate the base name on the right as needed, and (2) if there is a
                                857                 :                :      * conflict, append another underscore and some digits chosen to make it
                                858                 :                :      * unique.  This is similar to what ChooseRelationName() does.
                                859                 :                :      *
                                860                 :                :      * The actual name generation can be farmed out to makeObjectName() by
                                861                 :                :      * giving it an empty first name component.
                                862                 :                :      */
                                863                 :                : 
                                864                 :                :     /* First, try with no numeric suffix */
                                865                 :          46357 :     arr_name = makeObjectName("", typeName, NULL);
                                866                 :                : 
                                867                 :                :     for (;;)
                                868                 :                :     {
                                869         [ +  + ]:          46370 :         if (!SearchSysCacheExists2(TYPENAMENSP,
                                870                 :                :                                    CStringGetDatum(arr_name),
                                871                 :                :                                    ObjectIdGetDatum(typeNamespace)))
                                872                 :          46357 :             break;
                                873                 :                : 
                                874                 :                :         /* That attempt conflicted.  Prepare a new name with some digits. */
                                875                 :             13 :         pfree(arr_name);
                                876                 :             13 :         snprintf(suffix, sizeof(suffix), "%d", ++pass);
                                877                 :             13 :         arr_name = makeObjectName("", typeName, suffix);
                                878                 :                :     }
                                879                 :                : 
                                880                 :          46357 :     return arr_name;
                                881                 :                : }
                                882                 :                : 
                                883                 :                : 
                                884                 :                : /*
                                885                 :                :  * moveArrayTypeName
                                886                 :                :  *    - try to reassign an array type name that the user wants to use.
                                887                 :                :  *
                                888                 :                :  * The given type name has been discovered to already exist (with the given
                                889                 :                :  * OID).  If it is an autogenerated array type, change the array type's name
                                890                 :                :  * to not conflict.  This allows the user to create type "foo" followed by
                                891                 :                :  * type "_foo" without problems.  (Of course, there are race conditions if
                                892                 :                :  * two backends try to create similarly-named types concurrently, but the
                                893                 :                :  * worst that can happen is an unnecessary failure --- anything we do here
                                894                 :                :  * will be rolled back if the type creation fails due to conflicting names.)
                                895                 :                :  *
                                896                 :                :  * Note that this must be called *before* calling makeArrayTypeName to
                                897                 :                :  * determine the new type's own array type name; else the latter will
                                898                 :                :  * certainly pick the same name.
                                899                 :                :  *
                                900                 :                :  * Returns true if successfully moved the type, false if not.
                                901                 :                :  *
                                902                 :                :  * We also return true if the given type is a shell type.  In this case
                                903                 :                :  * the type has not been renamed out of the way, but nonetheless it can
                                904                 :                :  * be expected that TypeCreate will succeed.  This behavior is convenient
                                905                 :                :  * for most callers --- those that need to distinguish the shell-type case
                                906                 :                :  * must do their own typisdefined test.
                                907                 :                :  */
                                908                 :                : bool
 7047                           909                 :             26 : moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
                                910                 :                : {
                                911                 :                :     Oid         elemOid;
                                912                 :                :     char       *newname;
                                913                 :                : 
                                914                 :                :     /* We need do nothing if it's a shell type. */
                                915         [ +  + ]:             26 :     if (!get_typisdefined(typeOid))
                                916                 :              1 :         return true;
                                917                 :                : 
                                918                 :                :     /* Can't change it if it's not an autogenerated array type. */
                                919                 :             25 :     elemOid = get_element_type(typeOid);
                                920   [ +  +  -  + ]:             42 :     if (!OidIsValid(elemOid) ||
                                921                 :             17 :         get_array_type(elemOid) != typeOid)
                                922                 :              8 :         return false;
                                923                 :                : 
                                924                 :                :     /*
                                925                 :                :      * OK, use makeArrayTypeName to pick an unused modification of the name.
                                926                 :                :      * Note that since makeArrayTypeName is an iterative process, this will
                                927                 :                :      * produce a name that it might have produced the first time, had the
                                928                 :                :      * conflicting type we are about to create already existed.
                                929                 :                :      */
                                930                 :             17 :     newname = makeArrayTypeName(typeName, typeNamespace);
                                931                 :                : 
                                932                 :                :     /* Apply the rename */
 6735                           933                 :             17 :     RenameTypeInternal(typeOid, newname, typeNamespace);
                                934                 :                : 
                                935                 :                :     /*
                                936                 :                :      * We must bump the command counter so that any subsequent use of
                                937                 :                :      * makeArrayTypeName sees what we just did and doesn't pick the same name.
                                938                 :                :      */
 7047                           939                 :             17 :     CommandCounterIncrement();
                                940                 :                : 
                                941                 :             17 :     pfree(newname);
                                942                 :                : 
                                943                 :             17 :     return true;
                                944                 :                : }
                                945                 :                : 
                                946                 :                : 
                                947                 :                : /*
                                948                 :                :  * makeMultirangeTypeName
                                949                 :                :  *    - given a range type name, make a multirange type name for it
                                950                 :                :  *
                                951                 :                :  * caller is responsible for pfreeing the result
                                952                 :                :  */
                                953                 :                : char *
 2076 akorotkov@postgresql      954                 :            118 : makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
                                955                 :                : {
                                956                 :                :     char       *buf;
                                957                 :                :     const char *rangestr;
                                958                 :                : 
                                959                 :                :     /*
                                960                 :                :      * If the range type name contains "range" then change that to
                                961                 :                :      * "multirange". Otherwise add "_multirange" to the end.
                                962                 :                :      */
                                963                 :            118 :     rangestr = strstr(rangeTypeName, "range");
                                964         [ +  + ]:            118 :     if (rangestr)
                                965                 :                :     {
                                966                 :            106 :         char       *prefix = pnstrdup(rangeTypeName, rangestr - rangeTypeName);
                                967                 :                : 
                                968                 :            106 :         buf = psprintf("%s%s%s", prefix, "multi", rangestr);
                                969                 :                :     }
                                970                 :                :     else
                                971                 :             12 :         buf = psprintf("%s_multirange", pnstrdup(rangeTypeName, NAMEDATALEN - 12));
                                972                 :                : 
                                973                 :                :     /* clip it at NAMEDATALEN-1 bytes */
                                974                 :            118 :     buf[pg_mbcliplen(buf, strlen(buf), NAMEDATALEN - 1)] = '\0';
                                975                 :                : 
                                976         [ +  + ]:            118 :     if (SearchSysCacheExists2(TYPENAMENSP,
                                977                 :                :                               CStringGetDatum(buf),
                                978                 :                :                               ObjectIdGetDatum(typeNamespace)))
                                979         [ +  - ]:              8 :         ereport(ERROR,
                                980                 :                :                 (errcode(ERRCODE_DUPLICATE_OBJECT),
                                981                 :                :                  errmsg("type \"%s\" already exists", buf),
                                982                 :                :                  errdetail("Failed while creating a multirange type for type \"%s\".", rangeTypeName),
                                983                 :                :                  errhint("You can manually specify a multirange type name using the \"multirange_type_name\" attribute.")));
                                984                 :                : 
                                985                 :            110 :     return pstrdup(buf);
                                986                 :                : }
        

Generated by: LCOV version 2.0-1