LCOV - differential code coverage report
Current view: top level - src/backend/catalog - pg_type.c (source / functions) Coverage Total Hit LBC UIC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 93.6 % 281 263 1 17 2 135 8 118 16 136 8
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 7 7 7 7
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

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