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