]> granicus.if.org Git - postgresql/blob - src/backend/commands/typecmds.c
Make DROP IF EXISTS more consistently not fail
[postgresql] / src / backend / commands / typecmds.c
1 /*-------------------------------------------------------------------------
2  *
3  * typecmds.c
4  *        Routines for SQL commands that manipulate types (and domains).
5  *
6  * Portions Copyright (c) 1996-2014, 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 "FooDefine" routines (in src/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/heapam.h"
36 #include "access/htup_details.h"
37 #include "access/xact.h"
38 #include "catalog/binary_upgrade.h"
39 #include "catalog/catalog.h"
40 #include "catalog/dependency.h"
41 #include "catalog/heap.h"
42 #include "catalog/indexing.h"
43 #include "catalog/objectaccess.h"
44 #include "catalog/pg_authid.h"
45 #include "catalog/pg_collation.h"
46 #include "catalog/pg_constraint.h"
47 #include "catalog/pg_depend.h"
48 #include "catalog/pg_enum.h"
49 #include "catalog/pg_language.h"
50 #include "catalog/pg_namespace.h"
51 #include "catalog/pg_proc.h"
52 #include "catalog/pg_proc_fn.h"
53 #include "catalog/pg_range.h"
54 #include "catalog/pg_type.h"
55 #include "catalog/pg_type_fn.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/planner.h"
63 #include "optimizer/var.h"
64 #include "parser/parse_coerce.h"
65 #include "parser/parse_collate.h"
66 #include "parser/parse_expr.h"
67 #include "parser/parse_func.h"
68 #include "parser/parse_type.h"
69 #include "utils/acl.h"
70 #include "utils/builtins.h"
71 #include "utils/fmgroids.h"
72 #include "utils/lsyscache.h"
73 #include "utils/memutils.h"
74 #include "utils/rel.h"
75 #include "utils/snapmgr.h"
76 #include "utils/syscache.h"
77 #include "utils/tqual.h"
78
79
80 /* result structure for get_rels_with_domain() */
81 typedef struct
82 {
83         Relation        rel;                    /* opened and locked relation */
84         int                     natts;                  /* number of attributes of interest */
85         int                *atts;                       /* attribute numbers */
86         /* atts[] is of allocated length RelationGetNumberOfAttributes(rel) */
87 } RelToCheck;
88
89 /* Potentially set by contrib/pg_upgrade_support functions */
90 Oid                     binary_upgrade_next_array_pg_type_oid = InvalidOid;
91
92 static void makeRangeConstructors(const char *name, Oid namespace,
93                                           Oid rangeOid, Oid subtype);
94 static Oid      findTypeInputFunction(List *procname, Oid typeOid);
95 static Oid      findTypeOutputFunction(List *procname, Oid typeOid);
96 static Oid      findTypeReceiveFunction(List *procname, Oid typeOid);
97 static Oid      findTypeSendFunction(List *procname, Oid typeOid);
98 static Oid      findTypeTypmodinFunction(List *procname);
99 static Oid      findTypeTypmodoutFunction(List *procname);
100 static Oid      findTypeAnalyzeFunction(List *procname, Oid typeOid);
101 static Oid      findRangeSubOpclass(List *opcname, Oid subtype);
102 static Oid      findRangeCanonicalFunction(List *procname, Oid typeOid);
103 static Oid      findRangeSubtypeDiffFunction(List *procname, Oid subtype);
104 static void validateDomainConstraint(Oid domainoid, char *ccbin);
105 static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode);
106 static void checkEnumOwner(HeapTuple tup);
107 static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
108                                         Oid baseTypeOid,
109                                         int typMod, Constraint *constr,
110                                         char *domainName);
111
112
113 /*
114  * DefineType
115  *              Registers a new base type.
116  */
117 Oid
118 DefineType(List *names, List *parameters)
119 {
120         char       *typeName;
121         Oid                     typeNamespace;
122         int16           internalLength = -1;    /* default: variable-length */
123         List       *inputName = NIL;
124         List       *outputName = NIL;
125         List       *receiveName = NIL;
126         List       *sendName = NIL;
127         List       *typmodinName = NIL;
128         List       *typmodoutName = NIL;
129         List       *analyzeName = NIL;
130         char            category = TYPCATEGORY_USER;
131         bool            preferred = false;
132         char            delimiter = DEFAULT_TYPDELIM;
133         Oid                     elemType = InvalidOid;
134         char       *defaultValue = NULL;
135         bool            byValue = false;
136         char            alignment = 'i';        /* default alignment */
137         char            storage = 'p';  /* default TOAST storage method */
138         Oid                     collation = InvalidOid;
139         DefElem    *likeTypeEl = NULL;
140         DefElem    *internalLengthEl = NULL;
141         DefElem    *inputNameEl = NULL;
142         DefElem    *outputNameEl = NULL;
143         DefElem    *receiveNameEl = NULL;
144         DefElem    *sendNameEl = NULL;
145         DefElem    *typmodinNameEl = NULL;
146         DefElem    *typmodoutNameEl = NULL;
147         DefElem    *analyzeNameEl = NULL;
148         DefElem    *categoryEl = NULL;
149         DefElem    *preferredEl = NULL;
150         DefElem    *delimiterEl = NULL;
151         DefElem    *elemTypeEl = NULL;
152         DefElem    *defaultValueEl = NULL;
153         DefElem    *byValueEl = NULL;
154         DefElem    *alignmentEl = NULL;
155         DefElem    *storageEl = NULL;
156         DefElem    *collatableEl = NULL;
157         Oid                     inputOid;
158         Oid                     outputOid;
159         Oid                     receiveOid = InvalidOid;
160         Oid                     sendOid = InvalidOid;
161         Oid                     typmodinOid = InvalidOid;
162         Oid                     typmodoutOid = InvalidOid;
163         Oid                     analyzeOid = InvalidOid;
164         char       *array_type;
165         Oid                     array_oid;
166         Oid                     typoid;
167         Oid                     resulttype;
168         ListCell   *pl;
169
170         /*
171          * As of Postgres 8.4, we require superuser privilege to create a base
172          * type.  This is simple paranoia: there are too many ways to mess up the
173          * system with an incorrect type definition (for instance, representation
174          * parameters that don't match what the C code expects).  In practice it
175          * takes superuser privilege to create the I/O functions, and so the
176          * former requirement that you own the I/O functions pretty much forced
177          * superuserness anyway.  We're just making doubly sure here.
178          *
179          * XXX re-enable NOT_USED code sections below if you remove this test.
180          */
181         if (!superuser())
182                 ereport(ERROR,
183                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
184                                  errmsg("must be superuser to create a base type")));
185
186         /* Convert list of names to a name and namespace */
187         typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
188
189 #ifdef NOT_USED
190         /* XXX this is unnecessary given the superuser check above */
191         /* Check we have creation rights in target namespace */
192         aclresult = pg_namespace_aclcheck(typeNamespace, GetUserId(), ACL_CREATE);
193         if (aclresult != ACLCHECK_OK)
194                 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
195                                            get_namespace_name(typeNamespace));
196 #endif
197
198         /*
199          * Look to see if type already exists (presumably as a shell; if not,
200          * TypeCreate will complain).
201          */
202         typoid = GetSysCacheOid2(TYPENAMENSP,
203                                                          CStringGetDatum(typeName),
204                                                          ObjectIdGetDatum(typeNamespace));
205
206         /*
207          * If it's not a shell, see if it's an autogenerated array type, and if so
208          * rename it out of the way.
209          */
210         if (OidIsValid(typoid) && get_typisdefined(typoid))
211         {
212                 if (moveArrayTypeName(typoid, typeName, typeNamespace))
213                         typoid = InvalidOid;
214         }
215
216         /*
217          * If it doesn't exist, create it as a shell, so that the OID is known for
218          * use in the I/O function definitions.
219          */
220         if (!OidIsValid(typoid))
221         {
222                 typoid = TypeShellMake(typeName, typeNamespace, GetUserId());
223                 /* Make new shell type visible for modification below */
224                 CommandCounterIncrement();
225
226                 /*
227                  * If the command was a parameterless CREATE TYPE, we're done ---
228                  * creating the shell type was all we're supposed to do.
229                  */
230                 if (parameters == NIL)
231                         return InvalidOid;
232         }
233         else
234         {
235                 /* Complain if dummy CREATE TYPE and entry already exists */
236                 if (parameters == NIL)
237                         ereport(ERROR,
238                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
239                                          errmsg("type \"%s\" already exists", typeName)));
240         }
241
242         /* Extract the parameters from the parameter list */
243         foreach(pl, parameters)
244         {
245                 DefElem    *defel = (DefElem *) lfirst(pl);
246                 DefElem   **defelp;
247
248                 if (pg_strcasecmp(defel->defname, "like") == 0)
249                         defelp = &likeTypeEl;
250                 else if (pg_strcasecmp(defel->defname, "internallength") == 0)
251                         defelp = &internalLengthEl;
252                 else if (pg_strcasecmp(defel->defname, "input") == 0)
253                         defelp = &inputNameEl;
254                 else if (pg_strcasecmp(defel->defname, "output") == 0)
255                         defelp = &outputNameEl;
256                 else if (pg_strcasecmp(defel->defname, "receive") == 0)
257                         defelp = &receiveNameEl;
258                 else if (pg_strcasecmp(defel->defname, "send") == 0)
259                         defelp = &sendNameEl;
260                 else if (pg_strcasecmp(defel->defname, "typmod_in") == 0)
261                         defelp = &typmodinNameEl;
262                 else if (pg_strcasecmp(defel->defname, "typmod_out") == 0)
263                         defelp = &typmodoutNameEl;
264                 else if (pg_strcasecmp(defel->defname, "analyze") == 0 ||
265                                  pg_strcasecmp(defel->defname, "analyse") == 0)
266                         defelp = &analyzeNameEl;
267                 else if (pg_strcasecmp(defel->defname, "category") == 0)
268                         defelp = &categoryEl;
269                 else if (pg_strcasecmp(defel->defname, "preferred") == 0)
270                         defelp = &preferredEl;
271                 else if (pg_strcasecmp(defel->defname, "delimiter") == 0)
272                         defelp = &delimiterEl;
273                 else if (pg_strcasecmp(defel->defname, "element") == 0)
274                         defelp = &elemTypeEl;
275                 else if (pg_strcasecmp(defel->defname, "default") == 0)
276                         defelp = &defaultValueEl;
277                 else if (pg_strcasecmp(defel->defname, "passedbyvalue") == 0)
278                         defelp = &byValueEl;
279                 else if (pg_strcasecmp(defel->defname, "alignment") == 0)
280                         defelp = &alignmentEl;
281                 else if (pg_strcasecmp(defel->defname, "storage") == 0)
282                         defelp = &storageEl;
283                 else if (pg_strcasecmp(defel->defname, "collatable") == 0)
284                         defelp = &collatableEl;
285                 else
286                 {
287                         /* WARNING, not ERROR, for historical backwards-compatibility */
288                         ereport(WARNING,
289                                         (errcode(ERRCODE_SYNTAX_ERROR),
290                                          errmsg("type attribute \"%s\" not recognized",
291                                                         defel->defname)));
292                         continue;
293                 }
294                 if (*defelp != NULL)
295                         ereport(ERROR,
296                                         (errcode(ERRCODE_SYNTAX_ERROR),
297                                          errmsg("conflicting or redundant options")));
298                 *defelp = defel;
299         }
300
301         /*
302          * Now interpret the options; we do this separately so that LIKE can be
303          * overridden by other options regardless of the ordering in the parameter
304          * list.
305          */
306         if (likeTypeEl)
307         {
308                 Type            likeType;
309                 Form_pg_type likeForm;
310
311                 likeType = typenameType(NULL, defGetTypeName(likeTypeEl), NULL);
312                 likeForm = (Form_pg_type) GETSTRUCT(likeType);
313                 internalLength = likeForm->typlen;
314                 byValue = likeForm->typbyval;
315                 alignment = likeForm->typalign;
316                 storage = likeForm->typstorage;
317                 ReleaseSysCache(likeType);
318         }
319         if (internalLengthEl)
320                 internalLength = defGetTypeLength(internalLengthEl);
321         if (inputNameEl)
322                 inputName = defGetQualifiedName(inputNameEl);
323         if (outputNameEl)
324                 outputName = defGetQualifiedName(outputNameEl);
325         if (receiveNameEl)
326                 receiveName = defGetQualifiedName(receiveNameEl);
327         if (sendNameEl)
328                 sendName = defGetQualifiedName(sendNameEl);
329         if (typmodinNameEl)
330                 typmodinName = defGetQualifiedName(typmodinNameEl);
331         if (typmodoutNameEl)
332                 typmodoutName = defGetQualifiedName(typmodoutNameEl);
333         if (analyzeNameEl)
334                 analyzeName = defGetQualifiedName(analyzeNameEl);
335         if (categoryEl)
336         {
337                 char       *p = defGetString(categoryEl);
338
339                 category = p[0];
340                 /* restrict to non-control ASCII */
341                 if (category < 32 || category > 126)
342                         ereport(ERROR,
343                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
344                                  errmsg("invalid type category \"%s\": must be simple ASCII",
345                                                 p)));
346         }
347         if (preferredEl)
348                 preferred = defGetBoolean(preferredEl);
349         if (delimiterEl)
350         {
351                 char       *p = defGetString(delimiterEl);
352
353                 delimiter = p[0];
354                 /* XXX shouldn't we restrict the delimiter? */
355         }
356         if (elemTypeEl)
357         {
358                 elemType = typenameTypeId(NULL, defGetTypeName(elemTypeEl));
359                 /* disallow arrays of pseudotypes */
360                 if (get_typtype(elemType) == TYPTYPE_PSEUDO)
361                         ereport(ERROR,
362                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
363                                          errmsg("array element type cannot be %s",
364                                                         format_type_be(elemType))));
365         }
366         if (defaultValueEl)
367                 defaultValue = defGetString(defaultValueEl);
368         if (byValueEl)
369                 byValue = defGetBoolean(byValueEl);
370         if (alignmentEl)
371         {
372                 char       *a = defGetString(alignmentEl);
373
374                 /*
375                  * Note: if argument was an unquoted identifier, parser will have
376                  * applied translations to it, so be prepared to recognize translated
377                  * type names as well as the nominal form.
378                  */
379                 if (pg_strcasecmp(a, "double") == 0 ||
380                         pg_strcasecmp(a, "float8") == 0 ||
381                         pg_strcasecmp(a, "pg_catalog.float8") == 0)
382                         alignment = 'd';
383                 else if (pg_strcasecmp(a, "int4") == 0 ||
384                                  pg_strcasecmp(a, "pg_catalog.int4") == 0)
385                         alignment = 'i';
386                 else if (pg_strcasecmp(a, "int2") == 0 ||
387                                  pg_strcasecmp(a, "pg_catalog.int2") == 0)
388                         alignment = 's';
389                 else if (pg_strcasecmp(a, "char") == 0 ||
390                                  pg_strcasecmp(a, "pg_catalog.bpchar") == 0)
391                         alignment = 'c';
392                 else
393                         ereport(ERROR,
394                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
395                                          errmsg("alignment \"%s\" not recognized", a)));
396         }
397         if (storageEl)
398         {
399                 char       *a = defGetString(storageEl);
400
401                 if (pg_strcasecmp(a, "plain") == 0)
402                         storage = 'p';
403                 else if (pg_strcasecmp(a, "external") == 0)
404                         storage = 'e';
405                 else if (pg_strcasecmp(a, "extended") == 0)
406                         storage = 'x';
407                 else if (pg_strcasecmp(a, "main") == 0)
408                         storage = 'm';
409                 else
410                         ereport(ERROR,
411                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
412                                          errmsg("storage \"%s\" not recognized", a)));
413         }
414         if (collatableEl)
415                 collation = defGetBoolean(collatableEl) ? DEFAULT_COLLATION_OID : InvalidOid;
416
417         /*
418          * make sure we have our required definitions
419          */
420         if (inputName == NIL)
421                 ereport(ERROR,
422                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
423                                  errmsg("type input function must be specified")));
424         if (outputName == NIL)
425                 ereport(ERROR,
426                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
427                                  errmsg("type output function must be specified")));
428
429         if (typmodinName == NIL && typmodoutName != NIL)
430                 ereport(ERROR,
431                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
432                                  errmsg("type modifier output function is useless without a type modifier input function")));
433
434         /*
435          * Convert I/O proc names to OIDs
436          */
437         inputOid = findTypeInputFunction(inputName, typoid);
438         outputOid = findTypeOutputFunction(outputName, typoid);
439         if (receiveName)
440                 receiveOid = findTypeReceiveFunction(receiveName, typoid);
441         if (sendName)
442                 sendOid = findTypeSendFunction(sendName, typoid);
443
444         /*
445          * Verify that I/O procs return the expected thing.  If we see OPAQUE,
446          * complain and change it to the correct type-safe choice.
447          */
448         resulttype = get_func_rettype(inputOid);
449         if (resulttype != typoid)
450         {
451                 if (resulttype == OPAQUEOID)
452                 {
453                         /* backwards-compatibility hack */
454                         ereport(WARNING,
455                                         (errmsg("changing return type of function %s from \"opaque\" to %s",
456                                                         NameListToString(inputName), typeName)));
457                         SetFunctionReturnType(inputOid, typoid);
458                 }
459                 else
460                         ereport(ERROR,
461                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
462                                          errmsg("type input function %s must return type %s",
463                                                         NameListToString(inputName), typeName)));
464         }
465         resulttype = get_func_rettype(outputOid);
466         if (resulttype != CSTRINGOID)
467         {
468                 if (resulttype == OPAQUEOID)
469                 {
470                         /* backwards-compatibility hack */
471                         ereport(WARNING,
472                                         (errmsg("changing return type of function %s from \"opaque\" to \"cstring\"",
473                                                         NameListToString(outputName))));
474                         SetFunctionReturnType(outputOid, CSTRINGOID);
475                 }
476                 else
477                         ereport(ERROR,
478                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
479                            errmsg("type output function %s must return type \"cstring\"",
480                                           NameListToString(outputName))));
481         }
482         if (receiveOid)
483         {
484                 resulttype = get_func_rettype(receiveOid);
485                 if (resulttype != typoid)
486                         ereport(ERROR,
487                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
488                                          errmsg("type receive function %s must return type %s",
489                                                         NameListToString(receiveName), typeName)));
490         }
491         if (sendOid)
492         {
493                 resulttype = get_func_rettype(sendOid);
494                 if (resulttype != BYTEAOID)
495                         ereport(ERROR,
496                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
497                                    errmsg("type send function %s must return type \"bytea\"",
498                                                   NameListToString(sendName))));
499         }
500
501         /*
502          * Convert typmodin/out function proc names to OIDs.
503          */
504         if (typmodinName)
505                 typmodinOid = findTypeTypmodinFunction(typmodinName);
506         if (typmodoutName)
507                 typmodoutOid = findTypeTypmodoutFunction(typmodoutName);
508
509         /*
510          * Convert analysis function proc name to an OID. If no analysis function
511          * is specified, we'll use zero to select the built-in default algorithm.
512          */
513         if (analyzeName)
514                 analyzeOid = findTypeAnalyzeFunction(analyzeName, typoid);
515
516         /*
517          * Check permissions on functions.      We choose to require the creator/owner
518          * of a type to also own the underlying functions.      Since creating a type
519          * is tantamount to granting public execute access on the functions, the
520          * minimum sane check would be for execute-with-grant-option.  But we
521          * don't have a way to make the type go away if the grant option is
522          * revoked, so ownership seems better.
523          */
524 #ifdef NOT_USED
525         /* XXX this is unnecessary given the superuser check above */
526         if (inputOid && !pg_proc_ownercheck(inputOid, GetUserId()))
527                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
528                                            NameListToString(inputName));
529         if (outputOid && !pg_proc_ownercheck(outputOid, GetUserId()))
530                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
531                                            NameListToString(outputName));
532         if (receiveOid && !pg_proc_ownercheck(receiveOid, GetUserId()))
533                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
534                                            NameListToString(receiveName));
535         if (sendOid && !pg_proc_ownercheck(sendOid, GetUserId()))
536                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
537                                            NameListToString(sendName));
538         if (typmodinOid && !pg_proc_ownercheck(typmodinOid, GetUserId()))
539                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
540                                            NameListToString(typmodinName));
541         if (typmodoutOid && !pg_proc_ownercheck(typmodoutOid, GetUserId()))
542                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
543                                            NameListToString(typmodoutName));
544         if (analyzeOid && !pg_proc_ownercheck(analyzeOid, GetUserId()))
545                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
546                                            NameListToString(analyzeName));
547 #endif
548
549         array_oid = AssignTypeArrayOid();
550
551         /*
552          * now have TypeCreate do all the real work.
553          *
554          * Note: the pg_type.oid is stored in user tables as array elements (base
555          * types) in ArrayType and in composite types in DatumTupleFields.      This
556          * oid must be preserved by binary upgrades.
557          */
558         typoid =
559                 TypeCreate(InvalidOid,  /* no predetermined type OID */
560                                    typeName,    /* type name */
561                                    typeNamespace,               /* namespace */
562                                    InvalidOid,  /* relation oid (n/a here) */
563                                    0,                   /* relation kind (ditto) */
564                                    GetUserId(), /* owner's ID */
565                                    internalLength,              /* internal size */
566                                    TYPTYPE_BASE,        /* type-type (base type) */
567                                    category,    /* type-category */
568                                    preferred,   /* is it a preferred type? */
569                                    delimiter,   /* array element delimiter */
570                                    inputOid,    /* input procedure */
571                                    outputOid,   /* output procedure */
572                                    receiveOid,  /* receive procedure */
573                                    sendOid,             /* send procedure */
574                                    typmodinOid, /* typmodin procedure */
575                                    typmodoutOid,        /* typmodout procedure */
576                                    analyzeOid,  /* analyze procedure */
577                                    elemType,    /* element type ID */
578                                    false,               /* this is not an array type */
579                                    array_oid,   /* array type we are about to create */
580                                    InvalidOid,  /* base type ID (only for domains) */
581                                    defaultValue,        /* default type value */
582                                    NULL,                /* no binary form available */
583                                    byValue,             /* passed by value */
584                                    alignment,   /* required alignment */
585                                    storage,             /* TOAST strategy */
586                                    -1,                  /* typMod (Domains only) */
587                                    0,                   /* Array Dimensions of typbasetype */
588                                    false,               /* Type NOT NULL */
589                                    collation);  /* type's collation */
590
591         /*
592          * Create the array type that goes with it.
593          */
594         array_type = makeArrayTypeName(typeName, typeNamespace);
595
596         /* alignment must be 'i' or 'd' for arrays */
597         alignment = (alignment == 'd') ? 'd' : 'i';
598
599         typoid = TypeCreate(array_oid,          /* force assignment of this type OID */
600                                                 array_type,             /* type name */
601                                                 typeNamespace,  /* namespace */
602                                                 InvalidOid,             /* relation oid (n/a here) */
603                                                 0,              /* relation kind (ditto) */
604                                                 GetUserId(),    /* owner's ID */
605                                                 -1,             /* internal size (always varlena) */
606                                                 TYPTYPE_BASE,   /* type-type (base type) */
607                                                 TYPCATEGORY_ARRAY,              /* type-category (array) */
608                                                 false,  /* array types are never preferred */
609                                                 delimiter,              /* array element delimiter */
610                                                 F_ARRAY_IN,             /* input procedure */
611                                                 F_ARRAY_OUT,    /* output procedure */
612                                                 F_ARRAY_RECV,   /* receive procedure */
613                                                 F_ARRAY_SEND,   /* send procedure */
614                                                 typmodinOid,    /* typmodin procedure */
615                                                 typmodoutOid,   /* typmodout procedure */
616                                                 F_ARRAY_TYPANALYZE,             /* analyze procedure */
617                                                 typoid, /* element type ID */
618                                                 true,   /* yes this is an array type */
619                                                 InvalidOid,             /* no further array type */
620                                                 InvalidOid,             /* base type ID */
621                                                 NULL,   /* never a default type value */
622                                                 NULL,   /* binary default isn't sent either */
623                                                 false,  /* never passed by value */
624                                                 alignment,              /* see above */
625                                                 'x',    /* ARRAY is always toastable */
626                                                 -1,             /* typMod (Domains only) */
627                                                 0,              /* Array dimensions of typbasetype */
628                                                 false,  /* Type NOT NULL */
629                                                 collation);             /* type's collation */
630
631         pfree(array_type);
632
633         return typoid;
634 }
635
636 /*
637  * Guts of type deletion.
638  */
639 void
640 RemoveTypeById(Oid typeOid)
641 {
642         Relation        relation;
643         HeapTuple       tup;
644
645         relation = heap_open(TypeRelationId, RowExclusiveLock);
646
647         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
648         if (!HeapTupleIsValid(tup))
649                 elog(ERROR, "cache lookup failed for type %u", typeOid);
650
651         simple_heap_delete(relation, &tup->t_self);
652
653         /*
654          * If it is an enum, delete the pg_enum entries too; we don't bother with
655          * making dependency entries for those, so it has to be done "by hand"
656          * here.
657          */
658         if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_ENUM)
659                 EnumValuesDelete(typeOid);
660
661         /*
662          * If it is a range type, delete the pg_range entry too; we don't bother
663          * with making a dependency entry for that, so it has to be done "by hand"
664          * here.
665          */
666         if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_RANGE)
667                 RangeDelete(typeOid);
668
669         ReleaseSysCache(tup);
670
671         heap_close(relation, RowExclusiveLock);
672 }
673
674
675 /*
676  * DefineDomain
677  *              Registers a new domain.
678  */
679 Oid
680 DefineDomain(CreateDomainStmt *stmt)
681 {
682         char       *domainName;
683         Oid                     domainNamespace;
684         AclResult       aclresult;
685         int16           internalLength;
686         Oid                     inputProcedure;
687         Oid                     outputProcedure;
688         Oid                     receiveProcedure;
689         Oid                     sendProcedure;
690         Oid                     analyzeProcedure;
691         bool            byValue;
692         char            category;
693         char            delimiter;
694         char            alignment;
695         char            storage;
696         char            typtype;
697         Datum           datum;
698         bool            isnull;
699         char       *defaultValue = NULL;
700         char       *defaultValueBin = NULL;
701         bool            saw_default = false;
702         bool            typNotNull = false;
703         bool            nullDefined = false;
704         int32           typNDims = list_length(stmt->typeName->arrayBounds);
705         HeapTuple       typeTup;
706         List       *schema = stmt->constraints;
707         ListCell   *listptr;
708         Oid                     basetypeoid;
709         Oid                     domainoid;
710         Oid                     old_type_oid;
711         Oid                     domaincoll;
712         Form_pg_type baseType;
713         int32           basetypeMod;
714         Oid                     baseColl;
715
716         /* Convert list of names to a name and namespace */
717         domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
718                                                                                                                 &domainName);
719
720         /* Check we have creation rights in target namespace */
721         aclresult = pg_namespace_aclcheck(domainNamespace, GetUserId(),
722                                                                           ACL_CREATE);
723         if (aclresult != ACLCHECK_OK)
724                 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
725                                            get_namespace_name(domainNamespace));
726
727         /*
728          * Check for collision with an existing type name.      If there is one and
729          * it's an autogenerated array, we can rename it out of the way.
730          */
731         old_type_oid = GetSysCacheOid2(TYPENAMENSP,
732                                                                    CStringGetDatum(domainName),
733                                                                    ObjectIdGetDatum(domainNamespace));
734         if (OidIsValid(old_type_oid))
735         {
736                 if (!moveArrayTypeName(old_type_oid, domainName, domainNamespace))
737                         ereport(ERROR,
738                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
739                                          errmsg("type \"%s\" already exists", domainName)));
740         }
741
742         /*
743          * Look up the base type.
744          */
745         typeTup = typenameType(NULL, stmt->typeName, &basetypeMod);
746         baseType = (Form_pg_type) GETSTRUCT(typeTup);
747         basetypeoid = HeapTupleGetOid(typeTup);
748
749         /*
750          * Base type must be a plain base type, another domain, an enum or a range
751          * type. Domains over pseudotypes would create a security hole.  Domains
752          * over composite types might be made to work in the future, but not
753          * today.
754          */
755         typtype = baseType->typtype;
756         if (typtype != TYPTYPE_BASE &&
757                 typtype != TYPTYPE_DOMAIN &&
758                 typtype != TYPTYPE_ENUM &&
759                 typtype != TYPTYPE_RANGE)
760                 ereport(ERROR,
761                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
762                                  errmsg("\"%s\" is not a valid base type for a domain",
763                                                 TypeNameToString(stmt->typeName))));
764
765         aclresult = pg_type_aclcheck(basetypeoid, GetUserId(), ACL_USAGE);
766         if (aclresult != ACLCHECK_OK)
767                 aclcheck_error_type(aclresult, basetypeoid);
768
769         /*
770          * Identify the collation if any
771          */
772         baseColl = baseType->typcollation;
773         if (stmt->collClause)
774                 domaincoll = get_collation_oid(stmt->collClause->collname, false);
775         else
776                 domaincoll = baseColl;
777
778         /* Complain if COLLATE is applied to an uncollatable type */
779         if (OidIsValid(domaincoll) && !OidIsValid(baseColl))
780                 ereport(ERROR,
781                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
782                                  errmsg("collations are not supported by type %s",
783                                                 format_type_be(basetypeoid))));
784
785         /* passed by value */
786         byValue = baseType->typbyval;
787
788         /* Required Alignment */
789         alignment = baseType->typalign;
790
791         /* TOAST Strategy */
792         storage = baseType->typstorage;
793
794         /* Storage Length */
795         internalLength = baseType->typlen;
796
797         /* Type Category */
798         category = baseType->typcategory;
799
800         /* Array element Delimiter */
801         delimiter = baseType->typdelim;
802
803         /* I/O Functions */
804         inputProcedure = F_DOMAIN_IN;
805         outputProcedure = baseType->typoutput;
806         receiveProcedure = F_DOMAIN_RECV;
807         sendProcedure = baseType->typsend;
808
809         /* Domains never accept typmods, so no typmodin/typmodout needed */
810
811         /* Analysis function */
812         analyzeProcedure = baseType->typanalyze;
813
814         /* Inherited default value */
815         datum = SysCacheGetAttr(TYPEOID, typeTup,
816                                                         Anum_pg_type_typdefault, &isnull);
817         if (!isnull)
818                 defaultValue = TextDatumGetCString(datum);
819
820         /* Inherited default binary value */
821         datum = SysCacheGetAttr(TYPEOID, typeTup,
822                                                         Anum_pg_type_typdefaultbin, &isnull);
823         if (!isnull)
824                 defaultValueBin = TextDatumGetCString(datum);
825
826         /*
827          * Run through constraints manually to avoid the additional processing
828          * conducted by DefineRelation() and friends.
829          */
830         foreach(listptr, schema)
831         {
832                 Constraint *constr = lfirst(listptr);
833
834                 if (!IsA(constr, Constraint))
835                         elog(ERROR, "unrecognized node type: %d",
836                                  (int) nodeTag(constr));
837                 switch (constr->contype)
838                 {
839                         case CONSTR_DEFAULT:
840
841                                 /*
842                                  * The inherited default value may be overridden by the user
843                                  * with the DEFAULT <expr> clause ... but only once.
844                                  */
845                                 if (saw_default)
846                                         ereport(ERROR,
847                                                         (errcode(ERRCODE_SYNTAX_ERROR),
848                                                          errmsg("multiple default expressions")));
849                                 saw_default = true;
850
851                                 if (constr->raw_expr)
852                                 {
853                                         ParseState *pstate;
854                                         Node       *defaultExpr;
855
856                                         /* Create a dummy ParseState for transformExpr */
857                                         pstate = make_parsestate(NULL);
858
859                                         /*
860                                          * Cook the constr->raw_expr into an expression. Note:
861                                          * name is strictly for error message
862                                          */
863                                         defaultExpr = cookDefault(pstate, constr->raw_expr,
864                                                                                           basetypeoid,
865                                                                                           basetypeMod,
866                                                                                           domainName);
867
868                                         /*
869                                          * If the expression is just a NULL constant, we treat it
870                                          * like not having a default.
871                                          *
872                                          * Note that if the basetype is another domain, we'll see
873                                          * a CoerceToDomain expr here and not discard the default.
874                                          * This is critical because the domain default needs to be
875                                          * retained to override any default that the base domain
876                                          * might have.
877                                          */
878                                         if (defaultExpr == NULL ||
879                                                 (IsA(defaultExpr, Const) &&
880                                                  ((Const *) defaultExpr)->constisnull))
881                                         {
882                                                 defaultValue = NULL;
883                                                 defaultValueBin = NULL;
884                                         }
885                                         else
886                                         {
887                                                 /*
888                                                  * Expression must be stored as a nodeToString result,
889                                                  * but we also require a valid textual representation
890                                                  * (mainly to make life easier for pg_dump).
891                                                  */
892                                                 defaultValue =
893                                                         deparse_expression(defaultExpr,
894                                                                                            NIL, false, false);
895                                                 defaultValueBin = nodeToString(defaultExpr);
896                                         }
897                                 }
898                                 else
899                                 {
900                                         /* No default (can this still happen?) */
901                                         defaultValue = NULL;
902                                         defaultValueBin = NULL;
903                                 }
904                                 break;
905
906                         case CONSTR_NOTNULL:
907                                 if (nullDefined && !typNotNull)
908                                         ereport(ERROR,
909                                                         (errcode(ERRCODE_SYNTAX_ERROR),
910                                                    errmsg("conflicting NULL/NOT NULL constraints")));
911                                 typNotNull = true;
912                                 nullDefined = true;
913                                 break;
914
915                         case CONSTR_NULL:
916                                 if (nullDefined && typNotNull)
917                                         ereport(ERROR,
918                                                         (errcode(ERRCODE_SYNTAX_ERROR),
919                                                    errmsg("conflicting NULL/NOT NULL constraints")));
920                                 typNotNull = false;
921                                 nullDefined = true;
922                                 break;
923
924                         case CONSTR_CHECK:
925
926                                 /*
927                                  * Check constraints are handled after domain creation, as
928                                  * they require the Oid of the domain; at this point we can
929                                  * only check that they're not marked NO INHERIT, because that
930                                  * would be bogus.
931                                  */
932                                 if (constr->is_no_inherit)
933                                         ereport(ERROR,
934                                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
935                                                          errmsg("check constraints for domains cannot be marked NO INHERIT")));
936                                 break;
937
938                                 /*
939                                  * All else are error cases
940                                  */
941                         case CONSTR_UNIQUE:
942                                 ereport(ERROR,
943                                                 (errcode(ERRCODE_SYNTAX_ERROR),
944                                          errmsg("unique constraints not possible for domains")));
945                                 break;
946
947                         case CONSTR_PRIMARY:
948                                 ereport(ERROR,
949                                                 (errcode(ERRCODE_SYNTAX_ERROR),
950                                 errmsg("primary key constraints not possible for domains")));
951                                 break;
952
953                         case CONSTR_EXCLUSION:
954                                 ereport(ERROR,
955                                                 (errcode(ERRCODE_SYNTAX_ERROR),
956                                   errmsg("exclusion constraints not possible for domains")));
957                                 break;
958
959                         case CONSTR_FOREIGN:
960                                 ereport(ERROR,
961                                                 (errcode(ERRCODE_SYNTAX_ERROR),
962                                 errmsg("foreign key constraints not possible for domains")));
963                                 break;
964
965                         case CONSTR_ATTR_DEFERRABLE:
966                         case CONSTR_ATTR_NOT_DEFERRABLE:
967                         case CONSTR_ATTR_DEFERRED:
968                         case CONSTR_ATTR_IMMEDIATE:
969                                 ereport(ERROR,
970                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
971                                                  errmsg("specifying constraint deferrability not supported for domains")));
972                                 break;
973
974                         default:
975                                 elog(ERROR, "unrecognized constraint subtype: %d",
976                                          (int) constr->contype);
977                                 break;
978                 }
979         }
980
981         /*
982          * Have TypeCreate do all the real work.
983          */
984         domainoid =
985                 TypeCreate(InvalidOid,  /* no predetermined type OID */
986                                    domainName,  /* type name */
987                                    domainNamespace,             /* namespace */
988                                    InvalidOid,  /* relation oid (n/a here) */
989                                    0,                   /* relation kind (ditto) */
990                                    GetUserId(), /* owner's ID */
991                                    internalLength,              /* internal size */
992                                    TYPTYPE_DOMAIN,              /* type-type (domain type) */
993                                    category,    /* type-category */
994                                    false,               /* domain types are never preferred */
995                                    delimiter,   /* array element delimiter */
996                                    inputProcedure,              /* input procedure */
997                                    outputProcedure,             /* output procedure */
998                                    receiveProcedure,    /* receive procedure */
999                                    sendProcedure,               /* send procedure */
1000                                    InvalidOid,  /* typmodin procedure - none */
1001                                    InvalidOid,  /* typmodout procedure - none */
1002                                    analyzeProcedure,    /* analyze procedure */
1003                                    InvalidOid,  /* no array element type */
1004                                    false,               /* this isn't an array */
1005                                    InvalidOid,  /* no arrays for domains (yet) */
1006                                    basetypeoid, /* base type ID */
1007                                    defaultValue,        /* default type value (text) */
1008                                    defaultValueBin,             /* default type value (binary) */
1009                                    byValue,             /* passed by value */
1010                                    alignment,   /* required alignment */
1011                                    storage,             /* TOAST strategy */
1012                                    basetypeMod, /* typeMod value */
1013                                    typNDims,    /* Array dimensions for base type */
1014                                    typNotNull,  /* Type NOT NULL */
1015                                    domaincoll); /* type's collation */
1016
1017         /*
1018          * Process constraints which refer to the domain ID returned by TypeCreate
1019          */
1020         foreach(listptr, schema)
1021         {
1022                 Constraint *constr = lfirst(listptr);
1023
1024                 /* it must be a Constraint, per check above */
1025
1026                 switch (constr->contype)
1027                 {
1028                         case CONSTR_CHECK:
1029                                 domainAddConstraint(domainoid, domainNamespace,
1030                                                                         basetypeoid, basetypeMod,
1031                                                                         constr, domainName);
1032                                 break;
1033
1034                                 /* Other constraint types were fully processed above */
1035
1036                         default:
1037                                 break;
1038                 }
1039
1040                 /* CCI so we can detect duplicate constraint names */
1041                 CommandCounterIncrement();
1042         }
1043
1044         /*
1045          * Now we can clean up.
1046          */
1047         ReleaseSysCache(typeTup);
1048
1049         return domainoid;
1050 }
1051
1052
1053 /*
1054  * DefineEnum
1055  *              Registers a new enum.
1056  */
1057 Oid
1058 DefineEnum(CreateEnumStmt *stmt)
1059 {
1060         char       *enumName;
1061         char       *enumArrayName;
1062         Oid                     enumNamespace;
1063         Oid                     enumTypeOid;
1064         AclResult       aclresult;
1065         Oid                     old_type_oid;
1066         Oid                     enumArrayOid;
1067
1068         /* Convert list of names to a name and namespace */
1069         enumNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
1070                                                                                                           &enumName);
1071
1072         /* Check we have creation rights in target namespace */
1073         aclresult = pg_namespace_aclcheck(enumNamespace, GetUserId(), ACL_CREATE);
1074         if (aclresult != ACLCHECK_OK)
1075                 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1076                                            get_namespace_name(enumNamespace));
1077
1078         /*
1079          * Check for collision with an existing type name.      If there is one and
1080          * it's an autogenerated array, we can rename it out of the way.
1081          */
1082         old_type_oid = GetSysCacheOid2(TYPENAMENSP,
1083                                                                    CStringGetDatum(enumName),
1084                                                                    ObjectIdGetDatum(enumNamespace));
1085         if (OidIsValid(old_type_oid))
1086         {
1087                 if (!moveArrayTypeName(old_type_oid, enumName, enumNamespace))
1088                         ereport(ERROR,
1089                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
1090                                          errmsg("type \"%s\" already exists", enumName)));
1091         }
1092
1093         enumArrayOid = AssignTypeArrayOid();
1094
1095         /* Create the pg_type entry */
1096         enumTypeOid =
1097                 TypeCreate(InvalidOid,  /* no predetermined type OID */
1098                                    enumName,    /* type name */
1099                                    enumNamespace,               /* namespace */
1100                                    InvalidOid,  /* relation oid (n/a here) */
1101                                    0,                   /* relation kind (ditto) */
1102                                    GetUserId(), /* owner's ID */
1103                                    sizeof(Oid), /* internal size */
1104                                    TYPTYPE_ENUM,        /* type-type (enum type) */
1105                                    TYPCATEGORY_ENUM,    /* type-category (enum type) */
1106                                    false,               /* enum types are never preferred */
1107                                    DEFAULT_TYPDELIM,    /* array element delimiter */
1108                                    F_ENUM_IN,   /* input procedure */
1109                                    F_ENUM_OUT,  /* output procedure */
1110                                    F_ENUM_RECV, /* receive procedure */
1111                                    F_ENUM_SEND, /* send procedure */
1112                                    InvalidOid,  /* typmodin procedure - none */
1113                                    InvalidOid,  /* typmodout procedure - none */
1114                                    InvalidOid,  /* analyze procedure - default */
1115                                    InvalidOid,  /* element type ID */
1116                                    false,               /* this is not an array type */
1117                                    enumArrayOid,        /* array type we are about to create */
1118                                    InvalidOid,  /* base type ID (only for domains) */
1119                                    NULL,                /* never a default type value */
1120                                    NULL,                /* binary default isn't sent either */
1121                                    true,                /* always passed by value */
1122                                    'i',                 /* int alignment */
1123                                    'p',                 /* TOAST strategy always plain */
1124                                    -1,                  /* typMod (Domains only) */
1125                                    0,                   /* Array dimensions of typbasetype */
1126                                    false,               /* Type NOT NULL */
1127                                    InvalidOid); /* type's collation */
1128
1129         /* Enter the enum's values into pg_enum */
1130         EnumValuesCreate(enumTypeOid, stmt->vals);
1131
1132         /*
1133          * Create the array type that goes with it.
1134          */
1135         enumArrayName = makeArrayTypeName(enumName, enumNamespace);
1136
1137         TypeCreate(enumArrayOid,        /* force assignment of this type OID */
1138                            enumArrayName,       /* type name */
1139                            enumNamespace,       /* namespace */
1140                            InvalidOid,          /* relation oid (n/a here) */
1141                            0,                           /* relation kind (ditto) */
1142                            GetUserId(),         /* owner's ID */
1143                            -1,                          /* internal size (always varlena) */
1144                            TYPTYPE_BASE,        /* type-type (base type) */
1145                            TYPCATEGORY_ARRAY,           /* type-category (array) */
1146                            false,                       /* array types are never preferred */
1147                            DEFAULT_TYPDELIM,    /* array element delimiter */
1148                            F_ARRAY_IN,          /* input procedure */
1149                            F_ARRAY_OUT,         /* output procedure */
1150                            F_ARRAY_RECV,        /* receive procedure */
1151                            F_ARRAY_SEND,        /* send procedure */
1152                            InvalidOid,          /* typmodin procedure - none */
1153                            InvalidOid,          /* typmodout procedure - none */
1154                            F_ARRAY_TYPANALYZE,          /* analyze procedure */
1155                            enumTypeOid,         /* element type ID */
1156                            true,                        /* yes this is an array type */
1157                            InvalidOid,          /* no further array type */
1158                            InvalidOid,          /* base type ID */
1159                            NULL,                        /* never a default type value */
1160                            NULL,                        /* binary default isn't sent either */
1161                            false,                       /* never passed by value */
1162                            'i',                         /* enums have align i, so do their arrays */
1163                            'x',                         /* ARRAY is always toastable */
1164                            -1,                          /* typMod (Domains only) */
1165                            0,                           /* Array dimensions of typbasetype */
1166                            false,                       /* Type NOT NULL */
1167                            InvalidOid);         /* type's collation */
1168
1169         pfree(enumArrayName);
1170
1171         return enumTypeOid;
1172 }
1173
1174 /*
1175  * AlterEnum
1176  *              Adds a new label to an existing enum.
1177  */
1178 Oid
1179 AlterEnum(AlterEnumStmt *stmt, bool isTopLevel)
1180 {
1181         Oid                     enum_type_oid;
1182         TypeName   *typename;
1183         HeapTuple       tup;
1184
1185         /* Make a TypeName so we can use standard type lookup machinery */
1186         typename = makeTypeNameFromNameList(stmt->typeName);
1187         enum_type_oid = typenameTypeId(NULL, typename);
1188
1189         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(enum_type_oid));
1190         if (!HeapTupleIsValid(tup))
1191                 elog(ERROR, "cache lookup failed for type %u", enum_type_oid);
1192
1193         /*
1194          * Ordinarily we disallow adding values within transaction blocks, because
1195          * we can't cope with enum OID values getting into indexes and then having
1196          * their defining pg_enum entries go away.      However, it's okay if the enum
1197          * type was created in the current transaction, since then there can be no
1198          * such indexes that wouldn't themselves go away on rollback.  (We support
1199          * this case because pg_dump --binary-upgrade needs it.)  We test this by
1200          * seeing if the pg_type row has xmin == current XID and is not
1201          * HEAP_UPDATED.  If it is HEAP_UPDATED, we can't be sure whether the type
1202          * was created or only modified in this xact.  So we are disallowing some
1203          * cases that could theoretically be safe; but fortunately pg_dump only
1204          * needs the simplest case.
1205          */
1206         if (HeapTupleHeaderGetXmin(tup->t_data) == GetCurrentTransactionId() &&
1207                 !(tup->t_data->t_infomask & HEAP_UPDATED))
1208                  /* safe to do inside transaction block */ ;
1209         else
1210                 PreventTransactionChain(isTopLevel, "ALTER TYPE ... ADD");
1211
1212         /* Check it's an enum and check user has permission to ALTER the enum */
1213         checkEnumOwner(tup);
1214
1215         /* Add the new label */
1216         AddEnumLabel(enum_type_oid, stmt->newVal,
1217                                  stmt->newValNeighbor, stmt->newValIsAfter,
1218                                  stmt->skipIfExists);
1219
1220         InvokeObjectPostAlterHook(TypeRelationId, enum_type_oid, 0);
1221
1222         ReleaseSysCache(tup);
1223
1224         return enum_type_oid;
1225 }
1226
1227
1228 /*
1229  * checkEnumOwner
1230  *
1231  * Check that the type is actually an enum and that the current user
1232  * has permission to do ALTER TYPE on it.  Throw an error if not.
1233  */
1234 static void
1235 checkEnumOwner(HeapTuple tup)
1236 {
1237         Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
1238
1239         /* Check that this is actually an enum */
1240         if (typTup->typtype != TYPTYPE_ENUM)
1241                 ereport(ERROR,
1242                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1243                                  errmsg("%s is not an enum",
1244                                                 format_type_be(HeapTupleGetOid(tup)))));
1245
1246         /* Permission check: must own type */
1247         if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
1248                 aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup));
1249 }
1250
1251
1252 /*
1253  * DefineRange
1254  *              Registers a new range type.
1255  */
1256 Oid
1257 DefineRange(CreateRangeStmt *stmt)
1258 {
1259         char       *typeName;
1260         Oid                     typeNamespace;
1261         Oid                     typoid;
1262         char       *rangeArrayName;
1263         Oid                     rangeArrayOid;
1264         Oid                     rangeSubtype = InvalidOid;
1265         List       *rangeSubOpclassName = NIL;
1266         List       *rangeCollationName = NIL;
1267         List       *rangeCanonicalName = NIL;
1268         List       *rangeSubtypeDiffName = NIL;
1269         Oid                     rangeSubOpclass;
1270         Oid                     rangeCollation;
1271         regproc         rangeCanonical;
1272         regproc         rangeSubtypeDiff;
1273         int16           subtyplen;
1274         bool            subtypbyval;
1275         char            subtypalign;
1276         char            alignment;
1277         AclResult       aclresult;
1278         ListCell   *lc;
1279
1280         /* Convert list of names to a name and namespace */
1281         typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
1282                                                                                                           &typeName);
1283
1284         /* Check we have creation rights in target namespace */
1285         aclresult = pg_namespace_aclcheck(typeNamespace, GetUserId(), ACL_CREATE);
1286         if (aclresult != ACLCHECK_OK)
1287                 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1288                                            get_namespace_name(typeNamespace));
1289
1290         /*
1291          * Look to see if type already exists.
1292          */
1293         typoid = GetSysCacheOid2(TYPENAMENSP,
1294                                                          CStringGetDatum(typeName),
1295                                                          ObjectIdGetDatum(typeNamespace));
1296
1297         /*
1298          * If it's not a shell, see if it's an autogenerated array type, and if so
1299          * rename it out of the way.
1300          */
1301         if (OidIsValid(typoid) && get_typisdefined(typoid))
1302         {
1303                 if (moveArrayTypeName(typoid, typeName, typeNamespace))
1304                         typoid = InvalidOid;
1305                 else
1306                         ereport(ERROR,
1307                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
1308                                          errmsg("type \"%s\" already exists", typeName)));
1309         }
1310
1311         /*
1312          * If it doesn't exist, create it as a shell, so that the OID is known for
1313          * use in the range function definitions.
1314          */
1315         if (!OidIsValid(typoid))
1316         {
1317                 typoid = TypeShellMake(typeName, typeNamespace, GetUserId());
1318                 /* Make new shell type visible for modification below */
1319                 CommandCounterIncrement();
1320         }
1321
1322         /* Extract the parameters from the parameter list */
1323         foreach(lc, stmt->params)
1324         {
1325                 DefElem    *defel = (DefElem *) lfirst(lc);
1326
1327                 if (pg_strcasecmp(defel->defname, "subtype") == 0)
1328                 {
1329                         if (OidIsValid(rangeSubtype))
1330                                 ereport(ERROR,
1331                                                 (errcode(ERRCODE_SYNTAX_ERROR),
1332                                                  errmsg("conflicting or redundant options")));
1333                         /* we can look up the subtype name immediately */
1334                         rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
1335                 }
1336                 else if (pg_strcasecmp(defel->defname, "subtype_opclass") == 0)
1337                 {
1338                         if (rangeSubOpclassName != NIL)
1339                                 ereport(ERROR,
1340                                                 (errcode(ERRCODE_SYNTAX_ERROR),
1341                                                  errmsg("conflicting or redundant options")));
1342                         rangeSubOpclassName = defGetQualifiedName(defel);
1343                 }
1344                 else if (pg_strcasecmp(defel->defname, "collation") == 0)
1345                 {
1346                         if (rangeCollationName != NIL)
1347                                 ereport(ERROR,
1348                                                 (errcode(ERRCODE_SYNTAX_ERROR),
1349                                                  errmsg("conflicting or redundant options")));
1350                         rangeCollationName = defGetQualifiedName(defel);
1351                 }
1352                 else if (pg_strcasecmp(defel->defname, "canonical") == 0)
1353                 {
1354                         if (rangeCanonicalName != NIL)
1355                                 ereport(ERROR,
1356                                                 (errcode(ERRCODE_SYNTAX_ERROR),
1357                                                  errmsg("conflicting or redundant options")));
1358                         rangeCanonicalName = defGetQualifiedName(defel);
1359                 }
1360                 else if (pg_strcasecmp(defel->defname, "subtype_diff") == 0)
1361                 {
1362                         if (rangeSubtypeDiffName != NIL)
1363                                 ereport(ERROR,
1364                                                 (errcode(ERRCODE_SYNTAX_ERROR),
1365                                                  errmsg("conflicting or redundant options")));
1366                         rangeSubtypeDiffName = defGetQualifiedName(defel);
1367                 }
1368                 else
1369                         ereport(ERROR,
1370                                         (errcode(ERRCODE_SYNTAX_ERROR),
1371                                          errmsg("type attribute \"%s\" not recognized",
1372                                                         defel->defname)));
1373         }
1374
1375         /* Must have a subtype */
1376         if (!OidIsValid(rangeSubtype))
1377                 ereport(ERROR,
1378                                 (errcode(ERRCODE_SYNTAX_ERROR),
1379                                  errmsg("type attribute \"subtype\" is required")));
1380         /* disallow ranges of pseudotypes */
1381         if (get_typtype(rangeSubtype) == TYPTYPE_PSEUDO)
1382                 ereport(ERROR,
1383                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
1384                                  errmsg("range subtype cannot be %s",
1385                                                 format_type_be(rangeSubtype))));
1386
1387         /* Identify subopclass */
1388         rangeSubOpclass = findRangeSubOpclass(rangeSubOpclassName, rangeSubtype);
1389
1390         /* Identify collation to use, if any */
1391         if (type_is_collatable(rangeSubtype))
1392         {
1393                 if (rangeCollationName != NIL)
1394                         rangeCollation = get_collation_oid(rangeCollationName, false);
1395                 else
1396                         rangeCollation = get_typcollation(rangeSubtype);
1397         }
1398         else
1399         {
1400                 if (rangeCollationName != NIL)
1401                         ereport(ERROR,
1402                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1403                                          errmsg("range collation specified but subtype does not support collation")));
1404                 rangeCollation = InvalidOid;
1405         }
1406
1407         /* Identify support functions, if provided */
1408         if (rangeCanonicalName != NIL)
1409                 rangeCanonical = findRangeCanonicalFunction(rangeCanonicalName,
1410                                                                                                         typoid);
1411         else
1412                 rangeCanonical = InvalidOid;
1413
1414         if (rangeSubtypeDiffName != NIL)
1415                 rangeSubtypeDiff = findRangeSubtypeDiffFunction(rangeSubtypeDiffName,
1416                                                                                                                 rangeSubtype);
1417         else
1418                 rangeSubtypeDiff = InvalidOid;
1419
1420         get_typlenbyvalalign(rangeSubtype,
1421                                                  &subtyplen, &subtypbyval, &subtypalign);
1422
1423         /* alignment must be 'i' or 'd' for ranges */
1424         alignment = (subtypalign == 'd') ? 'd' : 'i';
1425
1426         /* Allocate OID for array type */
1427         rangeArrayOid = AssignTypeArrayOid();
1428
1429         /* Create the pg_type entry */
1430         typoid =
1431                 TypeCreate(InvalidOid,  /* no predetermined type OID */
1432                                    typeName,    /* type name */
1433                                    typeNamespace,               /* namespace */
1434                                    InvalidOid,  /* relation oid (n/a here) */
1435                                    0,                   /* relation kind (ditto) */
1436                                    GetUserId(), /* owner's ID */
1437                                    -1,                  /* internal size (always varlena) */
1438                                    TYPTYPE_RANGE,               /* type-type (range type) */
1439                                    TYPCATEGORY_RANGE,   /* type-category (range type) */
1440                                    false,               /* range types are never preferred */
1441                                    DEFAULT_TYPDELIM,    /* array element delimiter */
1442                                    F_RANGE_IN,  /* input procedure */
1443                                    F_RANGE_OUT, /* output procedure */
1444                                    F_RANGE_RECV,        /* receive procedure */
1445                                    F_RANGE_SEND,        /* send procedure */
1446                                    InvalidOid,  /* typmodin procedure - none */
1447                                    InvalidOid,  /* typmodout procedure - none */
1448                                    F_RANGE_TYPANALYZE,  /* analyze procedure */
1449                                    InvalidOid,  /* element type ID - none */
1450                                    false,               /* this is not an array type */
1451                                    rangeArrayOid,               /* array type we are about to create */
1452                                    InvalidOid,  /* base type ID (only for domains) */
1453                                    NULL,                /* never a default type value */
1454                                    NULL,                /* no binary form available either */
1455                                    false,               /* never passed by value */
1456                                    alignment,   /* alignment */
1457                                    'x',                 /* TOAST strategy (always extended) */
1458                                    -1,                  /* typMod (Domains only) */
1459                                    0,                   /* Array dimensions of typbasetype */
1460                                    false,               /* Type NOT NULL */
1461                                    InvalidOid); /* type's collation (ranges never have one) */
1462
1463         /* Create the entry in pg_range */
1464         RangeCreate(typoid, rangeSubtype, rangeCollation, rangeSubOpclass,
1465                                 rangeCanonical, rangeSubtypeDiff);
1466
1467         /*
1468          * Create the array type that goes with it.
1469          */
1470         rangeArrayName = makeArrayTypeName(typeName, typeNamespace);
1471
1472         TypeCreate(rangeArrayOid,       /* force assignment of this type OID */
1473                            rangeArrayName,      /* type name */
1474                            typeNamespace,       /* namespace */
1475                            InvalidOid,          /* relation oid (n/a here) */
1476                            0,                           /* relation kind (ditto) */
1477                            GetUserId(),         /* owner's ID */
1478                            -1,                          /* internal size (always varlena) */
1479                            TYPTYPE_BASE,        /* type-type (base type) */
1480                            TYPCATEGORY_ARRAY,           /* type-category (array) */
1481                            false,                       /* array types are never preferred */
1482                            DEFAULT_TYPDELIM,    /* array element delimiter */
1483                            F_ARRAY_IN,          /* input procedure */
1484                            F_ARRAY_OUT,         /* output procedure */
1485                            F_ARRAY_RECV,        /* receive procedure */
1486                            F_ARRAY_SEND,        /* send procedure */
1487                            InvalidOid,          /* typmodin procedure - none */
1488                            InvalidOid,          /* typmodout procedure - none */
1489                            F_ARRAY_TYPANALYZE,          /* analyze procedure */
1490                            typoid,                      /* element type ID */
1491                            true,                        /* yes this is an array type */
1492                            InvalidOid,          /* no further array type */
1493                            InvalidOid,          /* base type ID */
1494                            NULL,                        /* never a default type value */
1495                            NULL,                        /* binary default isn't sent either */
1496                            false,                       /* never passed by value */
1497                            alignment,           /* alignment - same as range's */
1498                            'x',                         /* ARRAY is always toastable */
1499                            -1,                          /* typMod (Domains only) */
1500                            0,                           /* Array dimensions of typbasetype */
1501                            false,                       /* Type NOT NULL */
1502                            InvalidOid);         /* typcollation */
1503
1504         pfree(rangeArrayName);
1505
1506         /* And create the constructor functions for this range type */
1507         makeRangeConstructors(typeName, typeNamespace, typoid, rangeSubtype);
1508
1509         return typoid;
1510 }
1511
1512 /*
1513  * Because there may exist several range types over the same subtype, the
1514  * range type can't be uniquely determined from the subtype.  So it's
1515  * impossible to define a polymorphic constructor; we have to generate new
1516  * constructor functions explicitly for each range type.
1517  *
1518  * We actually define 4 functions, with 0 through 3 arguments.  This is just
1519  * to offer more convenience for the user.
1520  */
1521 static void
1522 makeRangeConstructors(const char *name, Oid namespace,
1523                                           Oid rangeOid, Oid subtype)
1524 {
1525         static const char *const prosrc[2] = {"range_constructor2",
1526         "range_constructor3"};
1527         static const int pronargs[2] = {2, 3};
1528
1529         Oid                     constructorArgTypes[3];
1530         ObjectAddress myself,
1531                                 referenced;
1532         int                     i;
1533
1534         constructorArgTypes[0] = subtype;
1535         constructorArgTypes[1] = subtype;
1536         constructorArgTypes[2] = TEXTOID;
1537
1538         referenced.classId = TypeRelationId;
1539         referenced.objectId = rangeOid;
1540         referenced.objectSubId = 0;
1541
1542         for (i = 0; i < lengthof(prosrc); i++)
1543         {
1544                 oidvector  *constructorArgTypesVector;
1545                 Oid                     procOid;
1546
1547                 constructorArgTypesVector = buildoidvector(constructorArgTypes,
1548                                                                                                    pronargs[i]);
1549
1550                 procOid = ProcedureCreate(name, /* name: same as range type */
1551                                                                   namespace,    /* namespace */
1552                                                                   false,                /* replace */
1553                                                                   false,                /* returns set */
1554                                                                   rangeOid,             /* return type */
1555                                                                   BOOTSTRAP_SUPERUSERID,                /* proowner */
1556                                                                   INTERNALlanguageId,   /* language */
1557                                                                   F_FMGR_INTERNAL_VALIDATOR,    /* language validator */
1558                                                                   prosrc[i],    /* prosrc */
1559                                                                   NULL, /* probin */
1560                                                                   false,                /* isAgg */
1561                                                                   false,                /* isWindowFunc */
1562                                                                   false,                /* security_definer */
1563                                                                   false,                /* leakproof */
1564                                                                   false,                /* isStrict */
1565                                                                   PROVOLATILE_IMMUTABLE,                /* volatility */
1566                                                                   constructorArgTypesVector,    /* parameterTypes */
1567                                                                   PointerGetDatum(NULL),                /* allParameterTypes */
1568                                                                   PointerGetDatum(NULL),                /* parameterModes */
1569                                                                   PointerGetDatum(NULL),                /* parameterNames */
1570                                                                   NIL,  /* parameterDefaults */
1571                                                                   PointerGetDatum(NULL),                /* proconfig */
1572                                                                   1.0,  /* procost */
1573                                                                   0.0); /* prorows */
1574
1575                 /*
1576                  * Make the constructors internally-dependent on the range type so
1577                  * that they go away silently when the type is dropped.  Note that
1578                  * pg_dump depends on this choice to avoid dumping the constructors.
1579                  */
1580                 myself.classId = ProcedureRelationId;
1581                 myself.objectId = procOid;
1582                 myself.objectSubId = 0;
1583
1584                 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1585         }
1586 }
1587
1588
1589 /*
1590  * Find suitable I/O functions for a type.
1591  *
1592  * typeOid is the type's OID (which will already exist, if only as a shell
1593  * type).
1594  */
1595
1596 static Oid
1597 findTypeInputFunction(List *procname, Oid typeOid)
1598 {
1599         Oid                     argList[3];
1600         Oid                     procOid;
1601
1602         /*
1603          * Input functions can take a single argument of type CSTRING, or three
1604          * arguments (string, typioparam OID, typmod).
1605          *
1606          * For backwards compatibility we allow OPAQUE in place of CSTRING; if we
1607          * see this, we issue a warning and fix up the pg_proc entry.
1608          */
1609         argList[0] = CSTRINGOID;
1610
1611         procOid = LookupFuncName(procname, 1, argList, true);
1612         if (OidIsValid(procOid))
1613                 return procOid;
1614
1615         argList[1] = OIDOID;
1616         argList[2] = INT4OID;
1617
1618         procOid = LookupFuncName(procname, 3, argList, true);
1619         if (OidIsValid(procOid))
1620                 return procOid;
1621
1622         /* No luck, try it with OPAQUE */
1623         argList[0] = OPAQUEOID;
1624
1625         procOid = LookupFuncName(procname, 1, argList, true);
1626
1627         if (!OidIsValid(procOid))
1628         {
1629                 argList[1] = OIDOID;
1630                 argList[2] = INT4OID;
1631
1632                 procOid = LookupFuncName(procname, 3, argList, true);
1633         }
1634
1635         if (OidIsValid(procOid))
1636         {
1637                 /* Found, but must complain and fix the pg_proc entry */
1638                 ereport(WARNING,
1639                                 (errmsg("changing argument type of function %s from \"opaque\" to \"cstring\"",
1640                                                 NameListToString(procname))));
1641                 SetFunctionArgType(procOid, 0, CSTRINGOID);
1642
1643                 /*
1644                  * Need CommandCounterIncrement since DefineType will likely try to
1645                  * alter the pg_proc tuple again.
1646                  */
1647                 CommandCounterIncrement();
1648
1649                 return procOid;
1650         }
1651
1652         /* Use CSTRING (preferred) in the error message */
1653         argList[0] = CSTRINGOID;
1654
1655         ereport(ERROR,
1656                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
1657                          errmsg("function %s does not exist",
1658                                         func_signature_string(procname, 1, NIL, argList))));
1659
1660         return InvalidOid;                      /* keep compiler quiet */
1661 }
1662
1663 static Oid
1664 findTypeOutputFunction(List *procname, Oid typeOid)
1665 {
1666         Oid                     argList[1];
1667         Oid                     procOid;
1668
1669         /*
1670          * Output functions can take a single argument of the type.
1671          *
1672          * For backwards compatibility we allow OPAQUE in place of the actual type
1673          * name; if we see this, we issue a warning and fix up the pg_proc entry.
1674          */
1675         argList[0] = typeOid;
1676
1677         procOid = LookupFuncName(procname, 1, argList, true);
1678         if (OidIsValid(procOid))
1679                 return procOid;
1680
1681         /* No luck, try it with OPAQUE */
1682         argList[0] = OPAQUEOID;
1683
1684         procOid = LookupFuncName(procname, 1, argList, true);
1685
1686         if (OidIsValid(procOid))
1687         {
1688                 /* Found, but must complain and fix the pg_proc entry */
1689                 ereport(WARNING,
1690                 (errmsg("changing argument type of function %s from \"opaque\" to %s",
1691                                 NameListToString(procname), format_type_be(typeOid))));
1692                 SetFunctionArgType(procOid, 0, typeOid);
1693
1694                 /*
1695                  * Need CommandCounterIncrement since DefineType will likely try to
1696                  * alter the pg_proc tuple again.
1697                  */
1698                 CommandCounterIncrement();
1699
1700                 return procOid;
1701         }
1702
1703         /* Use type name, not OPAQUE, in the failure message. */
1704         argList[0] = typeOid;
1705
1706         ereport(ERROR,
1707                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
1708                          errmsg("function %s does not exist",
1709                                         func_signature_string(procname, 1, NIL, argList))));
1710
1711         return InvalidOid;                      /* keep compiler quiet */
1712 }
1713
1714 static Oid
1715 findTypeReceiveFunction(List *procname, Oid typeOid)
1716 {
1717         Oid                     argList[3];
1718         Oid                     procOid;
1719
1720         /*
1721          * Receive functions can take a single argument of type INTERNAL, or three
1722          * arguments (internal, typioparam OID, typmod).
1723          */
1724         argList[0] = INTERNALOID;
1725
1726         procOid = LookupFuncName(procname, 1, argList, true);
1727         if (OidIsValid(procOid))
1728                 return procOid;
1729
1730         argList[1] = OIDOID;
1731         argList[2] = INT4OID;
1732
1733         procOid = LookupFuncName(procname, 3, argList, true);
1734         if (OidIsValid(procOid))
1735                 return procOid;
1736
1737         ereport(ERROR,
1738                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
1739                          errmsg("function %s does not exist",
1740                                         func_signature_string(procname, 1, NIL, argList))));
1741
1742         return InvalidOid;                      /* keep compiler quiet */
1743 }
1744
1745 static Oid
1746 findTypeSendFunction(List *procname, Oid typeOid)
1747 {
1748         Oid                     argList[1];
1749         Oid                     procOid;
1750
1751         /*
1752          * Send functions can take a single argument of the type.
1753          */
1754         argList[0] = typeOid;
1755
1756         procOid = LookupFuncName(procname, 1, argList, true);
1757         if (OidIsValid(procOid))
1758                 return procOid;
1759
1760         ereport(ERROR,
1761                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
1762                          errmsg("function %s does not exist",
1763                                         func_signature_string(procname, 1, NIL, argList))));
1764
1765         return InvalidOid;                      /* keep compiler quiet */
1766 }
1767
1768 static Oid
1769 findTypeTypmodinFunction(List *procname)
1770 {
1771         Oid                     argList[1];
1772         Oid                     procOid;
1773
1774         /*
1775          * typmodin functions always take one cstring[] argument and return int4.
1776          */
1777         argList[0] = CSTRINGARRAYOID;
1778
1779         procOid = LookupFuncName(procname, 1, argList, true);
1780         if (!OidIsValid(procOid))
1781                 ereport(ERROR,
1782                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1783                                  errmsg("function %s does not exist",
1784                                                 func_signature_string(procname, 1, NIL, argList))));
1785
1786         if (get_func_rettype(procOid) != INT4OID)
1787                 ereport(ERROR,
1788                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1789                                  errmsg("typmod_in function %s must return type \"integer\"",
1790                                                 NameListToString(procname))));
1791
1792         return procOid;
1793 }
1794
1795 static Oid
1796 findTypeTypmodoutFunction(List *procname)
1797 {
1798         Oid                     argList[1];
1799         Oid                     procOid;
1800
1801         /*
1802          * typmodout functions always take one int4 argument and return cstring.
1803          */
1804         argList[0] = INT4OID;
1805
1806         procOid = LookupFuncName(procname, 1, argList, true);
1807         if (!OidIsValid(procOid))
1808                 ereport(ERROR,
1809                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1810                                  errmsg("function %s does not exist",
1811                                                 func_signature_string(procname, 1, NIL, argList))));
1812
1813         if (get_func_rettype(procOid) != CSTRINGOID)
1814                 ereport(ERROR,
1815                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1816                                  errmsg("typmod_out function %s must return type \"cstring\"",
1817                                                 NameListToString(procname))));
1818
1819         return procOid;
1820 }
1821
1822 static Oid
1823 findTypeAnalyzeFunction(List *procname, Oid typeOid)
1824 {
1825         Oid                     argList[1];
1826         Oid                     procOid;
1827
1828         /*
1829          * Analyze functions always take one INTERNAL argument and return bool.
1830          */
1831         argList[0] = INTERNALOID;
1832
1833         procOid = LookupFuncName(procname, 1, argList, true);
1834         if (!OidIsValid(procOid))
1835                 ereport(ERROR,
1836                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1837                                  errmsg("function %s does not exist",
1838                                                 func_signature_string(procname, 1, NIL, argList))));
1839
1840         if (get_func_rettype(procOid) != BOOLOID)
1841                 ereport(ERROR,
1842                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1843                           errmsg("type analyze function %s must return type \"boolean\"",
1844                                          NameListToString(procname))));
1845
1846         return procOid;
1847 }
1848
1849 /*
1850  * Find suitable support functions and opclasses for a range type.
1851  */
1852
1853 /*
1854  * Find named btree opclass for subtype, or default btree opclass if
1855  * opcname is NIL.
1856  */
1857 static Oid
1858 findRangeSubOpclass(List *opcname, Oid subtype)
1859 {
1860         Oid                     opcid;
1861         Oid                     opInputType;
1862
1863         if (opcname != NIL)
1864         {
1865                 opcid = get_opclass_oid(BTREE_AM_OID, opcname, false);
1866
1867                 /*
1868                  * Verify that the operator class accepts this datatype. Note we will
1869                  * accept binary compatibility.
1870                  */
1871                 opInputType = get_opclass_input_type(opcid);
1872                 if (!IsBinaryCoercible(subtype, opInputType))
1873                         ereport(ERROR,
1874                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
1875                                  errmsg("operator class \"%s\" does not accept data type %s",
1876                                                 NameListToString(opcname),
1877                                                 format_type_be(subtype))));
1878         }
1879         else
1880         {
1881                 opcid = GetDefaultOpClass(subtype, BTREE_AM_OID);
1882                 if (!OidIsValid(opcid))
1883                 {
1884                         /* We spell the error message identically to GetIndexOpClass */
1885                         ereport(ERROR,
1886                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
1887                                          errmsg("data type %s has no default operator class for access method \"%s\"",
1888                                                         format_type_be(subtype), "btree"),
1889                                          errhint("You must specify an operator class for the range type or define a default operator class for the subtype.")));
1890                 }
1891         }
1892
1893         return opcid;
1894 }
1895
1896 static Oid
1897 findRangeCanonicalFunction(List *procname, Oid typeOid)
1898 {
1899         Oid                     argList[1];
1900         Oid                     procOid;
1901         AclResult       aclresult;
1902
1903         /*
1904          * Range canonical functions must take and return the range type, and must
1905          * be immutable.
1906          */
1907         argList[0] = typeOid;
1908
1909         procOid = LookupFuncName(procname, 1, argList, true);
1910
1911         if (!OidIsValid(procOid))
1912                 ereport(ERROR,
1913                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1914                                  errmsg("function %s does not exist",
1915                                                 func_signature_string(procname, 1, NIL, argList))));
1916
1917         if (get_func_rettype(procOid) != typeOid)
1918                 ereport(ERROR,
1919                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1920                                  errmsg("range canonical function %s must return range type",
1921                                                 func_signature_string(procname, 1, NIL, argList))));
1922
1923         if (func_volatile(procOid) != PROVOLATILE_IMMUTABLE)
1924                 ereport(ERROR,
1925                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1926                                  errmsg("range canonical function %s must be immutable",
1927                                                 func_signature_string(procname, 1, NIL, argList))));
1928
1929         /* Also, range type's creator must have permission to call function */
1930         aclresult = pg_proc_aclcheck(procOid, GetUserId(), ACL_EXECUTE);
1931         if (aclresult != ACLCHECK_OK)
1932                 aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(procOid));
1933
1934         return procOid;
1935 }
1936
1937 static Oid
1938 findRangeSubtypeDiffFunction(List *procname, Oid subtype)
1939 {
1940         Oid                     argList[2];
1941         Oid                     procOid;
1942         AclResult       aclresult;
1943
1944         /*
1945          * Range subtype diff functions must take two arguments of the subtype,
1946          * must return float8, and must be immutable.
1947          */
1948         argList[0] = subtype;
1949         argList[1] = subtype;
1950
1951         procOid = LookupFuncName(procname, 2, argList, true);
1952
1953         if (!OidIsValid(procOid))
1954                 ereport(ERROR,
1955                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1956                                  errmsg("function %s does not exist",
1957                                                 func_signature_string(procname, 2, NIL, argList))));
1958
1959         if (get_func_rettype(procOid) != FLOAT8OID)
1960                 ereport(ERROR,
1961                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1962                                  errmsg("range subtype diff function %s must return type double precision",
1963                                                 func_signature_string(procname, 2, NIL, argList))));
1964
1965         if (func_volatile(procOid) != PROVOLATILE_IMMUTABLE)
1966                 ereport(ERROR,
1967                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1968                                  errmsg("range subtype diff function %s must be immutable",
1969                                                 func_signature_string(procname, 2, NIL, argList))));
1970
1971         /* Also, range type's creator must have permission to call function */
1972         aclresult = pg_proc_aclcheck(procOid, GetUserId(), ACL_EXECUTE);
1973         if (aclresult != ACLCHECK_OK)
1974                 aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(procOid));
1975
1976         return procOid;
1977 }
1978
1979 /*
1980  *      AssignTypeArrayOid
1981  *
1982  *      Pre-assign the type's array OID for use in pg_type.typarray
1983  */
1984 Oid
1985 AssignTypeArrayOid(void)
1986 {
1987         Oid                     type_array_oid;
1988
1989         /* Use binary-upgrade override for pg_type.typarray, if supplied. */
1990         if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_array_pg_type_oid))
1991         {
1992                 type_array_oid = binary_upgrade_next_array_pg_type_oid;
1993                 binary_upgrade_next_array_pg_type_oid = InvalidOid;
1994         }
1995         else
1996         {
1997                 Relation        pg_type = heap_open(TypeRelationId, AccessShareLock);
1998
1999                 type_array_oid = GetNewOid(pg_type);
2000                 heap_close(pg_type, AccessShareLock);
2001         }
2002
2003         return type_array_oid;
2004 }
2005
2006
2007 /*-------------------------------------------------------------------
2008  * DefineCompositeType
2009  *
2010  * Create a Composite Type relation.
2011  * `DefineRelation' does all the work, we just provide the correct
2012  * arguments!
2013  *
2014  * If the relation already exists, then 'DefineRelation' will abort
2015  * the xact...
2016  *
2017  * DefineCompositeType returns relid for use when creating
2018  * an implicit composite type during function creation
2019  *-------------------------------------------------------------------
2020  */
2021 Oid
2022 DefineCompositeType(RangeVar *typevar, List *coldeflist)
2023 {
2024         CreateStmt *createStmt = makeNode(CreateStmt);
2025         Oid                     old_type_oid;
2026         Oid                     typeNamespace;
2027         Oid                     relid;
2028
2029         /*
2030          * now set the parameters for keys/inheritance etc. All of these are
2031          * uninteresting for composite types...
2032          */
2033         createStmt->relation = typevar;
2034         createStmt->tableElts = coldeflist;
2035         createStmt->inhRelations = NIL;
2036         createStmt->constraints = NIL;
2037         createStmt->options = NIL;
2038         createStmt->oncommit = ONCOMMIT_NOOP;
2039         createStmt->tablespacename = NULL;
2040         createStmt->if_not_exists = false;
2041
2042         /*
2043          * Check for collision with an existing type name. If there is one and
2044          * it's an autogenerated array, we can rename it out of the way.  This
2045          * check is here mainly to get a better error message about a "type"
2046          * instead of below about a "relation".
2047          */
2048         typeNamespace = RangeVarGetAndCheckCreationNamespace(createStmt->relation,
2049                                                                                                                  NoLock, NULL);
2050         RangeVarAdjustRelationPersistence(createStmt->relation, typeNamespace);
2051         old_type_oid =
2052                 GetSysCacheOid2(TYPENAMENSP,
2053                                                 CStringGetDatum(createStmt->relation->relname),
2054                                                 ObjectIdGetDatum(typeNamespace));
2055         if (OidIsValid(old_type_oid))
2056         {
2057                 if (!moveArrayTypeName(old_type_oid, createStmt->relation->relname, typeNamespace))
2058                         ereport(ERROR,
2059                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
2060                                          errmsg("type \"%s\" already exists", createStmt->relation->relname)));
2061         }
2062
2063         /*
2064          * Finally create the relation.  This also creates the type.
2065          */
2066         relid = DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid);
2067         Assert(relid != InvalidOid);
2068         return relid;
2069 }
2070
2071 /*
2072  * AlterDomainDefault
2073  *
2074  * Routine implementing ALTER DOMAIN SET/DROP DEFAULT statements.
2075  */
2076 Oid
2077 AlterDomainDefault(List *names, Node *defaultRaw)
2078 {
2079         TypeName   *typename;
2080         Oid                     domainoid;
2081         HeapTuple       tup;
2082         ParseState *pstate;
2083         Relation        rel;
2084         char       *defaultValue;
2085         Node       *defaultExpr = NULL;         /* NULL if no default specified */
2086         Datum           new_record[Natts_pg_type];
2087         bool            new_record_nulls[Natts_pg_type];
2088         bool            new_record_repl[Natts_pg_type];
2089         HeapTuple       newtuple;
2090         Form_pg_type typTup;
2091
2092         /* Make a TypeName so we can use standard type lookup machinery */
2093         typename = makeTypeNameFromNameList(names);
2094         domainoid = typenameTypeId(NULL, typename);
2095
2096         /* Look up the domain in the type table */
2097         rel = heap_open(TypeRelationId, RowExclusiveLock);
2098
2099         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2100         if (!HeapTupleIsValid(tup))
2101                 elog(ERROR, "cache lookup failed for type %u", domainoid);
2102         typTup = (Form_pg_type) GETSTRUCT(tup);
2103
2104         /* Check it's a domain and check user has permission for ALTER DOMAIN */
2105         checkDomainOwner(tup);
2106
2107         /* Setup new tuple */
2108         MemSet(new_record, (Datum) 0, sizeof(new_record));
2109         MemSet(new_record_nulls, false, sizeof(new_record_nulls));
2110         MemSet(new_record_repl, false, sizeof(new_record_repl));
2111
2112         /* Store the new default into the tuple */
2113         if (defaultRaw)
2114         {
2115                 /* Create a dummy ParseState for transformExpr */
2116                 pstate = make_parsestate(NULL);
2117
2118                 /*
2119                  * Cook the colDef->raw_expr into an expression. Note: Name is
2120                  * strictly for error message
2121                  */
2122                 defaultExpr = cookDefault(pstate, defaultRaw,
2123                                                                   typTup->typbasetype,
2124                                                                   typTup->typtypmod,
2125                                                                   NameStr(typTup->typname));
2126
2127                 /*
2128                  * If the expression is just a NULL constant, we treat the command
2129                  * like ALTER ... DROP DEFAULT.  (But see note for same test in
2130                  * DefineDomain.)
2131                  */
2132                 if (defaultExpr == NULL ||
2133                         (IsA(defaultExpr, Const) &&((Const *) defaultExpr)->constisnull))
2134                 {
2135                         /* Default is NULL, drop it */
2136                         new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true;
2137                         new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
2138                         new_record_nulls[Anum_pg_type_typdefault - 1] = true;
2139                         new_record_repl[Anum_pg_type_typdefault - 1] = true;
2140                 }
2141                 else
2142                 {
2143                         /*
2144                          * Expression must be stored as a nodeToString result, but we also
2145                          * require a valid textual representation (mainly to make life
2146                          * easier for pg_dump).
2147                          */
2148                         defaultValue = deparse_expression(defaultExpr,
2149                                                                                           NIL, false, false);
2150
2151                         /*
2152                          * Form an updated tuple with the new default and write it back.
2153                          */
2154                         new_record[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(nodeToString(defaultExpr));
2155
2156                         new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
2157                         new_record[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultValue);
2158                         new_record_repl[Anum_pg_type_typdefault - 1] = true;
2159                 }
2160         }
2161         else
2162         {
2163                 /* ALTER ... DROP DEFAULT */
2164                 new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true;
2165                 new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
2166                 new_record_nulls[Anum_pg_type_typdefault - 1] = true;
2167                 new_record_repl[Anum_pg_type_typdefault - 1] = true;
2168         }
2169
2170         newtuple = heap_modify_tuple(tup, RelationGetDescr(rel),
2171                                                                  new_record, new_record_nulls,
2172                                                                  new_record_repl);
2173
2174         simple_heap_update(rel, &tup->t_self, newtuple);
2175
2176         CatalogUpdateIndexes(rel, newtuple);
2177
2178         /* Rebuild dependencies */
2179         GenerateTypeDependencies(typTup->typnamespace,
2180                                                          domainoid,
2181                                                          InvalidOid,            /* typrelid is n/a */
2182                                                          0, /* relation kind is n/a */
2183                                                          typTup->typowner,
2184                                                          typTup->typinput,
2185                                                          typTup->typoutput,
2186                                                          typTup->typreceive,
2187                                                          typTup->typsend,
2188                                                          typTup->typmodin,
2189                                                          typTup->typmodout,
2190                                                          typTup->typanalyze,
2191                                                          InvalidOid,
2192                                                          false,         /* a domain isn't an implicit array */
2193                                                          typTup->typbasetype,
2194                                                          typTup->typcollation,
2195                                                          defaultExpr,
2196                                                          true);         /* Rebuild is true */
2197
2198         InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
2199
2200         /* Clean up */
2201         heap_close(rel, NoLock);
2202         heap_freetuple(newtuple);
2203
2204         return domainoid;
2205 }
2206
2207 /*
2208  * AlterDomainNotNull
2209  *
2210  * Routine implementing ALTER DOMAIN SET/DROP NOT NULL statements.
2211  */
2212 Oid
2213 AlterDomainNotNull(List *names, bool notNull)
2214 {
2215         TypeName   *typename;
2216         Oid                     domainoid;
2217         Relation        typrel;
2218         HeapTuple       tup;
2219         Form_pg_type typTup;
2220
2221         /* Make a TypeName so we can use standard type lookup machinery */
2222         typename = makeTypeNameFromNameList(names);
2223         domainoid = typenameTypeId(NULL, typename);
2224
2225         /* Look up the domain in the type table */
2226         typrel = heap_open(TypeRelationId, RowExclusiveLock);
2227
2228         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2229         if (!HeapTupleIsValid(tup))
2230                 elog(ERROR, "cache lookup failed for type %u", domainoid);
2231         typTup = (Form_pg_type) GETSTRUCT(tup);
2232
2233         /* Check it's a domain and check user has permission for ALTER DOMAIN */
2234         checkDomainOwner(tup);
2235
2236         /* Is the domain already set to the desired constraint? */
2237         if (typTup->typnotnull == notNull)
2238         {
2239                 heap_close(typrel, RowExclusiveLock);
2240                 return InvalidOid;
2241         }
2242
2243         /* Adding a NOT NULL constraint requires checking existing columns */
2244         if (notNull)
2245         {
2246                 List       *rels;
2247                 ListCell   *rt;
2248
2249                 /* Fetch relation list with attributes based on this domain */
2250                 /* ShareLock is sufficient to prevent concurrent data changes */
2251
2252                 rels = get_rels_with_domain(domainoid, ShareLock);
2253
2254                 foreach(rt, rels)
2255                 {
2256                         RelToCheck *rtc = (RelToCheck *) lfirst(rt);
2257                         Relation        testrel = rtc->rel;
2258                         TupleDesc       tupdesc = RelationGetDescr(testrel);
2259                         HeapScanDesc scan;
2260                         HeapTuple       tuple;
2261                         Snapshot        snapshot;
2262
2263                         /* Scan all tuples in this relation */
2264                         snapshot = RegisterSnapshot(GetLatestSnapshot());
2265                         scan = heap_beginscan(testrel, snapshot, 0, NULL);
2266                         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2267                         {
2268                                 int                     i;
2269
2270                                 /* Test attributes that are of the domain */
2271                                 for (i = 0; i < rtc->natts; i++)
2272                                 {
2273                                         int                     attnum = rtc->atts[i];
2274
2275                                         if (heap_attisnull(tuple, attnum))
2276                                         {
2277                                                 /*
2278                                                  * In principle the auxiliary information for this
2279                                                  * error should be errdatatype(), but errtablecol()
2280                                                  * seems considerably more useful in practice.  Since
2281                                                  * this code only executes in an ALTER DOMAIN command,
2282                                                  * the client should already know which domain is in
2283                                                  * question.
2284                                                  */
2285                                                 ereport(ERROR,
2286                                                                 (errcode(ERRCODE_NOT_NULL_VIOLATION),
2287                                                                  errmsg("column \"%s\" of table \"%s\" contains null values",
2288                                                                 NameStr(tupdesc->attrs[attnum - 1]->attname),
2289                                                                                 RelationGetRelationName(testrel)),
2290                                                                  errtablecol(testrel, attnum)));
2291                                         }
2292                                 }
2293                         }
2294                         heap_endscan(scan);
2295                         UnregisterSnapshot(snapshot);
2296
2297                         /* Close each rel after processing, but keep lock */
2298                         heap_close(testrel, NoLock);
2299                 }
2300         }
2301
2302         /*
2303          * Okay to update pg_type row.  We can scribble on typTup because it's a
2304          * copy.
2305          */
2306         typTup->typnotnull = notNull;
2307
2308         simple_heap_update(typrel, &tup->t_self, tup);
2309
2310         CatalogUpdateIndexes(typrel, tup);
2311
2312         InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
2313
2314         /* Clean up */
2315         heap_freetuple(tup);
2316         heap_close(typrel, RowExclusiveLock);
2317
2318         return domainoid;
2319 }
2320
2321 /*
2322  * AlterDomainDropConstraint
2323  *
2324  * Implements the ALTER DOMAIN DROP CONSTRAINT statement
2325  */
2326 Oid
2327 AlterDomainDropConstraint(List *names, const char *constrName,
2328                                                   DropBehavior behavior, bool missing_ok)
2329 {
2330         TypeName   *typename;
2331         Oid                     domainoid;
2332         HeapTuple       tup;
2333         Relation        rel;
2334         Relation        conrel;
2335         SysScanDesc conscan;
2336         ScanKeyData key[1];
2337         HeapTuple       contup;
2338         bool            found = false;
2339
2340         /* Make a TypeName so we can use standard type lookup machinery */
2341         typename = makeTypeNameFromNameList(names);
2342         domainoid = typenameTypeId(NULL, typename);
2343
2344         /* Look up the domain in the type table */
2345         rel = heap_open(TypeRelationId, RowExclusiveLock);
2346
2347         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2348         if (!HeapTupleIsValid(tup))
2349                 elog(ERROR, "cache lookup failed for type %u", domainoid);
2350
2351         /* Check it's a domain and check user has permission for ALTER DOMAIN */
2352         checkDomainOwner(tup);
2353
2354         /* Grab an appropriate lock on the pg_constraint relation */
2355         conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
2356
2357         /* Use the index to scan only constraints of the target relation */
2358         ScanKeyInit(&key[0],
2359                                 Anum_pg_constraint_contypid,
2360                                 BTEqualStrategyNumber, F_OIDEQ,
2361                                 ObjectIdGetDatum(HeapTupleGetOid(tup)));
2362
2363         conscan = systable_beginscan(conrel, ConstraintTypidIndexId, true,
2364                                                                  NULL, 1, key);
2365
2366         /*
2367          * Scan over the result set, removing any matching entries.
2368          */
2369         while ((contup = systable_getnext(conscan)) != NULL)
2370         {
2371                 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(contup);
2372
2373                 if (strcmp(NameStr(con->conname), constrName) == 0)
2374                 {
2375                         ObjectAddress conobj;
2376
2377                         conobj.classId = ConstraintRelationId;
2378                         conobj.objectId = HeapTupleGetOid(contup);
2379                         conobj.objectSubId = 0;
2380
2381                         performDeletion(&conobj, behavior, 0);
2382                         found = true;
2383                 }
2384         }
2385         /* Clean up after the scan */
2386         systable_endscan(conscan);
2387         heap_close(conrel, RowExclusiveLock);
2388
2389         heap_close(rel, NoLock);
2390
2391         if (!found)
2392         {
2393                 if (!missing_ok)
2394                         ereport(ERROR,
2395                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
2396                                   errmsg("constraint \"%s\" of domain \"%s\" does not exist",
2397                                                  constrName, TypeNameToString(typename))));
2398                 else
2399                         ereport(NOTICE,
2400                                         (errmsg("constraint \"%s\" of domain \"%s\" does not exist, skipping",
2401                                                         constrName, TypeNameToString(typename))));
2402         }
2403
2404         return domainoid;
2405 }
2406
2407 /*
2408  * AlterDomainAddConstraint
2409  *
2410  * Implements the ALTER DOMAIN .. ADD CONSTRAINT statement.
2411  */
2412 Oid
2413 AlterDomainAddConstraint(List *names, Node *newConstraint)
2414 {
2415         TypeName   *typename;
2416         Oid                     domainoid;
2417         Relation        typrel;
2418         HeapTuple       tup;
2419         Form_pg_type typTup;
2420         Constraint *constr;
2421         char       *ccbin;
2422
2423         /* Make a TypeName so we can use standard type lookup machinery */
2424         typename = makeTypeNameFromNameList(names);
2425         domainoid = typenameTypeId(NULL, typename);
2426
2427         /* Look up the domain in the type table */
2428         typrel = heap_open(TypeRelationId, RowExclusiveLock);
2429
2430         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2431         if (!HeapTupleIsValid(tup))
2432                 elog(ERROR, "cache lookup failed for type %u", domainoid);
2433         typTup = (Form_pg_type) GETSTRUCT(tup);
2434
2435         /* Check it's a domain and check user has permission for ALTER DOMAIN */
2436         checkDomainOwner(tup);
2437
2438         if (!IsA(newConstraint, Constraint))
2439                 elog(ERROR, "unrecognized node type: %d",
2440                          (int) nodeTag(newConstraint));
2441
2442         constr = (Constraint *) newConstraint;
2443
2444         switch (constr->contype)
2445         {
2446                 case CONSTR_CHECK:
2447                         /* processed below */
2448                         break;
2449
2450                 case CONSTR_UNIQUE:
2451                         ereport(ERROR,
2452                                         (errcode(ERRCODE_SYNTAX_ERROR),
2453                                          errmsg("unique constraints not possible for domains")));
2454                         break;
2455
2456                 case CONSTR_PRIMARY:
2457                         ereport(ERROR,
2458                                         (errcode(ERRCODE_SYNTAX_ERROR),
2459                                 errmsg("primary key constraints not possible for domains")));
2460                         break;
2461
2462                 case CONSTR_EXCLUSION:
2463                         ereport(ERROR,
2464                                         (errcode(ERRCODE_SYNTAX_ERROR),
2465                                   errmsg("exclusion constraints not possible for domains")));
2466                         break;
2467
2468                 case CONSTR_FOREIGN:
2469                         ereport(ERROR,
2470                                         (errcode(ERRCODE_SYNTAX_ERROR),
2471                                 errmsg("foreign key constraints not possible for domains")));
2472                         break;
2473
2474                 case CONSTR_ATTR_DEFERRABLE:
2475                 case CONSTR_ATTR_NOT_DEFERRABLE:
2476                 case CONSTR_ATTR_DEFERRED:
2477                 case CONSTR_ATTR_IMMEDIATE:
2478                         ereport(ERROR,
2479                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2480                                          errmsg("specifying constraint deferrability not supported for domains")));
2481                         break;
2482
2483                 default:
2484                         elog(ERROR, "unrecognized constraint subtype: %d",
2485                                  (int) constr->contype);
2486                         break;
2487         }
2488
2489         /*
2490          * Since all other constraint types throw errors, this must be a check
2491          * constraint.  First, process the constraint expression and add an entry
2492          * to pg_constraint.
2493          */
2494
2495         ccbin = domainAddConstraint(domainoid, typTup->typnamespace,
2496                                                                 typTup->typbasetype, typTup->typtypmod,
2497                                                                 constr, NameStr(typTup->typname));
2498
2499         /*
2500          * If requested to validate the constraint, test all values stored in the
2501          * attributes based on the domain the constraint is being added to.
2502          */
2503         if (!constr->skip_validation)
2504                 validateDomainConstraint(domainoid, ccbin);
2505
2506         /* Clean up */
2507         heap_close(typrel, RowExclusiveLock);
2508
2509         return domainoid;
2510 }
2511
2512 /*
2513  * AlterDomainValidateConstraint
2514  *
2515  * Implements the ALTER DOMAIN .. VALIDATE CONSTRAINT statement.
2516  */
2517 Oid
2518 AlterDomainValidateConstraint(List *names, char *constrName)
2519 {
2520         TypeName   *typename;
2521         Oid                     domainoid;
2522         Relation        typrel;
2523         Relation        conrel;
2524         HeapTuple       tup;
2525         Form_pg_constraint con = NULL;
2526         Form_pg_constraint copy_con;
2527         char       *conbin;
2528         SysScanDesc scan;
2529         Datum           val;
2530         bool            found = false;
2531         bool            isnull;
2532         HeapTuple       tuple;
2533         HeapTuple       copyTuple;
2534         ScanKeyData key;
2535
2536         /* Make a TypeName so we can use standard type lookup machinery */
2537         typename = makeTypeNameFromNameList(names);
2538         domainoid = typenameTypeId(NULL, typename);
2539
2540         /* Look up the domain in the type table */
2541         typrel = heap_open(TypeRelationId, AccessShareLock);
2542
2543         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(domainoid));
2544         if (!HeapTupleIsValid(tup))
2545                 elog(ERROR, "cache lookup failed for type %u", domainoid);
2546
2547         /* Check it's a domain and check user has permission for ALTER DOMAIN */
2548         checkDomainOwner(tup);
2549
2550         /*
2551          * Find and check the target constraint
2552          */
2553         conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
2554         ScanKeyInit(&key,
2555                                 Anum_pg_constraint_contypid,
2556                                 BTEqualStrategyNumber, F_OIDEQ,
2557                                 ObjectIdGetDatum(domainoid));
2558         scan = systable_beginscan(conrel, ConstraintTypidIndexId,
2559                                                           true, NULL, 1, &key);
2560
2561         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2562         {
2563                 con = (Form_pg_constraint) GETSTRUCT(tuple);
2564                 if (strcmp(NameStr(con->conname), constrName) == 0)
2565                 {
2566                         found = true;
2567                         break;
2568                 }
2569         }
2570
2571         if (!found)
2572                 ereport(ERROR,
2573                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
2574                                  errmsg("constraint \"%s\" of domain \"%s\" does not exist",
2575                                                 constrName, TypeNameToString(typename))));
2576
2577         if (con->contype != CONSTRAINT_CHECK)
2578                 ereport(ERROR,
2579                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2580                 errmsg("constraint \"%s\" of domain \"%s\" is not a check constraint",
2581                            constrName, TypeNameToString(typename))));
2582
2583         val = SysCacheGetAttr(CONSTROID, tuple,
2584                                                   Anum_pg_constraint_conbin,
2585                                                   &isnull);
2586         if (isnull)
2587                 elog(ERROR, "null conbin for constraint %u",
2588                          HeapTupleGetOid(tuple));
2589         conbin = TextDatumGetCString(val);
2590
2591         validateDomainConstraint(domainoid, conbin);
2592
2593         /*
2594          * Now update the catalog, while we have the door open.
2595          */
2596         copyTuple = heap_copytuple(tuple);
2597         copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
2598         copy_con->convalidated = true;
2599         simple_heap_update(conrel, &copyTuple->t_self, copyTuple);
2600         CatalogUpdateIndexes(conrel, copyTuple);
2601
2602         InvokeObjectPostAlterHook(ConstraintRelationId,
2603                                                           HeapTupleGetOid(copyTuple), 0);
2604
2605         heap_freetuple(copyTuple);
2606
2607         systable_endscan(scan);
2608
2609         heap_close(typrel, AccessShareLock);
2610         heap_close(conrel, RowExclusiveLock);
2611
2612         ReleaseSysCache(tup);
2613
2614         return domainoid;
2615 }
2616
2617 static void
2618 validateDomainConstraint(Oid domainoid, char *ccbin)
2619 {
2620         Expr       *expr = (Expr *) stringToNode(ccbin);
2621         List       *rels;
2622         ListCell   *rt;
2623         EState     *estate;
2624         ExprContext *econtext;
2625         ExprState  *exprstate;
2626
2627         /* Need an EState to run ExecEvalExpr */
2628         estate = CreateExecutorState();
2629         econtext = GetPerTupleExprContext(estate);
2630
2631         /* build execution state for expr */
2632         exprstate = ExecPrepareExpr(expr, estate);
2633
2634         /* Fetch relation list with attributes based on this domain */
2635         /* ShareLock is sufficient to prevent concurrent data changes */
2636
2637         rels = get_rels_with_domain(domainoid, ShareLock);
2638
2639         foreach(rt, rels)
2640         {
2641                 RelToCheck *rtc = (RelToCheck *) lfirst(rt);
2642                 Relation        testrel = rtc->rel;
2643                 TupleDesc       tupdesc = RelationGetDescr(testrel);
2644                 HeapScanDesc scan;
2645                 HeapTuple       tuple;
2646                 Snapshot        snapshot;
2647
2648                 /* Scan all tuples in this relation */
2649                 snapshot = RegisterSnapshot(GetLatestSnapshot());
2650                 scan = heap_beginscan(testrel, snapshot, 0, NULL);
2651                 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2652                 {
2653                         int                     i;
2654
2655                         /* Test attributes that are of the domain */
2656                         for (i = 0; i < rtc->natts; i++)
2657                         {
2658                                 int                     attnum = rtc->atts[i];
2659                                 Datum           d;
2660                                 bool            isNull;
2661                                 Datum           conResult;
2662
2663                                 d = heap_getattr(tuple, attnum, tupdesc, &isNull);
2664
2665                                 econtext->domainValue_datum = d;
2666                                 econtext->domainValue_isNull = isNull;
2667
2668                                 conResult = ExecEvalExprSwitchContext(exprstate,
2669                                                                                                           econtext,
2670                                                                                                           &isNull, NULL);
2671
2672                                 if (!isNull && !DatumGetBool(conResult))
2673                                 {
2674                                         /*
2675                                          * In principle the auxiliary information for this error
2676                                          * should be errdomainconstraint(), but errtablecol()
2677                                          * seems considerably more useful in practice.  Since this
2678                                          * code only executes in an ALTER DOMAIN command, the
2679                                          * client should already know which domain is in question,
2680                                          * and which constraint too.
2681                                          */
2682                                         ereport(ERROR,
2683                                                         (errcode(ERRCODE_CHECK_VIOLATION),
2684                                                          errmsg("column \"%s\" of table \"%s\" contains values that violate the new constraint",
2685                                                                 NameStr(tupdesc->attrs[attnum - 1]->attname),
2686                                                                         RelationGetRelationName(testrel)),
2687                                                          errtablecol(testrel, attnum)));
2688                                 }
2689                         }
2690
2691                         ResetExprContext(econtext);
2692                 }
2693                 heap_endscan(scan);
2694                 UnregisterSnapshot(snapshot);
2695
2696                 /* Hold relation lock till commit (XXX bad for concurrency) */
2697                 heap_close(testrel, NoLock);
2698         }
2699
2700         FreeExecutorState(estate);
2701 }
2702
2703 /*
2704  * get_rels_with_domain
2705  *
2706  * Fetch all relations / attributes which are using the domain
2707  *
2708  * The result is a list of RelToCheck structs, one for each distinct
2709  * relation, each containing one or more attribute numbers that are of
2710  * the domain type.  We have opened each rel and acquired the specified lock
2711  * type on it.
2712  *
2713  * We support nested domains by including attributes that are of derived
2714  * domain types.  Current callers do not need to distinguish between attributes
2715  * that are of exactly the given domain and those that are of derived domains.
2716  *
2717  * XXX this is completely broken because there is no way to lock the domain
2718  * to prevent columns from being added or dropped while our command runs.
2719  * We can partially protect against column drops by locking relations as we
2720  * come across them, but there is still a race condition (the window between
2721  * seeing a pg_depend entry and acquiring lock on the relation it references).
2722  * Also, holding locks on all these relations simultaneously creates a non-
2723  * trivial risk of deadlock.  We can minimize but not eliminate the deadlock
2724  * risk by using the weakest suitable lock (ShareLock for most callers).
2725  *
2726  * XXX the API for this is not sufficient to support checking domain values
2727  * that are inside composite types or arrays.  Currently we just error out
2728  * if a composite type containing the target domain is stored anywhere.
2729  * There are not currently arrays of domains; if there were, we could take
2730  * the same approach, but it'd be nicer to fix it properly.
2731  *
2732  * Generally used for retrieving a list of tests when adding
2733  * new constraints to a domain.
2734  */
2735 static List *
2736 get_rels_with_domain(Oid domainOid, LOCKMODE lockmode)
2737 {
2738         List       *result = NIL;
2739         Relation        depRel;
2740         ScanKeyData key[2];
2741         SysScanDesc depScan;
2742         HeapTuple       depTup;
2743
2744         Assert(lockmode != NoLock);
2745
2746         /*
2747          * We scan pg_depend to find those things that depend on the domain. (We
2748          * assume we can ignore refobjsubid for a domain.)
2749          */
2750         depRel = heap_open(DependRelationId, AccessShareLock);
2751
2752         ScanKeyInit(&key[0],
2753                                 Anum_pg_depend_refclassid,
2754                                 BTEqualStrategyNumber, F_OIDEQ,
2755                                 ObjectIdGetDatum(TypeRelationId));
2756         ScanKeyInit(&key[1],
2757                                 Anum_pg_depend_refobjid,
2758                                 BTEqualStrategyNumber, F_OIDEQ,
2759                                 ObjectIdGetDatum(domainOid));
2760
2761         depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
2762                                                                  NULL, 2, key);
2763
2764         while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2765         {
2766                 Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2767                 RelToCheck *rtc = NULL;
2768                 ListCell   *rellist;
2769                 Form_pg_attribute pg_att;
2770                 int                     ptr;
2771
2772                 /* Check for directly dependent types --- must be domains */
2773                 if (pg_depend->classid == TypeRelationId)
2774                 {
2775                         Assert(get_typtype(pg_depend->objid) == TYPTYPE_DOMAIN);
2776
2777                         /*
2778                          * Recursively add dependent columns to the output list.  This is
2779                          * a bit inefficient since we may fail to combine RelToCheck
2780                          * entries when attributes of the same rel have different derived
2781                          * domain types, but it's probably not worth improving.
2782                          */
2783                         result = list_concat(result,
2784                                                                  get_rels_with_domain(pg_depend->objid,
2785                                                                                                           lockmode));
2786                         continue;
2787                 }
2788
2789                 /* Else, ignore dependees that aren't user columns of relations */
2790                 /* (we assume system columns are never of domain types) */
2791                 if (pg_depend->classid != RelationRelationId ||
2792                         pg_depend->objsubid <= 0)
2793                         continue;
2794
2795                 /* See if we already have an entry for this relation */
2796                 foreach(rellist, result)
2797                 {
2798                         RelToCheck *rt = (RelToCheck *) lfirst(rellist);
2799
2800                         if (RelationGetRelid(rt->rel) == pg_depend->objid)
2801                         {
2802                                 rtc = rt;
2803                                 break;
2804                         }
2805                 }
2806
2807                 if (rtc == NULL)
2808                 {
2809                         /* First attribute found for this relation */
2810                         Relation        rel;
2811
2812                         /* Acquire requested lock on relation */
2813                         rel = relation_open(pg_depend->objid, lockmode);
2814
2815                         /*
2816                          * Check to see if rowtype is stored anyplace as a composite-type
2817                          * column; if so we have to fail, for now anyway.
2818                          */
2819                         if (OidIsValid(rel->rd_rel->reltype))
2820                                 find_composite_type_dependencies(rel->rd_rel->reltype,
2821                                                                                                  NULL,
2822                                                                                                  format_type_be(domainOid));
2823
2824                         /*
2825                          * Otherwise, we can ignore relations except those with both
2826                          * storage and user-chosen column types.
2827                          *
2828                          * XXX If an index-only scan could satisfy "col::some_domain" from
2829                          * a suitable expression index, this should also check expression
2830                          * index columns.
2831                          */
2832                         if (rel->rd_rel->relkind != RELKIND_RELATION &&
2833                                 rel->rd_rel->relkind != RELKIND_MATVIEW)
2834                         {
2835                                 relation_close(rel, lockmode);
2836                                 continue;
2837                         }
2838
2839                         /* Build the RelToCheck entry with enough space for all atts */
2840                         rtc = (RelToCheck *) palloc(sizeof(RelToCheck));
2841                         rtc->rel = rel;
2842                         rtc->natts = 0;
2843                         rtc->atts = (int *) palloc(sizeof(int) * RelationGetNumberOfAttributes(rel));
2844                         result = lcons(rtc, result);
2845                 }
2846
2847                 /*
2848                  * Confirm column has not been dropped, and is of the expected type.
2849                  * This defends against an ALTER DROP COLUMN occurring just before we
2850                  * acquired lock ... but if the whole table were dropped, we'd still
2851                  * have a problem.
2852                  */
2853                 if (pg_depend->objsubid > RelationGetNumberOfAttributes(rtc->rel))
2854                         continue;
2855                 pg_att = rtc->rel->rd_att->attrs[pg_depend->objsubid - 1];
2856                 if (pg_att->attisdropped || pg_att->atttypid != domainOid)
2857                         continue;
2858
2859                 /*
2860                  * Okay, add column to result.  We store the columns in column-number
2861                  * order; this is just a hack to improve predictability of regression
2862                  * test output ...
2863                  */
2864                 Assert(rtc->natts < RelationGetNumberOfAttributes(rtc->rel));
2865
2866                 ptr = rtc->natts++;
2867                 while (ptr > 0 && rtc->atts[ptr - 1] > pg_depend->objsubid)
2868                 {
2869                         rtc->atts[ptr] = rtc->atts[ptr - 1];
2870                         ptr--;
2871                 }
2872                 rtc->atts[ptr] = pg_depend->objsubid;
2873         }
2874
2875         systable_endscan(depScan);
2876
2877         relation_close(depRel, AccessShareLock);
2878
2879         return result;
2880 }
2881
2882 /*
2883  * checkDomainOwner
2884  *
2885  * Check that the type is actually a domain and that the current user
2886  * has permission to do ALTER DOMAIN on it.  Throw an error if not.
2887  */
2888 void
2889 checkDomainOwner(HeapTuple tup)
2890 {
2891         Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
2892
2893         /* Check that this is actually a domain */
2894         if (typTup->typtype != TYPTYPE_DOMAIN)
2895                 ereport(ERROR,
2896                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2897                                  errmsg("%s is not a domain",
2898                                                 format_type_be(HeapTupleGetOid(tup)))));
2899
2900         /* Permission check: must own type */
2901         if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
2902                 aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup));
2903 }
2904
2905 /*
2906  * domainAddConstraint - code shared between CREATE and ALTER DOMAIN
2907  */
2908 static char *
2909 domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
2910                                         int typMod, Constraint *constr,
2911                                         char *domainName)
2912 {
2913         Node       *expr;
2914         char       *ccsrc;
2915         char       *ccbin;
2916         ParseState *pstate;
2917         CoerceToDomainValue *domVal;
2918
2919         /*
2920          * Assign or validate constraint name
2921          */
2922         if (constr->conname)
2923         {
2924                 if (ConstraintNameIsUsed(CONSTRAINT_DOMAIN,
2925                                                                  domainOid,
2926                                                                  domainNamespace,
2927                                                                  constr->conname))
2928                         ereport(ERROR,
2929                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
2930                                  errmsg("constraint \"%s\" for domain \"%s\" already exists",
2931                                                 constr->conname, domainName)));
2932         }
2933         else
2934                 constr->conname = ChooseConstraintName(domainName,
2935                                                                                            NULL,
2936                                                                                            "check",
2937                                                                                            domainNamespace,
2938                                                                                            NIL);
2939
2940         /*
2941          * Convert the A_EXPR in raw_expr into an EXPR
2942          */
2943         pstate = make_parsestate(NULL);
2944
2945         /*
2946          * Set up a CoerceToDomainValue to represent the occurrence of VALUE in
2947          * the expression.      Note that it will appear to have the type of the base
2948          * type, not the domain.  This seems correct since within the check
2949          * expression, we should not assume the input value can be considered a
2950          * member of the domain.
2951          */
2952         domVal = makeNode(CoerceToDomainValue);
2953         domVal->typeId = baseTypeOid;
2954         domVal->typeMod = typMod;
2955         domVal->collation = get_typcollation(baseTypeOid);
2956         domVal->location = -1;          /* will be set when/if used */
2957
2958         pstate->p_value_substitute = (Node *) domVal;
2959
2960         expr = transformExpr(pstate, constr->raw_expr, EXPR_KIND_DOMAIN_CHECK);
2961
2962         /*
2963          * Make sure it yields a boolean result.
2964          */
2965         expr = coerce_to_boolean(pstate, expr, "CHECK");
2966
2967         /*
2968          * Fix up collation information.
2969          */
2970         assign_expr_collations(pstate, expr);
2971
2972         /*
2973          * Domains don't allow variables (this is probably dead code now that
2974          * add_missing_from is history, but let's be sure).
2975          */
2976         if (list_length(pstate->p_rtable) != 0 ||
2977                 contain_var_clause(expr))
2978                 ereport(ERROR,
2979                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2980                   errmsg("cannot use table references in domain check constraint")));
2981
2982         /*
2983          * Convert to string form for storage.
2984          */
2985         ccbin = nodeToString(expr);
2986
2987         /*
2988          * Deparse it to produce text for consrc.
2989          */
2990         ccsrc = deparse_expression(expr,
2991                                                            NIL, false, false);
2992
2993         /*
2994          * Store the constraint in pg_constraint
2995          */
2996         CreateConstraintEntry(constr->conname,          /* Constraint Name */
2997                                                   domainNamespace,              /* namespace */
2998                                                   CONSTRAINT_CHECK,             /* Constraint Type */
2999                                                   false,        /* Is Deferrable */
3000                                                   false,        /* Is Deferred */
3001                                                   !constr->skip_validation,             /* Is Validated */
3002                                                   InvalidOid,   /* not a relation constraint */
3003                                                   NULL,
3004                                                   0,
3005                                                   domainOid,    /* domain constraint */
3006                                                   InvalidOid,   /* no associated index */
3007                                                   InvalidOid,   /* Foreign key fields */
3008                                                   NULL,
3009                                                   NULL,
3010                                                   NULL,
3011                                                   NULL,
3012                                                   0,
3013                                                   ' ',
3014                                                   ' ',
3015                                                   ' ',
3016                                                   NULL, /* not an exclusion constraint */
3017                                                   expr, /* Tree form of check constraint */
3018                                                   ccbin,        /* Binary form of check constraint */
3019                                                   ccsrc,        /* Source form of check constraint */
3020                                                   true, /* is local */
3021                                                   0,    /* inhcount */
3022                                                   false,        /* connoinherit */
3023                                                   false);               /* is_internal */
3024
3025         /*
3026          * Return the compiled constraint expression so the calling routine can
3027          * perform any additional required tests.
3028          */
3029         return ccbin;
3030 }
3031
3032 /*
3033  * GetDomainConstraints - get a list of the current constraints of domain
3034  *
3035  * Returns a possibly-empty list of DomainConstraintState nodes.
3036  *
3037  * This is called by the executor during plan startup for a CoerceToDomain
3038  * expression node.  The given constraints will be checked for each value
3039  * passed through the node.
3040  *
3041  * We allow this to be called for non-domain types, in which case the result
3042  * is always NIL.
3043  */
3044 List *
3045 GetDomainConstraints(Oid typeOid)
3046 {
3047         List       *result = NIL;
3048         bool            notNull = false;
3049         Relation        conRel;
3050
3051         conRel = heap_open(ConstraintRelationId, AccessShareLock);
3052
3053         for (;;)
3054         {
3055                 HeapTuple       tup;
3056                 HeapTuple       conTup;
3057                 Form_pg_type typTup;
3058                 ScanKeyData key[1];
3059                 SysScanDesc scan;
3060
3061                 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
3062                 if (!HeapTupleIsValid(tup))
3063                         elog(ERROR, "cache lookup failed for type %u", typeOid);
3064                 typTup = (Form_pg_type) GETSTRUCT(tup);
3065
3066                 if (typTup->typtype != TYPTYPE_DOMAIN)
3067                 {
3068                         /* Not a domain, so done */
3069                         ReleaseSysCache(tup);
3070                         break;
3071                 }
3072
3073                 /* Test for NOT NULL Constraint */
3074                 if (typTup->typnotnull)
3075                         notNull = true;
3076
3077                 /* Look for CHECK Constraints on this domain */
3078                 ScanKeyInit(&key[0],
3079                                         Anum_pg_constraint_contypid,
3080                                         BTEqualStrategyNumber, F_OIDEQ,
3081                                         ObjectIdGetDatum(typeOid));
3082
3083                 scan = systable_beginscan(conRel, ConstraintTypidIndexId, true,
3084                                                                   NULL, 1, key);
3085
3086                 while (HeapTupleIsValid(conTup = systable_getnext(scan)))
3087                 {
3088                         Form_pg_constraint c = (Form_pg_constraint) GETSTRUCT(conTup);
3089                         Datum           val;
3090                         bool            isNull;
3091                         Expr       *check_expr;
3092                         DomainConstraintState *r;
3093
3094                         /* Ignore non-CHECK constraints (presently, shouldn't be any) */
3095                         if (c->contype != CONSTRAINT_CHECK)
3096                                 continue;
3097
3098                         /*
3099                          * Not expecting conbin to be NULL, but we'll test for it anyway
3100                          */
3101                         val = fastgetattr(conTup, Anum_pg_constraint_conbin,
3102                                                           conRel->rd_att, &isNull);
3103                         if (isNull)
3104                                 elog(ERROR, "domain \"%s\" constraint \"%s\" has NULL conbin",
3105                                          NameStr(typTup->typname), NameStr(c->conname));
3106
3107                         check_expr = (Expr *) stringToNode(TextDatumGetCString(val));
3108
3109                         /* ExecInitExpr assumes we've planned the expression */
3110                         check_expr = expression_planner(check_expr);
3111
3112                         r = makeNode(DomainConstraintState);
3113                         r->constrainttype = DOM_CONSTRAINT_CHECK;
3114                         r->name = pstrdup(NameStr(c->conname));
3115                         r->check_expr = ExecInitExpr(check_expr, NULL);
3116
3117                         /*
3118                          * use lcons() here because constraints of lower domains should be
3119                          * applied earlier.
3120                          */
3121                         result = lcons(r, result);
3122                 }
3123
3124                 systable_endscan(scan);
3125
3126                 /* loop to next domain in stack */
3127                 typeOid = typTup->typbasetype;
3128                 ReleaseSysCache(tup);
3129         }
3130
3131         heap_close(conRel, AccessShareLock);
3132
3133         /*
3134          * Only need to add one NOT NULL check regardless of how many domains in
3135          * the stack request it.
3136          */
3137         if (notNull)
3138         {
3139                 DomainConstraintState *r = makeNode(DomainConstraintState);
3140
3141                 r->constrainttype = DOM_CONSTRAINT_NOTNULL;
3142                 r->name = pstrdup("NOT NULL");
3143                 r->check_expr = NULL;
3144
3145                 /* lcons to apply the nullness check FIRST */
3146                 result = lcons(r, result);
3147         }
3148
3149         return result;
3150 }
3151
3152
3153 /*
3154  * Execute ALTER TYPE RENAME
3155  */
3156 Oid
3157 RenameType(RenameStmt *stmt)
3158 {
3159         List       *names = stmt->object;
3160         const char *newTypeName = stmt->newname;
3161         TypeName   *typename;
3162         Oid                     typeOid;
3163         Relation        rel;
3164         HeapTuple       tup;
3165         Form_pg_type typTup;
3166
3167         /* Make a TypeName so we can use standard type lookup machinery */
3168         typename = makeTypeNameFromNameList(names);
3169         typeOid = typenameTypeId(NULL, typename);
3170
3171         /* Look up the type in the type table */
3172         rel = heap_open(TypeRelationId, RowExclusiveLock);
3173
3174         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
3175         if (!HeapTupleIsValid(tup))
3176                 elog(ERROR, "cache lookup failed for type %u", typeOid);
3177         typTup = (Form_pg_type) GETSTRUCT(tup);
3178
3179         /* check permissions on type */
3180         if (!pg_type_ownercheck(typeOid, GetUserId()))
3181                 aclcheck_error_type(ACLCHECK_NOT_OWNER, typeOid);
3182
3183         /* ALTER DOMAIN used on a non-domain? */
3184         if (stmt->renameType == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
3185                 ereport(ERROR,
3186                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3187                                  errmsg("\"%s\" is not a domain",
3188                                                 format_type_be(typeOid))));
3189
3190         /*
3191          * If it's a composite type, we need to check that it really is a
3192          * free-standing composite type, and not a table's rowtype. We want people
3193          * to use ALTER TABLE not ALTER TYPE for that case.
3194          */
3195         if (typTup->typtype == TYPTYPE_COMPOSITE &&
3196                 get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)
3197                 ereport(ERROR,
3198                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3199                                  errmsg("%s is a table's row type",
3200                                                 format_type_be(typeOid)),
3201                                  errhint("Use ALTER TABLE instead.")));
3202
3203         /* don't allow direct alteration of array types, either */
3204         if (OidIsValid(typTup->typelem) &&
3205                 get_array_type(typTup->typelem) == typeOid)
3206                 ereport(ERROR,
3207                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3208                                  errmsg("cannot alter array type %s",
3209                                                 format_type_be(typeOid)),
3210                                  errhint("You can alter type %s, which will alter the array type as well.",
3211                                                  format_type_be(typTup->typelem))));
3212
3213         /*
3214          * If type is composite we need to rename associated pg_class entry too.
3215          * RenameRelationInternal will call RenameTypeInternal automatically.
3216          */
3217         if (typTup->typtype == TYPTYPE_COMPOSITE)
3218                 RenameRelationInternal(typTup->typrelid, newTypeName, false);
3219         else
3220                 RenameTypeInternal(typeOid, newTypeName,
3221                                                    typTup->typnamespace);
3222
3223         /* Clean up */
3224         heap_close(rel, RowExclusiveLock);
3225
3226         return typeOid;
3227 }
3228
3229 /*
3230  * Change the owner of a type.
3231  */
3232 Oid
3233 AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
3234 {
3235         TypeName   *typename;
3236         Oid                     typeOid;
3237         Relation        rel;
3238         HeapTuple       tup;
3239         HeapTuple       newtup;
3240         Form_pg_type typTup;
3241         AclResult       aclresult;
3242
3243         rel = heap_open(TypeRelationId, RowExclusiveLock);
3244
3245         /* Make a TypeName so we can use standard type lookup machinery */
3246         typename = makeTypeNameFromNameList(names);
3247
3248         /* Use LookupTypeName here so that shell types can be processed */
3249         tup = LookupTypeName(NULL, typename, NULL, false);
3250         if (tup == NULL)
3251                 ereport(ERROR,
3252                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
3253                                  errmsg("type \"%s\" does not exist",
3254                                                 TypeNameToString(typename))));
3255         typeOid = typeTypeId(tup);
3256
3257         /* Copy the syscache entry so we can scribble on it below */
3258         newtup = heap_copytuple(tup);
3259         ReleaseSysCache(tup);
3260         tup = newtup;
3261         typTup = (Form_pg_type) GETSTRUCT(tup);
3262
3263         /* Don't allow ALTER DOMAIN on a type */
3264         if (objecttype == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
3265                 ereport(ERROR,
3266                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3267                                  errmsg("%s is not a domain",
3268                                                 format_type_be(typeOid))));
3269
3270         /*
3271          * If it's a composite type, we need to check that it really is a
3272          * free-standing composite type, and not a table's rowtype. We want people
3273          * to use ALTER TABLE not ALTER TYPE for that case.
3274          */
3275         if (typTup->typtype == TYPTYPE_COMPOSITE &&
3276                 get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)
3277                 ereport(ERROR,
3278                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3279                                  errmsg("%s is a table's row type",
3280                                                 format_type_be(typeOid)),
3281                                  errhint("Use ALTER TABLE instead.")));
3282
3283         /* don't allow direct alteration of array types, either */
3284         if (OidIsValid(typTup->typelem) &&
3285                 get_array_type(typTup->typelem) == typeOid)
3286                 ereport(ERROR,
3287                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3288                                  errmsg("cannot alter array type %s",
3289                                                 format_type_be(typeOid)),
3290                                  errhint("You can alter type %s, which will alter the array type as well.",
3291                                                  format_type_be(typTup->typelem))));
3292
3293         /*
3294          * If the new owner is the same as the existing owner, consider the
3295          * command to have succeeded.  This is for dump restoration purposes.
3296          */
3297         if (typTup->typowner != newOwnerId)
3298         {
3299                 /* Superusers can always do it */
3300                 if (!superuser())
3301                 {
3302                         /* Otherwise, must be owner of the existing object */
3303                         if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
3304                                 aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup));
3305
3306                         /* Must be able to become new owner */
3307                         check_is_member_of_role(GetUserId(), newOwnerId);
3308
3309                         /* New owner must have CREATE privilege on namespace */
3310                         aclresult = pg_namespace_aclcheck(typTup->typnamespace,
3311                                                                                           newOwnerId,
3312                                                                                           ACL_CREATE);
3313                         if (aclresult != ACLCHECK_OK)
3314                                 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
3315                                                            get_namespace_name(typTup->typnamespace));
3316                 }
3317
3318                 /*
3319                  * If it's a composite type, invoke ATExecChangeOwner so that we fix
3320                  * up the pg_class entry properly.      That will call back to
3321                  * AlterTypeOwnerInternal to take care of the pg_type entry(s).
3322                  */
3323                 if (typTup->typtype == TYPTYPE_COMPOSITE)
3324                         ATExecChangeOwner(typTup->typrelid, newOwnerId, true, AccessExclusiveLock);
3325                 else
3326                 {
3327                         /*
3328                          * We can just apply the modification directly.
3329                          *
3330                          * okay to scribble on typTup because it's a copy
3331                          */
3332                         typTup->typowner = newOwnerId;
3333
3334                         simple_heap_update(rel, &tup->t_self, tup);
3335
3336                         CatalogUpdateIndexes(rel, tup);
3337
3338                         /* Update owner dependency reference */
3339                         changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
3340
3341                         InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
3342
3343                         /* If it has an array type, update that too */
3344                         if (OidIsValid(typTup->typarray))
3345                                 AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
3346                 }
3347         }
3348
3349         /* Clean up */
3350         heap_close(rel, RowExclusiveLock);
3351
3352         return typeOid;
3353 }
3354
3355 /*
3356  * AlterTypeOwnerInternal - change type owner unconditionally
3357  *
3358  * This is currently only used to propagate ALTER TABLE/TYPE OWNER to a
3359  * table's rowtype or an array type, and to implement REASSIGN OWNED BY.
3360  * It assumes the caller has done all needed checks.  The function will
3361  * automatically recurse to an array type if the type has one.
3362  *
3363  * hasDependEntry should be TRUE if type is expected to have a pg_shdepend
3364  * entry (ie, it's not a table rowtype nor an array type).
3365  * is_primary_ops should be TRUE if this function is invoked with user's
3366  * direct operation (e.g, shdepReassignOwned). Elsewhere,
3367  */
3368 void
3369 AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
3370                                            bool hasDependEntry)
3371 {
3372         Relation        rel;
3373         HeapTuple       tup;
3374         Form_pg_type typTup;
3375
3376         rel = heap_open(TypeRelationId, RowExclusiveLock);
3377
3378         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
3379         if (!HeapTupleIsValid(tup))
3380                 elog(ERROR, "cache lookup failed for type %u", typeOid);
3381         typTup = (Form_pg_type) GETSTRUCT(tup);
3382
3383         /*
3384          * Modify the owner --- okay to scribble on typTup because it's a copy
3385          */
3386         typTup->typowner = newOwnerId;
3387
3388         simple_heap_update(rel, &tup->t_self, tup);
3389
3390         CatalogUpdateIndexes(rel, tup);
3391
3392         /* Update owner dependency reference, if it has one */
3393         if (hasDependEntry)
3394                 changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
3395
3396         /* If it has an array type, update that too */
3397         if (OidIsValid(typTup->typarray))
3398                 AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
3399
3400         InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
3401
3402         /* Clean up */
3403         heap_close(rel, RowExclusiveLock);
3404 }
3405
3406 /*
3407  * Execute ALTER TYPE SET SCHEMA
3408  */
3409 Oid
3410 AlterTypeNamespace(List *names, const char *newschema, ObjectType objecttype)
3411 {
3412         TypeName   *typename;
3413         Oid                     typeOid;
3414         Oid                     nspOid;
3415         ObjectAddresses *objsMoved;
3416
3417         /* Make a TypeName so we can use standard type lookup machinery */
3418         typename = makeTypeNameFromNameList(names);
3419         typeOid = typenameTypeId(NULL, typename);
3420
3421         /* Don't allow ALTER DOMAIN on a type */
3422         if (objecttype == OBJECT_DOMAIN && get_typtype(typeOid) != TYPTYPE_DOMAIN)
3423                 ereport(ERROR,
3424                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3425                                  errmsg("%s is not a domain",
3426                                                 format_type_be(typeOid))));
3427
3428         /* get schema OID and check its permissions */
3429         nspOid = LookupCreationNamespace(newschema);
3430
3431         objsMoved = new_object_addresses();
3432         AlterTypeNamespace_oid(typeOid, nspOid, objsMoved);
3433         free_object_addresses(objsMoved);
3434
3435         return typeOid;
3436 }
3437
3438 Oid
3439 AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses *objsMoved)
3440 {
3441         Oid                     elemOid;
3442
3443         /* check permissions on type */
3444         if (!pg_type_ownercheck(typeOid, GetUserId()))
3445                 aclcheck_error_type(ACLCHECK_NOT_OWNER, typeOid);
3446
3447         /* don't allow direct alteration of array types */
3448         elemOid = get_element_type(typeOid);
3449         if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid)
3450                 ereport(ERROR,
3451                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3452                                  errmsg("cannot alter array type %s",
3453                                                 format_type_be(typeOid)),
3454                                  errhint("You can alter type %s, which will alter the array type as well.",
3455                                                  format_type_be(elemOid))));
3456
3457         /* and do the work */
3458         return AlterTypeNamespaceInternal(typeOid, nspOid, false, true, objsMoved);
3459 }
3460
3461 /*
3462  * Move specified type to new namespace.
3463  *
3464  * Caller must have already checked privileges.
3465  *
3466  * The function automatically recurses to process the type's array type,
3467  * if any.      isImplicitArray should be TRUE only when doing this internal
3468  * recursion (outside callers must never try to move an array type directly).
3469  *
3470  * If errorOnTableType is TRUE, the function errors out if the type is
3471  * a table type.  ALTER TABLE has to be used to move a table to a new
3472  * namespace.
3473  *
3474  * Returns the type's old namespace OID.
3475  */
3476 Oid
3477 AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
3478                                                    bool isImplicitArray,
3479                                                    bool errorOnTableType,
3480                                                    ObjectAddresses *objsMoved)
3481 {
3482         Relation        rel;
3483         HeapTuple       tup;
3484         Form_pg_type typform;
3485         Oid                     oldNspOid;
3486         Oid                     arrayOid;
3487         bool            isCompositeType;
3488         ObjectAddress thisobj;
3489
3490         /*
3491          * Make sure we haven't moved this object previously.
3492          */
3493         thisobj.classId = TypeRelationId;
3494         thisobj.objectId = typeOid;
3495         thisobj.objectSubId = 0;
3496
3497         if (object_address_present(&thisobj, objsMoved))
3498                 return InvalidOid;
3499
3500         rel = heap_open(TypeRelationId, RowExclusiveLock);
3501
3502         tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
3503         if (!HeapTupleIsValid(tup))
3504                 elog(ERROR, "cache lookup failed for type %u", typeOid);
3505         typform = (Form_pg_type) GETSTRUCT(tup);
3506
3507         oldNspOid = typform->typnamespace;
3508         arrayOid = typform->typarray;
3509
3510         /* common checks on switching namespaces */
3511         CheckSetNamespace(oldNspOid, nspOid, TypeRelationId, typeOid);
3512
3513         /* check for duplicate name (more friendly than unique-index failure) */
3514         if (SearchSysCacheExists2(TYPENAMENSP,
3515                                                           CStringGetDatum(NameStr(typform->typname)),
3516                                                           ObjectIdGetDatum(nspOid)))
3517                 ereport(ERROR,
3518                                 (errcode(ERRCODE_DUPLICATE_OBJECT),
3519                                  errmsg("type \"%s\" already exists in schema \"%s\"",
3520                                                 NameStr(typform->typname),
3521                                                 get_namespace_name(nspOid))));
3522
3523         /* Detect whether type is a composite type (but not a table rowtype) */
3524         isCompositeType =
3525                 (typform->typtype == TYPTYPE_COMPOSITE &&
3526                  get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);
3527
3528         /* Enforce not-table-type if requested */
3529         if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType &&
3530                 errorOnTableType)
3531                 ereport(ERROR,
3532                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3533                                  errmsg("%s is a table's row type",
3534                                                 format_type_be(typeOid)),
3535                                  errhint("Use ALTER TABLE instead.")));
3536
3537         /* OK, modify the pg_type row */
3538
3539         /* tup is a copy, so we can scribble directly on it */
3540         typform->typnamespace = nspOid;
3541
3542         simple_heap_update(rel, &tup->t_self, tup);
3543         CatalogUpdateIndexes(rel, tup);
3544
3545         /*
3546          * Composite types have pg_class entries.
3547          *
3548          * We need to modify the pg_class tuple as well to reflect the change of
3549          * schema.
3550          */
3551         if (isCompositeType)
3552         {
3553                 Relation        classRel;
3554
3555                 classRel = heap_open(RelationRelationId, RowExclusiveLock);
3556
3557                 AlterRelationNamespaceInternal(classRel, typform->typrelid,
3558                                                                            oldNspOid, nspOid,
3559                                                                            false, objsMoved);
3560
3561                 heap_close(classRel, RowExclusiveLock);
3562
3563                 /*
3564                  * Check for constraints associated with the composite type (we don't
3565                  * currently support this, but probably will someday).
3566                  */
3567                 AlterConstraintNamespaces(typform->typrelid, oldNspOid,
3568                                                                   nspOid, false, objsMoved);
3569         }
3570         else
3571         {
3572                 /* If it's a domain, it might have constraints */
3573                 if (typform->typtype == TYPTYPE_DOMAIN)
3574                         AlterConstraintNamespaces(typeOid, oldNspOid, nspOid, true,
3575                                                                           objsMoved);
3576         }
3577
3578         /*
3579          * Update dependency on schema, if any --- a table rowtype has not got
3580          * one, and neither does an implicit array.
3581          */
3582         if ((isCompositeType || typform->typtype != TYPTYPE_COMPOSITE) &&
3583                 !isImplicitArray)
3584                 if (changeDependencyFor(TypeRelationId, typeOid,
3585                                                                 NamespaceRelationId, oldNspOid, nspOid) != 1)
3586                         elog(ERROR, "failed to change schema dependency for type %s",
3587                                  format_type_be(typeOid));
3588
3589         InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
3590
3591         heap_freetuple(tup);
3592
3593         heap_close(rel, RowExclusiveLock);
3594
3595         add_exact_object_address(&thisobj, objsMoved);
3596
3597         /* Recursively alter the associated array type, if any */
3598         if (OidIsValid(arrayOid))
3599                 AlterTypeNamespaceInternal(arrayOid, nspOid, true, true, objsMoved);
3600
3601         return oldNspOid;
3602 }