LCOV - code coverage report
Current view: top level - src/backend/commands - typecmds.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 1924 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 45 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 1318 0

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * typecmds.c
       4                 :             :  *        Routines for SQL commands that manipulate types (and domains).
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *        src/backend/commands/typecmds.c
      12                 :             :  *
      13                 :             :  * DESCRIPTION
      14                 :             :  *        The "DefineFoo" routines take the parse tree and pick out the
      15                 :             :  *        appropriate arguments/flags, passing the results to the
      16                 :             :  *        corresponding "FooCreate" routines (in src/backend/catalog) that do
      17                 :             :  *        the actual catalog-munging.  These routines also verify permission
      18                 :             :  *        of the user to execute the command.
      19                 :             :  *
      20                 :             :  * NOTES
      21                 :             :  *        These things must be defined and committed in the following order:
      22                 :             :  *              "create function":
      23                 :             :  *                              input/output, recv/send functions
      24                 :             :  *              "create type":
      25                 :             :  *                              type
      26                 :             :  *              "create operator":
      27                 :             :  *                              operators
      28                 :             :  *
      29                 :             :  *
      30                 :             :  *-------------------------------------------------------------------------
      31                 :             :  */
      32                 :             : #include "postgres.h"
      33                 :             : 
      34                 :             : #include "access/genam.h"
      35                 :             : #include "access/htup_details.h"
      36                 :             : #include "access/relation.h"
      37                 :             : #include "access/table.h"
      38                 :             : #include "access/tableam.h"
      39                 :             : #include "access/xact.h"
      40                 :             : #include "catalog/binary_upgrade.h"
      41                 :             : #include "catalog/catalog.h"
      42                 :             : #include "catalog/heap.h"
      43                 :             : #include "catalog/objectaccess.h"
      44                 :             : #include "catalog/pg_am.h"
      45                 :             : #include "catalog/pg_authid.h"
      46                 :             : #include "catalog/pg_cast.h"
      47                 :             : #include "catalog/pg_collation.h"
      48                 :             : #include "catalog/pg_constraint.h"
      49                 :             : #include "catalog/pg_depend.h"
      50                 :             : #include "catalog/pg_enum.h"
      51                 :             : #include "catalog/pg_language.h"
      52                 :             : #include "catalog/pg_namespace.h"
      53                 :             : #include "catalog/pg_proc.h"
      54                 :             : #include "catalog/pg_range.h"
      55                 :             : #include "catalog/pg_type.h"
      56                 :             : #include "commands/defrem.h"
      57                 :             : #include "commands/tablecmds.h"
      58                 :             : #include "commands/typecmds.h"
      59                 :             : #include "executor/executor.h"
      60                 :             : #include "miscadmin.h"
      61                 :             : #include "nodes/makefuncs.h"
      62                 :             : #include "optimizer/optimizer.h"
      63                 :             : #include "parser/parse_coerce.h"
      64                 :             : #include "parser/parse_collate.h"
      65                 :             : #include "parser/parse_expr.h"
      66                 :             : #include "parser/parse_func.h"
      67                 :             : #include "parser/parse_type.h"
      68                 :             : #include "utils/builtins.h"
      69                 :             : #include "utils/fmgroids.h"
      70                 :             : #include "utils/inval.h"
      71                 :             : #include "utils/lsyscache.h"
      72                 :             : #include "utils/rel.h"
      73                 :             : #include "utils/ruleutils.h"
      74                 :             : #include "utils/snapmgr.h"
      75                 :             : #include "utils/syscache.h"
      76                 :             : 
      77                 :             : 
      78                 :             : /* result structure for get_rels_with_domain() */
      79                 :             : typedef struct
      80                 :             : {
      81                 :             :         Relation        rel;                    /* opened and locked relation */
      82                 :             :         int                     natts;                  /* number of attributes of interest */
      83                 :             :         int                *atts;                       /* attribute numbers */
      84                 :             :         /* atts[] is of allocated length RelationGetNumberOfAttributes(rel) */
      85                 :             : } RelToCheck;
      86                 :             : 
      87                 :             : /* parameter structure for AlterTypeRecurse() */
      88                 :             : typedef struct
      89                 :             : {
      90                 :             :         /* Flags indicating which type attributes to update */
      91                 :             :         bool            updateStorage;
      92                 :             :         bool            updateReceive;
      93                 :             :         bool            updateSend;
      94                 :             :         bool            updateTypmodin;
      95                 :             :         bool            updateTypmodout;
      96                 :             :         bool            updateAnalyze;
      97                 :             :         bool            updateSubscript;
      98                 :             :         /* New values for relevant attributes */
      99                 :             :         char            storage;
     100                 :             :         Oid                     receiveOid;
     101                 :             :         Oid                     sendOid;
     102                 :             :         Oid                     typmodinOid;
     103                 :             :         Oid                     typmodoutOid;
     104                 :             :         Oid                     analyzeOid;
     105                 :             :         Oid                     subscriptOid;
     106                 :             : } AlterTypeRecurseParams;
     107                 :             : 
     108                 :             : /* Potentially set by pg_upgrade_support functions */
     109                 :             : Oid                     binary_upgrade_next_array_pg_type_oid = InvalidOid;
     110                 :             : Oid                     binary_upgrade_next_mrng_pg_type_oid = InvalidOid;
     111                 :             : Oid                     binary_upgrade_next_mrng_array_pg_type_oid = InvalidOid;
     112                 :             : 
     113                 :             : static void makeRangeConstructors(const char *name, Oid namespace,
     114                 :             :                                                                   Oid rangeOid, Oid subtype,
     115                 :             :                                                                   Oid *rangeConstruct2_p, Oid *rangeConstruct3_p);
     116                 :             : static void makeMultirangeConstructors(const char *name, Oid namespace,
     117                 :             :                                                                            Oid multirangeOid, Oid rangeOid,
     118                 :             :                                                                            Oid rangeArrayOid,
     119                 :             :                                                                            Oid *mltrngConstruct0_p, Oid *mltrngConstruct1_p, Oid *mltrngConstruct2_p);
     120                 :             : static Oid      findTypeInputFunction(List *procname, Oid typeOid);
     121                 :             : static Oid      findTypeOutputFunction(List *procname, Oid typeOid);
     122                 :             : static Oid      findTypeReceiveFunction(List *procname, Oid typeOid);
     123                 :             : static Oid      findTypeSendFunction(List *procname, Oid typeOid);
     124                 :             : static Oid      findTypeTypmodinFunction(List *procname);
     125                 :             : static Oid      findTypeTypmodoutFunction(List *procname);
     126                 :             : static Oid      findTypeAnalyzeFunction(List *procname, Oid typeOid);
     127                 :             : static Oid      findTypeSubscriptingFunction(List *procname, Oid typeOid);
     128                 :             : static Oid      findRangeSubOpclass(List *opcname, Oid subtype);
     129                 :             : static Oid      findRangeCanonicalFunction(List *procname, Oid typeOid);
     130                 :             : static Oid      findRangeSubtypeDiffFunction(List *procname, Oid subtype);
     131                 :             : static void validateDomainCheckConstraint(Oid domainoid, const char *ccbin, LOCKMODE lockmode);
     132                 :             : static void validateDomainNotNullConstraint(Oid domainoid);
     133                 :             : static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode);
     134                 :             : static void checkEnumOwner(HeapTuple tup);
     135                 :             : static char *domainAddCheckConstraint(Oid domainOid, Oid domainNamespace,
     136                 :             :                                                                           Oid baseTypeOid,
     137                 :             :                                                                           int typMod, Constraint *constr,
     138                 :             :                                                                           const char *domainName, ObjectAddress *constrAddr);
     139                 :             : static Node *replace_domain_constraint_value(ParseState *pstate,
     140                 :             :                                                                                          ColumnRef *cref);
     141                 :             : static void domainAddNotNullConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
     142                 :             :                                                                            int typMod, Constraint *constr,
     143                 :             :                                                                            const char *domainName, ObjectAddress *constrAddr);
     144                 :             : static void AlterTypeRecurse(Oid typeOid, bool isImplicitArray,
     145                 :             :                                                          HeapTuple tup, Relation catalog,
     146                 :             :                                                          AlterTypeRecurseParams *atparams);
     147                 :             : 
     148                 :             : 
     149                 :             : /*
     150                 :             :  * DefineType
     151                 :             :  *              Registers a new base type.
     152                 :             :  */
     153                 :             : ObjectAddress
     154                 :           0 : DefineType(ParseState *pstate, List *names, List *parameters)
     155                 :             : {
     156                 :           0 :         char       *typeName;
     157                 :           0 :         Oid                     typeNamespace;
     158                 :           0 :         int16           internalLength = -1;    /* default: variable-length */
     159                 :           0 :         List       *inputName = NIL;
     160                 :           0 :         List       *outputName = NIL;
     161                 :           0 :         List       *receiveName = NIL;
     162                 :           0 :         List       *sendName = NIL;
     163                 :           0 :         List       *typmodinName = NIL;
     164                 :           0 :         List       *typmodoutName = NIL;
     165                 :           0 :         List       *analyzeName = NIL;
     166                 :           0 :         List       *subscriptName = NIL;
     167                 :           0 :         char            category = TYPCATEGORY_USER;
     168                 :           0 :         bool            preferred = false;
     169                 :           0 :         char            delimiter = DEFAULT_TYPDELIM;
     170                 :           0 :         Oid                     elemType = InvalidOid;
     171                 :           0 :         char       *defaultValue = NULL;
     172                 :           0 :         bool            byValue = false;
     173                 :           0 :         char            alignment = TYPALIGN_INT;       /* default alignment */
     174                 :           0 :         char            storage = TYPSTORAGE_PLAIN; /* default TOAST storage method */
     175                 :           0 :         Oid                     collation = InvalidOid;
     176                 :           0 :         DefElem    *likeTypeEl = NULL;
     177                 :           0 :         DefElem    *internalLengthEl = NULL;
     178                 :           0 :         DefElem    *inputNameEl = NULL;
     179                 :           0 :         DefElem    *outputNameEl = NULL;
     180                 :           0 :         DefElem    *receiveNameEl = NULL;
     181                 :           0 :         DefElem    *sendNameEl = NULL;
     182                 :           0 :         DefElem    *typmodinNameEl = NULL;
     183                 :           0 :         DefElem    *typmodoutNameEl = NULL;
     184                 :           0 :         DefElem    *analyzeNameEl = NULL;
     185                 :           0 :         DefElem    *subscriptNameEl = NULL;
     186                 :           0 :         DefElem    *categoryEl = NULL;
     187                 :           0 :         DefElem    *preferredEl = NULL;
     188                 :           0 :         DefElem    *delimiterEl = NULL;
     189                 :           0 :         DefElem    *elemTypeEl = NULL;
     190                 :           0 :         DefElem    *defaultValueEl = NULL;
     191                 :           0 :         DefElem    *byValueEl = NULL;
     192                 :           0 :         DefElem    *alignmentEl = NULL;
     193                 :           0 :         DefElem    *storageEl = NULL;
     194                 :           0 :         DefElem    *collatableEl = NULL;
     195                 :           0 :         Oid                     inputOid;
     196                 :           0 :         Oid                     outputOid;
     197                 :           0 :         Oid                     receiveOid = InvalidOid;
     198                 :           0 :         Oid                     sendOid = InvalidOid;
     199                 :           0 :         Oid                     typmodinOid = InvalidOid;
     200                 :           0 :         Oid                     typmodoutOid = InvalidOid;
     201                 :           0 :         Oid                     analyzeOid = InvalidOid;
     202                 :           0 :         Oid                     subscriptOid = InvalidOid;
     203                 :           0 :         char       *array_type;
     204                 :           0 :         Oid                     array_oid;
     205                 :           0 :         Oid                     typoid;
     206                 :           0 :         ListCell   *pl;
     207                 :             :         ObjectAddress address;
     208                 :             : 
     209                 :             :         /*
     210                 :             :          * As of Postgres 8.4, we require superuser privilege to create a base
     211                 :             :          * type.  This is simple paranoia: there are too many ways to mess up the
     212                 :             :          * system with an incorrect type definition (for instance, representation
     213                 :             :          * parameters that don't match what the C code expects).  In practice it
     214                 :             :          * takes superuser privilege to create the I/O functions, and so the
     215                 :             :          * former requirement that you own the I/O functions pretty much forced
     216                 :             :          * superuserness anyway.  We're just making doubly sure here.
     217                 :             :          *
     218                 :             :          * XXX re-enable NOT_USED code sections below if you remove this test.
     219                 :             :          */
     220         [ #  # ]:           0 :         if (!superuser())
     221   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     222                 :             :                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     223                 :             :                                  errmsg("must be superuser to create a base type")));
     224                 :             : 
     225                 :             :         /* Convert list of names to a name and namespace */
     226                 :           0 :         typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
     227                 :             : 
     228                 :             : #ifdef NOT_USED
     229                 :             :         /* XXX this is unnecessary given the superuser check above */
     230                 :             :         /* Check we have creation rights in target namespace */
     231                 :             :         aclresult = object_aclcheck(NamespaceRelationId, typeNamespace, GetUserId(), ACL_CREATE);
     232                 :             :         if (aclresult != ACLCHECK_OK)
     233                 :             :                 aclcheck_error(aclresult, OBJECT_SCHEMA,
     234                 :             :                                            get_namespace_name(typeNamespace));
     235                 :             : #endif
     236                 :             : 
     237                 :             :         /*
     238                 :             :          * Look to see if type already exists.
     239                 :             :          */
     240                 :           0 :         typoid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
     241                 :             :                                                          CStringGetDatum(typeName),
     242                 :             :                                                          ObjectIdGetDatum(typeNamespace));
     243                 :             : 
     244                 :             :         /*
     245                 :             :          * If it's not a shell, see if it's an autogenerated array type, and if so
     246                 :             :          * rename it out of the way.
     247                 :             :          */
     248   [ #  #  #  # ]:           0 :         if (OidIsValid(typoid) && get_typisdefined(typoid))
     249                 :             :         {
     250         [ #  # ]:           0 :                 if (moveArrayTypeName(typoid, typeName, typeNamespace))
     251                 :           0 :                         typoid = InvalidOid;
     252                 :             :                 else
     253   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     254                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
     255                 :             :                                          errmsg("type \"%s\" already exists", typeName)));
     256                 :           0 :         }
     257                 :             : 
     258                 :             :         /*
     259                 :             :          * If this command is a parameterless CREATE TYPE, then we're just here to
     260                 :             :          * make a shell type, so do that (or fail if there already is a shell).
     261                 :             :          */
     262         [ #  # ]:           0 :         if (parameters == NIL)
     263                 :             :         {
     264         [ #  # ]:           0 :                 if (OidIsValid(typoid))
     265   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     266                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
     267                 :             :                                          errmsg("type \"%s\" already exists", typeName)));
     268                 :             : 
     269                 :           0 :                 address = TypeShellMake(typeName, typeNamespace, GetUserId());
     270                 :           0 :                 return address;
     271                 :             :         }
     272                 :             : 
     273                 :             :         /*
     274                 :             :          * Otherwise, we must already have a shell type, since there is no other
     275                 :             :          * way that the I/O functions could have been created.
     276                 :             :          */
     277         [ #  # ]:           0 :         if (!OidIsValid(typoid))
     278   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     279                 :             :                                 (errcode(ERRCODE_DUPLICATE_OBJECT),
     280                 :             :                                  errmsg("type \"%s\" does not exist", typeName),
     281                 :             :                                  errhint("Create the type as a shell type, then create its I/O functions, then do a full CREATE TYPE.")));
     282                 :             : 
     283                 :             :         /* Extract the parameters from the parameter list */
     284   [ #  #  #  #  :           0 :         foreach(pl, parameters)
                   #  # ]
     285                 :             :         {
     286                 :           0 :                 DefElem    *defel = (DefElem *) lfirst(pl);
     287                 :           0 :                 DefElem   **defelp;
     288                 :             : 
     289         [ #  # ]:           0 :                 if (strcmp(defel->defname, "like") == 0)
     290                 :           0 :                         defelp = &likeTypeEl;
     291         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "internallength") == 0)
     292                 :           0 :                         defelp = &internalLengthEl;
     293         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "input") == 0)
     294                 :           0 :                         defelp = &inputNameEl;
     295         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "output") == 0)
     296                 :           0 :                         defelp = &outputNameEl;
     297         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "receive") == 0)
     298                 :           0 :                         defelp = &receiveNameEl;
     299         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "send") == 0)
     300                 :           0 :                         defelp = &sendNameEl;
     301         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "typmod_in") == 0)
     302                 :           0 :                         defelp = &typmodinNameEl;
     303         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "typmod_out") == 0)
     304                 :           0 :                         defelp = &typmodoutNameEl;
     305   [ #  #  #  # ]:           0 :                 else if (strcmp(defel->defname, "analyze") == 0 ||
     306                 :           0 :                                  strcmp(defel->defname, "analyse") == 0)
     307                 :           0 :                         defelp = &analyzeNameEl;
     308         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "subscript") == 0)
     309                 :           0 :                         defelp = &subscriptNameEl;
     310         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "category") == 0)
     311                 :           0 :                         defelp = &categoryEl;
     312         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "preferred") == 0)
     313                 :           0 :                         defelp = &preferredEl;
     314         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "delimiter") == 0)
     315                 :           0 :                         defelp = &delimiterEl;
     316         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "element") == 0)
     317                 :           0 :                         defelp = &elemTypeEl;
     318         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "default") == 0)
     319                 :           0 :                         defelp = &defaultValueEl;
     320         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "passedbyvalue") == 0)
     321                 :           0 :                         defelp = &byValueEl;
     322         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "alignment") == 0)
     323                 :           0 :                         defelp = &alignmentEl;
     324         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "storage") == 0)
     325                 :           0 :                         defelp = &storageEl;
     326         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "collatable") == 0)
     327                 :           0 :                         defelp = &collatableEl;
     328                 :             :                 else
     329                 :             :                 {
     330                 :             :                         /* WARNING, not ERROR, for historical backwards-compatibility */
     331   [ #  #  #  # ]:           0 :                         ereport(WARNING,
     332                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
     333                 :             :                                          errmsg("type attribute \"%s\" not recognized",
     334                 :             :                                                         defel->defname),
     335                 :             :                                          parser_errposition(pstate, defel->location)));
     336                 :           0 :                         continue;
     337                 :             :                 }
     338         [ #  # ]:           0 :                 if (*defelp != NULL)
     339                 :           0 :                         errorConflictingDefElem(defel, pstate);
     340                 :           0 :                 *defelp = defel;
     341      [ #  #  # ]:           0 :         }
     342                 :             : 
     343                 :             :         /*
     344                 :             :          * Now interpret the options; we do this separately so that LIKE can be
     345                 :             :          * overridden by other options regardless of the ordering in the parameter
     346                 :             :          * list.
     347                 :             :          */
     348         [ #  # ]:           0 :         if (likeTypeEl)
     349                 :             :         {
     350                 :           0 :                 Type            likeType;
     351                 :           0 :                 Form_pg_type likeForm;
     352                 :             : 
     353                 :           0 :                 likeType = typenameType(pstate, defGetTypeName(likeTypeEl), NULL);
     354                 :           0 :                 likeForm = (Form_pg_type) GETSTRUCT(likeType);
     355                 :           0 :                 internalLength = likeForm->typlen;
     356                 :           0 :                 byValue = likeForm->typbyval;
     357                 :           0 :                 alignment = likeForm->typalign;
     358                 :           0 :                 storage = likeForm->typstorage;
     359                 :           0 :                 ReleaseSysCache(likeType);
     360                 :           0 :         }
     361         [ #  # ]:           0 :         if (internalLengthEl)
     362                 :           0 :                 internalLength = defGetTypeLength(internalLengthEl);
     363         [ #  # ]:           0 :         if (inputNameEl)
     364                 :           0 :                 inputName = defGetQualifiedName(inputNameEl);
     365         [ #  # ]:           0 :         if (outputNameEl)
     366                 :           0 :                 outputName = defGetQualifiedName(outputNameEl);
     367         [ #  # ]:           0 :         if (receiveNameEl)
     368                 :           0 :                 receiveName = defGetQualifiedName(receiveNameEl);
     369         [ #  # ]:           0 :         if (sendNameEl)
     370                 :           0 :                 sendName = defGetQualifiedName(sendNameEl);
     371         [ #  # ]:           0 :         if (typmodinNameEl)
     372                 :           0 :                 typmodinName = defGetQualifiedName(typmodinNameEl);
     373         [ #  # ]:           0 :         if (typmodoutNameEl)
     374                 :           0 :                 typmodoutName = defGetQualifiedName(typmodoutNameEl);
     375         [ #  # ]:           0 :         if (analyzeNameEl)
     376                 :           0 :                 analyzeName = defGetQualifiedName(analyzeNameEl);
     377         [ #  # ]:           0 :         if (subscriptNameEl)
     378                 :           0 :                 subscriptName = defGetQualifiedName(subscriptNameEl);
     379         [ #  # ]:           0 :         if (categoryEl)
     380                 :             :         {
     381                 :           0 :                 char       *p = defGetString(categoryEl);
     382                 :             : 
     383                 :           0 :                 category = p[0];
     384                 :             :                 /* restrict to non-control ASCII */
     385         [ #  # ]:           0 :                 if (category < 32 || category > 126)
     386   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     387                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     388                 :             :                                          errmsg("invalid type category \"%s\": must be simple ASCII",
     389                 :             :                                                         p)));
     390                 :           0 :         }
     391         [ #  # ]:           0 :         if (preferredEl)
     392                 :           0 :                 preferred = defGetBoolean(preferredEl);
     393         [ #  # ]:           0 :         if (delimiterEl)
     394                 :             :         {
     395                 :           0 :                 char       *p = defGetString(delimiterEl);
     396                 :             : 
     397                 :           0 :                 delimiter = p[0];
     398                 :             :                 /* XXX shouldn't we restrict the delimiter? */
     399                 :           0 :         }
     400         [ #  # ]:           0 :         if (elemTypeEl)
     401                 :             :         {
     402                 :           0 :                 elemType = typenameTypeId(NULL, defGetTypeName(elemTypeEl));
     403                 :             :                 /* disallow arrays of pseudotypes */
     404         [ #  # ]:           0 :                 if (get_typtype(elemType) == TYPTYPE_PSEUDO)
     405   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     406                 :             :                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
     407                 :             :                                          errmsg("array element type cannot be %s",
     408                 :             :                                                         format_type_be(elemType))));
     409                 :           0 :         }
     410         [ #  # ]:           0 :         if (defaultValueEl)
     411                 :           0 :                 defaultValue = defGetString(defaultValueEl);
     412         [ #  # ]:           0 :         if (byValueEl)
     413                 :           0 :                 byValue = defGetBoolean(byValueEl);
     414         [ #  # ]:           0 :         if (alignmentEl)
     415                 :             :         {
     416                 :           0 :                 char       *a = defGetString(alignmentEl);
     417                 :             : 
     418                 :             :                 /*
     419                 :             :                  * Note: if argument was an unquoted identifier, parser will have
     420                 :             :                  * applied translations to it, so be prepared to recognize translated
     421                 :             :                  * type names as well as the nominal form.
     422                 :             :                  */
     423         [ #  # ]:           0 :                 if (pg_strcasecmp(a, "double") == 0 ||
     424   [ #  #  #  # ]:           0 :                         pg_strcasecmp(a, "float8") == 0 ||
     425                 :           0 :                         pg_strcasecmp(a, "pg_catalog.float8") == 0)
     426                 :           0 :                         alignment = TYPALIGN_DOUBLE;
     427   [ #  #  #  # ]:           0 :                 else if (pg_strcasecmp(a, "int4") == 0 ||
     428                 :           0 :                                  pg_strcasecmp(a, "pg_catalog.int4") == 0)
     429                 :           0 :                         alignment = TYPALIGN_INT;
     430   [ #  #  #  # ]:           0 :                 else if (pg_strcasecmp(a, "int2") == 0 ||
     431                 :           0 :                                  pg_strcasecmp(a, "pg_catalog.int2") == 0)
     432                 :           0 :                         alignment = TYPALIGN_SHORT;
     433   [ #  #  #  # ]:           0 :                 else if (pg_strcasecmp(a, "char") == 0 ||
     434                 :           0 :                                  pg_strcasecmp(a, "pg_catalog.bpchar") == 0)
     435                 :           0 :                         alignment = TYPALIGN_CHAR;
     436                 :             :                 else
     437   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     438                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     439                 :             :                                          errmsg("alignment \"%s\" not recognized", a)));
     440                 :           0 :         }
     441         [ #  # ]:           0 :         if (storageEl)
     442                 :             :         {
     443                 :           0 :                 char       *a = defGetString(storageEl);
     444                 :             : 
     445         [ #  # ]:           0 :                 if (pg_strcasecmp(a, "plain") == 0)
     446                 :           0 :                         storage = TYPSTORAGE_PLAIN;
     447         [ #  # ]:           0 :                 else if (pg_strcasecmp(a, "external") == 0)
     448                 :           0 :                         storage = TYPSTORAGE_EXTERNAL;
     449         [ #  # ]:           0 :                 else if (pg_strcasecmp(a, "extended") == 0)
     450                 :           0 :                         storage = TYPSTORAGE_EXTENDED;
     451         [ #  # ]:           0 :                 else if (pg_strcasecmp(a, "main") == 0)
     452                 :           0 :                         storage = TYPSTORAGE_MAIN;
     453                 :             :                 else
     454   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     455                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     456                 :             :                                          errmsg("storage \"%s\" not recognized", a)));
     457                 :           0 :         }
     458         [ #  # ]:           0 :         if (collatableEl)
     459                 :           0 :                 collation = defGetBoolean(collatableEl) ? DEFAULT_COLLATION_OID : InvalidOid;
     460                 :             : 
     461                 :             :         /*
     462                 :             :          * make sure we have our required definitions
     463                 :             :          */
     464         [ #  # ]:           0 :         if (inputName == NIL)
     465   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     466                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
     467                 :             :                                  errmsg("type input function must be specified")));
     468         [ #  # ]:           0 :         if (outputName == NIL)
     469   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     470                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
     471                 :             :                                  errmsg("type output function must be specified")));
     472                 :             : 
     473   [ #  #  #  # ]:           0 :         if (typmodinName == NIL && typmodoutName != NIL)
     474   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     475                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
     476                 :             :                                  errmsg("type modifier output function is useless without a type modifier input function")));
     477                 :             : 
     478                 :             :         /*
     479                 :             :          * Convert I/O proc names to OIDs
     480                 :             :          */
     481                 :           0 :         inputOid = findTypeInputFunction(inputName, typoid);
     482                 :           0 :         outputOid = findTypeOutputFunction(outputName, typoid);
     483         [ #  # ]:           0 :         if (receiveName)
     484                 :           0 :                 receiveOid = findTypeReceiveFunction(receiveName, typoid);
     485         [ #  # ]:           0 :         if (sendName)
     486                 :           0 :                 sendOid = findTypeSendFunction(sendName, typoid);
     487                 :             : 
     488                 :             :         /*
     489                 :             :          * Convert typmodin/out function proc names to OIDs.
     490                 :             :          */
     491         [ #  # ]:           0 :         if (typmodinName)
     492                 :           0 :                 typmodinOid = findTypeTypmodinFunction(typmodinName);
     493         [ #  # ]:           0 :         if (typmodoutName)
     494                 :           0 :                 typmodoutOid = findTypeTypmodoutFunction(typmodoutName);
     495                 :             : 
     496                 :             :         /*
     497                 :             :          * Convert analysis function proc name to an OID. If no analysis function
     498                 :             :          * is specified, we'll use zero to select the built-in default algorithm.
     499                 :             :          */
     500         [ #  # ]:           0 :         if (analyzeName)
     501                 :           0 :                 analyzeOid = findTypeAnalyzeFunction(analyzeName, typoid);
     502                 :             : 
     503                 :             :         /*
     504                 :             :          * Likewise look up the subscripting function if any.  If it is not
     505                 :             :          * specified, but a typelem is specified, allow that if
     506                 :             :          * raw_array_subscript_handler can be used.  (This is for backwards
     507                 :             :          * compatibility; maybe someday we should throw an error instead.)
     508                 :             :          */
     509         [ #  # ]:           0 :         if (subscriptName)
     510                 :           0 :                 subscriptOid = findTypeSubscriptingFunction(subscriptName, typoid);
     511         [ #  # ]:           0 :         else if (OidIsValid(elemType))
     512                 :             :         {
     513         [ #  # ]:           0 :                 if (internalLength > 0 && !byValue && get_typlen(elemType) > 0)
     514                 :           0 :                         subscriptOid = F_RAW_ARRAY_SUBSCRIPT_HANDLER;
     515                 :             :                 else
     516   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     517                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     518                 :             :                                          errmsg("element type cannot be specified without a subscripting function")));
     519                 :           0 :         }
     520                 :             : 
     521                 :             :         /*
     522                 :             :          * Check permissions on functions.  We choose to require the creator/owner
     523                 :             :          * of a type to also own the underlying functions.  Since creating a type
     524                 :             :          * is tantamount to granting public execute access on the functions, the
     525                 :             :          * minimum sane check would be for execute-with-grant-option.  But we
     526                 :             :          * don't have a way to make the type go away if the grant option is
     527                 :             :          * revoked, so ownership seems better.
     528                 :             :          *
     529                 :             :          * XXX For now, this is all unnecessary given the superuser check above.
     530                 :             :          * If we ever relax that, these calls likely should be moved into
     531                 :             :          * findTypeInputFunction et al, where they could be shared by AlterType.
     532                 :             :          */
     533                 :             : #ifdef NOT_USED
     534                 :             :         if (inputOid && !object_ownercheck(ProcedureRelationId, inputOid, GetUserId()))
     535                 :             :                 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
     536                 :             :                                            NameListToString(inputName));
     537                 :             :         if (outputOid && !object_ownercheck(ProcedureRelationId, outputOid, GetUserId()))
     538                 :             :                 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
     539                 :             :                                            NameListToString(outputName));
     540                 :             :         if (receiveOid && !object_ownercheck(ProcedureRelationId, receiveOid, GetUserId()))
     541                 :             :                 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
     542                 :             :                                            NameListToString(receiveName));
     543                 :             :         if (sendOid && !object_ownercheck(ProcedureRelationId, sendOid, GetUserId()))
     544                 :             :                 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
     545                 :             :                                            NameListToString(sendName));
     546                 :             :         if (typmodinOid && !object_ownercheck(ProcedureRelationId, typmodinOid, GetUserId()))
     547                 :             :                 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
     548                 :             :                                            NameListToString(typmodinName));
     549                 :             :         if (typmodoutOid && !object_ownercheck(ProcedureRelationId, typmodoutOid, GetUserId()))
     550                 :             :                 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
     551                 :             :                                            NameListToString(typmodoutName));
     552                 :             :         if (analyzeOid && !object_ownercheck(ProcedureRelationId, analyzeOid, GetUserId()))
     553                 :             :                 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
     554                 :             :                                            NameListToString(analyzeName));
     555                 :             :         if (subscriptOid && !object_ownercheck(ProcedureRelationId, subscriptOid, GetUserId()))
     556                 :             :                 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
     557                 :             :                                            NameListToString(subscriptName));
     558                 :             : #endif
     559                 :             : 
     560                 :             :         /*
     561                 :             :          * OK, we're done checking, time to make the type.  We must assign the
     562                 :             :          * array type OID ahead of calling TypeCreate, since the base type and
     563                 :             :          * array type each refer to the other.
     564                 :             :          */
     565                 :           0 :         array_oid = AssignTypeArrayOid();
     566                 :             : 
     567                 :             :         /*
     568                 :             :          * now have TypeCreate do all the real work.
     569                 :             :          *
     570                 :             :          * Note: the pg_type.oid is stored in user tables as array elements (base
     571                 :             :          * types) in ArrayType and in composite types in DatumTupleFields.  This
     572                 :             :          * oid must be preserved by binary upgrades.
     573                 :             :          */
     574                 :             :         address =
     575                 :           0 :                 TypeCreate(InvalidOid,  /* no predetermined type OID */
     576                 :           0 :                                    typeName,    /* type name */
     577                 :           0 :                                    typeNamespace,       /* namespace */
     578                 :             :                                    InvalidOid,  /* relation oid (n/a here) */
     579                 :             :                                    0,                   /* relation kind (ditto) */
     580                 :           0 :                                    GetUserId(), /* owner's ID */
     581                 :           0 :                                    internalLength,      /* internal size */
     582                 :             :                                    TYPTYPE_BASE,        /* type-type (base type) */
     583                 :           0 :                                    category,    /* type-category */
     584                 :           0 :                                    preferred,   /* is it a preferred type? */
     585                 :           0 :                                    delimiter,   /* array element delimiter */
     586                 :           0 :                                    inputOid,    /* input procedure */
     587                 :           0 :                                    outputOid,   /* output procedure */
     588                 :           0 :                                    receiveOid,  /* receive procedure */
     589                 :           0 :                                    sendOid,             /* send procedure */
     590                 :           0 :                                    typmodinOid, /* typmodin procedure */
     591                 :           0 :                                    typmodoutOid,        /* typmodout procedure */
     592                 :           0 :                                    analyzeOid,  /* analyze procedure */
     593                 :           0 :                                    subscriptOid,        /* subscript procedure */
     594                 :           0 :                                    elemType,    /* element type ID */
     595                 :             :                                    false,               /* this is not an implicit array type */
     596                 :           0 :                                    array_oid,   /* array type we are about to create */
     597                 :             :                                    InvalidOid,  /* base type ID (only for domains) */
     598                 :           0 :                                    defaultValue,        /* default type value */
     599                 :             :                                    NULL,                /* no binary form available */
     600                 :           0 :                                    byValue,             /* passed by value */
     601                 :           0 :                                    alignment,   /* required alignment */
     602                 :           0 :                                    storage,             /* TOAST strategy */
     603                 :             :                                    -1,                  /* typMod (Domains only) */
     604                 :             :                                    0,                   /* Array Dimensions of typbasetype */
     605                 :             :                                    false,               /* Type NOT NULL */
     606                 :           0 :                                    collation);  /* type's collation */
     607         [ #  # ]:           0 :         Assert(typoid == address.objectId);
     608                 :             : 
     609                 :             :         /*
     610                 :             :          * Create the array type that goes with it.
     611                 :             :          */
     612                 :           0 :         array_type = makeArrayTypeName(typeName, typeNamespace);
     613                 :             : 
     614                 :             :         /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */
     615                 :           0 :         alignment = (alignment == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;
     616                 :             : 
     617                 :           0 :         TypeCreate(array_oid,           /* force assignment of this type OID */
     618                 :           0 :                            array_type,          /* type name */
     619                 :           0 :                            typeNamespace,       /* namespace */
     620                 :             :                            InvalidOid,          /* relation oid (n/a here) */
     621                 :             :                            0,                           /* relation kind (ditto) */
     622                 :           0 :                            GetUserId(),         /* owner's ID */
     623                 :             :                            -1,                          /* internal size (always varlena) */
     624                 :             :                            TYPTYPE_BASE,        /* type-type (base type) */
     625                 :             :                            TYPCATEGORY_ARRAY,   /* type-category (array) */
     626                 :             :                            false,                       /* array types are never preferred */
     627                 :           0 :                            delimiter,           /* array element delimiter */
     628                 :             :                            F_ARRAY_IN,          /* input procedure */
     629                 :             :                            F_ARRAY_OUT,         /* output procedure */
     630                 :             :                            F_ARRAY_RECV,        /* receive procedure */
     631                 :             :                            F_ARRAY_SEND,        /* send procedure */
     632                 :           0 :                            typmodinOid,         /* typmodin procedure */
     633                 :           0 :                            typmodoutOid,        /* typmodout procedure */
     634                 :             :                            F_ARRAY_TYPANALYZE,  /* analyze procedure */
     635                 :             :                            F_ARRAY_SUBSCRIPT_HANDLER,   /* array subscript procedure */
     636                 :           0 :                            typoid,                      /* element type ID */
     637                 :             :                            true,                        /* yes this is an array type */
     638                 :             :                            InvalidOid,          /* no further array type */
     639                 :             :                            InvalidOid,          /* base type ID */
     640                 :             :                            NULL,                        /* never a default type value */
     641                 :             :                            NULL,                        /* binary default isn't sent either */
     642                 :             :                            false,                       /* never passed by value */
     643                 :           0 :                            alignment,           /* see above */
     644                 :             :                            TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
     645                 :             :                            -1,                          /* typMod (Domains only) */
     646                 :             :                            0,                           /* Array dimensions of typbasetype */
     647                 :             :                            false,                       /* Type NOT NULL */
     648                 :           0 :                            collation);          /* type's collation */
     649                 :             : 
     650                 :           0 :         pfree(array_type);
     651                 :             : 
     652                 :           0 :         return address;
     653                 :           0 : }
     654                 :             : 
     655                 :             : /*
     656                 :             :  * Guts of type deletion.
     657                 :             :  */
     658                 :             : void
     659                 :           0 : RemoveTypeById(Oid typeOid)
     660                 :             : {
     661                 :           0 :         Relation        relation;
     662                 :           0 :         HeapTuple       tup;
     663                 :             : 
     664                 :           0 :         relation = table_open(TypeRelationId, RowExclusiveLock);
     665                 :             : 
     666                 :           0 :         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
     667         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
     668   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", typeOid);
     669                 :             : 
     670                 :           0 :         CatalogTupleDelete(relation, &tup->t_self);
     671                 :             : 
     672                 :             :         /*
     673                 :             :          * If it is an enum, delete the pg_enum entries too; we don't bother with
     674                 :             :          * making dependency entries for those, so it has to be done "by hand"
     675                 :             :          * here.
     676                 :             :          */
     677         [ #  # ]:           0 :         if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_ENUM)
     678                 :           0 :                 EnumValuesDelete(typeOid);
     679                 :             : 
     680                 :             :         /*
     681                 :             :          * If it is a range type, delete the pg_range entry too; we don't bother
     682                 :             :          * with making a dependency entry for that, so it has to be done "by hand"
     683                 :             :          * here.
     684                 :             :          */
     685         [ #  # ]:           0 :         if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_RANGE)
     686                 :           0 :                 RangeDelete(typeOid);
     687                 :             : 
     688                 :           0 :         ReleaseSysCache(tup);
     689                 :             : 
     690                 :           0 :         table_close(relation, RowExclusiveLock);
     691                 :           0 : }
     692                 :             : 
     693                 :             : 
     694                 :             : /*
     695                 :             :  * DefineDomain
     696                 :             :  *              Registers a new domain.
     697                 :             :  */
     698                 :             : ObjectAddress
     699                 :           0 : DefineDomain(ParseState *pstate, CreateDomainStmt *stmt)
     700                 :             : {
     701                 :           0 :         char       *domainName;
     702                 :           0 :         char       *domainArrayName;
     703                 :           0 :         Oid                     domainNamespace;
     704                 :           0 :         AclResult       aclresult;
     705                 :           0 :         int16           internalLength;
     706                 :           0 :         Oid                     inputProcedure;
     707                 :           0 :         Oid                     outputProcedure;
     708                 :           0 :         Oid                     receiveProcedure;
     709                 :           0 :         Oid                     sendProcedure;
     710                 :           0 :         Oid                     analyzeProcedure;
     711                 :           0 :         bool            byValue;
     712                 :           0 :         char            category;
     713                 :           0 :         char            delimiter;
     714                 :           0 :         char            alignment;
     715                 :           0 :         char            storage;
     716                 :           0 :         char            typtype;
     717                 :           0 :         Datum           datum;
     718                 :           0 :         bool            isnull;
     719                 :           0 :         char       *defaultValue = NULL;
     720                 :           0 :         char       *defaultValueBin = NULL;
     721                 :           0 :         bool            saw_default = false;
     722                 :           0 :         bool            typNotNull = false;
     723                 :           0 :         bool            nullDefined = false;
     724                 :           0 :         int32           typNDims = list_length(stmt->typeName->arrayBounds);
     725                 :           0 :         HeapTuple       typeTup;
     726                 :           0 :         List       *schema = stmt->constraints;
     727                 :           0 :         ListCell   *listptr;
     728                 :           0 :         Oid                     basetypeoid;
     729                 :           0 :         Oid                     old_type_oid;
     730                 :           0 :         Oid                     domaincoll;
     731                 :           0 :         Oid                     domainArrayOid;
     732                 :           0 :         Form_pg_type baseType;
     733                 :           0 :         int32           basetypeMod;
     734                 :           0 :         Oid                     baseColl;
     735                 :             :         ObjectAddress address;
     736                 :             : 
     737                 :             :         /* Convert list of names to a name and namespace */
     738                 :           0 :         domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
     739                 :             :                                                                                                                 &domainName);
     740                 :             : 
     741                 :             :         /* Check we have creation rights in target namespace */
     742                 :           0 :         aclresult = object_aclcheck(NamespaceRelationId, domainNamespace, GetUserId(),
     743                 :             :                                                                 ACL_CREATE);
     744         [ #  # ]:           0 :         if (aclresult != ACLCHECK_OK)
     745                 :           0 :                 aclcheck_error(aclresult, OBJECT_SCHEMA,
     746                 :           0 :                                            get_namespace_name(domainNamespace));
     747                 :             : 
     748                 :             :         /*
     749                 :             :          * Check for collision with an existing type name.  If there is one and
     750                 :             :          * it's an autogenerated array, we can rename it out of the way.
     751                 :             :          */
     752                 :           0 :         old_type_oid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
     753                 :             :                                                                    CStringGetDatum(domainName),
     754                 :             :                                                                    ObjectIdGetDatum(domainNamespace));
     755         [ #  # ]:           0 :         if (OidIsValid(old_type_oid))
     756                 :             :         {
     757         [ #  # ]:           0 :                 if (!moveArrayTypeName(old_type_oid, domainName, domainNamespace))
     758   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     759                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
     760                 :             :                                          errmsg("type \"%s\" already exists", domainName)));
     761                 :           0 :         }
     762                 :             : 
     763                 :             :         /*
     764                 :             :          * Look up the base type.
     765                 :             :          */
     766                 :           0 :         typeTup = typenameType(pstate, stmt->typeName, &basetypeMod);
     767                 :           0 :         baseType = (Form_pg_type) GETSTRUCT(typeTup);
     768                 :           0 :         basetypeoid = baseType->oid;
     769                 :             : 
     770                 :             :         /*
     771                 :             :          * Base type must be a plain base type, a composite type, another domain,
     772                 :             :          * an enum or a range type.  Domains over pseudotypes would create a
     773                 :             :          * security hole.  (It would be shorter to code this to just check for
     774                 :             :          * pseudotypes; but it seems safer to call out the specific typtypes that
     775                 :             :          * are supported, rather than assume that all future typtypes would be
     776                 :             :          * automatically supported.)
     777                 :             :          */
     778                 :           0 :         typtype = baseType->typtype;
     779         [ #  # ]:           0 :         if (typtype != TYPTYPE_BASE &&
     780         [ #  # ]:           0 :                 typtype != TYPTYPE_COMPOSITE &&
     781         [ #  # ]:           0 :                 typtype != TYPTYPE_DOMAIN &&
     782         [ #  # ]:           0 :                 typtype != TYPTYPE_ENUM &&
     783   [ #  #  #  # ]:           0 :                 typtype != TYPTYPE_RANGE &&
     784                 :           0 :                 typtype != TYPTYPE_MULTIRANGE)
     785   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     786                 :             :                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
     787                 :             :                                  errmsg("\"%s\" is not a valid base type for a domain",
     788                 :             :                                                 TypeNameToString(stmt->typeName)),
     789                 :             :                                  parser_errposition(pstate, stmt->typeName->location)));
     790                 :             : 
     791                 :           0 :         aclresult = object_aclcheck(TypeRelationId, basetypeoid, GetUserId(), ACL_USAGE);
     792         [ #  # ]:           0 :         if (aclresult != ACLCHECK_OK)
     793                 :           0 :                 aclcheck_error_type(aclresult, basetypeoid);
     794                 :             : 
     795                 :             :         /*
     796                 :             :          * Collect the properties of the new domain.  Some are inherited from the
     797                 :             :          * base type, some are not.  If you change any of this inheritance
     798                 :             :          * behavior, be sure to update AlterTypeRecurse() to match!
     799                 :             :          */
     800                 :             : 
     801                 :             :         /*
     802                 :             :          * Identify the collation if any
     803                 :             :          */
     804                 :           0 :         baseColl = baseType->typcollation;
     805         [ #  # ]:           0 :         if (stmt->collClause)
     806                 :           0 :                 domaincoll = get_collation_oid(stmt->collClause->collname, false);
     807                 :             :         else
     808                 :           0 :                 domaincoll = baseColl;
     809                 :             : 
     810                 :             :         /* Complain if COLLATE is applied to an uncollatable type */
     811   [ #  #  #  # ]:           0 :         if (OidIsValid(domaincoll) && !OidIsValid(baseColl))
     812   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     813                 :             :                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
     814                 :             :                                  errmsg("collations are not supported by type %s",
     815                 :             :                                                 format_type_be(basetypeoid)),
     816                 :             :                                  parser_errposition(pstate, stmt->typeName->location)));
     817                 :             : 
     818                 :             :         /* passed by value */
     819                 :           0 :         byValue = baseType->typbyval;
     820                 :             : 
     821                 :             :         /* Required Alignment */
     822                 :           0 :         alignment = baseType->typalign;
     823                 :             : 
     824                 :             :         /* TOAST Strategy */
     825                 :           0 :         storage = baseType->typstorage;
     826                 :             : 
     827                 :             :         /* Storage Length */
     828                 :           0 :         internalLength = baseType->typlen;
     829                 :             : 
     830                 :             :         /* Type Category */
     831                 :           0 :         category = baseType->typcategory;
     832                 :             : 
     833                 :             :         /* Array element Delimiter */
     834                 :           0 :         delimiter = baseType->typdelim;
     835                 :             : 
     836                 :             :         /* I/O Functions */
     837                 :           0 :         inputProcedure = F_DOMAIN_IN;
     838                 :           0 :         outputProcedure = baseType->typoutput;
     839                 :           0 :         receiveProcedure = F_DOMAIN_RECV;
     840                 :           0 :         sendProcedure = baseType->typsend;
     841                 :             : 
     842                 :             :         /* Domains never accept typmods, so no typmodin/typmodout needed */
     843                 :             : 
     844                 :             :         /* Analysis function */
     845                 :           0 :         analyzeProcedure = baseType->typanalyze;
     846                 :             : 
     847                 :             :         /*
     848                 :             :          * Domains don't need a subscript function, since they are not
     849                 :             :          * subscriptable on their own.  If the base type is subscriptable, the
     850                 :             :          * parser will reduce the type to the base type before subscripting.
     851                 :             :          */
     852                 :             : 
     853                 :             :         /* Inherited default value */
     854                 :           0 :         datum = SysCacheGetAttr(TYPEOID, typeTup,
     855                 :             :                                                         Anum_pg_type_typdefault, &isnull);
     856         [ #  # ]:           0 :         if (!isnull)
     857                 :           0 :                 defaultValue = TextDatumGetCString(datum);
     858                 :             : 
     859                 :             :         /* Inherited default binary value */
     860                 :           0 :         datum = SysCacheGetAttr(TYPEOID, typeTup,
     861                 :             :                                                         Anum_pg_type_typdefaultbin, &isnull);
     862         [ #  # ]:           0 :         if (!isnull)
     863                 :           0 :                 defaultValueBin = TextDatumGetCString(datum);
     864                 :             : 
     865                 :             :         /*
     866                 :             :          * Run through constraints manually to avoid the additional processing
     867                 :             :          * conducted by DefineRelation() and friends.
     868                 :             :          */
     869   [ #  #  #  #  :           0 :         foreach(listptr, schema)
                   #  # ]
     870                 :             :         {
     871                 :           0 :                 Constraint *constr = lfirst(listptr);
     872                 :             : 
     873         [ #  # ]:           0 :                 if (!IsA(constr, Constraint))
     874   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized node type: %d",
     875                 :             :                                  (int) nodeTag(constr));
     876   [ #  #  #  #  :           0 :                 switch (constr->contype)
          #  #  #  #  #  
                #  #  # ]
     877                 :             :                 {
     878                 :             :                         case CONSTR_DEFAULT:
     879                 :             : 
     880                 :             :                                 /*
     881                 :             :                                  * The inherited default value may be overridden by the user
     882                 :             :                                  * with the DEFAULT <expr> clause ... but only once.
     883                 :             :                                  */
     884         [ #  # ]:           0 :                                 if (saw_default)
     885   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
     886                 :             :                                                         errcode(ERRCODE_SYNTAX_ERROR),
     887                 :             :                                                         errmsg("multiple default expressions"),
     888                 :             :                                                         parser_errposition(pstate, constr->location));
     889                 :           0 :                                 saw_default = true;
     890                 :             : 
     891         [ #  # ]:           0 :                                 if (constr->raw_expr)
     892                 :             :                                 {
     893                 :           0 :                                         Node       *defaultExpr;
     894                 :             : 
     895                 :             :                                         /*
     896                 :             :                                          * Cook the constr->raw_expr into an expression. Note:
     897                 :             :                                          * name is strictly for error message
     898                 :             :                                          */
     899                 :           0 :                                         defaultExpr = cookDefault(pstate, constr->raw_expr,
     900                 :           0 :                                                                                           basetypeoid,
     901                 :           0 :                                                                                           basetypeMod,
     902                 :           0 :                                                                                           domainName,
     903                 :             :                                                                                           0);
     904                 :             : 
     905                 :             :                                         /*
     906                 :             :                                          * If the expression is just a NULL constant, we treat it
     907                 :             :                                          * like not having a default.
     908                 :             :                                          *
     909                 :             :                                          * Note that if the basetype is another domain, we'll see
     910                 :             :                                          * a CoerceToDomain expr here and not discard the default.
     911                 :             :                                          * This is critical because the domain default needs to be
     912                 :             :                                          * retained to override any default that the base domain
     913                 :             :                                          * might have.
     914                 :             :                                          */
     915   [ #  #  #  # ]:           0 :                                         if (defaultExpr == NULL ||
     916         [ #  # ]:           0 :                                                 (IsA(defaultExpr, Const) &&
     917                 :           0 :                                                  ((Const *) defaultExpr)->constisnull))
     918                 :             :                                         {
     919                 :           0 :                                                 defaultValue = NULL;
     920                 :           0 :                                                 defaultValueBin = NULL;
     921                 :           0 :                                         }
     922                 :             :                                         else
     923                 :             :                                         {
     924                 :             :                                                 /*
     925                 :             :                                                  * Expression must be stored as a nodeToString result,
     926                 :             :                                                  * but we also require a valid textual representation
     927                 :             :                                                  * (mainly to make life easier for pg_dump).
     928                 :             :                                                  */
     929                 :           0 :                                                 defaultValue =
     930                 :           0 :                                                         deparse_expression(defaultExpr,
     931                 :             :                                                                                            NIL, false, false);
     932                 :           0 :                                                 defaultValueBin = nodeToString(defaultExpr);
     933                 :             :                                         }
     934                 :           0 :                                 }
     935                 :             :                                 else
     936                 :             :                                 {
     937                 :             :                                         /* No default (can this still happen?) */
     938                 :           0 :                                         defaultValue = NULL;
     939                 :           0 :                                         defaultValueBin = NULL;
     940                 :             :                                 }
     941                 :           0 :                                 break;
     942                 :             : 
     943                 :             :                         case CONSTR_NOTNULL:
     944         [ #  # ]:           0 :                                 if (nullDefined)
     945                 :             :                                 {
     946         [ #  # ]:           0 :                                         if (!typNotNull)
     947   [ #  #  #  # ]:           0 :                                                 ereport(ERROR,
     948                 :             :                                                                 errcode(ERRCODE_SYNTAX_ERROR),
     949                 :             :                                                                 errmsg("conflicting NULL/NOT NULL constraints"),
     950                 :             :                                                                 parser_errposition(pstate, constr->location));
     951                 :             : 
     952   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
     953                 :             :                                                         errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
     954                 :             :                                                         errmsg("redundant NOT NULL constraint definition"),
     955                 :             :                                                         parser_errposition(pstate, constr->location));
     956                 :           0 :                                 }
     957         [ #  # ]:           0 :                                 if (constr->is_no_inherit)
     958   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
     959                 :             :                                                         errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
     960                 :             :                                                         errmsg("not-null constraints for domains cannot be marked NO INHERIT"),
     961                 :             :                                                         parser_errposition(pstate, constr->location));
     962                 :           0 :                                 typNotNull = true;
     963                 :           0 :                                 nullDefined = true;
     964                 :           0 :                                 break;
     965                 :             : 
     966                 :             :                         case CONSTR_NULL:
     967   [ #  #  #  # ]:           0 :                                 if (nullDefined && typNotNull)
     968   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
     969                 :             :                                                         errcode(ERRCODE_SYNTAX_ERROR),
     970                 :             :                                                         errmsg("conflicting NULL/NOT NULL constraints"),
     971                 :             :                                                         parser_errposition(pstate, constr->location));
     972                 :           0 :                                 typNotNull = false;
     973                 :           0 :                                 nullDefined = true;
     974                 :           0 :                                 break;
     975                 :             : 
     976                 :             :                         case CONSTR_CHECK:
     977                 :             : 
     978                 :             :                                 /*
     979                 :             :                                  * Check constraints are handled after domain creation, as
     980                 :             :                                  * they require the Oid of the domain; at this point we can
     981                 :             :                                  * only check that they're not marked NO INHERIT, because that
     982                 :             :                                  * would be bogus.
     983                 :             :                                  */
     984         [ #  # ]:           0 :                                 if (constr->is_no_inherit)
     985   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
     986                 :             :                                                         errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
     987                 :             :                                                         errmsg("check constraints for domains cannot be marked NO INHERIT"),
     988                 :             :                                                         parser_errposition(pstate, constr->location));
     989                 :             : 
     990                 :           0 :                                 break;
     991                 :             : 
     992                 :             :                                 /*
     993                 :             :                                  * All else are error cases
     994                 :             :                                  */
     995                 :             :                         case CONSTR_UNIQUE:
     996   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
     997                 :             :                                                 errcode(ERRCODE_SYNTAX_ERROR),
     998                 :             :                                                 errmsg("unique constraints not possible for domains"),
     999                 :             :                                                 parser_errposition(pstate, constr->location));
    1000                 :           0 :                                 break;
    1001                 :             : 
    1002                 :             :                         case CONSTR_PRIMARY:
    1003   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    1004                 :             :                                                 (errcode(ERRCODE_SYNTAX_ERROR),
    1005                 :             :                                                  errmsg("primary key constraints not possible for domains"),
    1006                 :             :                                                  parser_errposition(pstate, constr->location)));
    1007                 :           0 :                                 break;
    1008                 :             : 
    1009                 :             :                         case CONSTR_EXCLUSION:
    1010   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    1011                 :             :                                                 (errcode(ERRCODE_SYNTAX_ERROR),
    1012                 :             :                                                  errmsg("exclusion constraints not possible for domains"),
    1013                 :             :                                                  parser_errposition(pstate, constr->location)));
    1014                 :           0 :                                 break;
    1015                 :             : 
    1016                 :             :                         case CONSTR_FOREIGN:
    1017   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    1018                 :             :                                                 (errcode(ERRCODE_SYNTAX_ERROR),
    1019                 :             :                                                  errmsg("foreign key constraints not possible for domains"),
    1020                 :             :                                                  parser_errposition(pstate, constr->location)));
    1021                 :           0 :                                 break;
    1022                 :             : 
    1023                 :             :                         case CONSTR_ATTR_DEFERRABLE:
    1024                 :             :                         case CONSTR_ATTR_NOT_DEFERRABLE:
    1025                 :             :                         case CONSTR_ATTR_DEFERRED:
    1026                 :             :                         case CONSTR_ATTR_IMMEDIATE:
    1027   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    1028                 :             :                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1029                 :             :                                                  errmsg("specifying constraint deferrability not supported for domains"),
    1030                 :             :                                                  parser_errposition(pstate, constr->location)));
    1031                 :           0 :                                 break;
    1032                 :             : 
    1033                 :             :                         case CONSTR_GENERATED:
    1034                 :             :                         case CONSTR_IDENTITY:
    1035   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    1036                 :             :                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1037                 :             :                                                  errmsg("specifying GENERATED not supported for domains"),
    1038                 :             :                                                  parser_errposition(pstate, constr->location)));
    1039                 :           0 :                                 break;
    1040                 :             : 
    1041                 :             :                         case CONSTR_ATTR_ENFORCED:
    1042                 :             :                         case CONSTR_ATTR_NOT_ENFORCED:
    1043   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    1044                 :             :                                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    1045                 :             :                                                  errmsg("specifying constraint enforceability not supported for domains"),
    1046                 :             :                                                  parser_errposition(pstate, constr->location)));
    1047                 :           0 :                                 break;
    1048                 :             : 
    1049                 :             :                                 /* no default, to let compiler warn about missing case */
    1050                 :             :                 }
    1051                 :           0 :         }
    1052                 :             : 
    1053                 :             :         /* Allocate OID for array type */
    1054                 :           0 :         domainArrayOid = AssignTypeArrayOid();
    1055                 :             : 
    1056                 :             :         /*
    1057                 :             :          * Have TypeCreate do all the real work.
    1058                 :             :          */
    1059                 :             :         address =
    1060                 :           0 :                 TypeCreate(InvalidOid,  /* no predetermined type OID */
    1061                 :           0 :                                    domainName,  /* type name */
    1062                 :           0 :                                    domainNamespace, /* namespace */
    1063                 :             :                                    InvalidOid,  /* relation oid (n/a here) */
    1064                 :             :                                    0,                   /* relation kind (ditto) */
    1065                 :           0 :                                    GetUserId(), /* owner's ID */
    1066                 :           0 :                                    internalLength,      /* internal size */
    1067                 :             :                                    TYPTYPE_DOMAIN,      /* type-type (domain type) */
    1068                 :           0 :                                    category,    /* type-category */
    1069                 :             :                                    false,               /* domain types are never preferred */
    1070                 :           0 :                                    delimiter,   /* array element delimiter */
    1071                 :           0 :                                    inputProcedure,      /* input procedure */
    1072                 :           0 :                                    outputProcedure, /* output procedure */
    1073                 :           0 :                                    receiveProcedure,    /* receive procedure */
    1074                 :           0 :                                    sendProcedure,       /* send procedure */
    1075                 :             :                                    InvalidOid,  /* typmodin procedure - none */
    1076                 :             :                                    InvalidOid,  /* typmodout procedure - none */
    1077                 :           0 :                                    analyzeProcedure,    /* analyze procedure */
    1078                 :             :                                    InvalidOid,  /* subscript procedure - none */
    1079                 :             :                                    InvalidOid,  /* no array element type */
    1080                 :             :                                    false,               /* this isn't an array */
    1081                 :           0 :                                    domainArrayOid,      /* array type we are about to create */
    1082                 :           0 :                                    basetypeoid, /* base type ID */
    1083                 :           0 :                                    defaultValue,        /* default type value (text) */
    1084                 :           0 :                                    defaultValueBin, /* default type value (binary) */
    1085                 :           0 :                                    byValue,             /* passed by value */
    1086                 :           0 :                                    alignment,   /* required alignment */
    1087                 :           0 :                                    storage,             /* TOAST strategy */
    1088                 :           0 :                                    basetypeMod, /* typeMod value */
    1089                 :           0 :                                    typNDims,    /* Array dimensions for base type */
    1090                 :           0 :                                    typNotNull,  /* Type NOT NULL */
    1091                 :           0 :                                    domaincoll); /* type's collation */
    1092                 :             : 
    1093                 :             :         /*
    1094                 :             :          * Create the array type that goes with it.
    1095                 :             :          */
    1096                 :           0 :         domainArrayName = makeArrayTypeName(domainName, domainNamespace);
    1097                 :             : 
    1098                 :             :         /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */
    1099                 :           0 :         alignment = (alignment == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;
    1100                 :             : 
    1101                 :           0 :         TypeCreate(domainArrayOid,      /* force assignment of this type OID */
    1102                 :           0 :                            domainArrayName, /* type name */
    1103                 :           0 :                            domainNamespace, /* namespace */
    1104                 :             :                            InvalidOid,          /* relation oid (n/a here) */
    1105                 :             :                            0,                           /* relation kind (ditto) */
    1106                 :           0 :                            GetUserId(),         /* owner's ID */
    1107                 :             :                            -1,                          /* internal size (always varlena) */
    1108                 :             :                            TYPTYPE_BASE,        /* type-type (base type) */
    1109                 :             :                            TYPCATEGORY_ARRAY,   /* type-category (array) */
    1110                 :             :                            false,                       /* array types are never preferred */
    1111                 :           0 :                            delimiter,           /* array element delimiter */
    1112                 :             :                            F_ARRAY_IN,          /* input procedure */
    1113                 :             :                            F_ARRAY_OUT,         /* output procedure */
    1114                 :             :                            F_ARRAY_RECV,        /* receive procedure */
    1115                 :             :                            F_ARRAY_SEND,        /* send procedure */
    1116                 :             :                            InvalidOid,          /* typmodin procedure - none */
    1117                 :             :                            InvalidOid,          /* typmodout procedure - none */
    1118                 :             :                            F_ARRAY_TYPANALYZE,  /* analyze procedure */
    1119                 :             :                            F_ARRAY_SUBSCRIPT_HANDLER,   /* array subscript procedure */
    1120                 :           0 :                            address.objectId,    /* element type ID */
    1121                 :             :                            true,                        /* yes this is an array type */
    1122                 :             :                            InvalidOid,          /* no further array type */
    1123                 :             :                            InvalidOid,          /* base type ID */
    1124                 :             :                            NULL,                        /* never a default type value */
    1125                 :             :                            NULL,                        /* binary default isn't sent either */
    1126                 :             :                            false,                       /* never passed by value */
    1127                 :           0 :                            alignment,           /* see above */
    1128                 :             :                            TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
    1129                 :             :                            -1,                          /* typMod (Domains only) */
    1130                 :             :                            0,                           /* Array dimensions of typbasetype */
    1131                 :             :                            false,                       /* Type NOT NULL */
    1132                 :           0 :                            domaincoll);         /* type's collation */
    1133                 :             : 
    1134                 :           0 :         pfree(domainArrayName);
    1135                 :             : 
    1136                 :             :         /*
    1137                 :             :          * Process constraints which refer to the domain ID returned by TypeCreate
    1138                 :             :          */
    1139   [ #  #  #  #  :           0 :         foreach(listptr, schema)
                   #  # ]
    1140                 :             :         {
    1141                 :           0 :                 Constraint *constr = lfirst(listptr);
    1142                 :             : 
    1143                 :             :                 /* it must be a Constraint, per check above */
    1144                 :             : 
    1145      [ #  #  # ]:           0 :                 switch (constr->contype)
    1146                 :             :                 {
    1147                 :             :                         case CONSTR_CHECK:
    1148                 :           0 :                                 domainAddCheckConstraint(address.objectId, domainNamespace,
    1149                 :           0 :                                                                                  basetypeoid, basetypeMod,
    1150                 :           0 :                                                                                  constr, domainName, NULL);
    1151                 :           0 :                                 break;
    1152                 :             : 
    1153                 :             :                         case CONSTR_NOTNULL:
    1154                 :           0 :                                 domainAddNotNullConstraint(address.objectId, domainNamespace,
    1155                 :           0 :                                                                                    basetypeoid, basetypeMod,
    1156                 :           0 :                                                                                    constr, domainName, NULL);
    1157                 :           0 :                                 break;
    1158                 :             : 
    1159                 :             :                                 /* Other constraint types were fully processed above */
    1160                 :             : 
    1161                 :             :                         default:
    1162                 :           0 :                                 break;
    1163                 :             :                 }
    1164                 :             : 
    1165                 :             :                 /* CCI so we can detect duplicate constraint names */
    1166                 :           0 :                 CommandCounterIncrement();
    1167                 :           0 :         }
    1168                 :             : 
    1169                 :             :         /*
    1170                 :             :          * Now we can clean up.
    1171                 :             :          */
    1172                 :           0 :         ReleaseSysCache(typeTup);
    1173                 :             : 
    1174                 :             :         return address;
    1175                 :           0 : }
    1176                 :             : 
    1177                 :             : 
    1178                 :             : /*
    1179                 :             :  * DefineEnum
    1180                 :             :  *              Registers a new enum.
    1181                 :             :  */
    1182                 :             : ObjectAddress
    1183                 :           0 : DefineEnum(CreateEnumStmt *stmt)
    1184                 :             : {
    1185                 :           0 :         char       *enumName;
    1186                 :           0 :         char       *enumArrayName;
    1187                 :           0 :         Oid                     enumNamespace;
    1188                 :           0 :         AclResult       aclresult;
    1189                 :           0 :         Oid                     old_type_oid;
    1190                 :           0 :         Oid                     enumArrayOid;
    1191                 :             :         ObjectAddress enumTypeAddr;
    1192                 :             : 
    1193                 :             :         /* Convert list of names to a name and namespace */
    1194                 :           0 :         enumNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
    1195                 :             :                                                                                                           &enumName);
    1196                 :             : 
    1197                 :             :         /* Check we have creation rights in target namespace */
    1198                 :           0 :         aclresult = object_aclcheck(NamespaceRelationId, enumNamespace, GetUserId(), ACL_CREATE);
    1199         [ #  # ]:           0 :         if (aclresult != ACLCHECK_OK)
    1200                 :           0 :                 aclcheck_error(aclresult, OBJECT_SCHEMA,
    1201                 :           0 :                                            get_namespace_name(enumNamespace));
    1202                 :             : 
    1203                 :             :         /*
    1204                 :             :          * Check for collision with an existing type name.  If there is one and
    1205                 :             :          * it's an autogenerated array, we can rename it out of the way.
    1206                 :             :          */
    1207                 :           0 :         old_type_oid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
    1208                 :             :                                                                    CStringGetDatum(enumName),
    1209                 :             :                                                                    ObjectIdGetDatum(enumNamespace));
    1210         [ #  # ]:           0 :         if (OidIsValid(old_type_oid))
    1211                 :             :         {
    1212         [ #  # ]:           0 :                 if (!moveArrayTypeName(old_type_oid, enumName, enumNamespace))
    1213   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    1214                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
    1215                 :             :                                          errmsg("type \"%s\" already exists", enumName)));
    1216                 :           0 :         }
    1217                 :             : 
    1218                 :             :         /* Allocate OID for array type */
    1219                 :           0 :         enumArrayOid = AssignTypeArrayOid();
    1220                 :             : 
    1221                 :             :         /* Create the pg_type entry */
    1222                 :             :         enumTypeAddr =
    1223                 :           0 :                 TypeCreate(InvalidOid,  /* no predetermined type OID */
    1224                 :           0 :                                    enumName,    /* type name */
    1225                 :           0 :                                    enumNamespace,       /* namespace */
    1226                 :             :                                    InvalidOid,  /* relation oid (n/a here) */
    1227                 :             :                                    0,                   /* relation kind (ditto) */
    1228                 :           0 :                                    GetUserId(), /* owner's ID */
    1229                 :             :                                    sizeof(Oid), /* internal size */
    1230                 :             :                                    TYPTYPE_ENUM,        /* type-type (enum type) */
    1231                 :             :                                    TYPCATEGORY_ENUM,    /* type-category (enum type) */
    1232                 :             :                                    false,               /* enum types are never preferred */
    1233                 :             :                                    DEFAULT_TYPDELIM,    /* array element delimiter */
    1234                 :             :                                    F_ENUM_IN,   /* input procedure */
    1235                 :             :                                    F_ENUM_OUT,  /* output procedure */
    1236                 :             :                                    F_ENUM_RECV, /* receive procedure */
    1237                 :             :                                    F_ENUM_SEND, /* send procedure */
    1238                 :             :                                    InvalidOid,  /* typmodin procedure - none */
    1239                 :             :                                    InvalidOid,  /* typmodout procedure - none */
    1240                 :             :                                    InvalidOid,  /* analyze procedure - default */
    1241                 :             :                                    InvalidOid,  /* subscript procedure - none */
    1242                 :             :                                    InvalidOid,  /* element type ID */
    1243                 :             :                                    false,               /* this is not an array type */
    1244                 :           0 :                                    enumArrayOid,        /* array type we are about to create */
    1245                 :             :                                    InvalidOid,  /* base type ID (only for domains) */
    1246                 :             :                                    NULL,                /* never a default type value */
    1247                 :             :                                    NULL,                /* binary default isn't sent either */
    1248                 :             :                                    true,                /* always passed by value */
    1249                 :             :                                    TYPALIGN_INT,        /* int alignment */
    1250                 :             :                                    TYPSTORAGE_PLAIN,    /* TOAST strategy always plain */
    1251                 :             :                                    -1,                  /* typMod (Domains only) */
    1252                 :             :                                    0,                   /* Array dimensions of typbasetype */
    1253                 :             :                                    false,               /* Type NOT NULL */
    1254                 :             :                                    InvalidOid); /* type's collation */
    1255                 :             : 
    1256                 :             :         /* Enter the enum's values into pg_enum */
    1257                 :           0 :         EnumValuesCreate(enumTypeAddr.objectId, stmt->vals);
    1258                 :             : 
    1259                 :             :         /*
    1260                 :             :          * Create the array type that goes with it.
    1261                 :             :          */
    1262                 :           0 :         enumArrayName = makeArrayTypeName(enumName, enumNamespace);
    1263                 :             : 
    1264                 :           0 :         TypeCreate(enumArrayOid,        /* force assignment of this type OID */
    1265                 :           0 :                            enumArrayName,       /* type name */
    1266                 :           0 :                            enumNamespace,       /* namespace */
    1267                 :             :                            InvalidOid,          /* relation oid (n/a here) */
    1268                 :             :                            0,                           /* relation kind (ditto) */
    1269                 :           0 :                            GetUserId(),         /* owner's ID */
    1270                 :             :                            -1,                          /* internal size (always varlena) */
    1271                 :             :                            TYPTYPE_BASE,        /* type-type (base type) */
    1272                 :             :                            TYPCATEGORY_ARRAY,   /* type-category (array) */
    1273                 :             :                            false,                       /* array types are never preferred */
    1274                 :             :                            DEFAULT_TYPDELIM,    /* array element delimiter */
    1275                 :             :                            F_ARRAY_IN,          /* input procedure */
    1276                 :             :                            F_ARRAY_OUT,         /* output procedure */
    1277                 :             :                            F_ARRAY_RECV,        /* receive procedure */
    1278                 :             :                            F_ARRAY_SEND,        /* send procedure */
    1279                 :             :                            InvalidOid,          /* typmodin procedure - none */
    1280                 :             :                            InvalidOid,          /* typmodout procedure - none */
    1281                 :             :                            F_ARRAY_TYPANALYZE,  /* analyze procedure */
    1282                 :             :                            F_ARRAY_SUBSCRIPT_HANDLER,   /* array subscript procedure */
    1283                 :           0 :                            enumTypeAddr.objectId,       /* element type ID */
    1284                 :             :                            true,                        /* yes this is an array type */
    1285                 :             :                            InvalidOid,          /* no further array type */
    1286                 :             :                            InvalidOid,          /* base type ID */
    1287                 :             :                            NULL,                        /* never a default type value */
    1288                 :             :                            NULL,                        /* binary default isn't sent either */
    1289                 :             :                            false,                       /* never passed by value */
    1290                 :             :                            TYPALIGN_INT,        /* enums have int align, so do their arrays */
    1291                 :             :                            TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
    1292                 :             :                            -1,                          /* typMod (Domains only) */
    1293                 :             :                            0,                           /* Array dimensions of typbasetype */
    1294                 :             :                            false,                       /* Type NOT NULL */
    1295                 :             :                            InvalidOid);         /* type's collation */
    1296                 :             : 
    1297                 :           0 :         pfree(enumArrayName);
    1298                 :             : 
    1299                 :             :         return enumTypeAddr;
    1300                 :           0 : }
    1301                 :             : 
    1302                 :             : /*
    1303                 :             :  * AlterEnum
    1304                 :             :  *              Adds a new label to an existing enum.
    1305                 :             :  */
    1306                 :             : ObjectAddress
    1307                 :           0 : AlterEnum(AlterEnumStmt *stmt)
    1308                 :             : {
    1309                 :           0 :         Oid                     enum_type_oid;
    1310                 :           0 :         TypeName   *typename;
    1311                 :           0 :         HeapTuple       tup;
    1312                 :             :         ObjectAddress address;
    1313                 :             : 
    1314                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    1315                 :           0 :         typename = makeTypeNameFromNameList(stmt->typeName);
    1316                 :           0 :         enum_type_oid = typenameTypeId(NULL, typename);
    1317                 :             : 
    1318                 :           0 :         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(enum_type_oid));
    1319         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    1320   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", enum_type_oid);
    1321                 :             : 
    1322                 :             :         /* Check it's an enum and check user has permission to ALTER the enum */
    1323                 :           0 :         checkEnumOwner(tup);
    1324                 :             : 
    1325                 :           0 :         ReleaseSysCache(tup);
    1326                 :             : 
    1327         [ #  # ]:           0 :         if (stmt->oldVal)
    1328                 :             :         {
    1329                 :             :                 /* Rename an existing label */
    1330                 :           0 :                 RenameEnumLabel(enum_type_oid, stmt->oldVal, stmt->newVal);
    1331                 :           0 :         }
    1332                 :             :         else
    1333                 :             :         {
    1334                 :             :                 /* Add a new label */
    1335                 :           0 :                 AddEnumLabel(enum_type_oid, stmt->newVal,
    1336                 :           0 :                                          stmt->newValNeighbor, stmt->newValIsAfter,
    1337                 :           0 :                                          stmt->skipIfNewValExists);
    1338                 :             :         }
    1339                 :             : 
    1340         [ #  # ]:           0 :         InvokeObjectPostAlterHook(TypeRelationId, enum_type_oid, 0);
    1341                 :             : 
    1342                 :           0 :         ObjectAddressSet(address, TypeRelationId, enum_type_oid);
    1343                 :             : 
    1344                 :             :         return address;
    1345                 :           0 : }
    1346                 :             : 
    1347                 :             : 
    1348                 :             : /*
    1349                 :             :  * checkEnumOwner
    1350                 :             :  *
    1351                 :             :  * Check that the type is actually an enum and that the current user
    1352                 :             :  * has permission to do ALTER TYPE on it.  Throw an error if not.
    1353                 :             :  */
    1354                 :             : static void
    1355                 :           0 : checkEnumOwner(HeapTuple tup)
    1356                 :             : {
    1357                 :           0 :         Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
    1358                 :             : 
    1359                 :             :         /* Check that this is actually an enum */
    1360         [ #  # ]:           0 :         if (typTup->typtype != TYPTYPE_ENUM)
    1361   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    1362                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1363                 :             :                                  errmsg("%s is not an enum",
    1364                 :             :                                                 format_type_be(typTup->oid))));
    1365                 :             : 
    1366                 :             :         /* Permission check: must own type */
    1367         [ #  # ]:           0 :         if (!object_ownercheck(TypeRelationId, typTup->oid, GetUserId()))
    1368                 :           0 :                 aclcheck_error_type(ACLCHECK_NOT_OWNER, typTup->oid);
    1369                 :           0 : }
    1370                 :             : 
    1371                 :             : 
    1372                 :             : /*
    1373                 :             :  * DefineRange
    1374                 :             :  *              Registers a new range type.
    1375                 :             :  *
    1376                 :             :  * Perhaps it might be worthwhile to set pg_type.typelem to the base type,
    1377                 :             :  * and likewise on multiranges to set it to the range type. But having a
    1378                 :             :  * non-zero typelem is treated elsewhere as a synonym for being an array,
    1379                 :             :  * and users might have queries with that same assumption.
    1380                 :             :  */
    1381                 :             : ObjectAddress
    1382                 :           0 : DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
    1383                 :             : {
    1384                 :           0 :         char       *typeName;
    1385                 :           0 :         Oid                     typeNamespace;
    1386                 :           0 :         Oid                     typoid;
    1387                 :           0 :         char       *rangeArrayName;
    1388                 :           0 :         char       *multirangeTypeName = NULL;
    1389                 :           0 :         char       *multirangeArrayName;
    1390                 :           0 :         Oid                     multirangeNamespace = InvalidOid;
    1391                 :           0 :         Oid                     rangeArrayOid;
    1392                 :           0 :         Oid                     multirangeOid;
    1393                 :           0 :         Oid                     multirangeArrayOid;
    1394                 :           0 :         Oid                     rangeSubtype = InvalidOid;
    1395                 :           0 :         List       *rangeSubOpclassName = NIL;
    1396                 :           0 :         List       *rangeCollationName = NIL;
    1397                 :           0 :         List       *rangeCanonicalName = NIL;
    1398                 :           0 :         List       *rangeSubtypeDiffName = NIL;
    1399                 :           0 :         Oid                     rangeSubOpclass;
    1400                 :           0 :         Oid                     rangeCollation;
    1401                 :           0 :         regproc         rangeCanonical;
    1402                 :           0 :         regproc         rangeSubtypeDiff;
    1403                 :           0 :         int16           subtyplen;
    1404                 :           0 :         bool            subtypbyval;
    1405                 :           0 :         char            subtypalign;
    1406                 :           0 :         char            alignment;
    1407                 :           0 :         AclResult       aclresult;
    1408                 :           0 :         ListCell   *lc;
    1409                 :             :         ObjectAddress address;
    1410                 :           0 :         ObjectAddress mltrngaddress PG_USED_FOR_ASSERTS_ONLY;
    1411                 :           0 :         Oid                     rangeConstruct2Oid = InvalidOid;
    1412                 :           0 :         Oid                     rangeConstruct3Oid = InvalidOid;
    1413                 :           0 :         Oid                     mltrngConstruct0Oid = InvalidOid;
    1414                 :           0 :         Oid                     mltrngConstruct1Oid = InvalidOid;
    1415                 :           0 :         Oid                     mltrngConstruct2Oid = InvalidOid;
    1416                 :           0 :         Oid                     castFuncOid;
    1417                 :             : 
    1418                 :             :         /* Convert list of names to a name and namespace */
    1419                 :           0 :         typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
    1420                 :             :                                                                                                           &typeName);
    1421                 :             : 
    1422                 :             :         /* Check we have creation rights in target namespace */
    1423                 :           0 :         aclresult = object_aclcheck(NamespaceRelationId, typeNamespace, GetUserId(), ACL_CREATE);
    1424         [ #  # ]:           0 :         if (aclresult != ACLCHECK_OK)
    1425                 :           0 :                 aclcheck_error(aclresult, OBJECT_SCHEMA,
    1426                 :           0 :                                            get_namespace_name(typeNamespace));
    1427                 :             : 
    1428                 :             :         /*
    1429                 :             :          * Look to see if type already exists.
    1430                 :             :          */
    1431                 :           0 :         typoid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
    1432                 :             :                                                          CStringGetDatum(typeName),
    1433                 :             :                                                          ObjectIdGetDatum(typeNamespace));
    1434                 :             : 
    1435                 :             :         /*
    1436                 :             :          * If it's not a shell, see if it's an autogenerated array type, and if so
    1437                 :             :          * rename it out of the way.
    1438                 :             :          */
    1439   [ #  #  #  # ]:           0 :         if (OidIsValid(typoid) && get_typisdefined(typoid))
    1440                 :             :         {
    1441         [ #  # ]:           0 :                 if (moveArrayTypeName(typoid, typeName, typeNamespace))
    1442                 :           0 :                         typoid = InvalidOid;
    1443                 :             :                 else
    1444   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    1445                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
    1446                 :             :                                          errmsg("type \"%s\" already exists", typeName)));
    1447                 :           0 :         }
    1448                 :             : 
    1449                 :             :         /*
    1450                 :             :          * Unlike DefineType(), we don't insist on a shell type existing first, as
    1451                 :             :          * it's only needed if the user wants to specify a canonical function.
    1452                 :             :          */
    1453                 :             : 
    1454                 :             :         /* Extract the parameters from the parameter list */
    1455   [ #  #  #  #  :           0 :         foreach(lc, stmt->params)
                   #  # ]
    1456                 :             :         {
    1457                 :           0 :                 DefElem    *defel = (DefElem *) lfirst(lc);
    1458                 :             : 
    1459         [ #  # ]:           0 :                 if (strcmp(defel->defname, "subtype") == 0)
    1460                 :             :                 {
    1461         [ #  # ]:           0 :                         if (OidIsValid(rangeSubtype))
    1462                 :           0 :                                 errorConflictingDefElem(defel, pstate);
    1463                 :             :                         /* we can look up the subtype name immediately */
    1464                 :           0 :                         rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
    1465                 :           0 :                 }
    1466         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "subtype_opclass") == 0)
    1467                 :             :                 {
    1468         [ #  # ]:           0 :                         if (rangeSubOpclassName != NIL)
    1469                 :           0 :                                 errorConflictingDefElem(defel, pstate);
    1470                 :           0 :                         rangeSubOpclassName = defGetQualifiedName(defel);
    1471                 :           0 :                 }
    1472         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "collation") == 0)
    1473                 :             :                 {
    1474         [ #  # ]:           0 :                         if (rangeCollationName != NIL)
    1475                 :           0 :                                 errorConflictingDefElem(defel, pstate);
    1476                 :           0 :                         rangeCollationName = defGetQualifiedName(defel);
    1477                 :           0 :                 }
    1478         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "canonical") == 0)
    1479                 :             :                 {
    1480         [ #  # ]:           0 :                         if (rangeCanonicalName != NIL)
    1481                 :           0 :                                 errorConflictingDefElem(defel, pstate);
    1482                 :           0 :                         rangeCanonicalName = defGetQualifiedName(defel);
    1483                 :           0 :                 }
    1484         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "subtype_diff") == 0)
    1485                 :             :                 {
    1486         [ #  # ]:           0 :                         if (rangeSubtypeDiffName != NIL)
    1487                 :           0 :                                 errorConflictingDefElem(defel, pstate);
    1488                 :           0 :                         rangeSubtypeDiffName = defGetQualifiedName(defel);
    1489                 :           0 :                 }
    1490         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "multirange_type_name") == 0)
    1491                 :             :                 {
    1492         [ #  # ]:           0 :                         if (multirangeTypeName != NULL)
    1493                 :           0 :                                 errorConflictingDefElem(defel, pstate);
    1494                 :             :                         /* we can look up the subtype name immediately */
    1495                 :           0 :                         multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
    1496                 :             :                                                                                                                                         &multirangeTypeName);
    1497                 :           0 :                 }
    1498                 :             :                 else
    1499   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    1500                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
    1501                 :             :                                          errmsg("type attribute \"%s\" not recognized",
    1502                 :             :                                                         defel->defname)));
    1503                 :           0 :         }
    1504                 :             : 
    1505                 :             :         /* Must have a subtype */
    1506         [ #  # ]:           0 :         if (!OidIsValid(rangeSubtype))
    1507   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    1508                 :             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
    1509                 :             :                                  errmsg("type attribute \"subtype\" is required")));
    1510                 :             :         /* disallow ranges of pseudotypes */
    1511         [ #  # ]:           0 :         if (get_typtype(rangeSubtype) == TYPTYPE_PSEUDO)
    1512   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    1513                 :             :                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    1514                 :             :                                  errmsg("range subtype cannot be %s",
    1515                 :             :                                                 format_type_be(rangeSubtype))));
    1516                 :             : 
    1517                 :             :         /* Identify subopclass */
    1518                 :           0 :         rangeSubOpclass = findRangeSubOpclass(rangeSubOpclassName, rangeSubtype);
    1519                 :             : 
    1520                 :             :         /* Identify collation to use, if any */
    1521         [ #  # ]:           0 :         if (type_is_collatable(rangeSubtype))
    1522                 :             :         {
    1523         [ #  # ]:           0 :                 if (rangeCollationName != NIL)
    1524                 :           0 :                         rangeCollation = get_collation_oid(rangeCollationName, false);
    1525                 :             :                 else
    1526                 :           0 :                         rangeCollation = get_typcollation(rangeSubtype);
    1527                 :           0 :         }
    1528                 :             :         else
    1529                 :             :         {
    1530         [ #  # ]:           0 :                 if (rangeCollationName != NIL)
    1531   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    1532                 :             :                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1533                 :             :                                          errmsg("range collation specified but subtype does not support collation")));
    1534                 :           0 :                 rangeCollation = InvalidOid;
    1535                 :             :         }
    1536                 :             : 
    1537                 :             :         /* Identify support functions, if provided */
    1538         [ #  # ]:           0 :         if (rangeCanonicalName != NIL)
    1539                 :             :         {
    1540         [ #  # ]:           0 :                 if (!OidIsValid(typoid))
    1541   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    1542                 :             :                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    1543                 :             :                                          errmsg("cannot specify a canonical function without a pre-created shell type"),
    1544                 :             :                                          errhint("Create the type as a shell type, then create its canonicalization function, then do a full CREATE TYPE.")));
    1545                 :           0 :                 rangeCanonical = findRangeCanonicalFunction(rangeCanonicalName,
    1546                 :           0 :                                                                                                         typoid);
    1547                 :           0 :         }
    1548                 :             :         else
    1549                 :           0 :                 rangeCanonical = InvalidOid;
    1550                 :             : 
    1551         [ #  # ]:           0 :         if (rangeSubtypeDiffName != NIL)
    1552                 :           0 :                 rangeSubtypeDiff = findRangeSubtypeDiffFunction(rangeSubtypeDiffName,
    1553                 :           0 :                                                                                                                 rangeSubtype);
    1554                 :             :         else
    1555                 :           0 :                 rangeSubtypeDiff = InvalidOid;
    1556                 :             : 
    1557                 :           0 :         get_typlenbyvalalign(rangeSubtype,
    1558                 :             :                                                  &subtyplen, &subtypbyval, &subtypalign);
    1559                 :             : 
    1560                 :             :         /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for ranges */
    1561                 :           0 :         alignment = (subtypalign == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;
    1562                 :             : 
    1563                 :             :         /* Allocate OID for array type, its multirange, and its multirange array */
    1564                 :           0 :         rangeArrayOid = AssignTypeArrayOid();
    1565                 :           0 :         multirangeOid = AssignTypeMultirangeOid();
    1566                 :           0 :         multirangeArrayOid = AssignTypeMultirangeArrayOid();
    1567                 :             : 
    1568                 :             :         /* Create the pg_type entry */
    1569                 :             :         address =
    1570                 :           0 :                 TypeCreate(InvalidOid,  /* no predetermined type OID */
    1571                 :           0 :                                    typeName,    /* type name */
    1572                 :           0 :                                    typeNamespace,       /* namespace */
    1573                 :             :                                    InvalidOid,  /* relation oid (n/a here) */
    1574                 :             :                                    0,                   /* relation kind (ditto) */
    1575                 :           0 :                                    GetUserId(), /* owner's ID */
    1576                 :             :                                    -1,                  /* internal size (always varlena) */
    1577                 :             :                                    TYPTYPE_RANGE,       /* type-type (range type) */
    1578                 :             :                                    TYPCATEGORY_RANGE,   /* type-category (range type) */
    1579                 :             :                                    false,               /* range types are never preferred */
    1580                 :             :                                    DEFAULT_TYPDELIM,    /* array element delimiter */
    1581                 :             :                                    F_RANGE_IN,  /* input procedure */
    1582                 :             :                                    F_RANGE_OUT, /* output procedure */
    1583                 :             :                                    F_RANGE_RECV,        /* receive procedure */
    1584                 :             :                                    F_RANGE_SEND,        /* send procedure */
    1585                 :             :                                    InvalidOid,  /* typmodin procedure - none */
    1586                 :             :                                    InvalidOid,  /* typmodout procedure - none */
    1587                 :             :                                    F_RANGE_TYPANALYZE,  /* analyze procedure */
    1588                 :             :                                    InvalidOid,  /* subscript procedure - none */
    1589                 :             :                                    InvalidOid,  /* element type ID - none */
    1590                 :             :                                    false,               /* this is not an array type */
    1591                 :           0 :                                    rangeArrayOid,       /* array type we are about to create */
    1592                 :             :                                    InvalidOid,  /* base type ID (only for domains) */
    1593                 :             :                                    NULL,                /* never a default type value */
    1594                 :             :                                    NULL,                /* no binary form available either */
    1595                 :             :                                    false,               /* never passed by value */
    1596                 :           0 :                                    alignment,   /* alignment */
    1597                 :             :                                    TYPSTORAGE_EXTENDED, /* TOAST strategy (always extended) */
    1598                 :             :                                    -1,                  /* typMod (Domains only) */
    1599                 :             :                                    0,                   /* Array dimensions of typbasetype */
    1600                 :             :                                    false,               /* Type NOT NULL */
    1601                 :             :                                    InvalidOid); /* type's collation (ranges never have one) */
    1602   [ #  #  #  # ]:           0 :         Assert(typoid == InvalidOid || typoid == address.objectId);
    1603                 :           0 :         typoid = address.objectId;
    1604                 :             : 
    1605                 :             :         /* Create the multirange that goes with it */
    1606         [ #  # ]:           0 :         if (multirangeTypeName)
    1607                 :             :         {
    1608                 :           0 :                 Oid                     old_typoid;
    1609                 :             : 
    1610                 :             :                 /*
    1611                 :             :                  * Look to see if multirange type already exists.
    1612                 :             :                  */
    1613                 :           0 :                 old_typoid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
    1614                 :             :                                                                          CStringGetDatum(multirangeTypeName),
    1615                 :             :                                                                          ObjectIdGetDatum(multirangeNamespace));
    1616                 :             : 
    1617                 :             :                 /*
    1618                 :             :                  * If it's not a shell, see if it's an autogenerated array type, and
    1619                 :             :                  * if so rename it out of the way.
    1620                 :             :                  */
    1621   [ #  #  #  # ]:           0 :                 if (OidIsValid(old_typoid) && get_typisdefined(old_typoid))
    1622                 :             :                 {
    1623         [ #  # ]:           0 :                         if (!moveArrayTypeName(old_typoid, multirangeTypeName, multirangeNamespace))
    1624   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    1625                 :             :                                                 (errcode(ERRCODE_DUPLICATE_OBJECT),
    1626                 :             :                                                  errmsg("type \"%s\" already exists", multirangeTypeName)));
    1627                 :           0 :                 }
    1628                 :           0 :         }
    1629                 :             :         else
    1630                 :             :         {
    1631                 :             :                 /* Generate multirange name automatically */
    1632                 :           0 :                 multirangeNamespace = typeNamespace;
    1633                 :           0 :                 multirangeTypeName = makeMultirangeTypeName(typeName, multirangeNamespace);
    1634                 :             :         }
    1635                 :             : 
    1636                 :             :         mltrngaddress =
    1637                 :           0 :                 TypeCreate(multirangeOid,       /* force assignment of this type OID */
    1638                 :           0 :                                    multirangeTypeName,  /* type name */
    1639                 :           0 :                                    multirangeNamespace, /* namespace */
    1640                 :             :                                    InvalidOid,  /* relation oid (n/a here) */
    1641                 :             :                                    0,                   /* relation kind (ditto) */
    1642                 :           0 :                                    GetUserId(), /* owner's ID */
    1643                 :             :                                    -1,                  /* internal size (always varlena) */
    1644                 :             :                                    TYPTYPE_MULTIRANGE,  /* type-type (multirange type) */
    1645                 :             :                                    TYPCATEGORY_RANGE,   /* type-category (range type) */
    1646                 :             :                                    false,               /* multirange types are never preferred */
    1647                 :             :                                    DEFAULT_TYPDELIM,    /* array element delimiter */
    1648                 :             :                                    F_MULTIRANGE_IN, /* input procedure */
    1649                 :             :                                    F_MULTIRANGE_OUT,    /* output procedure */
    1650                 :             :                                    F_MULTIRANGE_RECV,   /* receive procedure */
    1651                 :             :                                    F_MULTIRANGE_SEND,   /* send procedure */
    1652                 :             :                                    InvalidOid,  /* typmodin procedure - none */
    1653                 :             :                                    InvalidOid,  /* typmodout procedure - none */
    1654                 :             :                                    F_MULTIRANGE_TYPANALYZE, /* analyze procedure */
    1655                 :             :                                    InvalidOid,  /* subscript procedure - none */
    1656                 :             :                                    InvalidOid,  /* element type ID - none */
    1657                 :             :                                    false,               /* this is not an array type */
    1658                 :           0 :                                    multirangeArrayOid,  /* array type we are about to create */
    1659                 :             :                                    InvalidOid,  /* base type ID (only for domains) */
    1660                 :             :                                    NULL,                /* never a default type value */
    1661                 :             :                                    NULL,                /* no binary form available either */
    1662                 :             :                                    false,               /* never passed by value */
    1663                 :           0 :                                    alignment,   /* alignment */
    1664                 :             :                                    'x',                 /* TOAST strategy (always extended) */
    1665                 :             :                                    -1,                  /* typMod (Domains only) */
    1666                 :             :                                    0,                   /* Array dimensions of typbasetype */
    1667                 :             :                                    false,               /* Type NOT NULL */
    1668                 :             :                                    InvalidOid); /* type's collation (ranges never have one) */
    1669         [ #  # ]:           0 :         Assert(multirangeOid == mltrngaddress.objectId);
    1670                 :             : 
    1671                 :             :         /*
    1672                 :             :          * Create the array type that goes with it.
    1673                 :             :          */
    1674                 :           0 :         rangeArrayName = makeArrayTypeName(typeName, typeNamespace);
    1675                 :             : 
    1676                 :           0 :         TypeCreate(rangeArrayOid,       /* force assignment of this type OID */
    1677                 :           0 :                            rangeArrayName,      /* type name */
    1678                 :           0 :                            typeNamespace,       /* namespace */
    1679                 :             :                            InvalidOid,          /* relation oid (n/a here) */
    1680                 :             :                            0,                           /* relation kind (ditto) */
    1681                 :           0 :                            GetUserId(),         /* owner's ID */
    1682                 :             :                            -1,                          /* internal size (always varlena) */
    1683                 :             :                            TYPTYPE_BASE,        /* type-type (base type) */
    1684                 :             :                            TYPCATEGORY_ARRAY,   /* type-category (array) */
    1685                 :             :                            false,                       /* array types are never preferred */
    1686                 :             :                            DEFAULT_TYPDELIM,    /* array element delimiter */
    1687                 :             :                            F_ARRAY_IN,          /* input procedure */
    1688                 :             :                            F_ARRAY_OUT,         /* output procedure */
    1689                 :             :                            F_ARRAY_RECV,        /* receive procedure */
    1690                 :             :                            F_ARRAY_SEND,        /* send procedure */
    1691                 :             :                            InvalidOid,          /* typmodin procedure - none */
    1692                 :             :                            InvalidOid,          /* typmodout procedure - none */
    1693                 :             :                            F_ARRAY_TYPANALYZE,  /* analyze procedure */
    1694                 :             :                            F_ARRAY_SUBSCRIPT_HANDLER,   /* array subscript procedure */
    1695                 :           0 :                            typoid,                      /* element type ID */
    1696                 :             :                            true,                        /* yes this is an array type */
    1697                 :             :                            InvalidOid,          /* no further array type */
    1698                 :             :                            InvalidOid,          /* base type ID */
    1699                 :             :                            NULL,                        /* never a default type value */
    1700                 :             :                            NULL,                        /* binary default isn't sent either */
    1701                 :             :                            false,                       /* never passed by value */
    1702                 :           0 :                            alignment,           /* alignment - same as range's */
    1703                 :             :                            TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
    1704                 :             :                            -1,                          /* typMod (Domains only) */
    1705                 :             :                            0,                           /* Array dimensions of typbasetype */
    1706                 :             :                            false,                       /* Type NOT NULL */
    1707                 :             :                            InvalidOid);         /* typcollation */
    1708                 :             : 
    1709                 :           0 :         pfree(rangeArrayName);
    1710                 :             : 
    1711                 :             :         /* Create the multirange's array type */
    1712                 :             : 
    1713                 :           0 :         multirangeArrayName = makeArrayTypeName(multirangeTypeName, typeNamespace);
    1714                 :             : 
    1715                 :           0 :         TypeCreate(multirangeArrayOid,  /* force assignment of this type OID */
    1716                 :           0 :                            multirangeArrayName, /* type name */
    1717                 :           0 :                            multirangeNamespace, /* namespace */
    1718                 :             :                            InvalidOid,          /* relation oid (n/a here) */
    1719                 :             :                            0,                           /* relation kind (ditto) */
    1720                 :           0 :                            GetUserId(),         /* owner's ID */
    1721                 :             :                            -1,                          /* internal size (always varlena) */
    1722                 :             :                            TYPTYPE_BASE,        /* type-type (base type) */
    1723                 :             :                            TYPCATEGORY_ARRAY,   /* type-category (array) */
    1724                 :             :                            false,                       /* array types are never preferred */
    1725                 :             :                            DEFAULT_TYPDELIM,    /* array element delimiter */
    1726                 :             :                            F_ARRAY_IN,          /* input procedure */
    1727                 :             :                            F_ARRAY_OUT,         /* output procedure */
    1728                 :             :                            F_ARRAY_RECV,        /* receive procedure */
    1729                 :             :                            F_ARRAY_SEND,        /* send procedure */
    1730                 :             :                            InvalidOid,          /* typmodin procedure - none */
    1731                 :             :                            InvalidOid,          /* typmodout procedure - none */
    1732                 :             :                            F_ARRAY_TYPANALYZE,  /* analyze procedure */
    1733                 :             :                            F_ARRAY_SUBSCRIPT_HANDLER,   /* array subscript procedure */
    1734                 :           0 :                            multirangeOid,       /* element type ID */
    1735                 :             :                            true,                        /* yes this is an array type */
    1736                 :             :                            InvalidOid,          /* no further array type */
    1737                 :             :                            InvalidOid,          /* base type ID */
    1738                 :             :                            NULL,                        /* never a default type value */
    1739                 :             :                            NULL,                        /* binary default isn't sent either */
    1740                 :             :                            false,                       /* never passed by value */
    1741                 :           0 :                            alignment,           /* alignment - same as range's */
    1742                 :             :                            'x',                         /* ARRAY is always toastable */
    1743                 :             :                            -1,                          /* typMod (Domains only) */
    1744                 :             :                            0,                           /* Array dimensions of typbasetype */
    1745                 :             :                            false,                       /* Type NOT NULL */
    1746                 :             :                            InvalidOid);         /* typcollation */
    1747                 :             : 
    1748                 :             :         /* Ensure these new types are visible to ProcedureCreate */
    1749                 :           0 :         CommandCounterIncrement();
    1750                 :             : 
    1751                 :             :         /* And create the constructor functions for this range type */
    1752                 :           0 :         makeRangeConstructors(typeName, typeNamespace, typoid, rangeSubtype,
    1753                 :             :                                                   &rangeConstruct2Oid, &rangeConstruct3Oid);
    1754                 :           0 :         makeMultirangeConstructors(multirangeTypeName, typeNamespace,
    1755                 :           0 :                                                            multirangeOid, typoid, rangeArrayOid,
    1756                 :             :                                                            &mltrngConstruct0Oid, &mltrngConstruct1Oid, &mltrngConstruct2Oid);
    1757                 :           0 :         castFuncOid = mltrngConstruct1Oid;
    1758                 :             : 
    1759                 :             :         /* Create the entry in pg_range */
    1760                 :           0 :         RangeCreate(typoid, rangeSubtype, rangeCollation, rangeSubOpclass,
    1761                 :           0 :                                 rangeCanonical, rangeSubtypeDiff, multirangeOid,
    1762                 :           0 :                                 rangeConstruct2Oid, rangeConstruct3Oid,
    1763                 :           0 :                                 mltrngConstruct0Oid, mltrngConstruct1Oid, mltrngConstruct2Oid);
    1764                 :             : 
    1765                 :             :         /* Create cast from the range type to its multirange type */
    1766                 :           0 :         CastCreate(typoid, multirangeOid, castFuncOid, InvalidOid, InvalidOid,
    1767                 :             :                            COERCION_CODE_EXPLICIT, COERCION_METHOD_FUNCTION,
    1768                 :             :                            DEPENDENCY_INTERNAL);
    1769                 :             : 
    1770                 :           0 :         pfree(multirangeArrayName);
    1771                 :             : 
    1772                 :             :         return address;
    1773                 :           0 : }
    1774                 :             : 
    1775                 :             : /*
    1776                 :             :  * Because there may exist several range types over the same subtype, the
    1777                 :             :  * range type can't be uniquely determined from the subtype.  So it's
    1778                 :             :  * impossible to define a polymorphic constructor; we have to generate new
    1779                 :             :  * constructor functions explicitly for each range type.
    1780                 :             :  *
    1781                 :             :  * We actually define 2 functions, with 2 through 3 arguments.  This is just
    1782                 :             :  * to offer more convenience for the user.
    1783                 :             :  *
    1784                 :             :  * The OIDs of the created functions are returned through the pointer
    1785                 :             :  * arguments.
    1786                 :             :  */
    1787                 :             : static void
    1788                 :           0 : makeRangeConstructors(const char *name, Oid namespace,
    1789                 :             :                                           Oid rangeOid, Oid subtype,
    1790                 :             :                                           Oid *rangeConstruct2_p, Oid *rangeConstruct3_p)
    1791                 :             : {
    1792                 :             :         static const char *const prosrc[2] = {"range_constructor2",
    1793                 :             :         "range_constructor3"};
    1794                 :             :         static const int pronargs[2] = {2, 3};
    1795                 :             : 
    1796                 :           0 :         Oid                     constructorArgTypes[3];
    1797                 :           0 :         ObjectAddress myself,
    1798                 :             :                                 referenced;
    1799                 :           0 :         int                     i;
    1800                 :             : 
    1801                 :           0 :         constructorArgTypes[0] = subtype;
    1802                 :           0 :         constructorArgTypes[1] = subtype;
    1803                 :           0 :         constructorArgTypes[2] = TEXTOID;
    1804                 :             : 
    1805                 :           0 :         referenced.classId = TypeRelationId;
    1806                 :           0 :         referenced.objectId = rangeOid;
    1807                 :           0 :         referenced.objectSubId = 0;
    1808                 :             : 
    1809         [ #  # ]:           0 :         for (i = 0; i < lengthof(prosrc); i++)
    1810                 :             :         {
    1811                 :           0 :                 oidvector  *constructorArgTypesVector;
    1812                 :             : 
    1813                 :           0 :                 constructorArgTypesVector = buildoidvector(constructorArgTypes,
    1814                 :           0 :                                                                                                    pronargs[i]);
    1815                 :             : 
    1816                 :           0 :                 myself = ProcedureCreate(name,  /* name: same as range type */
    1817                 :           0 :                                                                  namespace, /* namespace */
    1818                 :             :                                                                  false, /* replace */
    1819                 :             :                                                                  false, /* returns set */
    1820                 :           0 :                                                                  rangeOid,      /* return type */
    1821                 :             :                                                                  BOOTSTRAP_SUPERUSERID, /* proowner */
    1822                 :             :                                                                  INTERNALlanguageId,    /* language */
    1823                 :             :                                                                  F_FMGR_INTERNAL_VALIDATOR, /* language validator */
    1824                 :           0 :                                                                  prosrc[i], /* prosrc */
    1825                 :             :                                                                  NULL,  /* probin */
    1826                 :             :                                                                  NULL,  /* prosqlbody */
    1827                 :             :                                                                  PROKIND_FUNCTION,
    1828                 :             :                                                                  false, /* security_definer */
    1829                 :             :                                                                  false, /* leakproof */
    1830                 :             :                                                                  false, /* isStrict */
    1831                 :             :                                                                  PROVOLATILE_IMMUTABLE, /* volatility */
    1832                 :             :                                                                  PROPARALLEL_SAFE,      /* parallel safety */
    1833                 :           0 :                                                                  constructorArgTypesVector, /* parameterTypes */
    1834                 :           0 :                                                                  PointerGetDatum(NULL), /* allParameterTypes */
    1835                 :           0 :                                                                  PointerGetDatum(NULL), /* parameterModes */
    1836                 :           0 :                                                                  PointerGetDatum(NULL), /* parameterNames */
    1837                 :             :                                                                  NIL,   /* parameterDefaults */
    1838                 :           0 :                                                                  PointerGetDatum(NULL), /* trftypes */
    1839                 :             :                                                                  NIL,   /* trfoids */
    1840                 :           0 :                                                                  PointerGetDatum(NULL), /* proconfig */
    1841                 :             :                                                                  InvalidOid,    /* prosupport */
    1842                 :             :                                                                  1.0,   /* procost */
    1843                 :             :                                                                  0.0);  /* prorows */
    1844                 :             : 
    1845                 :             :                 /*
    1846                 :             :                  * Make the constructors internally-dependent on the range type so
    1847                 :             :                  * that they go away silently when the type is dropped.  Note that
    1848                 :             :                  * pg_dump depends on this choice to avoid dumping the constructors.
    1849                 :             :                  */
    1850                 :           0 :                 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
    1851                 :             : 
    1852         [ #  # ]:           0 :                 if (pronargs[i] == 2)
    1853                 :           0 :                         *rangeConstruct2_p = myself.objectId;
    1854         [ #  # ]:           0 :                 else if (pronargs[i] == 3)
    1855                 :           0 :                         *rangeConstruct3_p = myself.objectId;
    1856                 :           0 :         }
    1857                 :           0 : }
    1858                 :             : 
    1859                 :             : /*
    1860                 :             :  * We make a separate multirange constructor for each range type
    1861                 :             :  * so its name can include the base type, like range constructors do.
    1862                 :             :  * If we had an anyrangearray polymorphic type we could use it here,
    1863                 :             :  * but since each type has its own constructor name there's no need.
    1864                 :             :  *
    1865                 :             :  * The OIDs of the created functions are returned through the pointer
    1866                 :             :  * arguments.
    1867                 :             :  */
    1868                 :             : static void
    1869                 :           0 : makeMultirangeConstructors(const char *name, Oid namespace,
    1870                 :             :                                                    Oid multirangeOid, Oid rangeOid, Oid rangeArrayOid,
    1871                 :             :                                                    Oid *mltrngConstruct0_p, Oid *mltrngConstruct1_p, Oid *mltrngConstruct2_p)
    1872                 :             : {
    1873                 :           0 :         ObjectAddress myself,
    1874                 :             :                                 referenced;
    1875                 :           0 :         oidvector  *argtypes;
    1876                 :           0 :         Datum           allParamTypes;
    1877                 :           0 :         ArrayType  *allParameterTypes;
    1878                 :           0 :         Datum           paramModes;
    1879                 :           0 :         ArrayType  *parameterModes;
    1880                 :             : 
    1881                 :           0 :         referenced.classId = TypeRelationId;
    1882                 :           0 :         referenced.objectId = multirangeOid;
    1883                 :           0 :         referenced.objectSubId = 0;
    1884                 :             : 
    1885                 :             :         /* 0-arg constructor - for empty multiranges */
    1886                 :           0 :         argtypes = buildoidvector(NULL, 0);
    1887                 :           0 :         myself = ProcedureCreate(name,  /* name: same as multirange type */
    1888                 :           0 :                                                          namespace,
    1889                 :             :                                                          false, /* replace */
    1890                 :             :                                                          false, /* returns set */
    1891                 :           0 :                                                          multirangeOid, /* return type */
    1892                 :             :                                                          BOOTSTRAP_SUPERUSERID, /* proowner */
    1893                 :             :                                                          INTERNALlanguageId,    /* language */
    1894                 :             :                                                          F_FMGR_INTERNAL_VALIDATOR,
    1895                 :             :                                                          "multirange_constructor0", /* prosrc */
    1896                 :             :                                                          NULL,  /* probin */
    1897                 :             :                                                          NULL,  /* prosqlbody */
    1898                 :             :                                                          PROKIND_FUNCTION,
    1899                 :             :                                                          false, /* security_definer */
    1900                 :             :                                                          false, /* leakproof */
    1901                 :             :                                                          true,  /* isStrict */
    1902                 :             :                                                          PROVOLATILE_IMMUTABLE, /* volatility */
    1903                 :             :                                                          PROPARALLEL_SAFE,      /* parallel safety */
    1904                 :           0 :                                                          argtypes,      /* parameterTypes */
    1905                 :           0 :                                                          PointerGetDatum(NULL), /* allParameterTypes */
    1906                 :           0 :                                                          PointerGetDatum(NULL), /* parameterModes */
    1907                 :           0 :                                                          PointerGetDatum(NULL), /* parameterNames */
    1908                 :             :                                                          NIL,   /* parameterDefaults */
    1909                 :           0 :                                                          PointerGetDatum(NULL), /* trftypes */
    1910                 :             :                                                          NIL,   /* trfoids */
    1911                 :           0 :                                                          PointerGetDatum(NULL), /* proconfig */
    1912                 :             :                                                          InvalidOid,    /* prosupport */
    1913                 :             :                                                          1.0,   /* procost */
    1914                 :             :                                                          0.0);  /* prorows */
    1915                 :             : 
    1916                 :             :         /*
    1917                 :             :          * Make the constructor internally-dependent on the multirange type so
    1918                 :             :          * that they go away silently when the type is dropped.  Note that pg_dump
    1919                 :             :          * depends on this choice to avoid dumping the constructors.
    1920                 :             :          */
    1921                 :           0 :         recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
    1922                 :           0 :         *mltrngConstruct0_p = myself.objectId;
    1923                 :           0 :         pfree(argtypes);
    1924                 :             : 
    1925                 :             :         /*
    1926                 :             :          * 1-arg constructor - for casts
    1927                 :             :          *
    1928                 :             :          * In theory we shouldn't need both this and the vararg (n-arg)
    1929                 :             :          * constructor, but having a separate 1-arg function lets us define casts
    1930                 :             :          * against it.
    1931                 :             :          */
    1932                 :           0 :         argtypes = buildoidvector(&rangeOid, 1);
    1933                 :           0 :         myself = ProcedureCreate(name,  /* name: same as multirange type */
    1934                 :           0 :                                                          namespace,
    1935                 :             :                                                          false, /* replace */
    1936                 :             :                                                          false, /* returns set */
    1937                 :           0 :                                                          multirangeOid, /* return type */
    1938                 :             :                                                          BOOTSTRAP_SUPERUSERID, /* proowner */
    1939                 :             :                                                          INTERNALlanguageId,    /* language */
    1940                 :             :                                                          F_FMGR_INTERNAL_VALIDATOR,
    1941                 :             :                                                          "multirange_constructor1", /* prosrc */
    1942                 :             :                                                          NULL,  /* probin */
    1943                 :             :                                                          NULL,  /* prosqlbody */
    1944                 :             :                                                          PROKIND_FUNCTION,
    1945                 :             :                                                          false, /* security_definer */
    1946                 :             :                                                          false, /* leakproof */
    1947                 :             :                                                          true,  /* isStrict */
    1948                 :             :                                                          PROVOLATILE_IMMUTABLE, /* volatility */
    1949                 :             :                                                          PROPARALLEL_SAFE,      /* parallel safety */
    1950                 :           0 :                                                          argtypes,      /* parameterTypes */
    1951                 :           0 :                                                          PointerGetDatum(NULL), /* allParameterTypes */
    1952                 :           0 :                                                          PointerGetDatum(NULL), /* parameterModes */
    1953                 :           0 :                                                          PointerGetDatum(NULL), /* parameterNames */
    1954                 :             :                                                          NIL,   /* parameterDefaults */
    1955                 :           0 :                                                          PointerGetDatum(NULL), /* trftypes */
    1956                 :             :                                                          NIL,   /* trfoids */
    1957                 :           0 :                                                          PointerGetDatum(NULL), /* proconfig */
    1958                 :             :                                                          InvalidOid,    /* prosupport */
    1959                 :             :                                                          1.0,   /* procost */
    1960                 :             :                                                          0.0);  /* prorows */
    1961                 :             :         /* ditto */
    1962                 :           0 :         recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
    1963                 :           0 :         *mltrngConstruct1_p = myself.objectId;
    1964                 :           0 :         pfree(argtypes);
    1965                 :             : 
    1966                 :             :         /* n-arg constructor - vararg */
    1967                 :           0 :         argtypes = buildoidvector(&rangeArrayOid, 1);
    1968                 :           0 :         allParamTypes = ObjectIdGetDatum(rangeArrayOid);
    1969                 :           0 :         allParameterTypes = construct_array_builtin(&allParamTypes, 1, OIDOID);
    1970                 :           0 :         paramModes = CharGetDatum(FUNC_PARAM_VARIADIC);
    1971                 :           0 :         parameterModes = construct_array_builtin(&paramModes, 1, CHAROID);
    1972                 :           0 :         myself = ProcedureCreate(name,  /* name: same as multirange type */
    1973                 :           0 :                                                          namespace,
    1974                 :             :                                                          false, /* replace */
    1975                 :             :                                                          false, /* returns set */
    1976                 :           0 :                                                          multirangeOid, /* return type */
    1977                 :             :                                                          BOOTSTRAP_SUPERUSERID, /* proowner */
    1978                 :             :                                                          INTERNALlanguageId,    /* language */
    1979                 :             :                                                          F_FMGR_INTERNAL_VALIDATOR,
    1980                 :             :                                                          "multirange_constructor2", /* prosrc */
    1981                 :             :                                                          NULL,  /* probin */
    1982                 :             :                                                          NULL,  /* prosqlbody */
    1983                 :             :                                                          PROKIND_FUNCTION,
    1984                 :             :                                                          false, /* security_definer */
    1985                 :             :                                                          false, /* leakproof */
    1986                 :             :                                                          true,  /* isStrict */
    1987                 :             :                                                          PROVOLATILE_IMMUTABLE, /* volatility */
    1988                 :             :                                                          PROPARALLEL_SAFE,      /* parallel safety */
    1989                 :           0 :                                                          argtypes,      /* parameterTypes */
    1990                 :           0 :                                                          PointerGetDatum(allParameterTypes),    /* allParameterTypes */
    1991                 :           0 :                                                          PointerGetDatum(parameterModes),       /* parameterModes */
    1992                 :           0 :                                                          PointerGetDatum(NULL), /* parameterNames */
    1993                 :             :                                                          NIL,   /* parameterDefaults */
    1994                 :           0 :                                                          PointerGetDatum(NULL), /* trftypes */
    1995                 :             :                                                          NIL,   /* trfoids */
    1996                 :           0 :                                                          PointerGetDatum(NULL), /* proconfig */
    1997                 :             :                                                          InvalidOid,    /* prosupport */
    1998                 :             :                                                          1.0,   /* procost */
    1999                 :             :                                                          0.0);  /* prorows */
    2000                 :             :         /* ditto */
    2001                 :           0 :         recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
    2002                 :           0 :         *mltrngConstruct2_p = myself.objectId;
    2003                 :           0 :         pfree(argtypes);
    2004                 :           0 :         pfree(allParameterTypes);
    2005                 :           0 :         pfree(parameterModes);
    2006                 :           0 : }
    2007                 :             : 
    2008                 :             : /*
    2009                 :             :  * Find suitable I/O and other support functions for a type.
    2010                 :             :  *
    2011                 :             :  * typeOid is the type's OID (which will already exist, if only as a shell
    2012                 :             :  * type).
    2013                 :             :  */
    2014                 :             : 
    2015                 :             : static Oid
    2016                 :           0 : findTypeInputFunction(List *procname, Oid typeOid)
    2017                 :             : {
    2018                 :           0 :         Oid                     argList[3];
    2019                 :           0 :         Oid                     procOid;
    2020                 :           0 :         Oid                     procOid2;
    2021                 :             : 
    2022                 :             :         /*
    2023                 :             :          * Input functions can take a single argument of type CSTRING, or three
    2024                 :             :          * arguments (string, typioparam OID, typmod).  Whine about ambiguity if
    2025                 :             :          * both forms exist.
    2026                 :             :          */
    2027                 :           0 :         argList[0] = CSTRINGOID;
    2028                 :           0 :         argList[1] = OIDOID;
    2029                 :           0 :         argList[2] = INT4OID;
    2030                 :             : 
    2031                 :           0 :         procOid = LookupFuncName(procname, 1, argList, true);
    2032                 :           0 :         procOid2 = LookupFuncName(procname, 3, argList, true);
    2033         [ #  # ]:           0 :         if (OidIsValid(procOid))
    2034                 :             :         {
    2035         [ #  # ]:           0 :                 if (OidIsValid(procOid2))
    2036   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2037                 :             :                                         (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
    2038                 :             :                                          errmsg("type input function %s has multiple matches",
    2039                 :             :                                                         NameListToString(procname))));
    2040                 :           0 :         }
    2041                 :             :         else
    2042                 :             :         {
    2043                 :           0 :                 procOid = procOid2;
    2044                 :             :                 /* If not found, reference the 1-argument signature in error msg */
    2045         [ #  # ]:           0 :                 if (!OidIsValid(procOid))
    2046   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2047                 :             :                                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2048                 :             :                                          errmsg("function %s does not exist",
    2049                 :             :                                                         func_signature_string(procname, 1, NIL, argList))));
    2050                 :             :         }
    2051                 :             : 
    2052                 :             :         /* Input functions must return the target type. */
    2053         [ #  # ]:           0 :         if (get_func_rettype(procOid) != typeOid)
    2054   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2055                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2056                 :             :                                  errmsg("type input function %s must return type %s",
    2057                 :             :                                                 NameListToString(procname), format_type_be(typeOid))));
    2058                 :             : 
    2059                 :             :         /*
    2060                 :             :          * Print warnings if any of the type's I/O functions are marked volatile.
    2061                 :             :          * There is a general assumption that I/O functions are stable or
    2062                 :             :          * immutable; this allows us for example to mark record_in/record_out
    2063                 :             :          * stable rather than volatile.  Ideally we would throw errors not just
    2064                 :             :          * warnings here; but since this check is new as of 9.5, and since the
    2065                 :             :          * volatility marking might be just an error-of-omission and not a true
    2066                 :             :          * indication of how the function behaves, we'll let it pass as a warning
    2067                 :             :          * for now.
    2068                 :             :          */
    2069         [ #  # ]:           0 :         if (func_volatile(procOid) == PROVOLATILE_VOLATILE)
    2070   [ #  #  #  # ]:           0 :                 ereport(WARNING,
    2071                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2072                 :             :                                  errmsg("type input function %s should not be volatile",
    2073                 :             :                                                 NameListToString(procname))));
    2074                 :             : 
    2075                 :           0 :         return procOid;
    2076                 :           0 : }
    2077                 :             : 
    2078                 :             : static Oid
    2079                 :           0 : findTypeOutputFunction(List *procname, Oid typeOid)
    2080                 :             : {
    2081                 :           0 :         Oid                     argList[1];
    2082                 :           0 :         Oid                     procOid;
    2083                 :             : 
    2084                 :             :         /*
    2085                 :             :          * Output functions always take a single argument of the type and return
    2086                 :             :          * cstring.
    2087                 :             :          */
    2088                 :           0 :         argList[0] = typeOid;
    2089                 :             : 
    2090                 :           0 :         procOid = LookupFuncName(procname, 1, argList, true);
    2091         [ #  # ]:           0 :         if (!OidIsValid(procOid))
    2092   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2093                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2094                 :             :                                  errmsg("function %s does not exist",
    2095                 :             :                                                 func_signature_string(procname, 1, NIL, argList))));
    2096                 :             : 
    2097         [ #  # ]:           0 :         if (get_func_rettype(procOid) != CSTRINGOID)
    2098   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2099                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2100                 :             :                                  errmsg("type output function %s must return type %s",
    2101                 :             :                                                 NameListToString(procname), "cstring")));
    2102                 :             : 
    2103                 :             :         /* Just a warning for now, per comments in findTypeInputFunction */
    2104         [ #  # ]:           0 :         if (func_volatile(procOid) == PROVOLATILE_VOLATILE)
    2105   [ #  #  #  # ]:           0 :                 ereport(WARNING,
    2106                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2107                 :             :                                  errmsg("type output function %s should not be volatile",
    2108                 :             :                                                 NameListToString(procname))));
    2109                 :             : 
    2110                 :           0 :         return procOid;
    2111                 :           0 : }
    2112                 :             : 
    2113                 :             : static Oid
    2114                 :           0 : findTypeReceiveFunction(List *procname, Oid typeOid)
    2115                 :             : {
    2116                 :           0 :         Oid                     argList[3];
    2117                 :           0 :         Oid                     procOid;
    2118                 :           0 :         Oid                     procOid2;
    2119                 :             : 
    2120                 :             :         /*
    2121                 :             :          * Receive functions can take a single argument of type INTERNAL, or three
    2122                 :             :          * arguments (internal, typioparam OID, typmod).  Whine about ambiguity if
    2123                 :             :          * both forms exist.
    2124                 :             :          */
    2125                 :           0 :         argList[0] = INTERNALOID;
    2126                 :           0 :         argList[1] = OIDOID;
    2127                 :           0 :         argList[2] = INT4OID;
    2128                 :             : 
    2129                 :           0 :         procOid = LookupFuncName(procname, 1, argList, true);
    2130                 :           0 :         procOid2 = LookupFuncName(procname, 3, argList, true);
    2131         [ #  # ]:           0 :         if (OidIsValid(procOid))
    2132                 :             :         {
    2133         [ #  # ]:           0 :                 if (OidIsValid(procOid2))
    2134   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2135                 :             :                                         (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
    2136                 :             :                                          errmsg("type receive function %s has multiple matches",
    2137                 :             :                                                         NameListToString(procname))));
    2138                 :           0 :         }
    2139                 :             :         else
    2140                 :             :         {
    2141                 :           0 :                 procOid = procOid2;
    2142                 :             :                 /* If not found, reference the 1-argument signature in error msg */
    2143         [ #  # ]:           0 :                 if (!OidIsValid(procOid))
    2144   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2145                 :             :                                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2146                 :             :                                          errmsg("function %s does not exist",
    2147                 :             :                                                         func_signature_string(procname, 1, NIL, argList))));
    2148                 :             :         }
    2149                 :             : 
    2150                 :             :         /* Receive functions must return the target type. */
    2151         [ #  # ]:           0 :         if (get_func_rettype(procOid) != typeOid)
    2152   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2153                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2154                 :             :                                  errmsg("type receive function %s must return type %s",
    2155                 :             :                                                 NameListToString(procname), format_type_be(typeOid))));
    2156                 :             : 
    2157                 :             :         /* Just a warning for now, per comments in findTypeInputFunction */
    2158         [ #  # ]:           0 :         if (func_volatile(procOid) == PROVOLATILE_VOLATILE)
    2159   [ #  #  #  # ]:           0 :                 ereport(WARNING,
    2160                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2161                 :             :                                  errmsg("type receive function %s should not be volatile",
    2162                 :             :                                                 NameListToString(procname))));
    2163                 :             : 
    2164                 :           0 :         return procOid;
    2165                 :           0 : }
    2166                 :             : 
    2167                 :             : static Oid
    2168                 :           0 : findTypeSendFunction(List *procname, Oid typeOid)
    2169                 :             : {
    2170                 :           0 :         Oid                     argList[1];
    2171                 :           0 :         Oid                     procOid;
    2172                 :             : 
    2173                 :             :         /*
    2174                 :             :          * Send functions always take a single argument of the type and return
    2175                 :             :          * bytea.
    2176                 :             :          */
    2177                 :           0 :         argList[0] = typeOid;
    2178                 :             : 
    2179                 :           0 :         procOid = LookupFuncName(procname, 1, argList, true);
    2180         [ #  # ]:           0 :         if (!OidIsValid(procOid))
    2181   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2182                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2183                 :             :                                  errmsg("function %s does not exist",
    2184                 :             :                                                 func_signature_string(procname, 1, NIL, argList))));
    2185                 :             : 
    2186         [ #  # ]:           0 :         if (get_func_rettype(procOid) != BYTEAOID)
    2187   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2188                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2189                 :             :                                  errmsg("type send function %s must return type %s",
    2190                 :             :                                                 NameListToString(procname), "bytea")));
    2191                 :             : 
    2192                 :             :         /* Just a warning for now, per comments in findTypeInputFunction */
    2193         [ #  # ]:           0 :         if (func_volatile(procOid) == PROVOLATILE_VOLATILE)
    2194   [ #  #  #  # ]:           0 :                 ereport(WARNING,
    2195                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2196                 :             :                                  errmsg("type send function %s should not be volatile",
    2197                 :             :                                                 NameListToString(procname))));
    2198                 :             : 
    2199                 :           0 :         return procOid;
    2200                 :           0 : }
    2201                 :             : 
    2202                 :             : static Oid
    2203                 :           0 : findTypeTypmodinFunction(List *procname)
    2204                 :             : {
    2205                 :           0 :         Oid                     argList[1];
    2206                 :           0 :         Oid                     procOid;
    2207                 :             : 
    2208                 :             :         /*
    2209                 :             :          * typmodin functions always take one cstring[] argument and return int4.
    2210                 :             :          */
    2211                 :           0 :         argList[0] = CSTRINGARRAYOID;
    2212                 :             : 
    2213                 :           0 :         procOid = LookupFuncName(procname, 1, argList, true);
    2214         [ #  # ]:           0 :         if (!OidIsValid(procOid))
    2215   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2216                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2217                 :             :                                  errmsg("function %s does not exist",
    2218                 :             :                                                 func_signature_string(procname, 1, NIL, argList))));
    2219                 :             : 
    2220         [ #  # ]:           0 :         if (get_func_rettype(procOid) != INT4OID)
    2221   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2222                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2223                 :             :                                  errmsg("typmod_in function %s must return type %s",
    2224                 :             :                                                 NameListToString(procname), "integer")));
    2225                 :             : 
    2226                 :             :         /* Just a warning for now, per comments in findTypeInputFunction */
    2227         [ #  # ]:           0 :         if (func_volatile(procOid) == PROVOLATILE_VOLATILE)
    2228   [ #  #  #  # ]:           0 :                 ereport(WARNING,
    2229                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2230                 :             :                                  errmsg("type modifier input function %s should not be volatile",
    2231                 :             :                                                 NameListToString(procname))));
    2232                 :             : 
    2233                 :           0 :         return procOid;
    2234                 :           0 : }
    2235                 :             : 
    2236                 :             : static Oid
    2237                 :           0 : findTypeTypmodoutFunction(List *procname)
    2238                 :             : {
    2239                 :           0 :         Oid                     argList[1];
    2240                 :           0 :         Oid                     procOid;
    2241                 :             : 
    2242                 :             :         /*
    2243                 :             :          * typmodout functions always take one int4 argument and return cstring.
    2244                 :             :          */
    2245                 :           0 :         argList[0] = INT4OID;
    2246                 :             : 
    2247                 :           0 :         procOid = LookupFuncName(procname, 1, argList, true);
    2248         [ #  # ]:           0 :         if (!OidIsValid(procOid))
    2249   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2250                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2251                 :             :                                  errmsg("function %s does not exist",
    2252                 :             :                                                 func_signature_string(procname, 1, NIL, argList))));
    2253                 :             : 
    2254         [ #  # ]:           0 :         if (get_func_rettype(procOid) != CSTRINGOID)
    2255   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2256                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2257                 :             :                                  errmsg("typmod_out function %s must return type %s",
    2258                 :             :                                                 NameListToString(procname), "cstring")));
    2259                 :             : 
    2260                 :             :         /* Just a warning for now, per comments in findTypeInputFunction */
    2261         [ #  # ]:           0 :         if (func_volatile(procOid) == PROVOLATILE_VOLATILE)
    2262   [ #  #  #  # ]:           0 :                 ereport(WARNING,
    2263                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2264                 :             :                                  errmsg("type modifier output function %s should not be volatile",
    2265                 :             :                                                 NameListToString(procname))));
    2266                 :             : 
    2267                 :           0 :         return procOid;
    2268                 :           0 : }
    2269                 :             : 
    2270                 :             : static Oid
    2271                 :           0 : findTypeAnalyzeFunction(List *procname, Oid typeOid)
    2272                 :             : {
    2273                 :           0 :         Oid                     argList[1];
    2274                 :           0 :         Oid                     procOid;
    2275                 :             : 
    2276                 :             :         /*
    2277                 :             :          * Analyze functions always take one INTERNAL argument and return bool.
    2278                 :             :          */
    2279                 :           0 :         argList[0] = INTERNALOID;
    2280                 :             : 
    2281                 :           0 :         procOid = LookupFuncName(procname, 1, argList, true);
    2282         [ #  # ]:           0 :         if (!OidIsValid(procOid))
    2283   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2284                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2285                 :             :                                  errmsg("function %s does not exist",
    2286                 :             :                                                 func_signature_string(procname, 1, NIL, argList))));
    2287                 :             : 
    2288         [ #  # ]:           0 :         if (get_func_rettype(procOid) != BOOLOID)
    2289   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2290                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2291                 :             :                                  errmsg("type analyze function %s must return type %s",
    2292                 :             :                                                 NameListToString(procname), "boolean")));
    2293                 :             : 
    2294                 :           0 :         return procOid;
    2295                 :           0 : }
    2296                 :             : 
    2297                 :             : static Oid
    2298                 :           0 : findTypeSubscriptingFunction(List *procname, Oid typeOid)
    2299                 :             : {
    2300                 :           0 :         Oid                     argList[1];
    2301                 :           0 :         Oid                     procOid;
    2302                 :             : 
    2303                 :             :         /*
    2304                 :             :          * Subscripting support functions always take one INTERNAL argument and
    2305                 :             :          * return INTERNAL.  (The argument is not used, but we must have it to
    2306                 :             :          * maintain type safety.)
    2307                 :             :          */
    2308                 :           0 :         argList[0] = INTERNALOID;
    2309                 :             : 
    2310                 :           0 :         procOid = LookupFuncName(procname, 1, argList, true);
    2311         [ #  # ]:           0 :         if (!OidIsValid(procOid))
    2312   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2313                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2314                 :             :                                  errmsg("function %s does not exist",
    2315                 :             :                                                 func_signature_string(procname, 1, NIL, argList))));
    2316                 :             : 
    2317         [ #  # ]:           0 :         if (get_func_rettype(procOid) != INTERNALOID)
    2318   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2319                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2320                 :             :                                  errmsg("type subscripting function %s must return type %s",
    2321                 :             :                                                 NameListToString(procname), "internal")));
    2322                 :             : 
    2323                 :             :         /*
    2324                 :             :          * We disallow array_subscript_handler() from being selected explicitly,
    2325                 :             :          * since that must only be applied to autogenerated array types.
    2326                 :             :          */
    2327         [ #  # ]:           0 :         if (procOid == F_ARRAY_SUBSCRIPT_HANDLER)
    2328   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2329                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2330                 :             :                                  errmsg("user-defined types cannot use subscripting function %s",
    2331                 :             :                                                 NameListToString(procname))));
    2332                 :             : 
    2333                 :           0 :         return procOid;
    2334                 :           0 : }
    2335                 :             : 
    2336                 :             : /*
    2337                 :             :  * Find suitable support functions and opclasses for a range type.
    2338                 :             :  */
    2339                 :             : 
    2340                 :             : /*
    2341                 :             :  * Find named btree opclass for subtype, or default btree opclass if
    2342                 :             :  * opcname is NIL.
    2343                 :             :  */
    2344                 :             : static Oid
    2345                 :           0 : findRangeSubOpclass(List *opcname, Oid subtype)
    2346                 :             : {
    2347                 :           0 :         Oid                     opcid;
    2348                 :           0 :         Oid                     opInputType;
    2349                 :             : 
    2350         [ #  # ]:           0 :         if (opcname != NIL)
    2351                 :             :         {
    2352                 :           0 :                 opcid = get_opclass_oid(BTREE_AM_OID, opcname, false);
    2353                 :             : 
    2354                 :             :                 /*
    2355                 :             :                  * Verify that the operator class accepts this datatype. Note we will
    2356                 :             :                  * accept binary compatibility.
    2357                 :             :                  */
    2358                 :           0 :                 opInputType = get_opclass_input_type(opcid);
    2359         [ #  # ]:           0 :                 if (!IsBinaryCoercible(subtype, opInputType))
    2360   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2361                 :             :                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    2362                 :             :                                          errmsg("operator class \"%s\" does not accept data type %s",
    2363                 :             :                                                         NameListToString(opcname),
    2364                 :             :                                                         format_type_be(subtype))));
    2365                 :           0 :         }
    2366                 :             :         else
    2367                 :             :         {
    2368                 :           0 :                 opcid = GetDefaultOpClass(subtype, BTREE_AM_OID);
    2369         [ #  # ]:           0 :                 if (!OidIsValid(opcid))
    2370                 :             :                 {
    2371                 :             :                         /* We spell the error message identically to ResolveOpClass */
    2372   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2373                 :             :                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
    2374                 :             :                                          errmsg("data type %s has no default operator class for access method \"%s\"",
    2375                 :             :                                                         format_type_be(subtype), "btree"),
    2376                 :             :                                          errhint("You must specify an operator class for the range type or define a default operator class for the subtype.")));
    2377                 :           0 :                 }
    2378                 :             :         }
    2379                 :             : 
    2380                 :           0 :         return opcid;
    2381                 :           0 : }
    2382                 :             : 
    2383                 :             : static Oid
    2384                 :           0 : findRangeCanonicalFunction(List *procname, Oid typeOid)
    2385                 :             : {
    2386                 :           0 :         Oid                     argList[1];
    2387                 :           0 :         Oid                     procOid;
    2388                 :           0 :         AclResult       aclresult;
    2389                 :             : 
    2390                 :             :         /*
    2391                 :             :          * Range canonical functions must take and return the range type, and must
    2392                 :             :          * be immutable.
    2393                 :             :          */
    2394                 :           0 :         argList[0] = typeOid;
    2395                 :             : 
    2396                 :           0 :         procOid = LookupFuncName(procname, 1, argList, true);
    2397                 :             : 
    2398         [ #  # ]:           0 :         if (!OidIsValid(procOid))
    2399   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2400                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2401                 :             :                                  errmsg("function %s does not exist",
    2402                 :             :                                                 func_signature_string(procname, 1, NIL, argList))));
    2403                 :             : 
    2404         [ #  # ]:           0 :         if (get_func_rettype(procOid) != typeOid)
    2405   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2406                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2407                 :             :                                  errmsg("range canonical function %s must return range type",
    2408                 :             :                                                 func_signature_string(procname, 1, NIL, argList))));
    2409                 :             : 
    2410         [ #  # ]:           0 :         if (func_volatile(procOid) != PROVOLATILE_IMMUTABLE)
    2411   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2412                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2413                 :             :                                  errmsg("range canonical function %s must be immutable",
    2414                 :             :                                                 func_signature_string(procname, 1, NIL, argList))));
    2415                 :             : 
    2416                 :             :         /* Also, range type's creator must have permission to call function */
    2417                 :           0 :         aclresult = object_aclcheck(ProcedureRelationId, procOid, GetUserId(), ACL_EXECUTE);
    2418         [ #  # ]:           0 :         if (aclresult != ACLCHECK_OK)
    2419                 :           0 :                 aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(procOid));
    2420                 :             : 
    2421                 :           0 :         return procOid;
    2422                 :           0 : }
    2423                 :             : 
    2424                 :             : static Oid
    2425                 :           0 : findRangeSubtypeDiffFunction(List *procname, Oid subtype)
    2426                 :             : {
    2427                 :           0 :         Oid                     argList[2];
    2428                 :           0 :         Oid                     procOid;
    2429                 :           0 :         AclResult       aclresult;
    2430                 :             : 
    2431                 :             :         /*
    2432                 :             :          * Range subtype diff functions must take two arguments of the subtype,
    2433                 :             :          * must return float8, and must be immutable.
    2434                 :             :          */
    2435                 :           0 :         argList[0] = subtype;
    2436                 :           0 :         argList[1] = subtype;
    2437                 :             : 
    2438                 :           0 :         procOid = LookupFuncName(procname, 2, argList, true);
    2439                 :             : 
    2440         [ #  # ]:           0 :         if (!OidIsValid(procOid))
    2441   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2442                 :             :                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
    2443                 :             :                                  errmsg("function %s does not exist",
    2444                 :             :                                                 func_signature_string(procname, 2, NIL, argList))));
    2445                 :             : 
    2446         [ #  # ]:           0 :         if (get_func_rettype(procOid) != FLOAT8OID)
    2447   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2448                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2449                 :             :                                  errmsg("range subtype diff function %s must return type %s",
    2450                 :             :                                                 func_signature_string(procname, 2, NIL, argList),
    2451                 :             :                                                 "double precision")));
    2452                 :             : 
    2453         [ #  # ]:           0 :         if (func_volatile(procOid) != PROVOLATILE_IMMUTABLE)
    2454   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2455                 :             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    2456                 :             :                                  errmsg("range subtype diff function %s must be immutable",
    2457                 :             :                                                 func_signature_string(procname, 2, NIL, argList))));
    2458                 :             : 
    2459                 :             :         /* Also, range type's creator must have permission to call function */
    2460                 :           0 :         aclresult = object_aclcheck(ProcedureRelationId, procOid, GetUserId(), ACL_EXECUTE);
    2461         [ #  # ]:           0 :         if (aclresult != ACLCHECK_OK)
    2462                 :           0 :                 aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(procOid));
    2463                 :             : 
    2464                 :           0 :         return procOid;
    2465                 :           0 : }
    2466                 :             : 
    2467                 :             : /*
    2468                 :             :  *      AssignTypeArrayOid
    2469                 :             :  *
    2470                 :             :  *      Pre-assign the type's array OID for use in pg_type.typarray
    2471                 :             :  */
    2472                 :             : Oid
    2473                 :           0 : AssignTypeArrayOid(void)
    2474                 :             : {
    2475                 :           0 :         Oid                     type_array_oid;
    2476                 :             : 
    2477                 :             :         /* Use binary-upgrade override for pg_type.typarray? */
    2478         [ #  # ]:           0 :         if (IsBinaryUpgrade)
    2479                 :             :         {
    2480         [ #  # ]:           0 :                 if (!OidIsValid(binary_upgrade_next_array_pg_type_oid))
    2481   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2482                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2483                 :             :                                          errmsg("pg_type array OID value not set when in binary upgrade mode")));
    2484                 :             : 
    2485                 :           0 :                 type_array_oid = binary_upgrade_next_array_pg_type_oid;
    2486                 :           0 :                 binary_upgrade_next_array_pg_type_oid = InvalidOid;
    2487                 :           0 :         }
    2488                 :             :         else
    2489                 :             :         {
    2490                 :           0 :                 Relation        pg_type = table_open(TypeRelationId, AccessShareLock);
    2491                 :             : 
    2492                 :           0 :                 type_array_oid = GetNewOidWithIndex(pg_type, TypeOidIndexId,
    2493                 :             :                                                                                         Anum_pg_type_oid);
    2494                 :           0 :                 table_close(pg_type, AccessShareLock);
    2495                 :           0 :         }
    2496                 :             : 
    2497                 :           0 :         return type_array_oid;
    2498                 :           0 : }
    2499                 :             : 
    2500                 :             : /*
    2501                 :             :  *      AssignTypeMultirangeOid
    2502                 :             :  *
    2503                 :             :  *      Pre-assign the range type's multirange OID for use in pg_type.oid
    2504                 :             :  */
    2505                 :             : Oid
    2506                 :           0 : AssignTypeMultirangeOid(void)
    2507                 :             : {
    2508                 :           0 :         Oid                     type_multirange_oid;
    2509                 :             : 
    2510                 :             :         /* Use binary-upgrade override for pg_type.oid? */
    2511         [ #  # ]:           0 :         if (IsBinaryUpgrade)
    2512                 :             :         {
    2513         [ #  # ]:           0 :                 if (!OidIsValid(binary_upgrade_next_mrng_pg_type_oid))
    2514   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2515                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2516                 :             :                                          errmsg("pg_type multirange OID value not set when in binary upgrade mode")));
    2517                 :             : 
    2518                 :           0 :                 type_multirange_oid = binary_upgrade_next_mrng_pg_type_oid;
    2519                 :           0 :                 binary_upgrade_next_mrng_pg_type_oid = InvalidOid;
    2520                 :           0 :         }
    2521                 :             :         else
    2522                 :             :         {
    2523                 :           0 :                 Relation        pg_type = table_open(TypeRelationId, AccessShareLock);
    2524                 :             : 
    2525                 :           0 :                 type_multirange_oid = GetNewOidWithIndex(pg_type, TypeOidIndexId,
    2526                 :             :                                                                                                  Anum_pg_type_oid);
    2527                 :           0 :                 table_close(pg_type, AccessShareLock);
    2528                 :           0 :         }
    2529                 :             : 
    2530                 :           0 :         return type_multirange_oid;
    2531                 :           0 : }
    2532                 :             : 
    2533                 :             : /*
    2534                 :             :  *      AssignTypeMultirangeArrayOid
    2535                 :             :  *
    2536                 :             :  *      Pre-assign the range type's multirange array OID for use in pg_type.typarray
    2537                 :             :  */
    2538                 :             : Oid
    2539                 :           0 : AssignTypeMultirangeArrayOid(void)
    2540                 :             : {
    2541                 :           0 :         Oid                     type_multirange_array_oid;
    2542                 :             : 
    2543                 :             :         /* Use binary-upgrade override for pg_type.oid? */
    2544         [ #  # ]:           0 :         if (IsBinaryUpgrade)
    2545                 :             :         {
    2546         [ #  # ]:           0 :                 if (!OidIsValid(binary_upgrade_next_mrng_array_pg_type_oid))
    2547   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2548                 :             :                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2549                 :             :                                          errmsg("pg_type multirange array OID value not set when in binary upgrade mode")));
    2550                 :             : 
    2551                 :           0 :                 type_multirange_array_oid = binary_upgrade_next_mrng_array_pg_type_oid;
    2552                 :           0 :                 binary_upgrade_next_mrng_array_pg_type_oid = InvalidOid;
    2553                 :           0 :         }
    2554                 :             :         else
    2555                 :             :         {
    2556                 :           0 :                 Relation        pg_type = table_open(TypeRelationId, AccessShareLock);
    2557                 :             : 
    2558                 :           0 :                 type_multirange_array_oid = GetNewOidWithIndex(pg_type, TypeOidIndexId,
    2559                 :             :                                                                                                            Anum_pg_type_oid);
    2560                 :           0 :                 table_close(pg_type, AccessShareLock);
    2561                 :           0 :         }
    2562                 :             : 
    2563                 :           0 :         return type_multirange_array_oid;
    2564                 :           0 : }
    2565                 :             : 
    2566                 :             : 
    2567                 :             : /*-------------------------------------------------------------------
    2568                 :             :  * DefineCompositeType
    2569                 :             :  *
    2570                 :             :  * Create a Composite Type relation.
    2571                 :             :  * `DefineRelation' does all the work, we just provide the correct
    2572                 :             :  * arguments!
    2573                 :             :  *
    2574                 :             :  * If the relation already exists, then 'DefineRelation' will abort
    2575                 :             :  * the xact...
    2576                 :             :  *
    2577                 :             :  * Return type is the new type's object address.
    2578                 :             :  *-------------------------------------------------------------------
    2579                 :             :  */
    2580                 :             : ObjectAddress
    2581                 :           0 : DefineCompositeType(RangeVar *typevar, List *coldeflist)
    2582                 :             : {
    2583                 :           0 :         CreateStmt *createStmt = makeNode(CreateStmt);
    2584                 :           0 :         Oid                     old_type_oid;
    2585                 :           0 :         Oid                     typeNamespace;
    2586                 :             :         ObjectAddress address;
    2587                 :             : 
    2588                 :             :         /*
    2589                 :             :          * now set the parameters for keys/inheritance etc. All of these are
    2590                 :             :          * uninteresting for composite types...
    2591                 :             :          */
    2592                 :           0 :         createStmt->relation = typevar;
    2593                 :           0 :         createStmt->tableElts = coldeflist;
    2594                 :           0 :         createStmt->inhRelations = NIL;
    2595                 :           0 :         createStmt->constraints = NIL;
    2596                 :           0 :         createStmt->options = NIL;
    2597                 :           0 :         createStmt->oncommit = ONCOMMIT_NOOP;
    2598                 :           0 :         createStmt->tablespacename = NULL;
    2599                 :           0 :         createStmt->if_not_exists = false;
    2600                 :             : 
    2601                 :             :         /*
    2602                 :             :          * Check for collision with an existing type name. If there is one and
    2603                 :             :          * it's an autogenerated array, we can rename it out of the way.  This
    2604                 :             :          * check is here mainly to get a better error message about a "type"
    2605                 :             :          * instead of below about a "relation".
    2606                 :             :          */
    2607                 :           0 :         typeNamespace = RangeVarGetAndCheckCreationNamespace(createStmt->relation,
    2608                 :             :                                                                                                                  NoLock, NULL);
    2609                 :           0 :         RangeVarAdjustRelationPersistence(createStmt->relation, typeNamespace);
    2610                 :           0 :         old_type_oid =
    2611                 :           0 :                 GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
    2612                 :             :                                                 CStringGetDatum(createStmt->relation->relname),
    2613                 :             :                                                 ObjectIdGetDatum(typeNamespace));
    2614         [ #  # ]:           0 :         if (OidIsValid(old_type_oid))
    2615                 :             :         {
    2616         [ #  # ]:           0 :                 if (!moveArrayTypeName(old_type_oid, createStmt->relation->relname, typeNamespace))
    2617   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2618                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
    2619                 :             :                                          errmsg("type \"%s\" already exists", createStmt->relation->relname)));
    2620                 :           0 :         }
    2621                 :             : 
    2622                 :             :         /*
    2623                 :             :          * Finally create the relation.  This also creates the type.
    2624                 :             :          */
    2625                 :           0 :         DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid, &address,
    2626                 :             :                                    NULL);
    2627                 :             : 
    2628                 :             :         return address;
    2629                 :           0 : }
    2630                 :             : 
    2631                 :             : /*
    2632                 :             :  * AlterDomainDefault
    2633                 :             :  *
    2634                 :             :  * Routine implementing ALTER DOMAIN SET/DROP DEFAULT statements.
    2635                 :             :  *
    2636                 :             :  * Returns ObjectAddress of the modified domain.
    2637                 :             :  */
    2638                 :             : ObjectAddress
    2639                 :           0 : AlterDomainDefault(List *names, Node *defaultRaw)
    2640                 :             : {
    2641                 :           0 :         TypeName   *typename;
    2642                 :           0 :         Oid                     domainoid;
    2643                 :           0 :         HeapTuple       tup;
    2644                 :           0 :         ParseState *pstate;
    2645                 :           0 :         Relation        rel;
    2646                 :           0 :         char       *defaultValue;
    2647                 :           0 :         Node       *defaultExpr = NULL; /* NULL if no default specified */
    2648                 :           0 :         Datum           new_record[Natts_pg_type] = {0};
    2649                 :           0 :         bool            new_record_nulls[Natts_pg_type] = {0};
    2650                 :           0 :         bool            new_record_repl[Natts_pg_type] = {0};
    2651                 :           0 :         HeapTuple       newtuple;
    2652                 :           0 :         Form_pg_type typTup;
    2653                 :             :         ObjectAddress address;
    2654                 :             : 
    2655                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    2656                 :           0 :         typename = makeTypeNameFromNameList(names);
    2657                 :           0 :         domainoid = typenameTypeId(NULL, typename);
    2658                 :             : 
    2659                 :             :         /* Look up the domain in the type table */
    2660                 :           0 :         rel = table_open(TypeRelationId, RowExclusiveLock);
    2661                 :             : 
    2662                 :           0 :         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
    2663         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    2664   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", domainoid);
    2665                 :           0 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    2666                 :             : 
    2667                 :             :         /* Check it's a domain and check user has permission for ALTER DOMAIN */
    2668                 :           0 :         checkDomainOwner(tup);
    2669                 :             : 
    2670                 :             :         /* Setup new tuple */
    2671                 :             : 
    2672                 :             :         /* Store the new default into the tuple */
    2673         [ #  # ]:           0 :         if (defaultRaw)
    2674                 :             :         {
    2675                 :             :                 /* Create a dummy ParseState for transformExpr */
    2676                 :           0 :                 pstate = make_parsestate(NULL);
    2677                 :             : 
    2678                 :             :                 /*
    2679                 :             :                  * Cook the colDef->raw_expr into an expression. Note: Name is
    2680                 :             :                  * strictly for error message
    2681                 :             :                  */
    2682                 :           0 :                 defaultExpr = cookDefault(pstate, defaultRaw,
    2683                 :           0 :                                                                   typTup->typbasetype,
    2684                 :           0 :                                                                   typTup->typtypmod,
    2685                 :           0 :                                                                   NameStr(typTup->typname),
    2686                 :             :                                                                   0);
    2687                 :             : 
    2688                 :             :                 /*
    2689                 :             :                  * If the expression is just a NULL constant, we treat the command
    2690                 :             :                  * like ALTER ... DROP DEFAULT.  (But see note for same test in
    2691                 :             :                  * DefineDomain.)
    2692                 :             :                  */
    2693   [ #  #  #  # ]:           0 :                 if (defaultExpr == NULL ||
    2694         [ #  # ]:           0 :                         (IsA(defaultExpr, Const) && ((Const *) defaultExpr)->constisnull))
    2695                 :             :                 {
    2696                 :             :                         /* Default is NULL, drop it */
    2697                 :           0 :                         defaultExpr = NULL;
    2698                 :           0 :                         new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true;
    2699                 :           0 :                         new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
    2700                 :           0 :                         new_record_nulls[Anum_pg_type_typdefault - 1] = true;
    2701                 :           0 :                         new_record_repl[Anum_pg_type_typdefault - 1] = true;
    2702                 :           0 :                 }
    2703                 :             :                 else
    2704                 :             :                 {
    2705                 :             :                         /*
    2706                 :             :                          * Expression must be stored as a nodeToString result, but we also
    2707                 :             :                          * require a valid textual representation (mainly to make life
    2708                 :             :                          * easier for pg_dump).
    2709                 :             :                          */
    2710                 :           0 :                         defaultValue = deparse_expression(defaultExpr,
    2711                 :             :                                                                                           NIL, false, false);
    2712                 :             : 
    2713                 :             :                         /*
    2714                 :             :                          * Form an updated tuple with the new default and write it back.
    2715                 :             :                          */
    2716                 :           0 :                         new_record[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(nodeToString(defaultExpr));
    2717                 :             : 
    2718                 :           0 :                         new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
    2719                 :           0 :                         new_record[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultValue);
    2720                 :           0 :                         new_record_repl[Anum_pg_type_typdefault - 1] = true;
    2721                 :             :                 }
    2722                 :           0 :         }
    2723                 :             :         else
    2724                 :             :         {
    2725                 :             :                 /* ALTER ... DROP DEFAULT */
    2726                 :           0 :                 new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true;
    2727                 :           0 :                 new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
    2728                 :           0 :                 new_record_nulls[Anum_pg_type_typdefault - 1] = true;
    2729                 :           0 :                 new_record_repl[Anum_pg_type_typdefault - 1] = true;
    2730                 :             :         }
    2731                 :             : 
    2732                 :           0 :         newtuple = heap_modify_tuple(tup, RelationGetDescr(rel),
    2733                 :           0 :                                                                  new_record, new_record_nulls,
    2734                 :           0 :                                                                  new_record_repl);
    2735                 :             : 
    2736                 :           0 :         CatalogTupleUpdate(rel, &tup->t_self, newtuple);
    2737                 :             : 
    2738                 :             :         /* Rebuild dependencies */
    2739                 :           0 :         GenerateTypeDependencies(newtuple,
    2740                 :           0 :                                                          rel,
    2741                 :           0 :                                                          defaultExpr,
    2742                 :             :                                                          NULL,  /* don't have typacl handy */
    2743                 :             :                                                          0, /* relation kind is n/a */
    2744                 :             :                                                          false, /* a domain isn't an implicit array */
    2745                 :             :                                                          false, /* nor is it any kind of dependent type */
    2746                 :             :                                                          false, /* don't touch extension membership */
    2747                 :             :                                                          true); /* We do need to rebuild dependencies */
    2748                 :             : 
    2749         [ #  # ]:           0 :         InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
    2750                 :             : 
    2751                 :           0 :         ObjectAddressSet(address, TypeRelationId, domainoid);
    2752                 :             : 
    2753                 :             :         /* Clean up */
    2754                 :           0 :         table_close(rel, RowExclusiveLock);
    2755                 :           0 :         heap_freetuple(newtuple);
    2756                 :             : 
    2757                 :             :         return address;
    2758                 :           0 : }
    2759                 :             : 
    2760                 :             : /*
    2761                 :             :  * AlterDomainNotNull
    2762                 :             :  *
    2763                 :             :  * Routine implementing ALTER DOMAIN SET/DROP NOT NULL statements.
    2764                 :             :  *
    2765                 :             :  * Returns ObjectAddress of the modified domain.
    2766                 :             :  */
    2767                 :             : ObjectAddress
    2768                 :           0 : AlterDomainNotNull(List *names, bool notNull)
    2769                 :             : {
    2770                 :           0 :         TypeName   *typename;
    2771                 :           0 :         Oid                     domainoid;
    2772                 :           0 :         Relation        typrel;
    2773                 :           0 :         HeapTuple       tup;
    2774                 :           0 :         Form_pg_type typTup;
    2775                 :           0 :         ObjectAddress address = InvalidObjectAddress;
    2776                 :             : 
    2777                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    2778                 :           0 :         typename = makeTypeNameFromNameList(names);
    2779                 :           0 :         domainoid = typenameTypeId(NULL, typename);
    2780                 :             : 
    2781                 :             :         /* Look up the domain in the type table */
    2782                 :           0 :         typrel = table_open(TypeRelationId, RowExclusiveLock);
    2783                 :             : 
    2784                 :           0 :         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
    2785         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    2786   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", domainoid);
    2787                 :           0 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    2788                 :             : 
    2789                 :             :         /* Check it's a domain and check user has permission for ALTER DOMAIN */
    2790                 :           0 :         checkDomainOwner(tup);
    2791                 :             : 
    2792                 :             :         /* Is the domain already set to the desired constraint? */
    2793         [ #  # ]:           0 :         if (typTup->typnotnull == notNull)
    2794                 :             :         {
    2795                 :           0 :                 table_close(typrel, RowExclusiveLock);
    2796                 :           0 :                 return address;
    2797                 :             :         }
    2798                 :             : 
    2799         [ #  # ]:           0 :         if (notNull)
    2800                 :             :         {
    2801                 :           0 :                 Constraint *constr;
    2802                 :             : 
    2803                 :           0 :                 constr = makeNode(Constraint);
    2804                 :           0 :                 constr->contype = CONSTR_NOTNULL;
    2805                 :           0 :                 constr->initially_valid = true;
    2806                 :           0 :                 constr->location = -1;
    2807                 :             : 
    2808                 :           0 :                 domainAddNotNullConstraint(domainoid, typTup->typnamespace,
    2809                 :           0 :                                                                    typTup->typbasetype, typTup->typtypmod,
    2810                 :           0 :                                                                    constr, NameStr(typTup->typname), NULL);
    2811                 :             : 
    2812                 :           0 :                 validateDomainNotNullConstraint(domainoid);
    2813                 :           0 :         }
    2814                 :             :         else
    2815                 :             :         {
    2816                 :           0 :                 HeapTuple       conTup;
    2817                 :           0 :                 ObjectAddress conobj;
    2818                 :             : 
    2819                 :           0 :                 conTup = findDomainNotNullConstraint(domainoid);
    2820         [ #  # ]:           0 :                 if (conTup == NULL)
    2821   [ #  #  #  # ]:           0 :                         elog(ERROR, "could not find not-null constraint on domain \"%s\"", NameStr(typTup->typname));
    2822                 :             : 
    2823                 :           0 :                 ObjectAddressSet(conobj, ConstraintRelationId, ((Form_pg_constraint) GETSTRUCT(conTup))->oid);
    2824                 :           0 :                 performDeletion(&conobj, DROP_RESTRICT, 0);
    2825                 :           0 :         }
    2826                 :             : 
    2827                 :             :         /*
    2828                 :             :          * Okay to update pg_type row.  We can scribble on typTup because it's a
    2829                 :             :          * copy.
    2830                 :             :          */
    2831                 :           0 :         typTup->typnotnull = notNull;
    2832                 :             : 
    2833                 :           0 :         CatalogTupleUpdate(typrel, &tup->t_self, tup);
    2834                 :             : 
    2835         [ #  # ]:           0 :         InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
    2836                 :             : 
    2837                 :           0 :         ObjectAddressSet(address, TypeRelationId, domainoid);
    2838                 :             : 
    2839                 :             :         /* Clean up */
    2840                 :           0 :         heap_freetuple(tup);
    2841                 :           0 :         table_close(typrel, RowExclusiveLock);
    2842                 :             : 
    2843                 :           0 :         return address;
    2844                 :           0 : }
    2845                 :             : 
    2846                 :             : /*
    2847                 :             :  * AlterDomainDropConstraint
    2848                 :             :  *
    2849                 :             :  * Implements the ALTER DOMAIN DROP CONSTRAINT statement
    2850                 :             :  *
    2851                 :             :  * Returns ObjectAddress of the modified domain.
    2852                 :             :  */
    2853                 :             : ObjectAddress
    2854                 :           0 : AlterDomainDropConstraint(List *names, const char *constrName,
    2855                 :             :                                                   DropBehavior behavior, bool missing_ok)
    2856                 :             : {
    2857                 :           0 :         TypeName   *typename;
    2858                 :           0 :         Oid                     domainoid;
    2859                 :           0 :         HeapTuple       tup;
    2860                 :           0 :         Relation        rel;
    2861                 :           0 :         Relation        conrel;
    2862                 :           0 :         SysScanDesc conscan;
    2863                 :           0 :         ScanKeyData skey[3];
    2864                 :           0 :         HeapTuple       contup;
    2865                 :           0 :         bool            found = false;
    2866                 :             :         ObjectAddress address;
    2867                 :             : 
    2868                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    2869                 :           0 :         typename = makeTypeNameFromNameList(names);
    2870                 :           0 :         domainoid = typenameTypeId(NULL, typename);
    2871                 :             : 
    2872                 :             :         /* Look up the domain in the type table */
    2873                 :           0 :         rel = table_open(TypeRelationId, RowExclusiveLock);
    2874                 :             : 
    2875                 :           0 :         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
    2876         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    2877   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", domainoid);
    2878                 :             : 
    2879                 :             :         /* Check it's a domain and check user has permission for ALTER DOMAIN */
    2880                 :           0 :         checkDomainOwner(tup);
    2881                 :             : 
    2882                 :             :         /* Grab an appropriate lock on the pg_constraint relation */
    2883                 :           0 :         conrel = table_open(ConstraintRelationId, RowExclusiveLock);
    2884                 :             : 
    2885                 :             :         /* Find and remove the target constraint */
    2886                 :           0 :         ScanKeyInit(&skey[0],
    2887                 :             :                                 Anum_pg_constraint_conrelid,
    2888                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
    2889                 :           0 :                                 ObjectIdGetDatum(InvalidOid));
    2890                 :           0 :         ScanKeyInit(&skey[1],
    2891                 :             :                                 Anum_pg_constraint_contypid,
    2892                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
    2893                 :           0 :                                 ObjectIdGetDatum(domainoid));
    2894                 :           0 :         ScanKeyInit(&skey[2],
    2895                 :             :                                 Anum_pg_constraint_conname,
    2896                 :             :                                 BTEqualStrategyNumber, F_NAMEEQ,
    2897                 :           0 :                                 CStringGetDatum(constrName));
    2898                 :             : 
    2899                 :           0 :         conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
    2900                 :           0 :                                                                  NULL, 3, skey);
    2901                 :             : 
    2902                 :             :         /* There can be at most one matching row */
    2903         [ #  # ]:           0 :         if ((contup = systable_getnext(conscan)) != NULL)
    2904                 :             :         {
    2905                 :           0 :                 Form_pg_constraint construct = (Form_pg_constraint) GETSTRUCT(contup);
    2906                 :           0 :                 ObjectAddress conobj;
    2907                 :             : 
    2908         [ #  # ]:           0 :                 if (construct->contype == CONSTRAINT_NOTNULL)
    2909                 :             :                 {
    2910                 :           0 :                         ((Form_pg_type) GETSTRUCT(tup))->typnotnull = false;
    2911                 :           0 :                         CatalogTupleUpdate(rel, &tup->t_self, tup);
    2912                 :           0 :                 }
    2913                 :             : 
    2914                 :           0 :                 conobj.classId = ConstraintRelationId;
    2915                 :           0 :                 conobj.objectId = construct->oid;
    2916                 :           0 :                 conobj.objectSubId = 0;
    2917                 :             : 
    2918                 :           0 :                 performDeletion(&conobj, behavior, 0);
    2919                 :           0 :                 found = true;
    2920                 :           0 :         }
    2921                 :             : 
    2922                 :             :         /* Clean up after the scan */
    2923                 :           0 :         systable_endscan(conscan);
    2924                 :           0 :         table_close(conrel, RowExclusiveLock);
    2925                 :             : 
    2926         [ #  # ]:           0 :         if (!found)
    2927                 :             :         {
    2928         [ #  # ]:           0 :                 if (!missing_ok)
    2929   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    2930                 :             :                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
    2931                 :             :                                          errmsg("constraint \"%s\" of domain \"%s\" does not exist",
    2932                 :             :                                                         constrName, TypeNameToString(typename))));
    2933                 :             :                 else
    2934   [ #  #  #  # ]:           0 :                         ereport(NOTICE,
    2935                 :             :                                         (errmsg("constraint \"%s\" of domain \"%s\" does not exist, skipping",
    2936                 :             :                                                         constrName, TypeNameToString(typename))));
    2937                 :           0 :         }
    2938                 :             : 
    2939                 :             :         /*
    2940                 :             :          * We must send out an sinval message for the domain, to ensure that any
    2941                 :             :          * dependent plans get rebuilt.  Since this command doesn't change the
    2942                 :             :          * domain's pg_type row, that won't happen automatically; do it manually.
    2943                 :             :          */
    2944                 :           0 :         CacheInvalidateHeapTuple(rel, tup, NULL);
    2945                 :             : 
    2946                 :           0 :         ObjectAddressSet(address, TypeRelationId, domainoid);
    2947                 :             : 
    2948                 :             :         /* Clean up */
    2949                 :           0 :         table_close(rel, RowExclusiveLock);
    2950                 :             : 
    2951                 :             :         return address;
    2952                 :           0 : }
    2953                 :             : 
    2954                 :             : /*
    2955                 :             :  * AlterDomainAddConstraint
    2956                 :             :  *
    2957                 :             :  * Implements the ALTER DOMAIN .. ADD CONSTRAINT statement.
    2958                 :             :  */
    2959                 :             : ObjectAddress
    2960                 :           0 : AlterDomainAddConstraint(List *names, Node *newConstraint,
    2961                 :             :                                                  ObjectAddress *constrAddr)
    2962                 :             : {
    2963                 :           0 :         TypeName   *typename;
    2964                 :           0 :         Oid                     domainoid;
    2965                 :           0 :         Relation        typrel;
    2966                 :           0 :         HeapTuple       tup;
    2967                 :           0 :         Form_pg_type typTup;
    2968                 :           0 :         Constraint *constr;
    2969                 :           0 :         char       *ccbin;
    2970                 :           0 :         ObjectAddress address = InvalidObjectAddress;
    2971                 :             : 
    2972                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    2973                 :           0 :         typename = makeTypeNameFromNameList(names);
    2974                 :           0 :         domainoid = typenameTypeId(NULL, typename);
    2975                 :             : 
    2976                 :             :         /* Look up the domain in the type table */
    2977                 :           0 :         typrel = table_open(TypeRelationId, RowExclusiveLock);
    2978                 :             : 
    2979                 :           0 :         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
    2980         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    2981   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", domainoid);
    2982                 :           0 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    2983                 :             : 
    2984                 :             :         /* Check it's a domain and check user has permission for ALTER DOMAIN */
    2985                 :           0 :         checkDomainOwner(tup);
    2986                 :             : 
    2987         [ #  # ]:           0 :         if (!IsA(newConstraint, Constraint))
    2988   [ #  #  #  # ]:           0 :                 elog(ERROR, "unrecognized node type: %d",
    2989                 :             :                          (int) nodeTag(newConstraint));
    2990                 :             : 
    2991                 :           0 :         constr = (Constraint *) newConstraint;
    2992                 :             : 
    2993                 :             :         /* enforced by parser */
    2994   [ #  #  #  # ]:           0 :         Assert(constr->contype == CONSTR_CHECK || constr->contype == CONSTR_NOTNULL);
    2995                 :             : 
    2996         [ #  # ]:           0 :         if (constr->contype == CONSTR_CHECK)
    2997                 :             :         {
    2998                 :             :                 /*
    2999                 :             :                  * First, process the constraint expression and add an entry to
    3000                 :             :                  * pg_constraint.
    3001                 :             :                  */
    3002                 :             : 
    3003                 :           0 :                 ccbin = domainAddCheckConstraint(domainoid, typTup->typnamespace,
    3004                 :           0 :                                                                                  typTup->typbasetype, typTup->typtypmod,
    3005                 :           0 :                                                                                  constr, NameStr(typTup->typname), constrAddr);
    3006                 :             : 
    3007                 :             : 
    3008                 :             :                 /*
    3009                 :             :                  * If requested to validate the constraint, test all values stored in
    3010                 :             :                  * the attributes based on the domain the constraint is being added
    3011                 :             :                  * to.
    3012                 :             :                  */
    3013         [ #  # ]:           0 :                 if (!constr->skip_validation)
    3014                 :           0 :                         validateDomainCheckConstraint(domainoid, ccbin, ShareLock);
    3015                 :             : 
    3016                 :             :                 /*
    3017                 :             :                  * We must send out an sinval message for the domain, to ensure that
    3018                 :             :                  * any dependent plans get rebuilt.  Since this command doesn't change
    3019                 :             :                  * the domain's pg_type row, that won't happen automatically; do it
    3020                 :             :                  * manually.
    3021                 :             :                  */
    3022                 :           0 :                 CacheInvalidateHeapTuple(typrel, tup, NULL);
    3023                 :           0 :         }
    3024         [ #  # ]:           0 :         else if (constr->contype == CONSTR_NOTNULL)
    3025                 :             :         {
    3026                 :             :                 /* Is the domain already set NOT NULL? */
    3027         [ #  # ]:           0 :                 if (typTup->typnotnull)
    3028                 :             :                 {
    3029                 :           0 :                         table_close(typrel, RowExclusiveLock);
    3030                 :           0 :                         return address;
    3031                 :             :                 }
    3032                 :           0 :                 domainAddNotNullConstraint(domainoid, typTup->typnamespace,
    3033                 :           0 :                                                                    typTup->typbasetype, typTup->typtypmod,
    3034                 :           0 :                                                                    constr, NameStr(typTup->typname), constrAddr);
    3035                 :             : 
    3036         [ #  # ]:           0 :                 if (!constr->skip_validation)
    3037                 :           0 :                         validateDomainNotNullConstraint(domainoid);
    3038                 :             : 
    3039                 :           0 :                 typTup->typnotnull = true;
    3040                 :           0 :                 CatalogTupleUpdate(typrel, &tup->t_self, tup);
    3041                 :           0 :         }
    3042                 :             : 
    3043                 :           0 :         ObjectAddressSet(address, TypeRelationId, domainoid);
    3044                 :             : 
    3045                 :             :         /* Clean up */
    3046                 :           0 :         table_close(typrel, RowExclusiveLock);
    3047                 :             : 
    3048                 :           0 :         return address;
    3049                 :           0 : }
    3050                 :             : 
    3051                 :             : /*
    3052                 :             :  * AlterDomainValidateConstraint
    3053                 :             :  *
    3054                 :             :  * Implements the ALTER DOMAIN .. VALIDATE CONSTRAINT statement.
    3055                 :             :  */
    3056                 :             : ObjectAddress
    3057                 :           0 : AlterDomainValidateConstraint(List *names, const char *constrName)
    3058                 :             : {
    3059                 :           0 :         TypeName   *typename;
    3060                 :           0 :         Oid                     domainoid;
    3061                 :           0 :         Relation        typrel;
    3062                 :           0 :         Relation        conrel;
    3063                 :           0 :         HeapTuple       tup;
    3064                 :           0 :         Form_pg_constraint con;
    3065                 :           0 :         Form_pg_constraint copy_con;
    3066                 :           0 :         char       *conbin;
    3067                 :           0 :         SysScanDesc scan;
    3068                 :           0 :         Datum           val;
    3069                 :           0 :         HeapTuple       tuple;
    3070                 :           0 :         HeapTuple       copyTuple;
    3071                 :           0 :         ScanKeyData skey[3];
    3072                 :             :         ObjectAddress address;
    3073                 :             : 
    3074                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    3075                 :           0 :         typename = makeTypeNameFromNameList(names);
    3076                 :           0 :         domainoid = typenameTypeId(NULL, typename);
    3077                 :             : 
    3078                 :             :         /* Look up the domain in the type table */
    3079                 :           0 :         typrel = table_open(TypeRelationId, AccessShareLock);
    3080                 :             : 
    3081                 :           0 :         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(domainoid));
    3082         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    3083   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", domainoid);
    3084                 :             : 
    3085                 :             :         /* Check it's a domain and check user has permission for ALTER DOMAIN */
    3086                 :           0 :         checkDomainOwner(tup);
    3087                 :             : 
    3088                 :             :         /*
    3089                 :             :          * Find and check the target constraint
    3090                 :             :          */
    3091                 :           0 :         conrel = table_open(ConstraintRelationId, RowExclusiveLock);
    3092                 :             : 
    3093                 :           0 :         ScanKeyInit(&skey[0],
    3094                 :             :                                 Anum_pg_constraint_conrelid,
    3095                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
    3096                 :           0 :                                 ObjectIdGetDatum(InvalidOid));
    3097                 :           0 :         ScanKeyInit(&skey[1],
    3098                 :             :                                 Anum_pg_constraint_contypid,
    3099                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
    3100                 :           0 :                                 ObjectIdGetDatum(domainoid));
    3101                 :           0 :         ScanKeyInit(&skey[2],
    3102                 :             :                                 Anum_pg_constraint_conname,
    3103                 :             :                                 BTEqualStrategyNumber, F_NAMEEQ,
    3104                 :           0 :                                 CStringGetDatum(constrName));
    3105                 :             : 
    3106                 :           0 :         scan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
    3107                 :           0 :                                                           NULL, 3, skey);
    3108                 :             : 
    3109                 :             :         /* There can be at most one matching row */
    3110         [ #  # ]:           0 :         if (!HeapTupleIsValid(tuple = systable_getnext(scan)))
    3111   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3112                 :             :                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    3113                 :             :                                  errmsg("constraint \"%s\" of domain \"%s\" does not exist",
    3114                 :             :                                                 constrName, TypeNameToString(typename))));
    3115                 :             : 
    3116                 :           0 :         con = (Form_pg_constraint) GETSTRUCT(tuple);
    3117         [ #  # ]:           0 :         if (con->contype != CONSTRAINT_CHECK)
    3118   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3119                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    3120                 :             :                                  errmsg("constraint \"%s\" of domain \"%s\" is not a check constraint",
    3121                 :             :                                                 constrName, TypeNameToString(typename))));
    3122                 :             : 
    3123                 :           0 :         val = SysCacheGetAttrNotNull(CONSTROID, tuple, Anum_pg_constraint_conbin);
    3124                 :           0 :         conbin = TextDatumGetCString(val);
    3125                 :             : 
    3126                 :             :         /*
    3127                 :             :          * Locking related relations with ShareUpdateExclusiveLock is ok because
    3128                 :             :          * not-yet-valid constraints are still enforced against concurrent inserts
    3129                 :             :          * or updates.
    3130                 :             :          */
    3131                 :           0 :         validateDomainCheckConstraint(domainoid, conbin, ShareUpdateExclusiveLock);
    3132                 :             : 
    3133                 :             :         /*
    3134                 :             :          * Now update the catalog, while we have the door open.
    3135                 :             :          */
    3136                 :           0 :         copyTuple = heap_copytuple(tuple);
    3137                 :           0 :         copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
    3138                 :           0 :         copy_con->convalidated = true;
    3139                 :           0 :         CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
    3140                 :             : 
    3141         [ #  # ]:           0 :         InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0);
    3142                 :             : 
    3143                 :           0 :         ObjectAddressSet(address, TypeRelationId, domainoid);
    3144                 :             : 
    3145                 :           0 :         heap_freetuple(copyTuple);
    3146                 :             : 
    3147                 :           0 :         systable_endscan(scan);
    3148                 :             : 
    3149                 :           0 :         table_close(typrel, AccessShareLock);
    3150                 :           0 :         table_close(conrel, RowExclusiveLock);
    3151                 :             : 
    3152                 :           0 :         ReleaseSysCache(tup);
    3153                 :             : 
    3154                 :             :         return address;
    3155                 :           0 : }
    3156                 :             : 
    3157                 :             : /*
    3158                 :             :  * Verify that all columns currently using the domain are not null.
    3159                 :             :  */
    3160                 :             : static void
    3161                 :           0 : validateDomainNotNullConstraint(Oid domainoid)
    3162                 :             : {
    3163                 :           0 :         List       *rels;
    3164                 :           0 :         ListCell   *rt;
    3165                 :             : 
    3166                 :             :         /* Fetch relation list with attributes based on this domain */
    3167                 :             :         /* ShareLock is sufficient to prevent concurrent data changes */
    3168                 :             : 
    3169                 :           0 :         rels = get_rels_with_domain(domainoid, ShareLock);
    3170                 :             : 
    3171   [ #  #  #  #  :           0 :         foreach(rt, rels)
                   #  # ]
    3172                 :             :         {
    3173                 :           0 :                 RelToCheck *rtc = (RelToCheck *) lfirst(rt);
    3174                 :           0 :                 Relation        testrel = rtc->rel;
    3175                 :           0 :                 TupleDesc       tupdesc = RelationGetDescr(testrel);
    3176                 :           0 :                 TupleTableSlot *slot;
    3177                 :           0 :                 TableScanDesc scan;
    3178                 :           0 :                 Snapshot        snapshot;
    3179                 :             : 
    3180                 :             :                 /* Scan all tuples in this relation */
    3181                 :           0 :                 snapshot = RegisterSnapshot(GetLatestSnapshot());
    3182                 :           0 :                 scan = table_beginscan(testrel, snapshot, 0, NULL);
    3183                 :           0 :                 slot = table_slot_create(testrel, NULL);
    3184         [ #  # ]:           0 :                 while (table_scan_getnextslot(scan, ForwardScanDirection, slot))
    3185                 :             :                 {
    3186                 :           0 :                         int                     i;
    3187                 :             : 
    3188                 :             :                         /* Test attributes that are of the domain */
    3189         [ #  # ]:           0 :                         for (i = 0; i < rtc->natts; i++)
    3190                 :             :                         {
    3191                 :           0 :                                 int                     attnum = rtc->atts[i];
    3192                 :           0 :                                 Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
    3193                 :             : 
    3194         [ #  # ]:           0 :                                 if (slot_attisnull(slot, attnum))
    3195                 :             :                                 {
    3196                 :             :                                         /*
    3197                 :             :                                          * In principle the auxiliary information for this error
    3198                 :             :                                          * should be errdatatype(), but errtablecol() seems
    3199                 :             :                                          * considerably more useful in practice.  Since this code
    3200                 :             :                                          * only executes in an ALTER DOMAIN command, the client
    3201                 :             :                                          * should already know which domain is in question.
    3202                 :             :                                          */
    3203   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
    3204                 :             :                                                         (errcode(ERRCODE_NOT_NULL_VIOLATION),
    3205                 :             :                                                          errmsg("column \"%s\" of table \"%s\" contains null values",
    3206                 :             :                                                                         NameStr(attr->attname),
    3207                 :             :                                                                         RelationGetRelationName(testrel)),
    3208                 :             :                                                          errtablecol(testrel, attnum)));
    3209                 :           0 :                                 }
    3210                 :           0 :                         }
    3211                 :           0 :                 }
    3212                 :           0 :                 ExecDropSingleTupleTableSlot(slot);
    3213                 :           0 :                 table_endscan(scan);
    3214                 :           0 :                 UnregisterSnapshot(snapshot);
    3215                 :             : 
    3216                 :             :                 /* Close each rel after processing, but keep lock */
    3217                 :           0 :                 table_close(testrel, NoLock);
    3218                 :           0 :         }
    3219                 :           0 : }
    3220                 :             : 
    3221                 :             : /*
    3222                 :             :  * Verify that all columns currently using the domain satisfy the given check
    3223                 :             :  * constraint expression.
    3224                 :             :  *
    3225                 :             :  * It is used to validate existing constraints and to add newly created check
    3226                 :             :  * constraints to a domain.
    3227                 :             :  *
    3228                 :             :  * The lockmode is used for relations using the domain.  It should be
    3229                 :             :  * ShareLock when adding a new constraint to domain.  It can be
    3230                 :             :  * ShareUpdateExclusiveLock when validating an existing constraint.
    3231                 :             :  */
    3232                 :             : static void
    3233                 :           0 : validateDomainCheckConstraint(Oid domainoid, const char *ccbin, LOCKMODE lockmode)
    3234                 :             : {
    3235                 :           0 :         Expr       *expr = (Expr *) stringToNode(ccbin);
    3236                 :           0 :         List       *rels;
    3237                 :           0 :         ListCell   *rt;
    3238                 :           0 :         EState     *estate;
    3239                 :           0 :         ExprContext *econtext;
    3240                 :           0 :         ExprState  *exprstate;
    3241                 :             : 
    3242                 :             :         /* Need an EState to run ExecEvalExpr */
    3243                 :           0 :         estate = CreateExecutorState();
    3244         [ #  # ]:           0 :         econtext = GetPerTupleExprContext(estate);
    3245                 :             : 
    3246                 :             :         /* build execution state for expr */
    3247                 :           0 :         exprstate = ExecPrepareExpr(expr, estate);
    3248                 :             : 
    3249                 :             :         /* Fetch relation list with attributes based on this domain */
    3250                 :           0 :         rels = get_rels_with_domain(domainoid, lockmode);
    3251                 :             : 
    3252   [ #  #  #  #  :           0 :         foreach(rt, rels)
                   #  # ]
    3253                 :             :         {
    3254                 :           0 :                 RelToCheck *rtc = (RelToCheck *) lfirst(rt);
    3255                 :           0 :                 Relation        testrel = rtc->rel;
    3256                 :           0 :                 TupleDesc       tupdesc = RelationGetDescr(testrel);
    3257                 :           0 :                 TupleTableSlot *slot;
    3258                 :           0 :                 TableScanDesc scan;
    3259                 :           0 :                 Snapshot        snapshot;
    3260                 :             : 
    3261                 :             :                 /* Scan all tuples in this relation */
    3262                 :           0 :                 snapshot = RegisterSnapshot(GetLatestSnapshot());
    3263                 :           0 :                 scan = table_beginscan(testrel, snapshot, 0, NULL);
    3264                 :           0 :                 slot = table_slot_create(testrel, NULL);
    3265         [ #  # ]:           0 :                 while (table_scan_getnextslot(scan, ForwardScanDirection, slot))
    3266                 :             :                 {
    3267                 :           0 :                         int                     i;
    3268                 :             : 
    3269                 :             :                         /* Test attributes that are of the domain */
    3270         [ #  # ]:           0 :                         for (i = 0; i < rtc->natts; i++)
    3271                 :             :                         {
    3272                 :           0 :                                 int                     attnum = rtc->atts[i];
    3273                 :           0 :                                 Datum           d;
    3274                 :           0 :                                 bool            isNull;
    3275                 :           0 :                                 Datum           conResult;
    3276                 :             : 
    3277                 :           0 :                                 d = slot_getattr(slot, attnum, &isNull);
    3278                 :             : 
    3279                 :           0 :                                 econtext->domainValue_datum = d;
    3280                 :           0 :                                 econtext->domainValue_isNull = isNull;
    3281                 :             : 
    3282                 :           0 :                                 conResult = ExecEvalExprSwitchContext(exprstate,
    3283                 :           0 :                                                                                                           econtext,
    3284                 :             :                                                                                                           &isNull);
    3285                 :             : 
    3286   [ #  #  #  # ]:           0 :                                 if (!isNull && !DatumGetBool(conResult))
    3287                 :             :                                 {
    3288                 :           0 :                                         Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
    3289                 :             : 
    3290                 :             :                                         /*
    3291                 :             :                                          * In principle the auxiliary information for this error
    3292                 :             :                                          * should be errdomainconstraint(), but errtablecol()
    3293                 :             :                                          * seems considerably more useful in practice.  Since this
    3294                 :             :                                          * code only executes in an ALTER DOMAIN command, the
    3295                 :             :                                          * client should already know which domain is in question,
    3296                 :             :                                          * and which constraint too.
    3297                 :             :                                          */
    3298   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
    3299                 :             :                                                         (errcode(ERRCODE_CHECK_VIOLATION),
    3300                 :             :                                                          errmsg("column \"%s\" of table \"%s\" contains values that violate the new constraint",
    3301                 :             :                                                                         NameStr(attr->attname),
    3302                 :             :                                                                         RelationGetRelationName(testrel)),
    3303                 :             :                                                          errtablecol(testrel, attnum)));
    3304                 :           0 :                                 }
    3305                 :           0 :                         }
    3306                 :             : 
    3307                 :           0 :                         ResetExprContext(econtext);
    3308                 :           0 :                 }
    3309                 :           0 :                 ExecDropSingleTupleTableSlot(slot);
    3310                 :           0 :                 table_endscan(scan);
    3311                 :           0 :                 UnregisterSnapshot(snapshot);
    3312                 :             : 
    3313                 :             :                 /* Hold relation lock till commit (XXX bad for concurrency) */
    3314                 :           0 :                 table_close(testrel, NoLock);
    3315                 :           0 :         }
    3316                 :             : 
    3317                 :           0 :         FreeExecutorState(estate);
    3318                 :           0 : }
    3319                 :             : 
    3320                 :             : /*
    3321                 :             :  * get_rels_with_domain
    3322                 :             :  *
    3323                 :             :  * Fetch all relations / attributes which are using the domain
    3324                 :             :  *
    3325                 :             :  * The result is a list of RelToCheck structs, one for each distinct
    3326                 :             :  * relation, each containing one or more attribute numbers that are of
    3327                 :             :  * the domain type.  We have opened each rel and acquired the specified lock
    3328                 :             :  * type on it.
    3329                 :             :  *
    3330                 :             :  * We support nested domains by including attributes that are of derived
    3331                 :             :  * domain types.  Current callers do not need to distinguish between attributes
    3332                 :             :  * that are of exactly the given domain and those that are of derived domains.
    3333                 :             :  *
    3334                 :             :  * XXX this is completely broken because there is no way to lock the domain
    3335                 :             :  * to prevent columns from being added or dropped while our command runs.
    3336                 :             :  * We can partially protect against column drops by locking relations as we
    3337                 :             :  * come across them, but there is still a race condition (the window between
    3338                 :             :  * seeing a pg_depend entry and acquiring lock on the relation it references).
    3339                 :             :  * Also, holding locks on all these relations simultaneously creates a non-
    3340                 :             :  * trivial risk of deadlock.  We can minimize but not eliminate the deadlock
    3341                 :             :  * risk by using the weakest suitable lock (ShareLock for most callers).
    3342                 :             :  *
    3343                 :             :  * XXX the API for this is not sufficient to support checking domain values
    3344                 :             :  * that are inside container types, such as composite types, arrays, or
    3345                 :             :  * ranges.  Currently we just error out if a container type containing the
    3346                 :             :  * target domain is stored anywhere.
    3347                 :             :  *
    3348                 :             :  * Generally used for retrieving a list of tests when adding
    3349                 :             :  * new constraints to a domain.
    3350                 :             :  */
    3351                 :             : static List *
    3352                 :           0 : get_rels_with_domain(Oid domainOid, LOCKMODE lockmode)
    3353                 :             : {
    3354                 :           0 :         List       *result = NIL;
    3355                 :           0 :         char       *domainTypeName = format_type_be(domainOid);
    3356                 :           0 :         Relation        depRel;
    3357                 :           0 :         ScanKeyData key[2];
    3358                 :           0 :         SysScanDesc depScan;
    3359                 :           0 :         HeapTuple       depTup;
    3360                 :             : 
    3361         [ #  # ]:           0 :         Assert(lockmode != NoLock);
    3362                 :             : 
    3363                 :             :         /* since this function recurses, it could be driven to stack overflow */
    3364                 :           0 :         check_stack_depth();
    3365                 :             : 
    3366                 :             :         /*
    3367                 :             :          * We scan pg_depend to find those things that depend on the domain. (We
    3368                 :             :          * assume we can ignore refobjsubid for a domain.)
    3369                 :             :          */
    3370                 :           0 :         depRel = table_open(DependRelationId, AccessShareLock);
    3371                 :             : 
    3372                 :           0 :         ScanKeyInit(&key[0],
    3373                 :             :                                 Anum_pg_depend_refclassid,
    3374                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
    3375                 :           0 :                                 ObjectIdGetDatum(TypeRelationId));
    3376                 :           0 :         ScanKeyInit(&key[1],
    3377                 :             :                                 Anum_pg_depend_refobjid,
    3378                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
    3379                 :           0 :                                 ObjectIdGetDatum(domainOid));
    3380                 :             : 
    3381                 :           0 :         depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
    3382                 :           0 :                                                                  NULL, 2, key);
    3383                 :             : 
    3384         [ #  # ]:           0 :         while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
    3385                 :             :         {
    3386                 :           0 :                 Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
    3387                 :           0 :                 RelToCheck *rtc = NULL;
    3388                 :           0 :                 ListCell   *rellist;
    3389                 :           0 :                 Form_pg_attribute pg_att;
    3390                 :           0 :                 int                     ptr;
    3391                 :             : 
    3392                 :             :                 /* Check for directly dependent types */
    3393         [ #  # ]:           0 :                 if (pg_depend->classid == TypeRelationId)
    3394                 :             :                 {
    3395         [ #  # ]:           0 :                         if (get_typtype(pg_depend->objid) == TYPTYPE_DOMAIN)
    3396                 :             :                         {
    3397                 :             :                                 /*
    3398                 :             :                                  * This is a sub-domain, so recursively add dependent columns
    3399                 :             :                                  * to the output list.  This is a bit inefficient since we may
    3400                 :             :                                  * fail to combine RelToCheck entries when attributes of the
    3401                 :             :                                  * same rel have different derived domain types, but it's
    3402                 :             :                                  * probably not worth improving.
    3403                 :             :                                  */
    3404                 :           0 :                                 result = list_concat(result,
    3405                 :           0 :                                                                          get_rels_with_domain(pg_depend->objid,
    3406                 :           0 :                                                                                                                   lockmode));
    3407                 :           0 :                         }
    3408                 :             :                         else
    3409                 :             :                         {
    3410                 :             :                                 /*
    3411                 :             :                                  * Otherwise, it is some container type using the domain, so
    3412                 :             :                                  * fail if there are any columns of this type.
    3413                 :             :                                  */
    3414                 :           0 :                                 find_composite_type_dependencies(pg_depend->objid,
    3415                 :             :                                                                                                  NULL,
    3416                 :           0 :                                                                                                  domainTypeName);
    3417                 :             :                         }
    3418                 :           0 :                         continue;
    3419                 :             :                 }
    3420                 :             : 
    3421                 :             :                 /* Else, ignore dependees that aren't user columns of relations */
    3422                 :             :                 /* (we assume system columns are never of domain types) */
    3423   [ #  #  #  # ]:           0 :                 if (pg_depend->classid != RelationRelationId ||
    3424                 :           0 :                         pg_depend->objsubid <= 0)
    3425                 :           0 :                         continue;
    3426                 :             : 
    3427                 :             :                 /* See if we already have an entry for this relation */
    3428   [ #  #  #  #  :           0 :                 foreach(rellist, result)
                   #  # ]
    3429                 :             :                 {
    3430                 :           0 :                         RelToCheck *rt = (RelToCheck *) lfirst(rellist);
    3431                 :             : 
    3432         [ #  # ]:           0 :                         if (RelationGetRelid(rt->rel) == pg_depend->objid)
    3433                 :             :                         {
    3434                 :           0 :                                 rtc = rt;
    3435                 :           0 :                                 break;
    3436                 :             :                         }
    3437         [ #  # ]:           0 :                 }
    3438                 :             : 
    3439         [ #  # ]:           0 :                 if (rtc == NULL)
    3440                 :             :                 {
    3441                 :             :                         /* First attribute found for this relation */
    3442                 :           0 :                         Relation        rel;
    3443                 :             : 
    3444                 :             :                         /* Acquire requested lock on relation */
    3445                 :           0 :                         rel = relation_open(pg_depend->objid, lockmode);
    3446                 :             : 
    3447                 :             :                         /*
    3448                 :             :                          * Check to see if rowtype is stored anyplace as a composite-type
    3449                 :             :                          * column; if so we have to fail, for now anyway.
    3450                 :             :                          */
    3451         [ #  # ]:           0 :                         if (OidIsValid(rel->rd_rel->reltype))
    3452                 :           0 :                                 find_composite_type_dependencies(rel->rd_rel->reltype,
    3453                 :             :                                                                                                  NULL,
    3454                 :           0 :                                                                                                  domainTypeName);
    3455                 :             : 
    3456                 :             :                         /*
    3457                 :             :                          * Otherwise, we can ignore relations except those with both
    3458                 :             :                          * storage and user-chosen column types.
    3459                 :             :                          *
    3460                 :             :                          * XXX If an index-only scan could satisfy "col::some_domain" from
    3461                 :             :                          * a suitable expression index, this should also check expression
    3462                 :             :                          * index columns.
    3463                 :             :                          */
    3464   [ #  #  #  # ]:           0 :                         if (rel->rd_rel->relkind != RELKIND_RELATION &&
    3465                 :           0 :                                 rel->rd_rel->relkind != RELKIND_MATVIEW)
    3466                 :             :                         {
    3467                 :           0 :                                 relation_close(rel, lockmode);
    3468                 :           0 :                                 continue;
    3469                 :             :                         }
    3470                 :             : 
    3471                 :             :                         /* Build the RelToCheck entry with enough space for all atts */
    3472                 :           0 :                         rtc = palloc_object(RelToCheck);
    3473                 :           0 :                         rtc->rel = rel;
    3474                 :           0 :                         rtc->natts = 0;
    3475                 :           0 :                         rtc->atts = palloc_array(int, RelationGetNumberOfAttributes(rel));
    3476                 :           0 :                         result = lappend(result, rtc);
    3477         [ #  # ]:           0 :                 }
    3478                 :             : 
    3479                 :             :                 /*
    3480                 :             :                  * Confirm column has not been dropped, and is of the expected type.
    3481                 :             :                  * This defends against an ALTER DROP COLUMN occurring just before we
    3482                 :             :                  * acquired lock ... but if the whole table were dropped, we'd still
    3483                 :             :                  * have a problem.
    3484                 :             :                  */
    3485         [ #  # ]:           0 :                 if (pg_depend->objsubid > RelationGetNumberOfAttributes(rtc->rel))
    3486                 :           0 :                         continue;
    3487                 :           0 :                 pg_att = TupleDescAttr(rtc->rel->rd_att, pg_depend->objsubid - 1);
    3488   [ #  #  #  # ]:           0 :                 if (pg_att->attisdropped || pg_att->atttypid != domainOid)
    3489                 :           0 :                         continue;
    3490                 :             : 
    3491                 :             :                 /*
    3492                 :             :                  * Okay, add column to result.  We store the columns in column-number
    3493                 :             :                  * order; this is just a hack to improve predictability of regression
    3494                 :             :                  * test output ...
    3495                 :             :                  */
    3496         [ #  # ]:           0 :                 Assert(rtc->natts < RelationGetNumberOfAttributes(rtc->rel));
    3497                 :             : 
    3498                 :           0 :                 ptr = rtc->natts++;
    3499   [ #  #  #  # ]:           0 :                 while (ptr > 0 && rtc->atts[ptr - 1] > pg_depend->objsubid)
    3500                 :             :                 {
    3501                 :           0 :                         rtc->atts[ptr] = rtc->atts[ptr - 1];
    3502                 :           0 :                         ptr--;
    3503                 :             :                 }
    3504                 :           0 :                 rtc->atts[ptr] = pg_depend->objsubid;
    3505      [ #  #  # ]:           0 :         }
    3506                 :             : 
    3507                 :           0 :         systable_endscan(depScan);
    3508                 :             : 
    3509                 :           0 :         relation_close(depRel, AccessShareLock);
    3510                 :             : 
    3511                 :           0 :         return result;
    3512                 :           0 : }
    3513                 :             : 
    3514                 :             : /*
    3515                 :             :  * checkDomainOwner
    3516                 :             :  *
    3517                 :             :  * Check that the type is actually a domain and that the current user
    3518                 :             :  * has permission to do ALTER DOMAIN on it.  Throw an error if not.
    3519                 :             :  */
    3520                 :             : void
    3521                 :           0 : checkDomainOwner(HeapTuple tup)
    3522                 :             : {
    3523                 :           0 :         Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
    3524                 :             : 
    3525                 :             :         /* Check that this is actually a domain */
    3526         [ #  # ]:           0 :         if (typTup->typtype != TYPTYPE_DOMAIN)
    3527   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3528                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    3529                 :             :                                  errmsg("%s is not a domain",
    3530                 :             :                                                 format_type_be(typTup->oid))));
    3531                 :             : 
    3532                 :             :         /* Permission check: must own type */
    3533         [ #  # ]:           0 :         if (!object_ownercheck(TypeRelationId, typTup->oid, GetUserId()))
    3534                 :           0 :                 aclcheck_error_type(ACLCHECK_NOT_OWNER, typTup->oid);
    3535                 :           0 : }
    3536                 :             : 
    3537                 :             : /*
    3538                 :             :  * domainAddCheckConstraint - code shared between CREATE and ALTER DOMAIN
    3539                 :             :  */
    3540                 :             : static char *
    3541                 :           0 : domainAddCheckConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
    3542                 :             :                                                  int typMod, Constraint *constr,
    3543                 :             :                                                  const char *domainName, ObjectAddress *constrAddr)
    3544                 :             : {
    3545                 :           0 :         Node       *expr;
    3546                 :           0 :         char       *ccbin;
    3547                 :           0 :         ParseState *pstate;
    3548                 :           0 :         CoerceToDomainValue *domVal;
    3549                 :           0 :         Oid                     ccoid;
    3550                 :             : 
    3551         [ #  # ]:           0 :         Assert(constr->contype == CONSTR_CHECK);
    3552                 :             : 
    3553                 :             :         /*
    3554                 :             :          * Assign or validate constraint name
    3555                 :             :          */
    3556         [ #  # ]:           0 :         if (constr->conname)
    3557                 :             :         {
    3558         [ #  # ]:           0 :                 if (ConstraintNameIsUsed(CONSTRAINT_DOMAIN,
    3559                 :           0 :                                                                  domainOid,
    3560                 :           0 :                                                                  constr->conname))
    3561   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    3562                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
    3563                 :             :                                          errmsg("constraint \"%s\" for domain \"%s\" already exists",
    3564                 :             :                                                         constr->conname, domainName)));
    3565                 :           0 :         }
    3566                 :             :         else
    3567                 :           0 :                 constr->conname = ChooseConstraintName(domainName,
    3568                 :             :                                                                                            NULL,
    3569                 :             :                                                                                            "check",
    3570                 :           0 :                                                                                            domainNamespace,
    3571                 :             :                                                                                            NIL);
    3572                 :             : 
    3573                 :             :         /*
    3574                 :             :          * Convert the A_EXPR in raw_expr into an EXPR
    3575                 :             :          */
    3576                 :           0 :         pstate = make_parsestate(NULL);
    3577                 :             : 
    3578                 :             :         /*
    3579                 :             :          * Set up a CoerceToDomainValue to represent the occurrence of VALUE in
    3580                 :             :          * the expression.  Note that it will appear to have the type of the base
    3581                 :             :          * type, not the domain.  This seems correct since within the check
    3582                 :             :          * expression, we should not assume the input value can be considered a
    3583                 :             :          * member of the domain.
    3584                 :             :          */
    3585                 :           0 :         domVal = makeNode(CoerceToDomainValue);
    3586                 :           0 :         domVal->typeId = baseTypeOid;
    3587                 :           0 :         domVal->typeMod = typMod;
    3588                 :           0 :         domVal->collation = get_typcollation(baseTypeOid);
    3589                 :           0 :         domVal->location = -1;               /* will be set when/if used */
    3590                 :             : 
    3591                 :           0 :         pstate->p_pre_columnref_hook = replace_domain_constraint_value;
    3592                 :           0 :         pstate->p_ref_hook_state = domVal;
    3593                 :             : 
    3594                 :           0 :         expr = transformExpr(pstate, constr->raw_expr, EXPR_KIND_DOMAIN_CHECK);
    3595                 :             : 
    3596                 :             :         /*
    3597                 :             :          * Make sure it yields a boolean result.
    3598                 :             :          */
    3599                 :           0 :         expr = coerce_to_boolean(pstate, expr, "CHECK");
    3600                 :             : 
    3601                 :             :         /*
    3602                 :             :          * Fix up collation information.
    3603                 :             :          */
    3604                 :           0 :         assign_expr_collations(pstate, expr);
    3605                 :             : 
    3606                 :             :         /*
    3607                 :             :          * Domains don't allow variables (this is probably dead code now that
    3608                 :             :          * add_missing_from is history, but let's be sure).
    3609                 :             :          */
    3610         [ #  # ]:           0 :         if (pstate->p_rtable != NIL ||
    3611                 :           0 :                 contain_var_clause(expr))
    3612   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3613                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    3614                 :             :                                  errmsg("cannot use table references in domain check constraint")));
    3615                 :             : 
    3616                 :             :         /*
    3617                 :             :          * Convert to string form for storage.
    3618                 :             :          */
    3619                 :           0 :         ccbin = nodeToString(expr);
    3620                 :             : 
    3621                 :             :         /*
    3622                 :             :          * Store the constraint in pg_constraint
    3623                 :             :          */
    3624                 :           0 :         ccoid =
    3625                 :           0 :                 CreateConstraintEntry(constr->conname,       /* Constraint Name */
    3626                 :           0 :                                                           domainNamespace,      /* namespace */
    3627                 :             :                                                           CONSTRAINT_CHECK, /* Constraint Type */
    3628                 :             :                                                           false,        /* Is Deferrable */
    3629                 :             :                                                           false,        /* Is Deferred */
    3630                 :             :                                                           true, /* Is Enforced */
    3631                 :           0 :                                                           !constr->skip_validation, /* Is Validated */
    3632                 :             :                                                           InvalidOid,   /* no parent constraint */
    3633                 :             :                                                           InvalidOid,   /* not a relation constraint */
    3634                 :             :                                                           NULL,
    3635                 :             :                                                           0,
    3636                 :             :                                                           0,
    3637                 :           0 :                                                           domainOid,    /* domain constraint */
    3638                 :             :                                                           InvalidOid,   /* no associated index */
    3639                 :             :                                                           InvalidOid,   /* Foreign key fields */
    3640                 :             :                                                           NULL,
    3641                 :             :                                                           NULL,
    3642                 :             :                                                           NULL,
    3643                 :             :                                                           NULL,
    3644                 :             :                                                           0,
    3645                 :             :                                                           ' ',
    3646                 :             :                                                           ' ',
    3647                 :             :                                                           NULL,
    3648                 :             :                                                           0,
    3649                 :             :                                                           ' ',
    3650                 :             :                                                           NULL, /* not an exclusion constraint */
    3651                 :           0 :                                                           expr, /* Tree form of check constraint */
    3652                 :           0 :                                                           ccbin,        /* Binary form of check constraint */
    3653                 :             :                                                           true, /* is local */
    3654                 :             :                                                           0,    /* inhcount */
    3655                 :             :                                                           false,        /* connoinherit */
    3656                 :             :                                                           false,        /* conperiod */
    3657                 :             :                                                           false);       /* is_internal */
    3658         [ #  # ]:           0 :         if (constrAddr)
    3659                 :           0 :                 ObjectAddressSet(*constrAddr, ConstraintRelationId, ccoid);
    3660                 :             : 
    3661                 :             :         /*
    3662                 :             :          * Return the compiled constraint expression so the calling routine can
    3663                 :             :          * perform any additional required tests.
    3664                 :             :          */
    3665                 :           0 :         return ccbin;
    3666                 :           0 : }
    3667                 :             : 
    3668                 :             : /* Parser pre_columnref_hook for domain CHECK constraint parsing */
    3669                 :             : static Node *
    3670                 :           0 : replace_domain_constraint_value(ParseState *pstate, ColumnRef *cref)
    3671                 :             : {
    3672                 :             :         /*
    3673                 :             :          * Check for a reference to "value", and if that's what it is, replace
    3674                 :             :          * with a CoerceToDomainValue as prepared for us by
    3675                 :             :          * domainAddCheckConstraint. (We handle VALUE as a name, not a keyword, to
    3676                 :             :          * avoid breaking a lot of applications that have used VALUE as a column
    3677                 :             :          * name in the past.)
    3678                 :             :          */
    3679         [ #  # ]:           0 :         if (list_length(cref->fields) == 1)
    3680                 :             :         {
    3681                 :           0 :                 Node       *field1 = (Node *) linitial(cref->fields);
    3682                 :           0 :                 char       *colname;
    3683                 :             : 
    3684                 :           0 :                 colname = strVal(field1);
    3685         [ #  # ]:           0 :                 if (strcmp(colname, "value") == 0)
    3686                 :             :                 {
    3687                 :           0 :                         CoerceToDomainValue *domVal = copyObject(pstate->p_ref_hook_state);
    3688                 :             : 
    3689                 :             :                         /* Propagate location knowledge, if any */
    3690                 :           0 :                         domVal->location = cref->location;
    3691                 :           0 :                         return (Node *) domVal;
    3692                 :           0 :                 }
    3693      [ #  #  # ]:           0 :         }
    3694                 :           0 :         return NULL;
    3695                 :           0 : }
    3696                 :             : 
    3697                 :             : /*
    3698                 :             :  * domainAddNotNullConstraint - code shared between CREATE and ALTER DOMAIN
    3699                 :             :  */
    3700                 :             : static void
    3701                 :           0 : domainAddNotNullConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
    3702                 :             :                                                    int typMod, Constraint *constr,
    3703                 :             :                                                    const char *domainName, ObjectAddress *constrAddr)
    3704                 :             : {
    3705                 :           0 :         Oid                     ccoid;
    3706                 :             : 
    3707         [ #  # ]:           0 :         Assert(constr->contype == CONSTR_NOTNULL);
    3708                 :             : 
    3709                 :             :         /*
    3710                 :             :          * Assign or validate constraint name
    3711                 :             :          */
    3712         [ #  # ]:           0 :         if (constr->conname)
    3713                 :             :         {
    3714         [ #  # ]:           0 :                 if (ConstraintNameIsUsed(CONSTRAINT_DOMAIN,
    3715                 :           0 :                                                                  domainOid,
    3716                 :           0 :                                                                  constr->conname))
    3717   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    3718                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
    3719                 :             :                                          errmsg("constraint \"%s\" for domain \"%s\" already exists",
    3720                 :             :                                                         constr->conname, domainName)));
    3721                 :           0 :         }
    3722                 :             :         else
    3723                 :           0 :                 constr->conname = ChooseConstraintName(domainName,
    3724                 :             :                                                                                            NULL,
    3725                 :             :                                                                                            "not_null",
    3726                 :           0 :                                                                                            domainNamespace,
    3727                 :             :                                                                                            NIL);
    3728                 :             : 
    3729                 :             :         /*
    3730                 :             :          * Store the constraint in pg_constraint
    3731                 :             :          */
    3732                 :           0 :         ccoid =
    3733                 :           0 :                 CreateConstraintEntry(constr->conname,       /* Constraint Name */
    3734                 :           0 :                                                           domainNamespace,      /* namespace */
    3735                 :             :                                                           CONSTRAINT_NOTNULL,   /* Constraint Type */
    3736                 :             :                                                           false,        /* Is Deferrable */
    3737                 :             :                                                           false,        /* Is Deferred */
    3738                 :             :                                                           true, /* Is Enforced */
    3739                 :           0 :                                                           !constr->skip_validation, /* Is Validated */
    3740                 :             :                                                           InvalidOid,   /* no parent constraint */
    3741                 :             :                                                           InvalidOid,   /* not a relation constraint */
    3742                 :             :                                                           NULL,
    3743                 :             :                                                           0,
    3744                 :             :                                                           0,
    3745                 :           0 :                                                           domainOid,    /* domain constraint */
    3746                 :             :                                                           InvalidOid,   /* no associated index */
    3747                 :             :                                                           InvalidOid,   /* Foreign key fields */
    3748                 :             :                                                           NULL,
    3749                 :             :                                                           NULL,
    3750                 :             :                                                           NULL,
    3751                 :             :                                                           NULL,
    3752                 :             :                                                           0,
    3753                 :             :                                                           ' ',
    3754                 :             :                                                           ' ',
    3755                 :             :                                                           NULL,
    3756                 :             :                                                           0,
    3757                 :             :                                                           ' ',
    3758                 :             :                                                           NULL, /* not an exclusion constraint */
    3759                 :             :                                                           NULL,
    3760                 :             :                                                           NULL,
    3761                 :             :                                                           true, /* is local */
    3762                 :             :                                                           0,    /* inhcount */
    3763                 :             :                                                           false,        /* connoinherit */
    3764                 :             :                                                           false,        /* conperiod */
    3765                 :             :                                                           false);       /* is_internal */
    3766                 :             : 
    3767         [ #  # ]:           0 :         if (constrAddr)
    3768                 :           0 :                 ObjectAddressSet(*constrAddr, ConstraintRelationId, ccoid);
    3769                 :           0 : }
    3770                 :             : 
    3771                 :             : 
    3772                 :             : /*
    3773                 :             :  * Execute ALTER TYPE RENAME
    3774                 :             :  */
    3775                 :             : ObjectAddress
    3776                 :           0 : RenameType(RenameStmt *stmt)
    3777                 :             : {
    3778                 :           0 :         List       *names = castNode(List, stmt->object);
    3779                 :           0 :         const char *newTypeName = stmt->newname;
    3780                 :           0 :         TypeName   *typename;
    3781                 :           0 :         Oid                     typeOid;
    3782                 :           0 :         Relation        rel;
    3783                 :           0 :         HeapTuple       tup;
    3784                 :           0 :         Form_pg_type typTup;
    3785                 :             :         ObjectAddress address;
    3786                 :             : 
    3787                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    3788                 :           0 :         typename = makeTypeNameFromNameList(names);
    3789                 :           0 :         typeOid = typenameTypeId(NULL, typename);
    3790                 :             : 
    3791                 :             :         /* Look up the type in the type table */
    3792                 :           0 :         rel = table_open(TypeRelationId, RowExclusiveLock);
    3793                 :             : 
    3794                 :           0 :         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
    3795         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    3796   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", typeOid);
    3797                 :           0 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    3798                 :             : 
    3799                 :             :         /* check permissions on type */
    3800         [ #  # ]:           0 :         if (!object_ownercheck(TypeRelationId, typeOid, GetUserId()))
    3801                 :           0 :                 aclcheck_error_type(ACLCHECK_NOT_OWNER, typeOid);
    3802                 :             : 
    3803                 :             :         /* ALTER DOMAIN used on a non-domain? */
    3804   [ #  #  #  # ]:           0 :         if (stmt->renameType == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
    3805   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3806                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    3807                 :             :                                  errmsg("%s is not a domain",
    3808                 :             :                                                 format_type_be(typeOid))));
    3809                 :             : 
    3810                 :             :         /*
    3811                 :             :          * If it's a composite type, we need to check that it really is a
    3812                 :             :          * free-standing composite type, and not a table's rowtype. We want people
    3813                 :             :          * to use ALTER TABLE not ALTER TYPE for that case.
    3814                 :             :          */
    3815   [ #  #  #  # ]:           0 :         if (typTup->typtype == TYPTYPE_COMPOSITE &&
    3816                 :           0 :                 get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)
    3817   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3818                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    3819                 :             :                                  errmsg("%s is a table's row type",
    3820                 :             :                                                 format_type_be(typeOid)),
    3821                 :             :                 /* translator: %s is an SQL ALTER command */
    3822                 :             :                                  errhint("Use %s instead.",
    3823                 :             :                                                  "ALTER TABLE")));
    3824                 :             : 
    3825                 :             :         /* don't allow direct alteration of array types, either */
    3826   [ #  #  #  # ]:           0 :         if (IsTrueArrayType(typTup))
    3827   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3828                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    3829                 :             :                                  errmsg("cannot alter array type %s",
    3830                 :             :                                                 format_type_be(typeOid)),
    3831                 :             :                                  errhint("You can alter type %s, which will alter the array type as well.",
    3832                 :             :                                                  format_type_be(typTup->typelem))));
    3833                 :             : 
    3834                 :             :         /* we do allow separate renaming of multirange types, though */
    3835                 :             : 
    3836                 :             :         /*
    3837                 :             :          * If type is composite we need to rename associated pg_class entry too.
    3838                 :             :          * RenameRelationInternal will call RenameTypeInternal automatically.
    3839                 :             :          */
    3840         [ #  # ]:           0 :         if (typTup->typtype == TYPTYPE_COMPOSITE)
    3841                 :           0 :                 RenameRelationInternal(typTup->typrelid, newTypeName, false, false);
    3842                 :             :         else
    3843                 :           0 :                 RenameTypeInternal(typeOid, newTypeName,
    3844                 :           0 :                                                    typTup->typnamespace);
    3845                 :             : 
    3846                 :           0 :         ObjectAddressSet(address, TypeRelationId, typeOid);
    3847                 :             :         /* Clean up */
    3848                 :           0 :         table_close(rel, RowExclusiveLock);
    3849                 :             : 
    3850                 :             :         return address;
    3851                 :           0 : }
    3852                 :             : 
    3853                 :             : /*
    3854                 :             :  * Change the owner of a type.
    3855                 :             :  */
    3856                 :             : ObjectAddress
    3857                 :           0 : AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
    3858                 :             : {
    3859                 :           0 :         TypeName   *typename;
    3860                 :           0 :         Oid                     typeOid;
    3861                 :           0 :         Relation        rel;
    3862                 :           0 :         HeapTuple       tup;
    3863                 :           0 :         HeapTuple       newtup;
    3864                 :           0 :         Form_pg_type typTup;
    3865                 :           0 :         AclResult       aclresult;
    3866                 :             :         ObjectAddress address;
    3867                 :             : 
    3868                 :           0 :         rel = table_open(TypeRelationId, RowExclusiveLock);
    3869                 :             : 
    3870                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    3871                 :           0 :         typename = makeTypeNameFromNameList(names);
    3872                 :             : 
    3873                 :             :         /* Use LookupTypeName here so that shell types can be processed */
    3874                 :           0 :         tup = LookupTypeName(NULL, typename, NULL, false);
    3875         [ #  # ]:           0 :         if (tup == NULL)
    3876   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3877                 :             :                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    3878                 :             :                                  errmsg("type \"%s\" does not exist",
    3879                 :             :                                                 TypeNameToString(typename))));
    3880                 :           0 :         typeOid = typeTypeId(tup);
    3881                 :             : 
    3882                 :             :         /* Copy the syscache entry so we can scribble on it below */
    3883                 :           0 :         newtup = heap_copytuple(tup);
    3884                 :           0 :         ReleaseSysCache(tup);
    3885                 :           0 :         tup = newtup;
    3886                 :           0 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    3887                 :             : 
    3888                 :             :         /* Don't allow ALTER DOMAIN on a type */
    3889   [ #  #  #  # ]:           0 :         if (objecttype == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
    3890   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3891                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    3892                 :             :                                  errmsg("%s is not a domain",
    3893                 :             :                                                 format_type_be(typeOid))));
    3894                 :             : 
    3895                 :             :         /*
    3896                 :             :          * If it's a composite type, we need to check that it really is a
    3897                 :             :          * free-standing composite type, and not a table's rowtype. We want people
    3898                 :             :          * to use ALTER TABLE not ALTER TYPE for that case.
    3899                 :             :          */
    3900   [ #  #  #  # ]:           0 :         if (typTup->typtype == TYPTYPE_COMPOSITE &&
    3901                 :           0 :                 get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)
    3902   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3903                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    3904                 :             :                                  errmsg("%s is a table's row type",
    3905                 :             :                                                 format_type_be(typeOid)),
    3906                 :             :                 /* translator: %s is an SQL ALTER command */
    3907                 :             :                                  errhint("Use %s instead.",
    3908                 :             :                                                  "ALTER TABLE")));
    3909                 :             : 
    3910                 :             :         /* don't allow direct alteration of array types, either */
    3911   [ #  #  #  # ]:           0 :         if (IsTrueArrayType(typTup))
    3912   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    3913                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    3914                 :             :                                  errmsg("cannot alter array type %s",
    3915                 :             :                                                 format_type_be(typeOid)),
    3916                 :             :                                  errhint("You can alter type %s, which will alter the array type as well.",
    3917                 :             :                                                  format_type_be(typTup->typelem))));
    3918                 :             : 
    3919                 :             :         /* don't allow direct alteration of multirange types, either */
    3920         [ #  # ]:           0 :         if (typTup->typtype == TYPTYPE_MULTIRANGE)
    3921                 :             :         {
    3922                 :           0 :                 Oid                     rangetype = get_multirange_range(typeOid);
    3923                 :             : 
    3924                 :             :                 /* We don't expect get_multirange_range to fail, but cope if so */
    3925   [ #  #  #  #  :           0 :                 ereport(ERROR,
                   #  # ]
    3926                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    3927                 :             :                                  errmsg("cannot alter multirange type %s",
    3928                 :             :                                                 format_type_be(typeOid)),
    3929                 :             :                                  OidIsValid(rangetype) ?
    3930                 :             :                                  errhint("You can alter type %s, which will alter the multirange type as well.",
    3931                 :             :                                                  format_type_be(rangetype)) : 0));
    3932                 :           0 :         }
    3933                 :             : 
    3934                 :             :         /*
    3935                 :             :          * If the new owner is the same as the existing owner, consider the
    3936                 :             :          * command to have succeeded.  This is for dump restoration purposes.
    3937                 :             :          */
    3938         [ #  # ]:           0 :         if (typTup->typowner != newOwnerId)
    3939                 :             :         {
    3940                 :             :                 /* Superusers can always do it */
    3941         [ #  # ]:           0 :                 if (!superuser())
    3942                 :             :                 {
    3943                 :             :                         /* Otherwise, must be owner of the existing object */
    3944         [ #  # ]:           0 :                         if (!object_ownercheck(TypeRelationId, typTup->oid, GetUserId()))
    3945                 :           0 :                                 aclcheck_error_type(ACLCHECK_NOT_OWNER, typTup->oid);
    3946                 :             : 
    3947                 :             :                         /* Must be able to become new owner */
    3948                 :           0 :                         check_can_set_role(GetUserId(), newOwnerId);
    3949                 :             : 
    3950                 :             :                         /* New owner must have CREATE privilege on namespace */
    3951                 :           0 :                         aclresult = object_aclcheck(NamespaceRelationId, typTup->typnamespace,
    3952                 :           0 :                                                                                 newOwnerId,
    3953                 :             :                                                                                 ACL_CREATE);
    3954         [ #  # ]:           0 :                         if (aclresult != ACLCHECK_OK)
    3955                 :           0 :                                 aclcheck_error(aclresult, OBJECT_SCHEMA,
    3956                 :           0 :                                                            get_namespace_name(typTup->typnamespace));
    3957                 :           0 :                 }
    3958                 :             : 
    3959                 :           0 :                 AlterTypeOwner_oid(typeOid, newOwnerId, true);
    3960                 :           0 :         }
    3961                 :             : 
    3962                 :           0 :         ObjectAddressSet(address, TypeRelationId, typeOid);
    3963                 :             : 
    3964                 :             :         /* Clean up */
    3965                 :           0 :         table_close(rel, RowExclusiveLock);
    3966                 :             : 
    3967                 :             :         return address;
    3968                 :           0 : }
    3969                 :             : 
    3970                 :             : /*
    3971                 :             :  * AlterTypeOwner_oid - change type owner unconditionally
    3972                 :             :  *
    3973                 :             :  * This function recurses to handle dependent types (arrays and multiranges).
    3974                 :             :  * It invokes any necessary access object hooks.  If hasDependEntry is true,
    3975                 :             :  * this function modifies the pg_shdepend entry appropriately (this should be
    3976                 :             :  * passed as false only for table rowtypes and dependent types).
    3977                 :             :  *
    3978                 :             :  * This is used by ALTER TABLE/TYPE OWNER commands, as well as by REASSIGN
    3979                 :             :  * OWNED BY.  It assumes the caller has done all needed checks.
    3980                 :             :  */
    3981                 :             : void
    3982                 :           0 : AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
    3983                 :             : {
    3984                 :           0 :         Relation        rel;
    3985                 :           0 :         HeapTuple       tup;
    3986                 :           0 :         Form_pg_type typTup;
    3987                 :             : 
    3988                 :           0 :         rel = table_open(TypeRelationId, RowExclusiveLock);
    3989                 :             : 
    3990                 :           0 :         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
    3991         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    3992   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", typeOid);
    3993                 :           0 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    3994                 :             : 
    3995                 :             :         /*
    3996                 :             :          * If it's a composite type, invoke ATExecChangeOwner so that we fix up
    3997                 :             :          * the pg_class entry properly.  That will call back to
    3998                 :             :          * AlterTypeOwnerInternal to take care of the pg_type entry(s).
    3999                 :             :          */
    4000         [ #  # ]:           0 :         if (typTup->typtype == TYPTYPE_COMPOSITE)
    4001                 :           0 :                 ATExecChangeOwner(typTup->typrelid, newOwnerId, true, AccessExclusiveLock);
    4002                 :             :         else
    4003                 :           0 :                 AlterTypeOwnerInternal(typeOid, newOwnerId);
    4004                 :             : 
    4005                 :             :         /* Update owner dependency reference */
    4006         [ #  # ]:           0 :         if (hasDependEntry)
    4007                 :           0 :                 changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
    4008                 :             : 
    4009         [ #  # ]:           0 :         InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
    4010                 :             : 
    4011                 :           0 :         ReleaseSysCache(tup);
    4012                 :           0 :         table_close(rel, RowExclusiveLock);
    4013                 :           0 : }
    4014                 :             : 
    4015                 :             : /*
    4016                 :             :  * AlterTypeOwnerInternal - bare-bones type owner change.
    4017                 :             :  *
    4018                 :             :  * This routine simply modifies the owner of a pg_type entry, and recurses
    4019                 :             :  * to handle any dependent types.
    4020                 :             :  */
    4021                 :             : void
    4022                 :           0 : AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
    4023                 :             : {
    4024                 :           0 :         Relation        rel;
    4025                 :           0 :         HeapTuple       tup;
    4026                 :           0 :         Form_pg_type typTup;
    4027                 :           0 :         Datum           repl_val[Natts_pg_type];
    4028                 :           0 :         bool            repl_null[Natts_pg_type];
    4029                 :           0 :         bool            repl_repl[Natts_pg_type];
    4030                 :           0 :         Acl                *newAcl;
    4031                 :           0 :         Datum           aclDatum;
    4032                 :           0 :         bool            isNull;
    4033                 :             : 
    4034                 :           0 :         rel = table_open(TypeRelationId, RowExclusiveLock);
    4035                 :             : 
    4036                 :           0 :         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
    4037         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    4038   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", typeOid);
    4039                 :           0 :         typTup = (Form_pg_type) GETSTRUCT(tup);
    4040                 :             : 
    4041                 :           0 :         memset(repl_null, false, sizeof(repl_null));
    4042                 :           0 :         memset(repl_repl, false, sizeof(repl_repl));
    4043                 :             : 
    4044                 :           0 :         repl_repl[Anum_pg_type_typowner - 1] = true;
    4045                 :           0 :         repl_val[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(newOwnerId);
    4046                 :             : 
    4047                 :           0 :         aclDatum = heap_getattr(tup,
    4048                 :             :                                                         Anum_pg_type_typacl,
    4049                 :           0 :                                                         RelationGetDescr(rel),
    4050                 :             :                                                         &isNull);
    4051                 :             :         /* Null ACLs do not require changes */
    4052         [ #  # ]:           0 :         if (!isNull)
    4053                 :             :         {
    4054                 :           0 :                 newAcl = aclnewowner(DatumGetAclP(aclDatum),
    4055                 :           0 :                                                          typTup->typowner, newOwnerId);
    4056                 :           0 :                 repl_repl[Anum_pg_type_typacl - 1] = true;
    4057                 :           0 :                 repl_val[Anum_pg_type_typacl - 1] = PointerGetDatum(newAcl);
    4058                 :           0 :         }
    4059                 :             : 
    4060                 :           0 :         tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
    4061                 :           0 :                                                         repl_repl);
    4062                 :             : 
    4063                 :           0 :         CatalogTupleUpdate(rel, &tup->t_self, tup);
    4064                 :             : 
    4065                 :             :         /* If it has an array type, update that too */
    4066         [ #  # ]:           0 :         if (OidIsValid(typTup->typarray))
    4067                 :           0 :                 AlterTypeOwnerInternal(typTup->typarray, newOwnerId);
    4068                 :             : 
    4069                 :             :         /* If it is a range type, update the associated multirange too */
    4070         [ #  # ]:           0 :         if (typTup->typtype == TYPTYPE_RANGE)
    4071                 :             :         {
    4072                 :           0 :                 Oid                     multirange_typeid = get_range_multirange(typeOid);
    4073                 :             : 
    4074         [ #  # ]:           0 :                 if (!OidIsValid(multirange_typeid))
    4075   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4076                 :             :                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
    4077                 :             :                                          errmsg("could not find multirange type for data type %s",
    4078                 :             :                                                         format_type_be(typeOid))));
    4079                 :           0 :                 AlterTypeOwnerInternal(multirange_typeid, newOwnerId);
    4080                 :           0 :         }
    4081                 :             : 
    4082                 :             :         /* Clean up */
    4083                 :           0 :         table_close(rel, RowExclusiveLock);
    4084                 :           0 : }
    4085                 :             : 
    4086                 :             : /*
    4087                 :             :  * Execute ALTER TYPE SET SCHEMA
    4088                 :             :  */
    4089                 :             : ObjectAddress
    4090                 :           0 : AlterTypeNamespace(List *names, const char *newschema, ObjectType objecttype,
    4091                 :             :                                    Oid *oldschema)
    4092                 :             : {
    4093                 :           0 :         TypeName   *typename;
    4094                 :           0 :         Oid                     typeOid;
    4095                 :           0 :         Oid                     nspOid;
    4096                 :           0 :         Oid                     oldNspOid;
    4097                 :           0 :         ObjectAddresses *objsMoved;
    4098                 :             :         ObjectAddress myself;
    4099                 :             : 
    4100                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    4101                 :           0 :         typename = makeTypeNameFromNameList(names);
    4102                 :           0 :         typeOid = typenameTypeId(NULL, typename);
    4103                 :             : 
    4104                 :             :         /* Don't allow ALTER DOMAIN on a non-domain type */
    4105   [ #  #  #  # ]:           0 :         if (objecttype == OBJECT_DOMAIN && get_typtype(typeOid) != TYPTYPE_DOMAIN)
    4106   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4107                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    4108                 :             :                                  errmsg("%s is not a domain",
    4109                 :             :                                                 format_type_be(typeOid))));
    4110                 :             : 
    4111                 :             :         /* get schema OID and check its permissions */
    4112                 :           0 :         nspOid = LookupCreationNamespace(newschema);
    4113                 :             : 
    4114                 :           0 :         objsMoved = new_object_addresses();
    4115                 :           0 :         oldNspOid = AlterTypeNamespace_oid(typeOid, nspOid, false, objsMoved);
    4116                 :           0 :         free_object_addresses(objsMoved);
    4117                 :             : 
    4118         [ #  # ]:           0 :         if (oldschema)
    4119                 :           0 :                 *oldschema = oldNspOid;
    4120                 :             : 
    4121                 :           0 :         ObjectAddressSet(myself, TypeRelationId, typeOid);
    4122                 :             : 
    4123                 :             :         return myself;
    4124                 :           0 : }
    4125                 :             : 
    4126                 :             : /*
    4127                 :             :  * ALTER TYPE SET SCHEMA, where the caller has already looked up the OIDs
    4128                 :             :  * of the type and the target schema and checked the schema's privileges.
    4129                 :             :  *
    4130                 :             :  * If ignoreDependent is true, we silently ignore dependent types
    4131                 :             :  * (array types and table rowtypes) rather than raising errors.
    4132                 :             :  *
    4133                 :             :  * This entry point is exported for use by AlterObjectNamespace_oid,
    4134                 :             :  * which doesn't want errors when it passes OIDs of dependent types.
    4135                 :             :  *
    4136                 :             :  * Returns the type's old namespace OID, or InvalidOid if we did nothing.
    4137                 :             :  */
    4138                 :             : Oid
    4139                 :           0 : AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, bool ignoreDependent,
    4140                 :             :                                            ObjectAddresses *objsMoved)
    4141                 :             : {
    4142                 :           0 :         Oid                     elemOid;
    4143                 :             : 
    4144                 :             :         /* check permissions on type */
    4145         [ #  # ]:           0 :         if (!object_ownercheck(TypeRelationId, typeOid, GetUserId()))
    4146                 :           0 :                 aclcheck_error_type(ACLCHECK_NOT_OWNER, typeOid);
    4147                 :             : 
    4148                 :             :         /* don't allow direct alteration of array types */
    4149                 :           0 :         elemOid = get_element_type(typeOid);
    4150   [ #  #  #  # ]:           0 :         if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid)
    4151                 :             :         {
    4152         [ #  # ]:           0 :                 if (ignoreDependent)
    4153                 :           0 :                         return InvalidOid;
    4154   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4155                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    4156                 :             :                                  errmsg("cannot alter array type %s",
    4157                 :             :                                                 format_type_be(typeOid)),
    4158                 :             :                                  errhint("You can alter type %s, which will alter the array type as well.",
    4159                 :             :                                                  format_type_be(elemOid))));
    4160                 :           0 :         }
    4161                 :             : 
    4162                 :             :         /* and do the work */
    4163                 :           0 :         return AlterTypeNamespaceInternal(typeOid, nspOid,
    4164                 :             :                                                                           false,        /* isImplicitArray */
    4165                 :           0 :                                                                           ignoreDependent,      /* ignoreDependent */
    4166                 :             :                                                                           true, /* errorOnTableType */
    4167                 :           0 :                                                                           objsMoved);
    4168                 :           0 : }
    4169                 :             : 
    4170                 :             : /*
    4171                 :             :  * Move specified type to new namespace.
    4172                 :             :  *
    4173                 :             :  * Caller must have already checked privileges.
    4174                 :             :  *
    4175                 :             :  * The function automatically recurses to process the type's array type,
    4176                 :             :  * if any.  isImplicitArray should be true only when doing this internal
    4177                 :             :  * recursion (outside callers must never try to move an array type directly).
    4178                 :             :  *
    4179                 :             :  * If ignoreDependent is true, we silently don't process table types.
    4180                 :             :  *
    4181                 :             :  * If errorOnTableType is true, the function errors out if the type is
    4182                 :             :  * a table type.  ALTER TABLE has to be used to move a table to a new
    4183                 :             :  * namespace.  (This flag is ignored if ignoreDependent is true.)
    4184                 :             :  *
    4185                 :             :  * We also do nothing if the type is already listed in *objsMoved.
    4186                 :             :  * After a successful move, we add the type to *objsMoved.
    4187                 :             :  *
    4188                 :             :  * Returns the type's old namespace OID, or InvalidOid if we did nothing.
    4189                 :             :  */
    4190                 :             : Oid
    4191                 :           0 : AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
    4192                 :             :                                                    bool isImplicitArray,
    4193                 :             :                                                    bool ignoreDependent,
    4194                 :             :                                                    bool errorOnTableType,
    4195                 :             :                                                    ObjectAddresses *objsMoved)
    4196                 :             : {
    4197                 :           0 :         Relation        rel;
    4198                 :           0 :         HeapTuple       tup;
    4199                 :           0 :         Form_pg_type typform;
    4200                 :           0 :         Oid                     oldNspOid;
    4201                 :           0 :         Oid                     arrayOid;
    4202                 :           0 :         bool            isCompositeType;
    4203                 :           0 :         ObjectAddress thisobj;
    4204                 :             : 
    4205                 :             :         /*
    4206                 :             :          * Make sure we haven't moved this object previously.
    4207                 :             :          */
    4208                 :           0 :         thisobj.classId = TypeRelationId;
    4209                 :           0 :         thisobj.objectId = typeOid;
    4210                 :           0 :         thisobj.objectSubId = 0;
    4211                 :             : 
    4212         [ #  # ]:           0 :         if (object_address_present(&thisobj, objsMoved))
    4213                 :           0 :                 return InvalidOid;
    4214                 :             : 
    4215                 :           0 :         rel = table_open(TypeRelationId, RowExclusiveLock);
    4216                 :             : 
    4217                 :           0 :         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
    4218         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
    4219   [ #  #  #  # ]:           0 :                 elog(ERROR, "cache lookup failed for type %u", typeOid);
    4220                 :           0 :         typform = (Form_pg_type) GETSTRUCT(tup);
    4221                 :             : 
    4222                 :           0 :         oldNspOid = typform->typnamespace;
    4223                 :           0 :         arrayOid = typform->typarray;
    4224                 :             : 
    4225                 :             :         /* If the type is already there, we scan skip these next few checks. */
    4226         [ #  # ]:           0 :         if (oldNspOid != nspOid)
    4227                 :             :         {
    4228                 :             :                 /* common checks on switching namespaces */
    4229                 :           0 :                 CheckSetNamespace(oldNspOid, nspOid);
    4230                 :             : 
    4231                 :             :                 /* check for duplicate name (more friendly than unique-index failure) */
    4232         [ #  # ]:           0 :                 if (SearchSysCacheExists2(TYPENAMENSP,
    4233                 :             :                                                                   NameGetDatum(&typform->typname),
    4234                 :             :                                                                   ObjectIdGetDatum(nspOid)))
    4235   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4236                 :             :                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
    4237                 :             :                                          errmsg("type \"%s\" already exists in schema \"%s\"",
    4238                 :             :                                                         NameStr(typform->typname),
    4239                 :             :                                                         get_namespace_name(nspOid))));
    4240                 :           0 :         }
    4241                 :             : 
    4242                 :             :         /* Detect whether type is a composite type (but not a table rowtype) */
    4243                 :           0 :         isCompositeType =
    4244         [ #  # ]:           0 :                 (typform->typtype == TYPTYPE_COMPOSITE &&
    4245                 :           0 :                  get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);
    4246                 :             : 
    4247                 :             :         /* Enforce not-table-type if requested */
    4248   [ #  #  #  # ]:           0 :         if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType)
    4249                 :             :         {
    4250         [ #  # ]:           0 :                 if (ignoreDependent)
    4251                 :             :                 {
    4252                 :           0 :                         table_close(rel, RowExclusiveLock);
    4253                 :           0 :                         return InvalidOid;
    4254                 :             :                 }
    4255         [ #  # ]:           0 :                 if (errorOnTableType)
    4256   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4257                 :             :                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    4258                 :             :                                          errmsg("%s is a table's row type",
    4259                 :             :                                                         format_type_be(typeOid)),
    4260                 :             :                         /* translator: %s is an SQL ALTER command */
    4261                 :             :                                          errhint("Use %s instead.", "ALTER TABLE")));
    4262                 :           0 :         }
    4263                 :             : 
    4264         [ #  # ]:           0 :         if (oldNspOid != nspOid)
    4265                 :             :         {
    4266                 :             :                 /* OK, modify the pg_type row */
    4267                 :             : 
    4268                 :             :                 /* tup is a copy, so we can scribble directly on it */
    4269                 :           0 :                 typform->typnamespace = nspOid;
    4270                 :             : 
    4271                 :           0 :                 CatalogTupleUpdate(rel, &tup->t_self, tup);
    4272                 :           0 :         }
    4273                 :             : 
    4274                 :             :         /*
    4275                 :             :          * Composite types have pg_class entries.
    4276                 :             :          *
    4277                 :             :          * We need to modify the pg_class tuple as well to reflect the change of
    4278                 :             :          * schema.
    4279                 :             :          */
    4280         [ #  # ]:           0 :         if (isCompositeType)
    4281                 :             :         {
    4282                 :           0 :                 Relation        classRel;
    4283                 :             : 
    4284                 :           0 :                 classRel = table_open(RelationRelationId, RowExclusiveLock);
    4285                 :             : 
    4286                 :           0 :                 AlterRelationNamespaceInternal(classRel, typform->typrelid,
    4287                 :           0 :                                                                            oldNspOid, nspOid,
    4288                 :           0 :                                                                            false, objsMoved);
    4289                 :             : 
    4290                 :           0 :                 table_close(classRel, RowExclusiveLock);
    4291                 :             : 
    4292                 :             :                 /*
    4293                 :             :                  * Check for constraints associated with the composite type (we don't
    4294                 :             :                  * currently support this, but probably will someday).
    4295                 :             :                  */
    4296                 :           0 :                 AlterConstraintNamespaces(typform->typrelid, oldNspOid,
    4297                 :           0 :                                                                   nspOid, false, objsMoved);
    4298                 :           0 :         }
    4299                 :             :         else
    4300                 :             :         {
    4301                 :             :                 /* If it's a domain, it might have constraints */
    4302         [ #  # ]:           0 :                 if (typform->typtype == TYPTYPE_DOMAIN)
    4303                 :           0 :                         AlterConstraintNamespaces(typeOid, oldNspOid, nspOid, true,
    4304                 :           0 :                                                                           objsMoved);
    4305                 :             :         }
    4306                 :             : 
    4307                 :             :         /*
    4308                 :             :          * Update dependency on schema, if any --- a table rowtype has not got
    4309                 :             :          * one, and neither does an implicit array.
    4310                 :             :          */
    4311         [ #  # ]:           0 :         if (oldNspOid != nspOid &&
    4312   [ #  #  #  # ]:           0 :                 (isCompositeType || typform->typtype != TYPTYPE_COMPOSITE) &&
    4313                 :           0 :                 !isImplicitArray)
    4314                 :           0 :                 if (changeDependencyFor(TypeRelationId, typeOid,
    4315   [ #  #  #  # ]:           0 :                                                                 NamespaceRelationId, oldNspOid, nspOid) != 1)
    4316   [ #  #  #  # ]:           0 :                         elog(ERROR, "could not change schema dependency for type \"%s\"",
    4317                 :             :                                  format_type_be(typeOid));
    4318                 :             : 
    4319         [ #  # ]:           0 :         InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
    4320                 :             : 
    4321                 :           0 :         heap_freetuple(tup);
    4322                 :             : 
    4323                 :           0 :         table_close(rel, RowExclusiveLock);
    4324                 :             : 
    4325                 :           0 :         add_exact_object_address(&thisobj, objsMoved);
    4326                 :             : 
    4327                 :             :         /* Recursively alter the associated array type, if any */
    4328         [ #  # ]:           0 :         if (OidIsValid(arrayOid))
    4329                 :           0 :                 AlterTypeNamespaceInternal(arrayOid, nspOid,
    4330                 :             :                                                                    true,        /* isImplicitArray */
    4331                 :             :                                                                    false,       /* ignoreDependent */
    4332                 :             :                                                                    true,        /* errorOnTableType */
    4333                 :           0 :                                                                    objsMoved);
    4334                 :             : 
    4335                 :           0 :         return oldNspOid;
    4336                 :           0 : }
    4337                 :             : 
    4338                 :             : /*
    4339                 :             :  * AlterType
    4340                 :             :  *              ALTER TYPE <type> SET (option = ...)
    4341                 :             :  *
    4342                 :             :  * NOTE: the set of changes that can be allowed here is constrained by many
    4343                 :             :  * non-obvious implementation restrictions.  Tread carefully when considering
    4344                 :             :  * adding new flexibility.
    4345                 :             :  */
    4346                 :             : ObjectAddress
    4347                 :           0 : AlterType(AlterTypeStmt *stmt)
    4348                 :             : {
    4349                 :             :         ObjectAddress address;
    4350                 :           0 :         Relation        catalog;
    4351                 :           0 :         TypeName   *typename;
    4352                 :           0 :         HeapTuple       tup;
    4353                 :           0 :         Oid                     typeOid;
    4354                 :           0 :         Form_pg_type typForm;
    4355                 :           0 :         bool            requireSuper = false;
    4356                 :           0 :         AlterTypeRecurseParams atparams;
    4357                 :           0 :         ListCell   *pl;
    4358                 :             : 
    4359                 :           0 :         catalog = table_open(TypeRelationId, RowExclusiveLock);
    4360                 :             : 
    4361                 :             :         /* Make a TypeName so we can use standard type lookup machinery */
    4362                 :           0 :         typename = makeTypeNameFromNameList(stmt->typeName);
    4363                 :           0 :         tup = typenameType(NULL, typename, NULL);
    4364                 :             : 
    4365                 :           0 :         typeOid = typeTypeId(tup);
    4366                 :           0 :         typForm = (Form_pg_type) GETSTRUCT(tup);
    4367                 :             : 
    4368                 :             :         /* Process options */
    4369                 :           0 :         memset(&atparams, 0, sizeof(atparams));
    4370   [ #  #  #  #  :           0 :         foreach(pl, stmt->options)
                   #  # ]
    4371                 :             :         {
    4372                 :           0 :                 DefElem    *defel = (DefElem *) lfirst(pl);
    4373                 :             : 
    4374         [ #  # ]:           0 :                 if (strcmp(defel->defname, "storage") == 0)
    4375                 :             :                 {
    4376                 :           0 :                         char       *a = defGetString(defel);
    4377                 :             : 
    4378         [ #  # ]:           0 :                         if (pg_strcasecmp(a, "plain") == 0)
    4379                 :           0 :                                 atparams.storage = TYPSTORAGE_PLAIN;
    4380         [ #  # ]:           0 :                         else if (pg_strcasecmp(a, "external") == 0)
    4381                 :           0 :                                 atparams.storage = TYPSTORAGE_EXTERNAL;
    4382         [ #  # ]:           0 :                         else if (pg_strcasecmp(a, "extended") == 0)
    4383                 :           0 :                                 atparams.storage = TYPSTORAGE_EXTENDED;
    4384         [ #  # ]:           0 :                         else if (pg_strcasecmp(a, "main") == 0)
    4385                 :           0 :                                 atparams.storage = TYPSTORAGE_MAIN;
    4386                 :             :                         else
    4387   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    4388                 :             :                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4389                 :             :                                                  errmsg("storage \"%s\" not recognized", a)));
    4390                 :             : 
    4391                 :             :                         /*
    4392                 :             :                          * Validate the storage request.  If the type isn't varlena, it
    4393                 :             :                          * certainly doesn't support non-PLAIN storage.
    4394                 :             :                          */
    4395   [ #  #  #  # ]:           0 :                         if (atparams.storage != TYPSTORAGE_PLAIN && typForm->typlen != -1)
    4396   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    4397                 :             :                                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    4398                 :             :                                                  errmsg("fixed-size types must have storage PLAIN")));
    4399                 :             : 
    4400                 :             :                         /*
    4401                 :             :                          * Switching from PLAIN to non-PLAIN is allowed, but it requires
    4402                 :             :                          * superuser, since we can't validate that the type's C functions
    4403                 :             :                          * will support it.  Switching from non-PLAIN to PLAIN is
    4404                 :             :                          * disallowed outright, because it's not practical to ensure that
    4405                 :             :                          * no tables have toasted values of the type.  Switching among
    4406                 :             :                          * different non-PLAIN settings is OK, since it just constitutes a
    4407                 :             :                          * change in the strategy requested for columns created in the
    4408                 :             :                          * future.
    4409                 :             :                          */
    4410   [ #  #  #  # ]:           0 :                         if (atparams.storage != TYPSTORAGE_PLAIN &&
    4411                 :           0 :                                 typForm->typstorage == TYPSTORAGE_PLAIN)
    4412                 :           0 :                                 requireSuper = true;
    4413   [ #  #  #  # ]:           0 :                         else if (atparams.storage == TYPSTORAGE_PLAIN &&
    4414                 :           0 :                                          typForm->typstorage != TYPSTORAGE_PLAIN)
    4415   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    4416                 :             :                                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    4417                 :             :                                                  errmsg("cannot change type's storage to PLAIN")));
    4418                 :             : 
    4419                 :           0 :                         atparams.updateStorage = true;
    4420                 :           0 :                 }
    4421         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "receive") == 0)
    4422                 :             :                 {
    4423         [ #  # ]:           0 :                         if (defel->arg != NULL)
    4424                 :           0 :                                 atparams.receiveOid =
    4425                 :           0 :                                         findTypeReceiveFunction(defGetQualifiedName(defel),
    4426                 :           0 :                                                                                         typeOid);
    4427                 :             :                         else
    4428                 :           0 :                                 atparams.receiveOid = InvalidOid;       /* NONE, remove function */
    4429                 :           0 :                         atparams.updateReceive = true;
    4430                 :             :                         /* Replacing an I/O function requires superuser. */
    4431                 :           0 :                         requireSuper = true;
    4432                 :           0 :                 }
    4433         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "send") == 0)
    4434                 :             :                 {
    4435         [ #  # ]:           0 :                         if (defel->arg != NULL)
    4436                 :           0 :                                 atparams.sendOid =
    4437                 :           0 :                                         findTypeSendFunction(defGetQualifiedName(defel),
    4438                 :           0 :                                                                                  typeOid);
    4439                 :             :                         else
    4440                 :           0 :                                 atparams.sendOid = InvalidOid;  /* NONE, remove function */
    4441                 :           0 :                         atparams.updateSend = true;
    4442                 :             :                         /* Replacing an I/O function requires superuser. */
    4443                 :           0 :                         requireSuper = true;
    4444                 :           0 :                 }
    4445         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "typmod_in") == 0)
    4446                 :             :                 {
    4447         [ #  # ]:           0 :                         if (defel->arg != NULL)
    4448                 :           0 :                                 atparams.typmodinOid =
    4449                 :           0 :                                         findTypeTypmodinFunction(defGetQualifiedName(defel));
    4450                 :             :                         else
    4451                 :           0 :                                 atparams.typmodinOid = InvalidOid;      /* NONE, remove function */
    4452                 :           0 :                         atparams.updateTypmodin = true;
    4453                 :             :                         /* Replacing an I/O function requires superuser. */
    4454                 :           0 :                         requireSuper = true;
    4455                 :           0 :                 }
    4456         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "typmod_out") == 0)
    4457                 :             :                 {
    4458         [ #  # ]:           0 :                         if (defel->arg != NULL)
    4459                 :           0 :                                 atparams.typmodoutOid =
    4460                 :           0 :                                         findTypeTypmodoutFunction(defGetQualifiedName(defel));
    4461                 :             :                         else
    4462                 :           0 :                                 atparams.typmodoutOid = InvalidOid; /* NONE, remove function */
    4463                 :           0 :                         atparams.updateTypmodout = true;
    4464                 :             :                         /* Replacing an I/O function requires superuser. */
    4465                 :           0 :                         requireSuper = true;
    4466                 :           0 :                 }
    4467         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "analyze") == 0)
    4468                 :             :                 {
    4469         [ #  # ]:           0 :                         if (defel->arg != NULL)
    4470                 :           0 :                                 atparams.analyzeOid =
    4471                 :           0 :                                         findTypeAnalyzeFunction(defGetQualifiedName(defel),
    4472                 :           0 :                                                                                         typeOid);
    4473                 :             :                         else
    4474                 :           0 :                                 atparams.analyzeOid = InvalidOid;       /* NONE, remove function */
    4475                 :           0 :                         atparams.updateAnalyze = true;
    4476                 :             :                         /* Replacing an analyze function requires superuser. */
    4477                 :           0 :                         requireSuper = true;
    4478                 :           0 :                 }
    4479         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "subscript") == 0)
    4480                 :             :                 {
    4481         [ #  # ]:           0 :                         if (defel->arg != NULL)
    4482                 :           0 :                                 atparams.subscriptOid =
    4483                 :           0 :                                         findTypeSubscriptingFunction(defGetQualifiedName(defel),
    4484                 :           0 :                                                                                                  typeOid);
    4485                 :             :                         else
    4486                 :           0 :                                 atparams.subscriptOid = InvalidOid; /* NONE, remove function */
    4487                 :           0 :                         atparams.updateSubscript = true;
    4488                 :             :                         /* Replacing a subscript function requires superuser. */
    4489                 :           0 :                         requireSuper = true;
    4490                 :           0 :                 }
    4491                 :             : 
    4492                 :             :                 /*
    4493                 :             :                  * The rest of the options that CREATE accepts cannot be changed.
    4494                 :             :                  * Check for them so that we can give a meaningful error message.
    4495                 :             :                  */
    4496         [ #  # ]:           0 :                 else if (strcmp(defel->defname, "input") == 0 ||
    4497         [ #  # ]:           0 :                                  strcmp(defel->defname, "output") == 0 ||
    4498         [ #  # ]:           0 :                                  strcmp(defel->defname, "internallength") == 0 ||
    4499         [ #  # ]:           0 :                                  strcmp(defel->defname, "passedbyvalue") == 0 ||
    4500         [ #  # ]:           0 :                                  strcmp(defel->defname, "alignment") == 0 ||
    4501         [ #  # ]:           0 :                                  strcmp(defel->defname, "like") == 0 ||
    4502         [ #  # ]:           0 :                                  strcmp(defel->defname, "category") == 0 ||
    4503         [ #  # ]:           0 :                                  strcmp(defel->defname, "preferred") == 0 ||
    4504         [ #  # ]:           0 :                                  strcmp(defel->defname, "default") == 0 ||
    4505         [ #  # ]:           0 :                                  strcmp(defel->defname, "element") == 0 ||
    4506   [ #  #  #  # ]:           0 :                                  strcmp(defel->defname, "delimiter") == 0 ||
    4507                 :           0 :                                  strcmp(defel->defname, "collatable") == 0)
    4508   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4509                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
    4510                 :             :                                          errmsg("type attribute \"%s\" cannot be changed",
    4511                 :             :                                                         defel->defname)));
    4512                 :             :                 else
    4513   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4514                 :             :                                         (errcode(ERRCODE_SYNTAX_ERROR),
    4515                 :             :                                          errmsg("type attribute \"%s\" not recognized",
    4516                 :             :                                                         defel->defname)));
    4517                 :           0 :         }
    4518                 :             : 
    4519                 :             :         /*
    4520                 :             :          * Permissions check.  Require superuser if we decided the command
    4521                 :             :          * requires that, else must own the type.
    4522                 :             :          */
    4523         [ #  # ]:           0 :         if (requireSuper)
    4524                 :             :         {
    4525         [ #  # ]:           0 :                 if (!superuser())
    4526   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    4527                 :             :                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    4528                 :             :                                          errmsg("must be superuser to alter a type")));
    4529                 :           0 :         }
    4530                 :             :         else
    4531                 :             :         {
    4532         [ #  # ]:           0 :                 if (!object_ownercheck(TypeRelationId, typeOid, GetUserId()))
    4533                 :           0 :                         aclcheck_error_type(ACLCHECK_NOT_OWNER, typeOid);
    4534                 :             :         }
    4535                 :             : 
    4536                 :             :         /*
    4537                 :             :          * We disallow all forms of ALTER TYPE SET on types that aren't plain base
    4538                 :             :          * types.  It would for example be highly unsafe, not to mention
    4539                 :             :          * pointless, to change the send/receive functions for a composite type.
    4540                 :             :          * Moreover, pg_dump has no support for changing these properties on
    4541                 :             :          * non-base types.  We might weaken this someday, but not now.
    4542                 :             :          *
    4543                 :             :          * Note: if you weaken this enough to allow composite types, be sure to
    4544                 :             :          * adjust the GenerateTypeDependencies call in AlterTypeRecurse.
    4545                 :             :          */
    4546         [ #  # ]:           0 :         if (typForm->typtype != TYPTYPE_BASE)
    4547   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4548                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    4549                 :             :                                  errmsg("%s is not a base type",
    4550                 :             :                                                 format_type_be(typeOid))));
    4551                 :             : 
    4552                 :             :         /*
    4553                 :             :          * For the same reasons, don't allow direct alteration of array types.
    4554                 :             :          */
    4555   [ #  #  #  # ]:           0 :         if (IsTrueArrayType(typForm))
    4556   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    4557                 :             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    4558                 :             :                                  errmsg("%s is not a base type",
    4559                 :             :                                                 format_type_be(typeOid))));
    4560                 :             : 
    4561                 :             :         /* OK, recursively update this type and any arrays/domains over it */
    4562                 :           0 :         AlterTypeRecurse(typeOid, false, tup, catalog, &atparams);
    4563                 :             : 
    4564                 :             :         /* Clean up */
    4565                 :           0 :         ReleaseSysCache(tup);
    4566                 :             : 
    4567                 :           0 :         table_close(catalog, RowExclusiveLock);
    4568                 :             : 
    4569                 :           0 :         ObjectAddressSet(address, TypeRelationId, typeOid);
    4570                 :             : 
    4571                 :             :         return address;
    4572                 :           0 : }
    4573                 :             : 
    4574                 :             : /*
    4575                 :             :  * AlterTypeRecurse: one recursion step for AlterType()
    4576                 :             :  *
    4577                 :             :  * Apply the changes specified by "atparams" to the type identified by
    4578                 :             :  * "typeOid", whose existing pg_type tuple is "tup".  If necessary,
    4579                 :             :  * recursively update its array type as well.  Then search for any domains
    4580                 :             :  * over this type, and recursively apply (most of) the same changes to those
    4581                 :             :  * domains.
    4582                 :             :  *
    4583                 :             :  * We need this because the system generally assumes that a domain inherits
    4584                 :             :  * many properties from its base type.  See DefineDomain() above for details
    4585                 :             :  * of what is inherited.  Arrays inherit a smaller number of properties,
    4586                 :             :  * but not none.
    4587                 :             :  *
    4588                 :             :  * There's a race condition here, in that some other transaction could
    4589                 :             :  * concurrently add another domain atop this base type; we'd miss updating
    4590                 :             :  * that one.  Hence, be wary of allowing ALTER TYPE to change properties for
    4591                 :             :  * which it'd be really fatal for a domain to be out of sync with its base
    4592                 :             :  * type (typlen, for example).  In practice, races seem unlikely to be an
    4593                 :             :  * issue for plausible use-cases for ALTER TYPE.  If one does happen, it could
    4594                 :             :  * be fixed by re-doing the same ALTER TYPE once all prior transactions have
    4595                 :             :  * committed.
    4596                 :             :  */
    4597                 :             : static void
    4598                 :           0 : AlterTypeRecurse(Oid typeOid, bool isImplicitArray,
    4599                 :             :                                  HeapTuple tup, Relation catalog,
    4600                 :             :                                  AlterTypeRecurseParams *atparams)
    4601                 :             : {
    4602                 :           0 :         Datum           values[Natts_pg_type];
    4603                 :           0 :         bool            nulls[Natts_pg_type];
    4604                 :           0 :         bool            replaces[Natts_pg_type];
    4605                 :           0 :         HeapTuple       newtup;
    4606                 :           0 :         SysScanDesc scan;
    4607                 :           0 :         ScanKeyData key[1];
    4608                 :           0 :         HeapTuple       domainTup;
    4609                 :             : 
    4610                 :             :         /* Since this function recurses, it could be driven to stack overflow */
    4611                 :           0 :         check_stack_depth();
    4612                 :             : 
    4613                 :             :         /* Update the current type's tuple */
    4614                 :           0 :         memset(values, 0, sizeof(values));
    4615                 :           0 :         memset(nulls, 0, sizeof(nulls));
    4616                 :           0 :         memset(replaces, 0, sizeof(replaces));
    4617                 :             : 
    4618         [ #  # ]:           0 :         if (atparams->updateStorage)
    4619                 :             :         {
    4620                 :           0 :                 replaces[Anum_pg_type_typstorage - 1] = true;
    4621                 :           0 :                 values[Anum_pg_type_typstorage - 1] = CharGetDatum(atparams->storage);
    4622                 :           0 :         }
    4623         [ #  # ]:           0 :         if (atparams->updateReceive)
    4624                 :             :         {
    4625                 :           0 :                 replaces[Anum_pg_type_typreceive - 1] = true;
    4626                 :           0 :                 values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(atparams->receiveOid);
    4627                 :           0 :         }
    4628         [ #  # ]:           0 :         if (atparams->updateSend)
    4629                 :             :         {
    4630                 :           0 :                 replaces[Anum_pg_type_typsend - 1] = true;
    4631                 :           0 :                 values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(atparams->sendOid);
    4632                 :           0 :         }
    4633         [ #  # ]:           0 :         if (atparams->updateTypmodin)
    4634                 :             :         {
    4635                 :           0 :                 replaces[Anum_pg_type_typmodin - 1] = true;
    4636                 :           0 :                 values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(atparams->typmodinOid);
    4637                 :           0 :         }
    4638         [ #  # ]:           0 :         if (atparams->updateTypmodout)
    4639                 :             :         {
    4640                 :           0 :                 replaces[Anum_pg_type_typmodout - 1] = true;
    4641                 :           0 :                 values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(atparams->typmodoutOid);
    4642                 :           0 :         }
    4643         [ #  # ]:           0 :         if (atparams->updateAnalyze)
    4644                 :             :         {
    4645                 :           0 :                 replaces[Anum_pg_type_typanalyze - 1] = true;
    4646                 :           0 :                 values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(atparams->analyzeOid);
    4647                 :           0 :         }
    4648         [ #  # ]:           0 :         if (atparams->updateSubscript)
    4649                 :             :         {
    4650                 :           0 :                 replaces[Anum_pg_type_typsubscript - 1] = true;
    4651                 :           0 :                 values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(atparams->subscriptOid);
    4652                 :           0 :         }
    4653                 :             : 
    4654                 :           0 :         newtup = heap_modify_tuple(tup, RelationGetDescr(catalog),
    4655                 :           0 :                                                            values, nulls, replaces);
    4656                 :             : 
    4657                 :           0 :         CatalogTupleUpdate(catalog, &newtup->t_self, newtup);
    4658                 :             : 
    4659                 :             :         /* Rebuild dependencies for this type */
    4660                 :           0 :         GenerateTypeDependencies(newtup,
    4661                 :           0 :                                                          catalog,
    4662                 :             :                                                          NULL,  /* don't have defaultExpr handy */
    4663                 :             :                                                          NULL,  /* don't have typacl handy */
    4664                 :             :                                                          0, /* we rejected composite types above */
    4665                 :           0 :                                                          isImplicitArray,       /* it might be an array */
    4666                 :           0 :                                                          isImplicitArray,       /* dependent iff it's array */
    4667                 :             :                                                          false, /* don't touch extension membership */
    4668                 :             :                                                          true);
    4669                 :             : 
    4670         [ #  # ]:           0 :         InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
    4671                 :             : 
    4672                 :             :         /*
    4673                 :             :          * Arrays inherit their base type's typmodin and typmodout, but none of
    4674                 :             :          * the other properties we're concerned with here.  Recurse to the array
    4675                 :             :          * type if needed.
    4676                 :             :          */
    4677   [ #  #  #  # ]:           0 :         if (!isImplicitArray &&
    4678         [ #  # ]:           0 :                 (atparams->updateTypmodin || atparams->updateTypmodout))
    4679                 :             :         {
    4680                 :           0 :                 Oid                     arrtypoid = ((Form_pg_type) GETSTRUCT(newtup))->typarray;
    4681                 :             : 
    4682         [ #  # ]:           0 :                 if (OidIsValid(arrtypoid))
    4683                 :             :                 {
    4684                 :           0 :                         HeapTuple       arrtup;
    4685                 :           0 :                         AlterTypeRecurseParams arrparams;
    4686                 :             : 
    4687                 :           0 :                         arrtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrtypoid));
    4688         [ #  # ]:           0 :                         if (!HeapTupleIsValid(arrtup))
    4689   [ #  #  #  # ]:           0 :                                 elog(ERROR, "cache lookup failed for type %u", arrtypoid);
    4690                 :             : 
    4691                 :           0 :                         memset(&arrparams, 0, sizeof(arrparams));
    4692                 :           0 :                         arrparams.updateTypmodin = atparams->updateTypmodin;
    4693                 :           0 :                         arrparams.updateTypmodout = atparams->updateTypmodout;
    4694                 :           0 :                         arrparams.typmodinOid = atparams->typmodinOid;
    4695                 :           0 :                         arrparams.typmodoutOid = atparams->typmodoutOid;
    4696                 :             : 
    4697                 :           0 :                         AlterTypeRecurse(arrtypoid, true, arrtup, catalog, &arrparams);
    4698                 :             : 
    4699                 :           0 :                         ReleaseSysCache(arrtup);
    4700                 :           0 :                 }
    4701                 :           0 :         }
    4702                 :             : 
    4703                 :             :         /*
    4704                 :             :          * Now we need to recurse to domains.  However, some properties are not
    4705                 :             :          * inherited by domains, so clear the update flags for those.
    4706                 :             :          */
    4707                 :           0 :         atparams->updateReceive = false;     /* domains use F_DOMAIN_RECV */
    4708                 :           0 :         atparams->updateTypmodin = false;    /* domains don't have typmods */
    4709                 :           0 :         atparams->updateTypmodout = false;
    4710                 :           0 :         atparams->updateSubscript = false;   /* domains don't have subscriptors */
    4711                 :             : 
    4712                 :             :         /* Skip the scan if nothing remains to be done */
    4713   [ #  #  #  # ]:           0 :         if (!(atparams->updateStorage ||
    4714         [ #  # ]:           0 :                   atparams->updateSend ||
    4715                 :           0 :                   atparams->updateAnalyze))
    4716                 :           0 :                 return;
    4717                 :             : 
    4718                 :             :         /* Search pg_type for possible domains over this type */
    4719                 :           0 :         ScanKeyInit(&key[0],
    4720                 :             :                                 Anum_pg_type_typbasetype,
    4721                 :             :                                 BTEqualStrategyNumber, F_OIDEQ,
    4722                 :           0 :                                 ObjectIdGetDatum(typeOid));
    4723                 :             : 
    4724                 :           0 :         scan = systable_beginscan(catalog, InvalidOid, false,
    4725                 :           0 :                                                           NULL, 1, key);
    4726                 :             : 
    4727         [ #  # ]:           0 :         while ((domainTup = systable_getnext(scan)) != NULL)
    4728                 :             :         {
    4729                 :           0 :                 Form_pg_type domainForm = (Form_pg_type) GETSTRUCT(domainTup);
    4730                 :             : 
    4731                 :             :                 /*
    4732                 :             :                  * Shouldn't have a nonzero typbasetype in a non-domain, but let's
    4733                 :             :                  * check
    4734                 :             :                  */
    4735         [ #  # ]:           0 :                 if (domainForm->typtype != TYPTYPE_DOMAIN)
    4736                 :           0 :                         continue;
    4737                 :             : 
    4738                 :           0 :                 AlterTypeRecurse(domainForm->oid, false, domainTup, catalog, atparams);
    4739         [ #  # ]:           0 :         }
    4740                 :             : 
    4741                 :           0 :         systable_endscan(scan);
    4742                 :           0 : }
        

Generated by: LCOV version 2.3.2-1