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

Generated by: LCOV version 2.4-beta