PostgreSQL Source Code git master
Loading...
Searching...
No Matches
typecmds.h File Reference
#include "access/htup.h"
#include "catalog/dependency.h"
#include "parser/parse_node.h"
Include dependency graph for typecmds.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define DEFAULT_TYPDELIM   ','
 

Functions

ObjectAddress DefineType (ParseState *pstate, List *names, List *parameters)
 
void RemoveTypeById (Oid typeOid)
 
ObjectAddress DefineDomain (ParseState *pstate, CreateDomainStmt *stmt)
 
ObjectAddress DefineEnum (CreateEnumStmt *stmt)
 
ObjectAddress DefineRange (ParseState *pstate, CreateRangeStmt *stmt)
 
ObjectAddress AlterEnum (AlterEnumStmt *stmt)
 
ObjectAddress DefineCompositeType (RangeVar *typevar, List *coldeflist)
 
Oid AssignTypeArrayOid (void)
 
Oid AssignTypeMultirangeOid (void)
 
Oid AssignTypeMultirangeArrayOid (void)
 
ObjectAddress AlterDomainDefault (List *names, Node *defaultRaw)
 
ObjectAddress AlterDomainNotNull (List *names, bool notNull)
 
ObjectAddress AlterDomainAddConstraint (List *names, Node *newConstraint, ObjectAddress *constrAddr)
 
ObjectAddress AlterDomainValidateConstraint (List *names, const char *constrName)
 
ObjectAddress AlterDomainDropConstraint (List *names, const char *constrName, DropBehavior behavior, bool missing_ok)
 
void checkDomainOwner (HeapTuple tup)
 
ObjectAddress RenameType (RenameStmt *stmt)
 
ObjectAddress AlterTypeOwner (List *names, Oid newOwnerId, ObjectType objecttype)
 
void AlterTypeOwner_oid (Oid typeOid, Oid newOwnerId, bool hasDependEntry)
 
void AlterTypeOwnerInternal (Oid typeOid, Oid newOwnerId)
 
ObjectAddress AlterTypeNamespace (List *names, const char *newschema, ObjectType objecttype, Oid *oldschema)
 
Oid AlterTypeNamespace_oid (Oid typeOid, Oid nspOid, bool ignoreDependent, ObjectAddresses *objsMoved)
 
Oid AlterTypeNamespaceInternal (Oid typeOid, Oid nspOid, bool isImplicitArray, bool ignoreDependent, bool errorOnTableType, ObjectAddresses *objsMoved)
 
ObjectAddress AlterType (AlterTypeStmt *stmt)
 

Macro Definition Documentation

◆ DEFAULT_TYPDELIM

#define DEFAULT_TYPDELIM   ','

Definition at line 22 of file typecmds.h.

Function Documentation

◆ AlterDomainAddConstraint()

ObjectAddress AlterDomainAddConstraint ( List names,
Node newConstraint,
ObjectAddress constrAddr 
)
extern

Definition at line 2967 of file typecmds.c.

2969{
2970 TypeName *typename;
2971 Oid domainoid;
2973 HeapTuple tup;
2975 Constraint *constr;
2976 char *ccbin;
2978
2979 /* Make a TypeName so we can use standard type lookup machinery */
2980 typename = makeTypeNameFromNameList(names);
2981 domainoid = typenameTypeId(NULL, typename);
2982
2983 /* Look up the domain in the type table */
2985
2987 if (!HeapTupleIsValid(tup))
2988 elog(ERROR, "cache lookup failed for type %u", domainoid);
2990
2991 /* Check it's a domain and check user has permission for ALTER DOMAIN */
2993
2995 elog(ERROR, "unrecognized node type: %d",
2996 (int) nodeTag(newConstraint));
2997
2998 constr = (Constraint *) newConstraint;
2999
3000 /* enforced by parser */
3001 Assert(constr->contype == CONSTR_CHECK || constr->contype == CONSTR_NOTNULL);
3002
3003 if (constr->contype == CONSTR_CHECK)
3004 {
3005 /*
3006 * First, process the constraint expression and add an entry to
3007 * pg_constraint.
3008 */
3009
3010 ccbin = domainAddCheckConstraint(domainoid, typTup->typnamespace,
3011 typTup->typbasetype, typTup->typtypmod,
3012 constr, NameStr(typTup->typname), constrAddr);
3013
3014
3015 /*
3016 * If requested to validate the constraint, test all values stored in
3017 * the attributes based on the domain the constraint is being added
3018 * to.
3019 */
3020 if (!constr->skip_validation)
3022
3023 /*
3024 * We must send out an sinval message for the domain, to ensure that
3025 * any dependent plans get rebuilt. Since this command doesn't change
3026 * the domain's pg_type row, that won't happen automatically; do it
3027 * manually.
3028 */
3030 }
3031 else if (constr->contype == CONSTR_NOTNULL)
3032 {
3033 /* Is the domain already set NOT NULL? */
3034 if (typTup->typnotnull)
3035 {
3037 return address;
3038 }
3040 typTup->typbasetype, typTup->typtypmod,
3041 constr, NameStr(typTup->typname), constrAddr);
3042
3043 if (!constr->skip_validation)
3045
3046 typTup->typnotnull = true;
3047 CatalogTupleUpdate(typrel, &tup->t_self, tup);
3048 }
3049
3051
3052 /* Clean up */
3054
3055 return address;
3056}
#define NameStr(name)
Definition c.h:835
#define Assert(condition)
Definition c.h:943
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple, HeapTuple newtuple)
Definition inval.c:1568
#define ShareLock
Definition lockdefs.h:40
#define RowExclusiveLock
Definition lockdefs.h:38
TypeName * makeTypeNameFromNameList(List *names)
Definition makefuncs.c:531
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define nodeTag(nodeptr)
Definition nodes.h:139
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition parse_type.c:291
@ CONSTR_NOTNULL
@ CONSTR_CHECK
END_CATALOG_STRUCT typedef FormData_pg_type * Form_pg_type
Definition pg_type.h:265
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
unsigned int Oid
static int fb(int x)
ConstrType contype
bool skip_validation
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
static char * domainAddCheckConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, int typMod, Constraint *constr, const char *domainName, ObjectAddress *constrAddr)
Definition typecmds.c:3556
void checkDomainOwner(HeapTuple tup)
Definition typecmds.c:3536
static void domainAddNotNullConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, int typMod, Constraint *constr, const char *domainName, ObjectAddress *constrAddr)
Definition typecmds.c:3716
static void validateDomainNotNullConstraint(Oid domainoid)
Definition typecmds.c:3174
static void validateDomainCheckConstraint(Oid domainoid, const char *ccbin, LOCKMODE lockmode)
Definition typecmds.c:3247

References Assert, CacheInvalidateHeapTuple(), CatalogTupleUpdate(), checkDomainOwner(), CONSTR_CHECK, CONSTR_NOTNULL, Constraint::contype, domainAddCheckConstraint(), domainAddNotNullConstraint(), elog, ERROR, fb(), Form_pg_type, GETSTRUCT(), HeapTupleIsValid, InvalidObjectAddress, IsA, makeTypeNameFromNameList(), NameStr, nodeTag, ObjectAddressSet, ObjectIdGetDatum(), RowExclusiveLock, SearchSysCacheCopy1, ShareLock, Constraint::skip_validation, table_close(), table_open(), typenameTypeId(), validateDomainCheckConstraint(), and validateDomainNotNullConstraint().

Referenced by ATExecCmd(), and ProcessUtilitySlow().

◆ AlterDomainDefault()

ObjectAddress AlterDomainDefault ( List names,
Node defaultRaw 
)
extern

Definition at line 2646 of file typecmds.c.

2647{
2648 TypeName *typename;
2649 Oid domainoid;
2650 HeapTuple tup;
2651 ParseState *pstate;
2652 Relation rel;
2653 char *defaultValue;
2654 Node *defaultExpr = NULL; /* NULL if no default specified */
2656 bool new_record_nulls[Natts_pg_type] = {0};
2657 bool new_record_repl[Natts_pg_type] = {0};
2658 HeapTuple newtuple;
2660 ObjectAddress address;
2661
2662 /* Make a TypeName so we can use standard type lookup machinery */
2663 typename = makeTypeNameFromNameList(names);
2664 domainoid = typenameTypeId(NULL, typename);
2665
2666 /* Look up the domain in the type table */
2668
2670 if (!HeapTupleIsValid(tup))
2671 elog(ERROR, "cache lookup failed for type %u", domainoid);
2673
2674 /* Check it's a domain and check user has permission for ALTER DOMAIN */
2676
2677 /* Setup new tuple */
2678
2679 /* Store the new default into the tuple */
2680 if (defaultRaw)
2681 {
2682 /* Create a dummy ParseState for transformExpr */
2683 pstate = make_parsestate(NULL);
2684
2685 /*
2686 * Cook the colDef->raw_expr into an expression. Note: Name is
2687 * strictly for error message
2688 */
2690 typTup->typbasetype,
2691 typTup->typtypmod,
2692 NameStr(typTup->typname),
2693 0);
2694
2695 /*
2696 * If the expression is just a NULL constant, we treat the command
2697 * like ALTER ... DROP DEFAULT. (But see note for same test in
2698 * DefineDomain.)
2699 */
2700 if (defaultExpr == NULL ||
2702 {
2703 /* Default is NULL, drop it */
2704 defaultExpr = NULL;
2709 }
2710 else
2711 {
2712 /*
2713 * Expression must be stored as a nodeToString result, but we also
2714 * require a valid textual representation (mainly to make life
2715 * easier for pg_dump).
2716 */
2718 NIL, false, false);
2719
2720 /*
2721 * Form an updated tuple with the new default and write it back.
2722 */
2724
2728 }
2729 }
2730 else
2731 {
2732 /* ALTER ... DROP DEFAULT */
2737 }
2738
2739 newtuple = heap_modify_tuple(tup, RelationGetDescr(rel),
2742
2743 CatalogTupleUpdate(rel, &tup->t_self, newtuple);
2744
2745 /* Rebuild dependencies */
2746 GenerateTypeDependencies(newtuple,
2747 rel,
2749 NULL, /* don't have typacl handy */
2750 0, /* relation kind is n/a */
2751 false, /* a domain isn't an implicit array */
2752 false, /* nor is it any kind of dependent type */
2753 false, /* don't touch extension membership */
2754 true); /* We do need to rebuild dependencies */
2755
2757
2759
2760 /* Clean up */
2762 heap_freetuple(newtuple);
2763
2764 return address;
2765}
#define CStringGetTextDatum(s)
Definition builtins.h:98
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname, char attgenerated)
Definition heap.c:3340
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1118
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
#define InvokeObjectPostAlterHook(classId, objectId, subId)
char * nodeToString(const void *obj)
Definition outfuncs.c:811
ParseState * make_parsestate(ParseState *parentParseState)
Definition parse_node.c:39
#define NIL
Definition pg_list.h:68
void GenerateTypeDependencies(HeapTuple typeTuple, Relation typeCatalog, Node *defaultExpr, void *typacl, char relationKind, bool isImplicitArray, bool isDependentType, bool makeExtensionDep, bool rebuild)
Definition pg_type.c:555
uint64_t Datum
Definition postgres.h:70
#define RelationGetDescr(relation)
Definition rel.h:542
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition ruleutils.c:4007
Definition nodes.h:135

References CatalogTupleUpdate(), checkDomainOwner(), cookDefault(), CStringGetTextDatum, deparse_expression(), elog, ERROR, fb(), Form_pg_type, GenerateTypeDependencies(), GETSTRUCT(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, IsA, make_parsestate(), makeTypeNameFromNameList(), NameStr, NIL, nodeToString(), ObjectAddressSet, ObjectIdGetDatum(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, table_close(), table_open(), and typenameTypeId().

Referenced by ProcessUtilitySlow().

◆ AlterDomainDropConstraint()

ObjectAddress AlterDomainDropConstraint ( List names,
const char constrName,
DropBehavior  behavior,
bool  missing_ok 
)
extern

Definition at line 2861 of file typecmds.c.

2863{
2864 TypeName *typename;
2865 Oid domainoid;
2866 HeapTuple tup;
2867 Relation rel;
2870 ScanKeyData skey[3];
2872 bool found = false;
2873 ObjectAddress address;
2874
2875 /* Make a TypeName so we can use standard type lookup machinery */
2876 typename = makeTypeNameFromNameList(names);
2877 domainoid = typenameTypeId(NULL, typename);
2878
2879 /* Look up the domain in the type table */
2881
2883 if (!HeapTupleIsValid(tup))
2884 elog(ERROR, "cache lookup failed for type %u", domainoid);
2885
2886 /* Check it's a domain and check user has permission for ALTER DOMAIN */
2888
2889 /* Grab an appropriate lock on the pg_constraint relation */
2891
2892 /* Find and remove the target constraint */
2893 ScanKeyInit(&skey[0],
2897 ScanKeyInit(&skey[1],
2901 ScanKeyInit(&skey[2],
2905
2907 NULL, 3, skey);
2908
2909 /* There can be at most one matching row */
2910 if ((contup = systable_getnext(conscan)) != NULL)
2911 {
2914
2915 if (construct->contype == CONSTRAINT_NOTNULL)
2916 {
2917 ((Form_pg_type) GETSTRUCT(tup))->typnotnull = false;
2918 CatalogTupleUpdate(rel, &tup->t_self, tup);
2919 }
2920
2921 conobj.classId = ConstraintRelationId;
2922 conobj.objectId = construct->oid;
2923 conobj.objectSubId = 0;
2924
2925 performDeletion(&conobj, behavior, 0);
2926 found = true;
2927 }
2928
2929 /* Clean up after the scan */
2932
2933 if (!found)
2934 {
2935 if (!missing_ok)
2936 ereport(ERROR,
2938 errmsg("constraint \"%s\" of domain \"%s\" does not exist",
2939 constrName, TypeNameToString(typename))));
2940 else
2942 (errmsg("constraint \"%s\" of domain \"%s\" does not exist, skipping",
2943 constrName, TypeNameToString(typename))));
2944 }
2945
2946 /*
2947 * We must send out an sinval message for the domain, to ensure that any
2948 * dependent plans get rebuilt. Since this command doesn't change the
2949 * domain's pg_type row, that won't happen automatically; do it manually.
2950 */
2952
2954
2955 /* Clean up */
2957
2958 return address;
2959}
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition dependency.c:279
int errcode(int sqlerrcode)
Definition elog.c:875
#define NOTICE
Definition elog.h:36
#define ereport(elevel,...)
Definition elog.h:152
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:612
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:523
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
static char * errmsg
char * TypeNameToString(const TypeName *typeName)
Definition parse_type.c:478
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
#define InvalidOid
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
#define BTEqualStrategyNumber
Definition stratnum.h:31

References BTEqualStrategyNumber, CacheInvalidateHeapTuple(), CatalogTupleUpdate(), checkDomainOwner(), CStringGetDatum(), elog, ereport, errcode(), errmsg, ERROR, fb(), Form_pg_constraint, Form_pg_type, GETSTRUCT(), HeapTupleIsValid, InvalidOid, makeTypeNameFromNameList(), NOTICE, ObjectAddressSet, ObjectIdGetDatum(), performDeletion(), RowExclusiveLock, ScanKeyInit(), SearchSysCacheCopy1, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TypeNameToString(), and typenameTypeId().

Referenced by ProcessUtilitySlow().

◆ AlterDomainNotNull()

ObjectAddress AlterDomainNotNull ( List names,
bool  notNull 
)
extern

Definition at line 2775 of file typecmds.c.

2776{
2777 TypeName *typename;
2778 Oid domainoid;
2780 HeapTuple tup;
2783
2784 /* Make a TypeName so we can use standard type lookup machinery */
2785 typename = makeTypeNameFromNameList(names);
2786 domainoid = typenameTypeId(NULL, typename);
2787
2788 /* Look up the domain in the type table */
2790
2792 if (!HeapTupleIsValid(tup))
2793 elog(ERROR, "cache lookup failed for type %u", domainoid);
2795
2796 /* Check it's a domain and check user has permission for ALTER DOMAIN */
2798
2799 /* Is the domain already set to the desired constraint? */
2800 if (typTup->typnotnull == notNull)
2801 {
2803 return address;
2804 }
2805
2806 if (notNull)
2807 {
2808 Constraint *constr;
2809
2810 constr = makeNode(Constraint);
2811 constr->contype = CONSTR_NOTNULL;
2812 constr->initially_valid = true;
2813 constr->location = -1;
2814
2816 typTup->typbasetype, typTup->typtypmod,
2817 constr, NameStr(typTup->typname), NULL);
2818
2820 }
2821 else
2822 {
2825
2827 if (conTup == NULL)
2828 elog(ERROR, "could not find not-null constraint on domain \"%s\"", NameStr(typTup->typname));
2829
2832 }
2833
2834 /*
2835 * Okay to update pg_type row. We can scribble on typTup because it's a
2836 * copy.
2837 */
2838 typTup->typnotnull = notNull;
2839
2840 CatalogTupleUpdate(typrel, &tup->t_self, tup);
2841
2843
2845
2846 /* Clean up */
2849
2850 return address;
2851}
#define makeNode(_type_)
Definition nodes.h:161
@ DROP_RESTRICT
HeapTuple findDomainNotNullConstraint(Oid typid)
ParseLoc location
bool initially_valid

References CatalogTupleUpdate(), checkDomainOwner(), CONSTR_NOTNULL, Constraint::contype, domainAddNotNullConstraint(), DROP_RESTRICT, elog, ERROR, fb(), findDomainNotNullConstraint(), Form_pg_constraint, Form_pg_type, GETSTRUCT(), heap_freetuple(), HeapTupleIsValid, Constraint::initially_valid, InvalidObjectAddress, InvokeObjectPostAlterHook, Constraint::location, makeNode, makeTypeNameFromNameList(), NameStr, ObjectAddressSet, ObjectIdGetDatum(), performDeletion(), RowExclusiveLock, SearchSysCacheCopy1, table_close(), table_open(), typenameTypeId(), and validateDomainNotNullConstraint().

Referenced by ProcessUtilitySlow().

◆ AlterDomainValidateConstraint()

ObjectAddress AlterDomainValidateConstraint ( List names,
const char constrName 
)
extern

Definition at line 3067 of file typecmds.c.

3068{
3069 TypeName *typename;
3070 Oid domainoid;
3073 HeapTuple tup;
3076 char *conbin;
3077 SysScanDesc scan;
3078 Datum val;
3079 HeapTuple tuple;
3081 ScanKeyData skey[3];
3083
3084 /* Make a TypeName so we can use standard type lookup machinery */
3085 typename = makeTypeNameFromNameList(names);
3086 domainoid = typenameTypeId(NULL, typename);
3087
3088 /* Look up the domain in the type table */
3090
3092 if (!HeapTupleIsValid(tup))
3093 elog(ERROR, "cache lookup failed for type %u", domainoid);
3094
3095 /* Check it's a domain and check user has permission for ALTER DOMAIN */
3097
3098 /*
3099 * Find and check the target constraint
3100 */
3102
3103 ScanKeyInit(&skey[0],
3107 ScanKeyInit(&skey[1],
3111 ScanKeyInit(&skey[2],
3115
3117 NULL, 3, skey);
3118
3119 /* There can be at most one matching row */
3120 if (!HeapTupleIsValid(tuple = systable_getnext(scan)))
3121 ereport(ERROR,
3123 errmsg("constraint \"%s\" of domain \"%s\" does not exist",
3124 constrName, TypeNameToString(typename))));
3125
3126 con = (Form_pg_constraint) GETSTRUCT(tuple);
3127 if (con->contype != CONSTRAINT_CHECK)
3128 ereport(ERROR,
3130 errmsg("constraint \"%s\" of domain \"%s\" is not a check constraint",
3131 constrName, TypeNameToString(typename))));
3132
3133 if (!con->convalidated)
3134 {
3137
3138 /*
3139 * Locking related relations with ShareUpdateExclusiveLock is ok
3140 * because not-yet-valid constraints are still enforced against
3141 * concurrent inserts or updates.
3142 */
3144
3145 /*
3146 * Now update the catalog, while we have the door open.
3147 */
3148 copyTuple = heap_copytuple(tuple);
3150 copy_con->convalidated = true;
3152
3154
3156
3158 }
3159
3160 systable_endscan(scan);
3161
3164
3166
3167 return address;
3168}
#define TextDatumGetCString(d)
Definition builtins.h:99
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:686
long val
Definition informix.c:689
#define AccessShareLock
Definition lockdefs.h:36
#define ShareUpdateExclusiveLock
Definition lockdefs.h:39
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:626
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221

References AccessShareLock, BTEqualStrategyNumber, CatalogTupleUpdate(), checkDomainOwner(), CStringGetDatum(), elog, ereport, errcode(), errmsg, ERROR, fb(), Form_pg_constraint, GETSTRUCT(), heap_copytuple(), heap_freetuple(), HeapTupleIsValid, InvalidObjectAddress, InvalidOid, InvokeObjectPostAlterHook, makeTypeNameFromNameList(), ObjectAddressSet, ObjectIdGetDatum(), ReleaseSysCache(), RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), ShareUpdateExclusiveLock, SysCacheGetAttrNotNull(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, TypeNameToString(), typenameTypeId(), val, and validateDomainCheckConstraint().

Referenced by ProcessUtilitySlow().

◆ AlterEnum()

ObjectAddress AlterEnum ( AlterEnumStmt stmt)
extern

Definition at line 1307 of file typecmds.c.

1308{
1310 TypeName *typename;
1311 HeapTuple tup;
1312 ObjectAddress address;
1313
1314 /* Make a TypeName so we can use standard type lookup machinery */
1315 typename = makeTypeNameFromNameList(stmt->typeName);
1316 enum_type_oid = typenameTypeId(NULL, typename);
1317
1319 if (!HeapTupleIsValid(tup))
1320 elog(ERROR, "cache lookup failed for type %u", enum_type_oid);
1321
1322 /* Check it's an enum and check user has permission to ALTER the enum */
1324
1326
1327 if (stmt->oldVal)
1328 {
1329 /* Rename an existing label */
1330 RenameEnumLabel(enum_type_oid, stmt->oldVal, stmt->newVal);
1331 }
1332 else
1333 {
1334 /* Add a new label */
1336 stmt->newValNeighbor, stmt->newValIsAfter,
1337 stmt->skipIfNewValExists);
1338 }
1339
1341
1343
1344 return address;
1345}
#define stmt
void RenameEnumLabel(Oid enumTypeOid, const char *oldVal, const char *newVal)
Definition pg_enum.c:620
void AddEnumLabel(Oid enumTypeOid, const char *newVal, const char *neighbor, bool newValIsAfter, bool skipIfExists)
Definition pg_enum.c:305
static void checkEnumOwner(HeapTuple tup)
Definition typecmds.c:1355

References AddEnumLabel(), checkEnumOwner(), elog, ERROR, fb(), HeapTupleIsValid, InvokeObjectPostAlterHook, makeTypeNameFromNameList(), ObjectAddressSet, ObjectIdGetDatum(), ReleaseSysCache(), RenameEnumLabel(), SearchSysCache1(), stmt, and typenameTypeId().

Referenced by ProcessUtilitySlow().

◆ AlterType()

ObjectAddress AlterType ( AlterTypeStmt stmt)
extern

Definition at line 4362 of file typecmds.c.

4363{
4364 ObjectAddress address;
4366 TypeName *typename;
4367 HeapTuple tup;
4368 Oid typeOid;
4370 bool requireSuper = false;
4372 ListCell *pl;
4373
4375
4376 /* Make a TypeName so we can use standard type lookup machinery */
4377 typename = makeTypeNameFromNameList(stmt->typeName);
4378 tup = typenameType(NULL, typename, NULL);
4379
4380 typeOid = typeTypeId(tup);
4382
4383 /* Process options */
4384 memset(&atparams, 0, sizeof(atparams));
4385 foreach(pl, stmt->options)
4386 {
4387 DefElem *defel = (DefElem *) lfirst(pl);
4388
4389 if (strcmp(defel->defname, "storage") == 0)
4390 {
4391 char *a = defGetString(defel);
4392
4393 if (pg_strcasecmp(a, "plain") == 0)
4394 atparams.storage = TYPSTORAGE_PLAIN;
4395 else if (pg_strcasecmp(a, "external") == 0)
4396 atparams.storage = TYPSTORAGE_EXTERNAL;
4397 else if (pg_strcasecmp(a, "extended") == 0)
4398 atparams.storage = TYPSTORAGE_EXTENDED;
4399 else if (pg_strcasecmp(a, "main") == 0)
4400 atparams.storage = TYPSTORAGE_MAIN;
4401 else
4402 ereport(ERROR,
4404 errmsg("storage \"%s\" not recognized", a)));
4405
4406 /*
4407 * Validate the storage request. If the type isn't varlena, it
4408 * certainly doesn't support non-PLAIN storage.
4409 */
4410 if (atparams.storage != TYPSTORAGE_PLAIN && typForm->typlen != -1)
4411 ereport(ERROR,
4413 errmsg("fixed-size types must have storage PLAIN")));
4414
4415 /*
4416 * Switching from PLAIN to non-PLAIN is allowed, but it requires
4417 * superuser, since we can't validate that the type's C functions
4418 * will support it. Switching from non-PLAIN to PLAIN is
4419 * disallowed outright, because it's not practical to ensure that
4420 * no tables have toasted values of the type. Switching among
4421 * different non-PLAIN settings is OK, since it just constitutes a
4422 * change in the strategy requested for columns created in the
4423 * future.
4424 */
4425 if (atparams.storage != TYPSTORAGE_PLAIN &&
4426 typForm->typstorage == TYPSTORAGE_PLAIN)
4427 requireSuper = true;
4428 else if (atparams.storage == TYPSTORAGE_PLAIN &&
4429 typForm->typstorage != TYPSTORAGE_PLAIN)
4430 ereport(ERROR,
4432 errmsg("cannot change type's storage to PLAIN")));
4433
4434 atparams.updateStorage = true;
4435 }
4436 else if (strcmp(defel->defname, "receive") == 0)
4437 {
4438 if (defel->arg != NULL)
4439 atparams.receiveOid =
4441 typeOid);
4442 else
4443 atparams.receiveOid = InvalidOid; /* NONE, remove function */
4444 atparams.updateReceive = true;
4445 /* Replacing an I/O function requires superuser. */
4446 requireSuper = true;
4447 }
4448 else if (strcmp(defel->defname, "send") == 0)
4449 {
4450 if (defel->arg != NULL)
4451 atparams.sendOid =
4453 typeOid);
4454 else
4455 atparams.sendOid = InvalidOid; /* NONE, remove function */
4456 atparams.updateSend = true;
4457 /* Replacing an I/O function requires superuser. */
4458 requireSuper = true;
4459 }
4460 else if (strcmp(defel->defname, "typmod_in") == 0)
4461 {
4462 if (defel->arg != NULL)
4463 atparams.typmodinOid =
4465 else
4466 atparams.typmodinOid = InvalidOid; /* NONE, remove function */
4467 atparams.updateTypmodin = true;
4468 /* Replacing an I/O function requires superuser. */
4469 requireSuper = true;
4470 }
4471 else if (strcmp(defel->defname, "typmod_out") == 0)
4472 {
4473 if (defel->arg != NULL)
4474 atparams.typmodoutOid =
4476 else
4477 atparams.typmodoutOid = InvalidOid; /* NONE, remove function */
4478 atparams.updateTypmodout = true;
4479 /* Replacing an I/O function requires superuser. */
4480 requireSuper = true;
4481 }
4482 else if (strcmp(defel->defname, "analyze") == 0)
4483 {
4484 if (defel->arg != NULL)
4485 atparams.analyzeOid =
4487 typeOid);
4488 else
4489 atparams.analyzeOid = InvalidOid; /* NONE, remove function */
4490 atparams.updateAnalyze = true;
4491 /* Replacing an analyze function requires superuser. */
4492 requireSuper = true;
4493 }
4494 else if (strcmp(defel->defname, "subscript") == 0)
4495 {
4496 if (defel->arg != NULL)
4497 atparams.subscriptOid =
4499 typeOid);
4500 else
4501 atparams.subscriptOid = InvalidOid; /* NONE, remove function */
4502 atparams.updateSubscript = true;
4503 /* Replacing a subscript function requires superuser. */
4504 requireSuper = true;
4505 }
4506
4507 /*
4508 * The rest of the options that CREATE accepts cannot be changed.
4509 * Check for them so that we can give a meaningful error message.
4510 */
4511 else if (strcmp(defel->defname, "input") == 0 ||
4512 strcmp(defel->defname, "output") == 0 ||
4513 strcmp(defel->defname, "internallength") == 0 ||
4514 strcmp(defel->defname, "passedbyvalue") == 0 ||
4515 strcmp(defel->defname, "alignment") == 0 ||
4516 strcmp(defel->defname, "like") == 0 ||
4517 strcmp(defel->defname, "category") == 0 ||
4518 strcmp(defel->defname, "preferred") == 0 ||
4519 strcmp(defel->defname, "default") == 0 ||
4520 strcmp(defel->defname, "element") == 0 ||
4521 strcmp(defel->defname, "delimiter") == 0 ||
4522 strcmp(defel->defname, "collatable") == 0)
4523 ereport(ERROR,
4525 errmsg("type attribute \"%s\" cannot be changed",
4526 defel->defname)));
4527 else
4528 ereport(ERROR,
4530 errmsg("type attribute \"%s\" not recognized",
4531 defel->defname)));
4532 }
4533
4534 /*
4535 * Permissions check. Require superuser if we decided the command
4536 * requires that, else must own the type.
4537 */
4538 if (requireSuper)
4539 {
4540 if (!superuser())
4541 ereport(ERROR,
4543 errmsg("must be superuser to alter a type")));
4544 }
4545 else
4546 {
4547 if (!object_ownercheck(TypeRelationId, typeOid, GetUserId()))
4549 }
4550
4551 /*
4552 * We disallow all forms of ALTER TYPE SET on types that aren't plain base
4553 * types. It would for example be highly unsafe, not to mention
4554 * pointless, to change the send/receive functions for a composite type.
4555 * Moreover, pg_dump has no support for changing these properties on
4556 * non-base types. We might weaken this someday, but not now.
4557 *
4558 * Note: if you weaken this enough to allow composite types, be sure to
4559 * adjust the GenerateTypeDependencies call in AlterTypeRecurse.
4560 */
4561 if (typForm->typtype != TYPTYPE_BASE)
4562 ereport(ERROR,
4564 errmsg("%s is not a base type",
4565 format_type_be(typeOid))));
4566
4567 /*
4568 * For the same reasons, don't allow direct alteration of array types.
4569 */
4571 ereport(ERROR,
4573 errmsg("%s is not a base type",
4574 format_type_be(typeOid))));
4575
4576 /* OK, recursively update this type and any arrays/domains over it */
4577 AlterTypeRecurse(typeOid, false, tup, catalog, &atparams);
4578
4579 /* Clean up */
4581
4583
4584 ObjectAddressSet(address, TypeRelationId, typeOid);
4585
4586 return address;
4587}
@ ACLCHECK_NOT_OWNER
Definition acl.h:186
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4134
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition aclchk.c:2997
char * defGetString(DefElem *def)
Definition define.c:34
List * defGetQualifiedName(DefElem *def)
Definition define.c:238
char * format_type_be(Oid type_oid)
int a
Definition isn.c:73
Oid GetUserId(void)
Definition miscinit.c:470
Type typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
Definition parse_type.c:264
Oid typeTypeId(Type tp)
Definition parse_type.c:590
#define lfirst(lc)
Definition pg_list.h:172
int pg_strcasecmp(const char *s1, const char *s2)
bool superuser(void)
Definition superuser.c:47
static Oid findTypeReceiveFunction(List *procname, Oid typeOid)
Definition typecmds.c:2121
static void AlterTypeRecurse(Oid typeOid, bool isImplicitArray, HeapTuple tup, Relation catalog, AlterTypeRecurseParams *atparams)
Definition typecmds.c:4613
static Oid findTypeAnalyzeFunction(List *procname, Oid typeOid)
Definition typecmds.c:2278
static Oid findTypeSendFunction(List *procname, Oid typeOid)
Definition typecmds.c:2175
static Oid findTypeSubscriptingFunction(List *procname, Oid typeOid)
Definition typecmds.c:2305
static Oid findTypeTypmodoutFunction(List *procname)
Definition typecmds.c:2244
static Oid findTypeTypmodinFunction(List *procname)
Definition typecmds.c:2210

References a, aclcheck_error_type(), ACLCHECK_NOT_OWNER, AlterTypeRecurse(), defGetQualifiedName(), defGetString(), ereport, errcode(), errmsg, ERROR, fb(), findTypeAnalyzeFunction(), findTypeReceiveFunction(), findTypeSendFunction(), findTypeSubscriptingFunction(), findTypeTypmodinFunction(), findTypeTypmodoutFunction(), Form_pg_type, format_type_be(), GETSTRUCT(), GetUserId(), InvalidOid, lfirst, makeTypeNameFromNameList(), object_ownercheck(), ObjectAddressSet, pg_strcasecmp(), ReleaseSysCache(), RowExclusiveLock, stmt, superuser(), table_close(), table_open(), typenameType(), and typeTypeId().

Referenced by ProcessUtilitySlow().

◆ AlterTypeNamespace()

ObjectAddress AlterTypeNamespace ( List names,
const char newschema,
ObjectType  objecttype,
Oid oldschema 
)
extern

Definition at line 4105 of file typecmds.c.

4107{
4108 TypeName *typename;
4109 Oid typeOid;
4110 Oid nspOid;
4111 Oid oldNspOid;
4114
4115 /* Make a TypeName so we can use standard type lookup machinery */
4116 typename = makeTypeNameFromNameList(names);
4117 typeOid = typenameTypeId(NULL, typename);
4118
4119 /* Don't allow ALTER DOMAIN on a non-domain type */
4120 if (objecttype == OBJECT_DOMAIN && get_typtype(typeOid) != TYPTYPE_DOMAIN)
4121 ereport(ERROR,
4123 errmsg("%s is not a domain",
4124 format_type_be(typeOid))));
4125
4126 /* get schema OID and check its permissions */
4127 nspOid = LookupCreationNamespace(newschema);
4128
4132
4133 if (oldschema)
4135
4137
4138 return myself;
4139}
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
char get_typtype(Oid typid)
Definition lsyscache.c:2862
Oid LookupCreationNamespace(const char *nspname)
Definition namespace.c:3500
@ OBJECT_DOMAIN
Oid AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, bool ignoreDependent, ObjectAddresses *objsMoved)
Definition typecmds.c:4154

References AlterTypeNamespace_oid(), ereport, errcode(), errmsg, ERROR, fb(), format_type_be(), free_object_addresses(), get_typtype(), LookupCreationNamespace(), makeTypeNameFromNameList(), new_object_addresses(), OBJECT_DOMAIN, ObjectAddressSet, and typenameTypeId().

Referenced by ExecAlterObjectSchemaStmt().

◆ AlterTypeNamespace_oid()

Oid AlterTypeNamespace_oid ( Oid  typeOid,
Oid  nspOid,
bool  ignoreDependent,
ObjectAddresses objsMoved 
)
extern

Definition at line 4154 of file typecmds.c.

4156{
4157 Oid elemOid;
4158
4159 /* check permissions on type */
4160 if (!object_ownercheck(TypeRelationId, typeOid, GetUserId()))
4162
4163 /* don't allow direct alteration of array types */
4164 elemOid = get_element_type(typeOid);
4165 if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid)
4166 {
4167 if (ignoreDependent)
4168 return InvalidOid;
4169 ereport(ERROR,
4171 errmsg("cannot alter array type %s",
4172 format_type_be(typeOid)),
4173 errhint("You can alter type %s, which will alter the array type as well.",
4175 }
4176
4177 /* and do the work */
4178 return AlterTypeNamespaceInternal(typeOid, nspOid,
4179 false, /* isImplicitArray */
4180 ignoreDependent, /* ignoreDependent */
4181 true, /* errorOnTableType */
4182 objsMoved);
4183}
#define OidIsValid(objectId)
Definition c.h:858
int errhint(const char *fmt,...) pg_attribute_printf(1
Oid get_element_type(Oid typid)
Definition lsyscache.c:2992
Oid get_array_type(Oid typid)
Definition lsyscache.c:3020
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool ignoreDependent, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition typecmds.c:4206

References aclcheck_error_type(), ACLCHECK_NOT_OWNER, AlterTypeNamespaceInternal(), ereport, errcode(), errhint(), errmsg, ERROR, fb(), format_type_be(), get_array_type(), get_element_type(), GetUserId(), InvalidOid, object_ownercheck(), and OidIsValid.

Referenced by AlterObjectNamespace_oid(), and AlterTypeNamespace().

◆ AlterTypeNamespaceInternal()

Oid AlterTypeNamespaceInternal ( Oid  typeOid,
Oid  nspOid,
bool  isImplicitArray,
bool  ignoreDependent,
bool  errorOnTableType,
ObjectAddresses objsMoved 
)
extern

Definition at line 4206 of file typecmds.c.

4211{
4212 Relation rel;
4213 HeapTuple tup;
4215 Oid oldNspOid;
4216 Oid arrayOid;
4217 bool isCompositeType;
4219
4220 /*
4221 * Make sure we haven't moved this object previously.
4222 */
4224 thisobj.objectId = typeOid;
4225 thisobj.objectSubId = 0;
4226
4228 return InvalidOid;
4229
4231
4233 if (!HeapTupleIsValid(tup))
4234 elog(ERROR, "cache lookup failed for type %u", typeOid);
4236
4237 oldNspOid = typform->typnamespace;
4238 arrayOid = typform->typarray;
4239
4240 /* If the type is already there, we scan skip these next few checks. */
4241 if (oldNspOid != nspOid)
4242 {
4243 /* common checks on switching namespaces */
4245
4246 /* check for duplicate name (more friendly than unique-index failure) */
4248 NameGetDatum(&typform->typname),
4250 ereport(ERROR,
4252 errmsg("type \"%s\" already exists in schema \"%s\"",
4253 NameStr(typform->typname),
4255 }
4256
4257 /* Detect whether type is a composite type (but not a table rowtype) */
4259 (typform->typtype == TYPTYPE_COMPOSITE &&
4261
4262 /* Enforce not-table-type if requested */
4263 if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType)
4264 {
4265 if (ignoreDependent)
4266 {
4268 return InvalidOid;
4269 }
4270 if (errorOnTableType)
4271 ereport(ERROR,
4273 errmsg("%s is a table's row type",
4274 format_type_be(typeOid)),
4275 /* translator: %s is an SQL ALTER command */
4276 errhint("Use %s instead.", "ALTER TABLE")));
4277 }
4278
4279 if (oldNspOid != nspOid)
4280 {
4281 /* OK, modify the pg_type row */
4282
4283 /* tup is a copy, so we can scribble directly on it */
4284 typform->typnamespace = nspOid;
4285
4286 CatalogTupleUpdate(rel, &tup->t_self, tup);
4287 }
4288
4289 /*
4290 * Composite types have pg_class entries.
4291 *
4292 * We need to modify the pg_class tuple as well to reflect the change of
4293 * schema.
4294 */
4295 if (isCompositeType)
4296 {
4298
4300
4303 false, objsMoved);
4304
4306
4307 /*
4308 * Check for constraints associated with the composite type (we don't
4309 * currently support this, but probably will someday).
4310 */
4312 nspOid, false, objsMoved);
4313 }
4314 else
4315 {
4316 /* If it's a domain, it might have constraints */
4317 if (typform->typtype == TYPTYPE_DOMAIN)
4319 objsMoved);
4320 }
4321
4322 /*
4323 * Update dependency on schema, if any --- a table rowtype has not got
4324 * one, and neither does an implicit array.
4325 */
4326 if (oldNspOid != nspOid &&
4327 (isCompositeType || typform->typtype != TYPTYPE_COMPOSITE) &&
4331 elog(ERROR, "could not change schema dependency for type \"%s\"",
4332 format_type_be(typeOid));
4333
4335
4337
4339
4341
4342 /* Recursively alter the associated array type, if any */
4343 if (OidIsValid(arrayOid))
4345 true, /* isImplicitArray */
4346 false, /* ignoreDependent */
4347 true, /* errorOnTableType */
4348 objsMoved);
4349
4350 return oldNspOid;
4351}
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2234
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3599
void CheckSetNamespace(Oid oldNspOid, Oid nspOid)
Definition namespace.c:3531
static bool isCompositeType(Oid typid)
void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId, Oid newNspId, bool isType, ObjectAddresses *objsMoved)
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition pg_depend.c:459
static Datum NameGetDatum(const NameData *X)
Definition postgres.h:406
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition syscache.h:102
void AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid, bool hasDependEntry, ObjectAddresses *objsMoved)

References add_exact_object_address(), AlterConstraintNamespaces(), AlterRelationNamespaceInternal(), AlterTypeNamespaceInternal(), CatalogTupleUpdate(), changeDependencyFor(), CheckSetNamespace(), ObjectAddress::classId, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg, ERROR, fb(), Form_pg_type, format_type_be(), get_namespace_name(), get_rel_relkind(), GETSTRUCT(), heap_freetuple(), HeapTupleIsValid, InvalidOid, InvokeObjectPostAlterHook, isCompositeType(), NameGetDatum(), NameStr, object_address_present(), ObjectIdGetDatum(), OidIsValid, RowExclusiveLock, SearchSysCacheCopy1, SearchSysCacheExists2, table_close(), and table_open().

Referenced by AlterTableNamespaceInternal(), AlterTypeNamespace_oid(), and AlterTypeNamespaceInternal().

◆ AlterTypeOwner()

ObjectAddress AlterTypeOwner ( List names,
Oid  newOwnerId,
ObjectType  objecttype 
)
extern

Definition at line 3872 of file typecmds.c.

3873{
3874 TypeName *typename;
3875 Oid typeOid;
3876 Relation rel;
3877 HeapTuple tup;
3881 ObjectAddress address;
3882
3884
3885 /* Make a TypeName so we can use standard type lookup machinery */
3886 typename = makeTypeNameFromNameList(names);
3887
3888 /* Use LookupTypeName here so that shell types can be processed */
3889 tup = LookupTypeName(NULL, typename, NULL, false);
3890 if (tup == NULL)
3891 ereport(ERROR,
3893 errmsg("type \"%s\" does not exist",
3894 TypeNameToString(typename))));
3895 typeOid = typeTypeId(tup);
3896
3897 /* Copy the syscache entry so we can scribble on it below */
3900 tup = newtup;
3902
3903 /* Don't allow ALTER DOMAIN on a type */
3904 if (objecttype == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
3905 ereport(ERROR,
3907 errmsg("%s is not a domain",
3908 format_type_be(typeOid))));
3909
3910 /*
3911 * If it's a composite type, we need to check that it really is a
3912 * free-standing composite type, and not a table's rowtype. We want people
3913 * to use ALTER TABLE not ALTER TYPE for that case.
3914 */
3915 if (typTup->typtype == TYPTYPE_COMPOSITE &&
3917 ereport(ERROR,
3919 errmsg("%s is a table's row type",
3920 format_type_be(typeOid)),
3921 /* translator: %s is an SQL ALTER command */
3922 errhint("Use %s instead.",
3923 "ALTER TABLE")));
3924
3925 /* don't allow direct alteration of array types, either */
3927 ereport(ERROR,
3929 errmsg("cannot alter array type %s",
3930 format_type_be(typeOid)),
3931 errhint("You can alter type %s, which will alter the array type as well.",
3932 format_type_be(typTup->typelem))));
3933
3934 /* don't allow direct alteration of multirange types, either */
3935 if (typTup->typtype == TYPTYPE_MULTIRANGE)
3936 {
3938
3939 /* We don't expect get_multirange_range to fail, but cope if so */
3940 ereport(ERROR,
3942 errmsg("cannot alter multirange type %s",
3943 format_type_be(typeOid)),
3945 errhint("You can alter type %s, which will alter the multirange type as well.",
3946 format_type_be(rangetype)) : 0));
3947 }
3948
3949 /*
3950 * If the new owner is the same as the existing owner, consider the
3951 * command to have succeeded. This is for dump restoration purposes.
3952 */
3953 if (typTup->typowner != newOwnerId)
3954 {
3955 /* Superusers can always do it */
3956 if (!superuser())
3957 {
3958 /* Otherwise, must be owner of the existing object */
3961
3962 /* Must be able to become new owner */
3964
3965 /* New owner must have CREATE privilege on namespace */
3967 newOwnerId,
3968 ACL_CREATE);
3969 if (aclresult != ACLCHECK_OK)
3971 get_namespace_name(typTup->typnamespace));
3972 }
3973
3974 AlterTypeOwner_oid(typeOid, newOwnerId, true);
3975 }
3976
3977 ObjectAddressSet(address, TypeRelationId, typeOid);
3978
3979 /* Clean up */
3981
3982 return address;
3983}
void check_can_set_role(Oid member, Oid role)
Definition acl.c:5371
AclResult
Definition acl.h:183
@ ACLCHECK_OK
Definition acl.h:184
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3880
Oid get_multirange_range(Oid multirangeOid)
Definition lsyscache.c:3761
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition parse_type.c:38
@ OBJECT_SCHEMA
#define ACL_CREATE
Definition parsenodes.h:85
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition typecmds.c:3997

References ACL_CREATE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, AlterTypeOwner_oid(), check_can_set_role(), ereport, errcode(), errhint(), errmsg, ERROR, fb(), Form_pg_type, format_type_be(), get_multirange_range(), get_namespace_name(), get_rel_relkind(), GETSTRUCT(), GetUserId(), heap_copytuple(), LookupTypeName(), makeTypeNameFromNameList(), object_aclcheck(), OBJECT_DOMAIN, object_ownercheck(), OBJECT_SCHEMA, ObjectAddressSet, OidIsValid, ReleaseSysCache(), RowExclusiveLock, superuser(), table_close(), table_open(), TypeNameToString(), and typeTypeId().

Referenced by ExecAlterOwnerStmt().

◆ AlterTypeOwner_oid()

void AlterTypeOwner_oid ( Oid  typeOid,
Oid  newOwnerId,
bool  hasDependEntry 
)
extern

Definition at line 3997 of file typecmds.c.

3998{
3999 Relation rel;
4000 HeapTuple tup;
4002
4004
4006 if (!HeapTupleIsValid(tup))
4007 elog(ERROR, "cache lookup failed for type %u", typeOid);
4009
4010 /*
4011 * If it's a composite type, invoke ATExecChangeOwner so that we fix up
4012 * the pg_class entry properly. That will call back to
4013 * AlterTypeOwnerInternal to take care of the pg_type entry(s).
4014 */
4015 if (typTup->typtype == TYPTYPE_COMPOSITE)
4017 else
4019
4020 /* Update owner dependency reference */
4021 if (hasDependEntry)
4023
4025
4028}
#define AccessExclusiveLock
Definition lockdefs.h:43
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition typecmds.c:4037

References AccessExclusiveLock, AlterTypeOwnerInternal(), ATExecChangeOwner(), changeDependencyOnOwner(), elog, ERROR, fb(), Form_pg_type, GETSTRUCT(), HeapTupleIsValid, InvokeObjectPostAlterHook, ObjectIdGetDatum(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), table_close(), and table_open().

Referenced by AlterTypeOwner(), and shdepReassignOwned_Owner().

◆ AlterTypeOwnerInternal()

void AlterTypeOwnerInternal ( Oid  typeOid,
Oid  newOwnerId 
)
extern

Definition at line 4037 of file typecmds.c.

4038{
4039 Relation rel;
4040 HeapTuple tup;
4045 Acl *newAcl;
4047 bool isNull;
4048
4050
4052 if (!HeapTupleIsValid(tup))
4053 elog(ERROR, "cache lookup failed for type %u", typeOid);
4055
4056 memset(repl_null, false, sizeof(repl_null));
4057 memset(repl_repl, false, sizeof(repl_repl));
4058
4059 repl_repl[Anum_pg_type_typowner - 1] = true;
4061
4064 RelationGetDescr(rel),
4065 &isNull);
4066 /* Null ACLs do not require changes */
4067 if (!isNull)
4068 {
4070 typTup->typowner, newOwnerId);
4071 repl_repl[Anum_pg_type_typacl - 1] = true;
4073 }
4074
4076 repl_repl);
4077
4078 CatalogTupleUpdate(rel, &tup->t_self, tup);
4079
4080 /* If it has an array type, update that too */
4081 if (OidIsValid(typTup->typarray))
4083
4084 /* If it is a range type, update the associated multirange too */
4085 if (typTup->typtype == TYPTYPE_RANGE)
4086 {
4088
4090 ereport(ERROR,
4092 errmsg("could not find multirange type for data type %s",
4093 format_type_be(typeOid))));
4095 }
4096
4097 /* Clean up */
4099}
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition acl.c:1147
#define DatumGetAclP(X)
Definition acl.h:120
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Oid get_range_multirange(Oid rangeOid)
Definition lsyscache.c:3736
#define PointerGetDatum(X)
Definition postgres.h:354

References aclnewowner(), AlterTypeOwnerInternal(), CatalogTupleUpdate(), DatumGetAclP, elog, ereport, errcode(), errmsg, ERROR, fb(), Form_pg_type, format_type_be(), get_range_multirange(), GETSTRUCT(), heap_getattr(), heap_modify_tuple(), HeapTupleIsValid, ObjectIdGetDatum(), OidIsValid, PointerGetDatum, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, table_close(), and table_open().

Referenced by AlterTypeOwner_oid(), AlterTypeOwnerInternal(), and ATExecChangeOwner().

◆ AssignTypeArrayOid()

Oid AssignTypeArrayOid ( void  )
extern

Definition at line 2480 of file typecmds.c.

2481{
2483
2484 /* Use binary-upgrade override for pg_type.typarray? */
2485 if (IsBinaryUpgrade)
2486 {
2488 ereport(ERROR,
2490 errmsg("pg_type array OID value not set when in binary upgrade mode")));
2491
2494 }
2495 else
2496 {
2498
2502 }
2503
2504 return type_array_oid;
2505}
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:448
bool IsBinaryUpgrade
Definition globals.c:123
Oid binary_upgrade_next_array_pg_type_oid
Definition typecmds.c:109

References AccessShareLock, binary_upgrade_next_array_pg_type_oid, ereport, errcode(), errmsg, ERROR, fb(), GetNewOidWithIndex(), InvalidOid, IsBinaryUpgrade, OidIsValid, table_close(), and table_open().

Referenced by DefineDomain(), DefineEnum(), DefineRange(), DefineType(), and heap_create_with_catalog().

◆ AssignTypeMultirangeArrayOid()

Oid AssignTypeMultirangeArrayOid ( void  )
extern

Definition at line 2546 of file typecmds.c.

2547{
2549
2550 /* Use binary-upgrade override for pg_type.oid? */
2551 if (IsBinaryUpgrade)
2552 {
2554 ereport(ERROR,
2556 errmsg("pg_type multirange array OID value not set when in binary upgrade mode")));
2557
2560 }
2561 else
2562 {
2564
2568 }
2569
2571}
Oid binary_upgrade_next_mrng_array_pg_type_oid
Definition typecmds.c:111

References AccessShareLock, binary_upgrade_next_mrng_array_pg_type_oid, ereport, errcode(), errmsg, ERROR, fb(), GetNewOidWithIndex(), InvalidOid, IsBinaryUpgrade, OidIsValid, table_close(), and table_open().

Referenced by DefineRange().

◆ AssignTypeMultirangeOid()

Oid AssignTypeMultirangeOid ( void  )
extern

Definition at line 2513 of file typecmds.c.

2514{
2516
2517 /* Use binary-upgrade override for pg_type.oid? */
2518 if (IsBinaryUpgrade)
2519 {
2521 ereport(ERROR,
2523 errmsg("pg_type multirange OID value not set when in binary upgrade mode")));
2524
2527 }
2528 else
2529 {
2531
2535 }
2536
2537 return type_multirange_oid;
2538}
Oid binary_upgrade_next_mrng_pg_type_oid
Definition typecmds.c:110

References AccessShareLock, binary_upgrade_next_mrng_pg_type_oid, ereport, errcode(), errmsg, ERROR, fb(), GetNewOidWithIndex(), InvalidOid, IsBinaryUpgrade, OidIsValid, table_close(), and table_open().

Referenced by DefineRange().

◆ checkDomainOwner()

void checkDomainOwner ( HeapTuple  tup)
extern

Definition at line 3536 of file typecmds.c.

3537{
3539
3540 /* Check that this is actually a domain */
3541 if (typTup->typtype != TYPTYPE_DOMAIN)
3542 ereport(ERROR,
3544 errmsg("%s is not a domain",
3545 format_type_be(typTup->oid))));
3546
3547 /* Permission check: must own type */
3550}

References aclcheck_error_type(), ACLCHECK_NOT_OWNER, ereport, errcode(), errmsg, ERROR, fb(), Form_pg_type, format_type_be(), GETSTRUCT(), GetUserId(), and object_ownercheck().

Referenced by AlterDomainAddConstraint(), AlterDomainDefault(), AlterDomainDropConstraint(), AlterDomainNotNull(), AlterDomainValidateConstraint(), and RenameConstraint().

◆ DefineCompositeType()

ObjectAddress DefineCompositeType ( RangeVar typevar,
List coldeflist 
)
extern

Definition at line 2588 of file typecmds.c.

2589{
2590 CreateStmt *createStmt = makeNode(CreateStmt);
2593 ObjectAddress address;
2594
2595 /*
2596 * now set the parameters for keys/inheritance etc. All of these are
2597 * uninteresting for composite types...
2598 */
2599 createStmt->relation = typevar;
2600 createStmt->tableElts = coldeflist;
2601 createStmt->inhRelations = NIL;
2602 createStmt->constraints = NIL;
2603 createStmt->options = NIL;
2604 createStmt->oncommit = ONCOMMIT_NOOP;
2605 createStmt->tablespacename = NULL;
2606 createStmt->if_not_exists = false;
2607
2608 /*
2609 * Check for collision with an existing type name. If there is one and
2610 * it's an autogenerated array, we can rename it out of the way. This
2611 * check is here mainly to get a better error message about a "type"
2612 * instead of below about a "relation".
2613 */
2615 NoLock, NULL);
2617 old_type_oid =
2619 CStringGetDatum(createStmt->relation->relname),
2622 {
2624 ereport(ERROR,
2626 errmsg("type \"%s\" already exists", createStmt->relation->relname)));
2627 }
2628
2629 /*
2630 * Finally create the relation. This also creates the type.
2631 */
2632 DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid, &address,
2633 NULL);
2634
2635 return address;
2636}
#define NoLock
Definition lockdefs.h:34
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition namespace.c:740
void RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
Definition namespace.c:847
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition pg_type.c:903
@ ONCOMMIT_NOOP
Definition primnodes.h:59
List * tableElts
OnCommitAction oncommit
List * options
bool if_not_exists
List * inhRelations
RangeVar * relation
char * tablespacename
List * constraints
char * relname
Definition primnodes.h:84
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition syscache.h:111
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition tablecmds.c:810

References CreateStmt::constraints, CStringGetDatum(), DefineRelation(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg, ERROR, fb(), GetSysCacheOid2, CreateStmt::if_not_exists, CreateStmt::inhRelations, InvalidOid, makeNode, moveArrayTypeName(), NIL, NoLock, ObjectIdGetDatum(), OidIsValid, CreateStmt::oncommit, ONCOMMIT_NOOP, CreateStmt::options, RangeVarAdjustRelationPersistence(), RangeVarGetAndCheckCreationNamespace(), CreateStmt::relation, RangeVar::relname, CreateStmt::tableElts, and CreateStmt::tablespacename.

Referenced by ProcessUtilitySlow().

◆ DefineDomain()

ObjectAddress DefineDomain ( ParseState pstate,
CreateDomainStmt stmt 
)
extern

Definition at line 699 of file typecmds.c.

700{
701 char *domainName;
702 char *domainArrayName;
711 bool byValue;
712 char category;
713 char delimiter;
714 char alignment;
715 char storage;
716 char typtype;
717 Datum datum;
718 bool isnull;
719 char *defaultValue = NULL;
720 char *defaultValueBin = NULL;
721 bool saw_default = false;
722 bool typNotNull = false;
723 bool nullDefined = false;
724 int32 typNDims = list_length(stmt->typeName->arrayBounds);
726 List *schema = stmt->constraints;
732 Form_pg_type baseType;
735 ObjectAddress address;
736
737 /* Convert list of names to a name and namespace */
739 &domainName);
740
741 /* Check we have creation rights in target namespace */
743 ACL_CREATE);
744 if (aclresult != ACLCHECK_OK)
747
748 /*
749 * Check for collision with an existing type name. If there is one and
750 * it's an autogenerated array, we can rename it out of the way.
751 */
756 {
760 errmsg("type \"%s\" already exists", domainName)));
761 }
762
763 /*
764 * Look up the base type.
765 */
766 typeTup = typenameType(pstate, stmt->typeName, &basetypeMod);
767 baseType = (Form_pg_type) GETSTRUCT(typeTup);
768 basetypeoid = baseType->oid;
769
770 /*
771 * Base type must be a plain base type, a composite type, another domain,
772 * an enum or a range type. Domains over pseudotypes would create a
773 * security hole. (It would be shorter to code this to just check for
774 * pseudotypes; but it seems safer to call out the specific typtypes that
775 * are supported, rather than assume that all future typtypes would be
776 * automatically supported.)
777 */
778 typtype = baseType->typtype;
779 if (typtype != TYPTYPE_BASE &&
780 typtype != TYPTYPE_COMPOSITE &&
781 typtype != TYPTYPE_DOMAIN &&
782 typtype != TYPTYPE_ENUM &&
783 typtype != TYPTYPE_RANGE &&
784 typtype != TYPTYPE_MULTIRANGE)
787 errmsg("\"%s\" is not a valid base type for a domain",
788 TypeNameToString(stmt->typeName)),
789 parser_errposition(pstate, stmt->typeName->location)));
790
792 if (aclresult != ACLCHECK_OK)
794
795 /*
796 * Collect the properties of the new domain. Some are inherited from the
797 * base type, some are not. If you change any of this inheritance
798 * behavior, be sure to update AlterTypeRecurse() to match!
799 */
800
801 /*
802 * Identify the collation if any
803 */
804 baseColl = baseType->typcollation;
805 if (stmt->collClause)
806 domaincoll = get_collation_oid(stmt->collClause->collname, false);
807 else
809
810 /* Complain if COLLATE is applied to an uncollatable type */
814 errmsg("collations are not supported by type %s",
816 parser_errposition(pstate, stmt->typeName->location)));
817
818 /* passed by value */
819 byValue = baseType->typbyval;
820
821 /* Required Alignment */
822 alignment = baseType->typalign;
823
824 /* TOAST Strategy */
825 storage = baseType->typstorage;
826
827 /* Storage Length */
828 internalLength = baseType->typlen;
829
830 /* Type Category */
831 category = baseType->typcategory;
832
833 /* Array element Delimiter */
834 delimiter = baseType->typdelim;
835
836 /* I/O Functions */
838 outputProcedure = baseType->typoutput;
840 sendProcedure = baseType->typsend;
841
842 /* Domains never accept typmods, so no typmodin/typmodout needed */
843
844 /* Analysis function */
845 analyzeProcedure = baseType->typanalyze;
846
847 /*
848 * Domains don't need a subscript function, since they are not
849 * subscriptable on their own. If the base type is subscriptable, the
850 * parser will reduce the type to the base type before subscripting.
851 */
852
853 /* Inherited default value */
855 Anum_pg_type_typdefault, &isnull);
856 if (!isnull)
858
859 /* Inherited default binary value */
862 if (!isnull)
864
865 /*
866 * Run through constraints manually to avoid the additional processing
867 * conducted by DefineRelation() and friends.
868 */
869 foreach(listptr, schema)
870 {
871 Constraint *constr = lfirst(listptr);
872
873 if (!IsA(constr, Constraint))
874 elog(ERROR, "unrecognized node type: %d",
875 (int) nodeTag(constr));
876 switch (constr->contype)
877 {
878 case CONSTR_DEFAULT:
879
880 /*
881 * The inherited default value may be overridden by the user
882 * with the DEFAULT <expr> clause ... but only once.
883 */
884 if (saw_default)
887 errmsg("multiple default expressions"),
888 parser_errposition(pstate, constr->location));
889 saw_default = true;
890
891 if (constr->raw_expr)
892 {
894
895 /*
896 * Cook the constr->raw_expr into an expression. Note:
897 * name is strictly for error message
898 */
899 defaultExpr = cookDefault(pstate, constr->raw_expr,
903 0);
904
905 /*
906 * If the expression is just a NULL constant, we treat it
907 * like not having a default.
908 *
909 * Note that if the basetype is another domain, we'll see
910 * a CoerceToDomain expr here and not discard the default.
911 * This is critical because the domain default needs to be
912 * retained to override any default that the base domain
913 * might have.
914 */
915 if (defaultExpr == NULL ||
916 (IsA(defaultExpr, Const) &&
918 {
921 }
922 else
923 {
924 /*
925 * Expression must be stored as a nodeToString result,
926 * but we also require a valid textual representation
927 * (mainly to make life easier for pg_dump).
928 */
931 NIL, false, false);
933 }
934 }
935 else
936 {
937 /* No default (can this still happen?) */
940 }
941 break;
942
943 case CONSTR_NOTNULL:
944 if (nullDefined)
945 {
946 if (!typNotNull)
949 errmsg("conflicting NULL/NOT NULL constraints"),
950 parser_errposition(pstate, constr->location));
951
954 errmsg("redundant NOT NULL constraint definition"),
955 parser_errposition(pstate, constr->location));
956 }
957 if (constr->is_no_inherit)
960 errmsg("not-null constraints for domains cannot be marked NO INHERIT"),
961 parser_errposition(pstate, constr->location));
962 typNotNull = true;
963 nullDefined = true;
964 break;
965
966 case CONSTR_NULL:
967 if (nullDefined && typNotNull)
970 errmsg("conflicting NULL/NOT NULL constraints"),
971 parser_errposition(pstate, constr->location));
972 typNotNull = false;
973 nullDefined = true;
974 break;
975
976 case CONSTR_CHECK:
977
978 /*
979 * Check constraints are handled after domain creation, as
980 * they require the Oid of the domain; at this point we can
981 * only check that they're not marked NO INHERIT, because that
982 * would be bogus.
983 */
984 if (constr->is_no_inherit)
987 errmsg("check constraints for domains cannot be marked NO INHERIT"),
988 parser_errposition(pstate, constr->location));
989
990 break;
991
992 /*
993 * All else are error cases
994 */
995 case CONSTR_UNIQUE:
998 errmsg("unique constraints not possible for domains"),
999 parser_errposition(pstate, constr->location));
1000 break;
1001
1002 case CONSTR_PRIMARY:
1003 ereport(ERROR,
1005 errmsg("primary key constraints not possible for domains"),
1006 parser_errposition(pstate, constr->location)));
1007 break;
1008
1009 case CONSTR_EXCLUSION:
1010 ereport(ERROR,
1012 errmsg("exclusion constraints not possible for domains"),
1013 parser_errposition(pstate, constr->location)));
1014 break;
1015
1016 case CONSTR_FOREIGN:
1017 ereport(ERROR,
1019 errmsg("foreign key constraints not possible for domains"),
1020 parser_errposition(pstate, constr->location)));
1021 break;
1022
1027 ereport(ERROR,
1029 errmsg("specifying constraint deferrability not supported for domains"),
1030 parser_errposition(pstate, constr->location)));
1031 break;
1032
1033 case CONSTR_GENERATED:
1034 case CONSTR_IDENTITY:
1035 ereport(ERROR,
1037 errmsg("specifying GENERATED not supported for domains"),
1038 parser_errposition(pstate, constr->location)));
1039 break;
1040
1043 ereport(ERROR,
1045 errmsg("specifying constraint enforceability not supported for domains"),
1046 parser_errposition(pstate, constr->location)));
1047 break;
1048
1049 /* no default, to let compiler warn about missing case */
1050 }
1051 }
1052
1053 /* Allocate OID for array type */
1055
1056 /*
1057 * Have TypeCreate do all the real work.
1058 */
1059 address =
1060 TypeCreate(InvalidOid, /* no predetermined type OID */
1061 domainName, /* type name */
1062 domainNamespace, /* namespace */
1063 InvalidOid, /* relation oid (n/a here) */
1064 0, /* relation kind (ditto) */
1065 GetUserId(), /* owner's ID */
1066 internalLength, /* internal size */
1067 TYPTYPE_DOMAIN, /* type-type (domain type) */
1068 category, /* type-category */
1069 false, /* domain types are never preferred */
1070 delimiter, /* array element delimiter */
1071 inputProcedure, /* input procedure */
1072 outputProcedure, /* output procedure */
1073 receiveProcedure, /* receive procedure */
1074 sendProcedure, /* send procedure */
1075 InvalidOid, /* typmodin procedure - none */
1076 InvalidOid, /* typmodout procedure - none */
1077 analyzeProcedure, /* analyze procedure */
1078 InvalidOid, /* subscript procedure - none */
1079 InvalidOid, /* no array element type */
1080 false, /* this isn't an array */
1081 domainArrayOid, /* array type we are about to create */
1082 basetypeoid, /* base type ID */
1083 defaultValue, /* default type value (text) */
1084 defaultValueBin, /* default type value (binary) */
1085 byValue, /* passed by value */
1086 alignment, /* required alignment */
1087 storage, /* TOAST strategy */
1088 basetypeMod, /* typeMod value */
1089 typNDims, /* Array dimensions for base type */
1090 typNotNull, /* Type NOT NULL */
1091 domaincoll); /* type's collation */
1092
1093 /*
1094 * Create the array type that goes with it.
1095 */
1097
1098 /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */
1099 alignment = (alignment == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;
1100
1101 TypeCreate(domainArrayOid, /* force assignment of this type OID */
1102 domainArrayName, /* type name */
1103 domainNamespace, /* namespace */
1104 InvalidOid, /* relation oid (n/a here) */
1105 0, /* relation kind (ditto) */
1106 GetUserId(), /* owner's ID */
1107 -1, /* internal size (always varlena) */
1108 TYPTYPE_BASE, /* type-type (base type) */
1109 TYPCATEGORY_ARRAY, /* type-category (array) */
1110 false, /* array types are never preferred */
1111 delimiter, /* array element delimiter */
1112 F_ARRAY_IN, /* input procedure */
1113 F_ARRAY_OUT, /* output procedure */
1114 F_ARRAY_RECV, /* receive procedure */
1115 F_ARRAY_SEND, /* send procedure */
1116 InvalidOid, /* typmodin procedure - none */
1117 InvalidOid, /* typmodout procedure - none */
1118 F_ARRAY_TYPANALYZE, /* analyze procedure */
1119 F_ARRAY_SUBSCRIPT_HANDLER, /* array subscript procedure */
1120 address.objectId, /* element type ID */
1121 true, /* yes this is an array type */
1122 InvalidOid, /* no further array type */
1123 InvalidOid, /* base type ID */
1124 NULL, /* never a default type value */
1125 NULL, /* binary default isn't sent either */
1126 false, /* never passed by value */
1127 alignment, /* see above */
1128 TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
1129 -1, /* typMod (Domains only) */
1130 0, /* Array dimensions of typbasetype */
1131 false, /* Type NOT NULL */
1132 domaincoll); /* type's collation */
1133
1135
1136 /*
1137 * Process constraints which refer to the domain ID returned by TypeCreate
1138 */
1139 foreach(listptr, schema)
1140 {
1141 Constraint *constr = lfirst(listptr);
1142
1143 /* it must be a Constraint, per check above */
1144
1145 switch (constr->contype)
1146 {
1147 case CONSTR_CHECK:
1150 constr, domainName, NULL);
1151 break;
1152
1153 case CONSTR_NOTNULL:
1156 constr, domainName, NULL);
1157 break;
1158
1159 /* Other constraint types were fully processed above */
1160
1161 default:
1162 break;
1163 }
1164
1165 /* CCI so we can detect duplicate constraint names */
1167 }
1168
1169 /*
1170 * Now we can clean up.
1171 */
1173
1174 return address;
1175}
int16_t int16
Definition c.h:619
int32_t int32
Definition c.h:620
#define storage
void pfree(void *pointer)
Definition mcxt.c:1619
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Definition namespace.c:3559
Oid get_collation_oid(List *collname, bool missing_ok)
Definition namespace.c:4043
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
#define ACL_USAGE
Definition parsenodes.h:84
@ CONSTR_ATTR_ENFORCED
@ CONSTR_FOREIGN
@ CONSTR_ATTR_DEFERRED
@ CONSTR_IDENTITY
@ CONSTR_UNIQUE
@ CONSTR_ATTR_NOT_DEFERRABLE
@ CONSTR_DEFAULT
@ CONSTR_ATTR_IMMEDIATE
@ CONSTR_NULL
@ CONSTR_GENERATED
@ CONSTR_EXCLUSION
@ CONSTR_ATTR_DEFERRABLE
@ CONSTR_ATTR_NOT_ENFORCED
@ CONSTR_PRIMARY
static int list_length(const List *l)
Definition pg_list.h:152
ObjectAddress TypeCreate(Oid newTypeOid, const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, Oid ownerId, int16 internalSize, char typeType, char typeCategory, bool typePreferred, char typDelim, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid subscriptProcedure, Oid elementType, bool isImplicitArray, Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, bool passedByValue, char alignment, char storage, int32 typeMod, int32 typNDims, bool typeNotNull, Oid typeCollation)
Definition pg_type.c:195
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition pg_type.c:838
bool is_no_inherit
Node * raw_expr
Definition pg_list.h:54
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
Oid AssignTypeArrayOid(void)
Definition typecmds.c:2480
void CommandCounterIncrement(void)
Definition xact.c:1130

References ACL_CREATE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_OK, AssignTypeArrayOid(), CommandCounterIncrement(), CONSTR_ATTR_DEFERRABLE, CONSTR_ATTR_DEFERRED, CONSTR_ATTR_ENFORCED, CONSTR_ATTR_IMMEDIATE, CONSTR_ATTR_NOT_DEFERRABLE, CONSTR_ATTR_NOT_ENFORCED, CONSTR_CHECK, CONSTR_DEFAULT, CONSTR_EXCLUSION, CONSTR_FOREIGN, CONSTR_GENERATED, CONSTR_IDENTITY, CONSTR_NOTNULL, CONSTR_NULL, CONSTR_PRIMARY, CONSTR_UNIQUE, Constraint::contype, cookDefault(), CStringGetDatum(), deparse_expression(), domainAddCheckConstraint(), domainAddNotNullConstraint(), elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg, ERROR, fb(), Form_pg_type, format_type_be(), get_collation_oid(), get_namespace_name(), GETSTRUCT(), GetSysCacheOid2, GetUserId(), InvalidOid, Constraint::is_no_inherit, IsA, lfirst, list_length(), Constraint::location, makeArrayTypeName(), moveArrayTypeName(), NIL, nodeTag, nodeToString(), object_aclcheck(), OBJECT_SCHEMA, ObjectAddress::objectId, ObjectIdGetDatum(), OidIsValid, parser_errposition(), pfree(), QualifiedNameGetCreationNamespace(), Constraint::raw_expr, ReleaseSysCache(), stmt, storage, SysCacheGetAttr(), TextDatumGetCString, TypeCreate(), TypeNameToString(), and typenameType().

Referenced by ProcessUtilitySlow().

◆ DefineEnum()

ObjectAddress DefineEnum ( CreateEnumStmt stmt)
extern

Definition at line 1183 of file typecmds.c.

1184{
1185 char *enumName;
1186 char *enumArrayName;
1192
1193 /* Convert list of names to a name and namespace */
1195 &enumName);
1196
1197 /* Check we have creation rights in target namespace */
1199 if (aclresult != ACLCHECK_OK)
1202
1203 /*
1204 * Check for collision with an existing type name. If there is one and
1205 * it's an autogenerated array, we can rename it out of the way.
1206 */
1211 {
1213 ereport(ERROR,
1215 errmsg("type \"%s\" already exists", enumName)));
1216 }
1217
1218 /* Allocate OID for array type */
1220
1221 /* Create the pg_type entry */
1222 enumTypeAddr =
1223 TypeCreate(InvalidOid, /* no predetermined type OID */
1224 enumName, /* type name */
1225 enumNamespace, /* namespace */
1226 InvalidOid, /* relation oid (n/a here) */
1227 0, /* relation kind (ditto) */
1228 GetUserId(), /* owner's ID */
1229 sizeof(Oid), /* internal size */
1230 TYPTYPE_ENUM, /* type-type (enum type) */
1231 TYPCATEGORY_ENUM, /* type-category (enum type) */
1232 false, /* enum types are never preferred */
1233 DEFAULT_TYPDELIM, /* array element delimiter */
1234 F_ENUM_IN, /* input procedure */
1235 F_ENUM_OUT, /* output procedure */
1236 F_ENUM_RECV, /* receive procedure */
1237 F_ENUM_SEND, /* send procedure */
1238 InvalidOid, /* typmodin procedure - none */
1239 InvalidOid, /* typmodout procedure - none */
1240 InvalidOid, /* analyze procedure - default */
1241 InvalidOid, /* subscript procedure - none */
1242 InvalidOid, /* element type ID */
1243 false, /* this is not an array type */
1244 enumArrayOid, /* array type we are about to create */
1245 InvalidOid, /* base type ID (only for domains) */
1246 NULL, /* never a default type value */
1247 NULL, /* binary default isn't sent either */
1248 true, /* always passed by value */
1249 TYPALIGN_INT, /* int alignment */
1250 TYPSTORAGE_PLAIN, /* TOAST strategy always plain */
1251 -1, /* typMod (Domains only) */
1252 0, /* Array dimensions of typbasetype */
1253 false, /* Type NOT NULL */
1254 InvalidOid); /* type's collation */
1255
1256 /* Enter the enum's values into pg_enum */
1257 EnumValuesCreate(enumTypeAddr.objectId, stmt->vals);
1258
1259 /*
1260 * Create the array type that goes with it.
1261 */
1263
1264 TypeCreate(enumArrayOid, /* force assignment of this type OID */
1265 enumArrayName, /* type name */
1266 enumNamespace, /* namespace */
1267 InvalidOid, /* relation oid (n/a here) */
1268 0, /* relation kind (ditto) */
1269 GetUserId(), /* owner's ID */
1270 -1, /* internal size (always varlena) */
1271 TYPTYPE_BASE, /* type-type (base type) */
1272 TYPCATEGORY_ARRAY, /* type-category (array) */
1273 false, /* array types are never preferred */
1274 DEFAULT_TYPDELIM, /* array element delimiter */
1275 F_ARRAY_IN, /* input procedure */
1276 F_ARRAY_OUT, /* output procedure */
1277 F_ARRAY_RECV, /* receive procedure */
1278 F_ARRAY_SEND, /* send procedure */
1279 InvalidOid, /* typmodin procedure - none */
1280 InvalidOid, /* typmodout procedure - none */
1281 F_ARRAY_TYPANALYZE, /* analyze procedure */
1282 F_ARRAY_SUBSCRIPT_HANDLER, /* array subscript procedure */
1283 enumTypeAddr.objectId, /* element type ID */
1284 true, /* yes this is an array type */
1285 InvalidOid, /* no further array type */
1286 InvalidOid, /* base type ID */
1287 NULL, /* never a default type value */
1288 NULL, /* binary default isn't sent either */
1289 false, /* never passed by value */
1290 TYPALIGN_INT, /* enums have int align, so do their arrays */
1291 TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
1292 -1, /* typMod (Domains only) */
1293 0, /* Array dimensions of typbasetype */
1294 false, /* Type NOT NULL */
1295 InvalidOid); /* type's collation */
1296
1298
1299 return enumTypeAddr;
1300}
void EnumValuesCreate(Oid enumTypeOid, List *vals)
Definition pg_enum.c:84
#define DEFAULT_TYPDELIM
Definition typecmds.h:22

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, AssignTypeArrayOid(), CStringGetDatum(), DEFAULT_TYPDELIM, EnumValuesCreate(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg, ERROR, fb(), get_namespace_name(), GetSysCacheOid2, GetUserId(), InvalidOid, makeArrayTypeName(), moveArrayTypeName(), object_aclcheck(), OBJECT_SCHEMA, ObjectIdGetDatum(), OidIsValid, pfree(), QualifiedNameGetCreationNamespace(), stmt, and TypeCreate().

Referenced by ProcessUtilitySlow().

◆ DefineRange()

ObjectAddress DefineRange ( ParseState pstate,
CreateRangeStmt stmt 
)
extern

Definition at line 1382 of file typecmds.c.

1383{
1384 char *typeName;
1386 Oid typoid;
1387 char *rangeArrayName;
1388 char *multirangeTypeName = NULL;
1389 char *multirangeArrayName;
1404 bool subtypbyval;
1405 char subtypalign;
1406 char alignment;
1408 ListCell *lc;
1409 ObjectAddress address;
1417
1418 /* Convert list of names to a name and namespace */
1420 &typeName);
1421
1422 /* Check we have creation rights in target namespace */
1424 if (aclresult != ACLCHECK_OK)
1427
1428 /*
1429 * Look to see if type already exists.
1430 */
1432 CStringGetDatum(typeName),
1434
1435 /*
1436 * If it's not a shell, see if it's an autogenerated array type, and if so
1437 * rename it out of the way.
1438 */
1439 if (OidIsValid(typoid) && get_typisdefined(typoid))
1440 {
1441 if (moveArrayTypeName(typoid, typeName, typeNamespace))
1442 typoid = InvalidOid;
1443 else
1444 ereport(ERROR,
1446 errmsg("type \"%s\" already exists", typeName)));
1447 }
1448
1449 /*
1450 * Unlike DefineType(), we don't insist on a shell type existing first, as
1451 * it's only needed if the user wants to specify a canonical function.
1452 */
1453
1454 /* Extract the parameters from the parameter list */
1455 foreach(lc, stmt->params)
1456 {
1457 DefElem *defel = (DefElem *) lfirst(lc);
1458
1459 if (strcmp(defel->defname, "subtype") == 0)
1460 {
1463 /* we can look up the subtype name immediately */
1465 }
1466 else if (strcmp(defel->defname, "subtype_opclass") == 0)
1467 {
1468 if (rangeSubOpclassName != NIL)
1471 }
1472 else if (strcmp(defel->defname, "collation") == 0)
1473 {
1474 if (rangeCollationName != NIL)
1477 }
1478 else if (strcmp(defel->defname, "canonical") == 0)
1479 {
1480 if (rangeCanonicalName != NIL)
1483 }
1484 else if (strcmp(defel->defname, "subtype_diff") == 0)
1485 {
1489 }
1490 else if (strcmp(defel->defname, "multirange_type_name") == 0)
1491 {
1492 if (multirangeTypeName != NULL)
1494 /* we can look up the subtype name immediately */
1497
1498 /* Check we have creation rights in target namespace */
1501 if (aclresult != ACLCHECK_OK)
1504 }
1505 else
1506 ereport(ERROR,
1508 errmsg("type attribute \"%s\" not recognized",
1509 defel->defname)));
1510 }
1511
1512 /* Must have a subtype */
1514 ereport(ERROR,
1516 errmsg("type attribute \"subtype\" is required")));
1517 /* disallow ranges of pseudotypes */
1519 ereport(ERROR,
1521 errmsg("range subtype cannot be %s",
1523
1524 /* Identify subopclass */
1526
1527 /* Identify collation to use, if any */
1529 {
1530 if (rangeCollationName != NIL)
1532 else
1534 }
1535 else
1536 {
1537 if (rangeCollationName != NIL)
1538 ereport(ERROR,
1540 errmsg("range collation specified but subtype does not support collation")));
1542 }
1543
1544 /* Identify support functions, if provided */
1545 if (rangeCanonicalName != NIL)
1546 {
1547 if (!OidIsValid(typoid))
1548 ereport(ERROR,
1550 errmsg("cannot specify a canonical function without a pre-created shell type"),
1551 errhint("Create the type as a shell type, then create its canonicalization function, then do a full CREATE TYPE.")));
1553 typoid);
1554 }
1555 else
1557
1560 rangeSubtype);
1561 else
1563
1566
1567 /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for ranges */
1569
1570 /* Allocate OID for array type, its multirange, and its multirange array */
1574
1575 /* Create the pg_type entry */
1576 address =
1577 TypeCreate(InvalidOid, /* no predetermined type OID */
1578 typeName, /* type name */
1579 typeNamespace, /* namespace */
1580 InvalidOid, /* relation oid (n/a here) */
1581 0, /* relation kind (ditto) */
1582 GetUserId(), /* owner's ID */
1583 -1, /* internal size (always varlena) */
1584 TYPTYPE_RANGE, /* type-type (range type) */
1585 TYPCATEGORY_RANGE, /* type-category (range type) */
1586 false, /* range types are never preferred */
1587 DEFAULT_TYPDELIM, /* array element delimiter */
1588 F_RANGE_IN, /* input procedure */
1589 F_RANGE_OUT, /* output procedure */
1590 F_RANGE_RECV, /* receive procedure */
1591 F_RANGE_SEND, /* send procedure */
1592 InvalidOid, /* typmodin procedure - none */
1593 InvalidOid, /* typmodout procedure - none */
1594 F_RANGE_TYPANALYZE, /* analyze procedure */
1595 InvalidOid, /* subscript procedure - none */
1596 InvalidOid, /* element type ID - none */
1597 false, /* this is not an array type */
1598 rangeArrayOid, /* array type we are about to create */
1599 InvalidOid, /* base type ID (only for domains) */
1600 NULL, /* never a default type value */
1601 NULL, /* no binary form available either */
1602 false, /* never passed by value */
1603 alignment, /* alignment */
1604 TYPSTORAGE_EXTENDED, /* TOAST strategy (always extended) */
1605 -1, /* typMod (Domains only) */
1606 0, /* Array dimensions of typbasetype */
1607 false, /* Type NOT NULL */
1608 InvalidOid); /* type's collation (ranges never have one) */
1609 Assert(typoid == InvalidOid || typoid == address.objectId);
1610 typoid = address.objectId;
1611
1612 /* Create the multirange that goes with it */
1614 {
1616
1617 /*
1618 * Look to see if multirange type already exists.
1619 */
1623
1624 /*
1625 * If it's not a shell, see if it's an autogenerated array type, and
1626 * if so rename it out of the way.
1627 */
1629 {
1631 ereport(ERROR,
1633 errmsg("type \"%s\" already exists", multirangeTypeName)));
1634 }
1635 }
1636 else
1637 {
1638 /* Generate multirange name automatically */
1641 }
1642
1644 TypeCreate(multirangeOid, /* force assignment of this type OID */
1645 multirangeTypeName, /* type name */
1646 multirangeNamespace, /* namespace */
1647 InvalidOid, /* relation oid (n/a here) */
1648 0, /* relation kind (ditto) */
1649 GetUserId(), /* owner's ID */
1650 -1, /* internal size (always varlena) */
1651 TYPTYPE_MULTIRANGE, /* type-type (multirange type) */
1652 TYPCATEGORY_RANGE, /* type-category (range type) */
1653 false, /* multirange types are never preferred */
1654 DEFAULT_TYPDELIM, /* array element delimiter */
1655 F_MULTIRANGE_IN, /* input procedure */
1656 F_MULTIRANGE_OUT, /* output procedure */
1657 F_MULTIRANGE_RECV, /* receive procedure */
1658 F_MULTIRANGE_SEND, /* send procedure */
1659 InvalidOid, /* typmodin procedure - none */
1660 InvalidOid, /* typmodout procedure - none */
1661 F_MULTIRANGE_TYPANALYZE, /* analyze procedure */
1662 InvalidOid, /* subscript procedure - none */
1663 InvalidOid, /* element type ID - none */
1664 false, /* this is not an array type */
1665 multirangeArrayOid, /* array type we are about to create */
1666 InvalidOid, /* base type ID (only for domains) */
1667 NULL, /* never a default type value */
1668 NULL, /* no binary form available either */
1669 false, /* never passed by value */
1670 alignment, /* alignment */
1671 'x', /* TOAST strategy (always extended) */
1672 -1, /* typMod (Domains only) */
1673 0, /* Array dimensions of typbasetype */
1674 false, /* Type NOT NULL */
1675 InvalidOid); /* type's collation (ranges never have one) */
1676 Assert(multirangeOid == mltrngaddress.objectId);
1677
1678 /*
1679 * Create the array type that goes with it.
1680 */
1682
1683 TypeCreate(rangeArrayOid, /* force assignment of this type OID */
1684 rangeArrayName, /* type name */
1685 typeNamespace, /* namespace */
1686 InvalidOid, /* relation oid (n/a here) */
1687 0, /* relation kind (ditto) */
1688 GetUserId(), /* owner's ID */
1689 -1, /* internal size (always varlena) */
1690 TYPTYPE_BASE, /* type-type (base type) */
1691 TYPCATEGORY_ARRAY, /* type-category (array) */
1692 false, /* array types are never preferred */
1693 DEFAULT_TYPDELIM, /* array element delimiter */
1694 F_ARRAY_IN, /* input procedure */
1695 F_ARRAY_OUT, /* output procedure */
1696 F_ARRAY_RECV, /* receive procedure */
1697 F_ARRAY_SEND, /* send procedure */
1698 InvalidOid, /* typmodin procedure - none */
1699 InvalidOid, /* typmodout procedure - none */
1700 F_ARRAY_TYPANALYZE, /* analyze procedure */
1701 F_ARRAY_SUBSCRIPT_HANDLER, /* array subscript procedure */
1702 typoid, /* element type ID */
1703 true, /* yes this is an array type */
1704 InvalidOid, /* no further array type */
1705 InvalidOid, /* base type ID */
1706 NULL, /* never a default type value */
1707 NULL, /* binary default isn't sent either */
1708 false, /* never passed by value */
1709 alignment, /* alignment - same as range's */
1710 TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
1711 -1, /* typMod (Domains only) */
1712 0, /* Array dimensions of typbasetype */
1713 false, /* Type NOT NULL */
1714 InvalidOid); /* typcollation */
1715
1717
1718 /* Create the multirange's array type */
1719
1721
1722 TypeCreate(multirangeArrayOid, /* force assignment of this type OID */
1723 multirangeArrayName, /* type name */
1724 multirangeNamespace, /* namespace */
1725 InvalidOid, /* relation oid (n/a here) */
1726 0, /* relation kind (ditto) */
1727 GetUserId(), /* owner's ID */
1728 -1, /* internal size (always varlena) */
1729 TYPTYPE_BASE, /* type-type (base type) */
1730 TYPCATEGORY_ARRAY, /* type-category (array) */
1731 false, /* array types are never preferred */
1732 DEFAULT_TYPDELIM, /* array element delimiter */
1733 F_ARRAY_IN, /* input procedure */
1734 F_ARRAY_OUT, /* output procedure */
1735 F_ARRAY_RECV, /* receive procedure */
1736 F_ARRAY_SEND, /* send procedure */
1737 InvalidOid, /* typmodin procedure - none */
1738 InvalidOid, /* typmodout procedure - none */
1739 F_ARRAY_TYPANALYZE, /* analyze procedure */
1740 F_ARRAY_SUBSCRIPT_HANDLER, /* array subscript procedure */
1741 multirangeOid, /* element type ID */
1742 true, /* yes this is an array type */
1743 InvalidOid, /* no further array type */
1744 InvalidOid, /* base type ID */
1745 NULL, /* never a default type value */
1746 NULL, /* binary default isn't sent either */
1747 false, /* never passed by value */
1748 alignment, /* alignment - same as range's */
1749 'x', /* ARRAY is always toastable */
1750 -1, /* typMod (Domains only) */
1751 0, /* Array dimensions of typbasetype */
1752 false, /* Type NOT NULL */
1753 InvalidOid); /* typcollation */
1754
1755 /* Ensure these new types are visible to ProcedureCreate */
1757
1758 /* And create the constructor functions for this range type */
1765
1766 /* Create the entry in pg_range */
1771
1772 /* Create cast from the range type to its multirange type */
1776
1778
1779 return address;
1780}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:249
Oid regproc
Definition c.h:733
TypeName * defGetTypeName(DefElem *def)
Definition define.c:270
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition define.c:370
@ DEPENDENCY_INTERNAL
Definition dependency.h:35
bool get_typisdefined(Oid typid)
Definition lsyscache.c:2404
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2502
Oid get_typcollation(Oid typid)
Definition lsyscache.c:3289
bool type_is_collatable(Oid typid)
Definition lsyscache.c:3314
ObjectAddress CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, Oid incastid, Oid outcastid, char castcontext, char castmethod, DependencyType behavior)
Definition pg_cast.c:49
void RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation, Oid rangeSubOpclass, RegProcedure rangeCanonical, RegProcedure rangeSubDiff, Oid multirangeTypeOid, RegProcedure rangeConstruct2, RegProcedure rangeConstruct3, RegProcedure mltrngConstruct0, RegProcedure mltrngConstruct1, RegProcedure mltrngConstruct2)
Definition pg_range.c:36
char * makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
Definition pg_type.c:948
Oid AssignTypeMultirangeOid(void)
Definition typecmds.c:2513
static Oid findRangeSubOpclass(List *opcname, Oid subtype)
Definition typecmds.c:2352
static void makeMultirangeConstructors(const char *name, Oid namespace, Oid multirangeOid, Oid rangeOid, Oid rangeArrayOid, Oid *mltrngConstruct0_p, Oid *mltrngConstruct1_p, Oid *mltrngConstruct2_p)
Definition typecmds.c:1876
static Oid findRangeSubtypeDiffFunction(List *procname, Oid subtype)
Definition typecmds.c:2432
static Oid findRangeCanonicalFunction(List *procname, Oid typeOid)
Definition typecmds.c:2391
static void makeRangeConstructors(const char *name, Oid namespace, Oid rangeOid, Oid subtype, Oid *rangeConstruct2_p, Oid *rangeConstruct3_p)
Definition typecmds.c:1795
Oid AssignTypeMultirangeArrayOid(void)
Definition typecmds.c:2546

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, Assert, AssignTypeArrayOid(), AssignTypeMultirangeArrayOid(), AssignTypeMultirangeOid(), CastCreate(), CommandCounterIncrement(), CStringGetDatum(), DEFAULT_TYPDELIM, defGetQualifiedName(), defGetTypeName(), DEPENDENCY_INTERNAL, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg, ERROR, errorConflictingDefElem(), fb(), findRangeCanonicalFunction(), findRangeSubOpclass(), findRangeSubtypeDiffFunction(), format_type_be(), get_collation_oid(), get_namespace_name(), get_typcollation(), get_typisdefined(), get_typlenbyvalalign(), get_typtype(), GetSysCacheOid2, GetUserId(), InvalidOid, lfirst, makeArrayTypeName(), makeMultirangeConstructors(), makeMultirangeTypeName(), makeRangeConstructors(), moveArrayTypeName(), NIL, object_aclcheck(), OBJECT_SCHEMA, ObjectAddress::objectId, ObjectIdGetDatum(), OidIsValid, pfree(), PG_USED_FOR_ASSERTS_ONLY, QualifiedNameGetCreationNamespace(), RangeCreate(), stmt, type_is_collatable(), TypeCreate(), and typenameTypeId().

Referenced by ProcessUtilitySlow().

◆ DefineType()

ObjectAddress DefineType ( ParseState pstate,
List names,
List parameters 
)
extern

Definition at line 154 of file typecmds.c.

155{
156 char *typeName;
158 int16 internalLength = -1; /* default: variable-length */
159 List *inputName = NIL;
162 List *sendName = NIL;
167 char category = TYPCATEGORY_USER;
168 bool preferred = false;
171 char *defaultValue = NULL;
172 bool byValue = false;
173 char alignment = TYPALIGN_INT; /* default alignment */
174 char storage = TYPSTORAGE_PLAIN; /* default TOAST storage method */
175 Oid collation = InvalidOid;
197 Oid receiveOid = InvalidOid;
198 Oid sendOid = InvalidOid;
199 Oid typmodinOid = InvalidOid;
200 Oid typmodoutOid = InvalidOid;
201 Oid analyzeOid = InvalidOid;
202 Oid subscriptOid = InvalidOid;
203 char *array_type;
205 Oid typoid;
206 ListCell *pl;
207 ObjectAddress address;
208
209 /*
210 * As of Postgres 8.4, we require superuser privilege to create a base
211 * type. This is simple paranoia: there are too many ways to mess up the
212 * system with an incorrect type definition (for instance, representation
213 * parameters that don't match what the C code expects). In practice it
214 * takes superuser privilege to create the I/O functions, and so the
215 * former requirement that you own the I/O functions pretty much forced
216 * superuserness anyway. We're just making doubly sure here.
217 *
218 * XXX re-enable NOT_USED code sections below if you remove this test.
219 */
220 if (!superuser())
223 errmsg("must be superuser to create a base type")));
224
225 /* Convert list of names to a name and namespace */
227
228#ifdef NOT_USED
229 /* XXX this is unnecessary given the superuser check above */
230 /* Check we have creation rights in target namespace */
232 if (aclresult != ACLCHECK_OK)
235#endif
236
237 /*
238 * Look to see if type already exists.
239 */
241 CStringGetDatum(typeName),
243
244 /*
245 * If it's not a shell, see if it's an autogenerated array type, and if so
246 * rename it out of the way.
247 */
248 if (OidIsValid(typoid) && get_typisdefined(typoid))
249 {
250 if (moveArrayTypeName(typoid, typeName, typeNamespace))
251 typoid = InvalidOid;
252 else
255 errmsg("type \"%s\" already exists", typeName)));
256 }
257
258 /*
259 * If this command is a parameterless CREATE TYPE, then we're just here to
260 * make a shell type, so do that (or fail if there already is a shell).
261 */
262 if (parameters == NIL)
263 {
264 if (OidIsValid(typoid))
267 errmsg("type \"%s\" already exists", typeName)));
268
269 address = TypeShellMake(typeName, typeNamespace, GetUserId());
270 return address;
271 }
272
273 /*
274 * Otherwise, we must already have a shell type, since there is no other
275 * way that the I/O functions could have been created.
276 */
277 if (!OidIsValid(typoid))
280 errmsg("type \"%s\" does not exist", typeName),
281 errhint("Create the type as a shell type, then create its I/O functions, then do a full CREATE TYPE.")));
282
283 /* Extract the parameters from the parameter list */
284 foreach(pl, parameters)
285 {
286 DefElem *defel = (DefElem *) lfirst(pl);
287 DefElem **defelp;
288
289 if (strcmp(defel->defname, "like") == 0)
291 else if (strcmp(defel->defname, "internallength") == 0)
293 else if (strcmp(defel->defname, "input") == 0)
295 else if (strcmp(defel->defname, "output") == 0)
297 else if (strcmp(defel->defname, "receive") == 0)
299 else if (strcmp(defel->defname, "send") == 0)
301 else if (strcmp(defel->defname, "typmod_in") == 0)
303 else if (strcmp(defel->defname, "typmod_out") == 0)
305 else if (strcmp(defel->defname, "analyze") == 0 ||
306 strcmp(defel->defname, "analyse") == 0)
308 else if (strcmp(defel->defname, "subscript") == 0)
310 else if (strcmp(defel->defname, "category") == 0)
312 else if (strcmp(defel->defname, "preferred") == 0)
314 else if (strcmp(defel->defname, "delimiter") == 0)
316 else if (strcmp(defel->defname, "element") == 0)
318 else if (strcmp(defel->defname, "default") == 0)
320 else if (strcmp(defel->defname, "passedbyvalue") == 0)
321 defelp = &byValueEl;
322 else if (strcmp(defel->defname, "alignment") == 0)
324 else if (strcmp(defel->defname, "storage") == 0)
325 defelp = &storageEl;
326 else if (strcmp(defel->defname, "collatable") == 0)
328 else
329 {
330 /* WARNING, not ERROR, for historical backwards-compatibility */
333 errmsg("type attribute \"%s\" not recognized",
334 defel->defname),
335 parser_errposition(pstate, defel->location)));
336 continue;
337 }
338 if (*defelp != NULL)
340 *defelp = defel;
341 }
342
343 /*
344 * Now interpret the options; we do this separately so that LIKE can be
345 * overridden by other options regardless of the ordering in the parameter
346 * list.
347 */
348 if (likeTypeEl)
349 {
352
355 internalLength = likeForm->typlen;
356 byValue = likeForm->typbyval;
357 alignment = likeForm->typalign;
358 storage = likeForm->typstorage;
360 }
363 if (inputNameEl)
365 if (outputNameEl)
367 if (receiveNameEl)
369 if (sendNameEl)
371 if (typmodinNameEl)
373 if (typmodoutNameEl)
375 if (analyzeNameEl)
377 if (subscriptNameEl)
379 if (categoryEl)
380 {
381 char *p = defGetString(categoryEl);
382
383 category = p[0];
384 /* restrict to non-control ASCII */
388 errmsg("invalid type category \"%s\": must be simple ASCII",
389 p)));
390 }
391 if (preferredEl)
393 if (delimiterEl)
394 {
395 char *p = defGetString(delimiterEl);
396
397 delimiter = p[0];
398 /* XXX shouldn't we restrict the delimiter? */
399 }
400 if (elemTypeEl)
401 {
403 /* disallow arrays of pseudotypes */
407 errmsg("array element type cannot be %s",
409 }
410 if (defaultValueEl)
412 if (byValueEl)
414 if (alignmentEl)
415 {
416 char *a = defGetString(alignmentEl);
417
418 /*
419 * Note: if argument was an unquoted identifier, parser will have
420 * applied translations to it, so be prepared to recognize translated
421 * type names as well as the nominal form.
422 */
423 if (pg_strcasecmp(a, "double") == 0 ||
424 pg_strcasecmp(a, "float8") == 0 ||
425 pg_strcasecmp(a, "pg_catalog.float8") == 0)
426 alignment = TYPALIGN_DOUBLE;
427 else if (pg_strcasecmp(a, "int4") == 0 ||
428 pg_strcasecmp(a, "pg_catalog.int4") == 0)
429 alignment = TYPALIGN_INT;
430 else if (pg_strcasecmp(a, "int2") == 0 ||
431 pg_strcasecmp(a, "pg_catalog.int2") == 0)
432 alignment = TYPALIGN_SHORT;
433 else if (pg_strcasecmp(a, "char") == 0 ||
434 pg_strcasecmp(a, "pg_catalog.bpchar") == 0)
435 alignment = TYPALIGN_CHAR;
436 else
439 errmsg("alignment \"%s\" not recognized", a)));
440 }
441 if (storageEl)
442 {
443 char *a = defGetString(storageEl);
444
445 if (pg_strcasecmp(a, "plain") == 0)
447 else if (pg_strcasecmp(a, "external") == 0)
449 else if (pg_strcasecmp(a, "extended") == 0)
451 else if (pg_strcasecmp(a, "main") == 0)
453 else
456 errmsg("storage \"%s\" not recognized", a)));
457 }
458 if (collatableEl)
460
461 /*
462 * make sure we have our required definitions
463 */
464 if (inputName == NIL)
467 errmsg("type input function must be specified")));
468 if (outputName == NIL)
471 errmsg("type output function must be specified")));
472
473 if (typmodinName == NIL && typmodoutName != NIL)
476 errmsg("type modifier output function is useless without a type modifier input function")));
477
478 /*
479 * Convert I/O proc names to OIDs
480 */
483 if (receiveName)
484 receiveOid = findTypeReceiveFunction(receiveName, typoid);
485 if (sendName)
486 sendOid = findTypeSendFunction(sendName, typoid);
487
488 /*
489 * Convert typmodin/out function proc names to OIDs.
490 */
491 if (typmodinName)
493 if (typmodoutName)
495
496 /*
497 * Convert analysis function proc name to an OID. If no analysis function
498 * is specified, we'll use zero to select the built-in default algorithm.
499 */
500 if (analyzeName)
501 analyzeOid = findTypeAnalyzeFunction(analyzeName, typoid);
502
503 /*
504 * Likewise look up the subscripting function if any. If it is not
505 * specified, but a typelem is specified, allow that if
506 * raw_array_subscript_handler can be used. (This is for backwards
507 * compatibility; maybe someday we should throw an error instead.)
508 */
509 if (subscriptName)
510 subscriptOid = findTypeSubscriptingFunction(subscriptName, typoid);
511 else if (OidIsValid(elemType))
512 {
513 if (internalLength > 0 && !byValue && get_typlen(elemType) > 0)
514 subscriptOid = F_RAW_ARRAY_SUBSCRIPT_HANDLER;
515 else
518 errmsg("element type cannot be specified without a subscripting function")));
519 }
520
521 /*
522 * Check permissions on functions. We choose to require the creator/owner
523 * of a type to also own the underlying functions. Since creating a type
524 * is tantamount to granting public execute access on the functions, the
525 * minimum sane check would be for execute-with-grant-option. But we
526 * don't have a way to make the type go away if the grant option is
527 * revoked, so ownership seems better.
528 *
529 * XXX For now, this is all unnecessary given the superuser check above.
530 * If we ever relax that, these calls likely should be moved into
531 * findTypeInputFunction et al, where they could be shared by AlterType.
532 */
533#ifdef NOT_USED
540 if (receiveOid && !object_ownercheck(ProcedureRelationId, receiveOid, GetUserId()))
543 if (sendOid && !object_ownercheck(ProcedureRelationId, sendOid, GetUserId()))
546 if (typmodinOid && !object_ownercheck(ProcedureRelationId, typmodinOid, GetUserId()))
549 if (typmodoutOid && !object_ownercheck(ProcedureRelationId, typmodoutOid, GetUserId()))
552 if (analyzeOid && !object_ownercheck(ProcedureRelationId, analyzeOid, GetUserId()))
555 if (subscriptOid && !object_ownercheck(ProcedureRelationId, subscriptOid, GetUserId()))
558#endif
559
560 /*
561 * OK, we're done checking, time to make the type. We must assign the
562 * array type OID ahead of calling TypeCreate, since the base type and
563 * array type each refer to the other.
564 */
566
567 /*
568 * now have TypeCreate do all the real work.
569 *
570 * Note: the pg_type.oid is stored in user tables as array elements (base
571 * types) in ArrayType and in composite types in DatumTupleFields. This
572 * oid must be preserved by binary upgrades.
573 */
574 address =
575 TypeCreate(InvalidOid, /* no predetermined type OID */
576 typeName, /* type name */
577 typeNamespace, /* namespace */
578 InvalidOid, /* relation oid (n/a here) */
579 0, /* relation kind (ditto) */
580 GetUserId(), /* owner's ID */
581 internalLength, /* internal size */
582 TYPTYPE_BASE, /* type-type (base type) */
583 category, /* type-category */
584 preferred, /* is it a preferred type? */
585 delimiter, /* array element delimiter */
586 inputOid, /* input procedure */
587 outputOid, /* output procedure */
588 receiveOid, /* receive procedure */
589 sendOid, /* send procedure */
590 typmodinOid, /* typmodin procedure */
591 typmodoutOid, /* typmodout procedure */
592 analyzeOid, /* analyze procedure */
593 subscriptOid, /* subscript procedure */
594 elemType, /* element type ID */
595 false, /* this is not an implicit array type */
596 array_oid, /* array type we are about to create */
597 InvalidOid, /* base type ID (only for domains) */
598 defaultValue, /* default type value */
599 NULL, /* no binary form available */
600 byValue, /* passed by value */
601 alignment, /* required alignment */
602 storage, /* TOAST strategy */
603 -1, /* typMod (Domains only) */
604 0, /* Array Dimensions of typbasetype */
605 false, /* Type NOT NULL */
606 collation); /* type's collation */
607 Assert(typoid == address.objectId);
608
609 /*
610 * Create the array type that goes with it.
611 */
612 array_type = makeArrayTypeName(typeName, typeNamespace);
613
614 /* alignment must be TYPALIGN_INT or TYPALIGN_DOUBLE for arrays */
615 alignment = (alignment == TYPALIGN_DOUBLE) ? TYPALIGN_DOUBLE : TYPALIGN_INT;
616
617 TypeCreate(array_oid, /* force assignment of this type OID */
618 array_type, /* type name */
619 typeNamespace, /* namespace */
620 InvalidOid, /* relation oid (n/a here) */
621 0, /* relation kind (ditto) */
622 GetUserId(), /* owner's ID */
623 -1, /* internal size (always varlena) */
624 TYPTYPE_BASE, /* type-type (base type) */
625 TYPCATEGORY_ARRAY, /* type-category (array) */
626 false, /* array types are never preferred */
627 delimiter, /* array element delimiter */
628 F_ARRAY_IN, /* input procedure */
629 F_ARRAY_OUT, /* output procedure */
630 F_ARRAY_RECV, /* receive procedure */
631 F_ARRAY_SEND, /* send procedure */
632 typmodinOid, /* typmodin procedure */
633 typmodoutOid, /* typmodout procedure */
634 F_ARRAY_TYPANALYZE, /* analyze procedure */
635 F_ARRAY_SUBSCRIPT_HANDLER, /* array subscript procedure */
636 typoid, /* element type ID */
637 true, /* yes this is an array type */
638 InvalidOid, /* no further array type */
639 InvalidOid, /* base type ID */
640 NULL, /* never a default type value */
641 NULL, /* binary default isn't sent either */
642 false, /* never passed by value */
643 alignment, /* see above */
644 TYPSTORAGE_EXTENDED, /* ARRAY is always toastable */
645 -1, /* typMod (Domains only) */
646 0, /* Array dimensions of typbasetype */
647 false, /* Type NOT NULL */
648 collation); /* type's collation */
649
650 pfree(array_type);
651
652 return address;
653}
int defGetTypeLength(DefElem *def)
Definition define.c:298
bool defGetBoolean(DefElem *def)
Definition define.c:93
#define WARNING
Definition elog.h:37
int16 get_typlen(Oid typid)
Definition lsyscache.c:2428
char * NameListToString(const List *names)
Definition namespace.c:3666
@ OBJECT_FUNCTION
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition pg_type.c:57
static Oid findTypeOutputFunction(List *procname, Oid typeOid)
Definition typecmds.c:2086
static Oid findTypeInputFunction(List *procname, Oid typeOid)
Definition typecmds.c:2023

References a, ACL_CREATE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, Assert, AssignTypeArrayOid(), CStringGetDatum(), DEFAULT_TYPDELIM, defGetBoolean(), defGetQualifiedName(), defGetString(), defGetTypeLength(), defGetTypeName(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg, ERROR, errorConflictingDefElem(), fb(), findTypeAnalyzeFunction(), findTypeInputFunction(), findTypeOutputFunction(), findTypeReceiveFunction(), findTypeSendFunction(), findTypeSubscriptingFunction(), findTypeTypmodinFunction(), findTypeTypmodoutFunction(), Form_pg_type, format_type_be(), get_namespace_name(), get_typisdefined(), get_typlen(), get_typtype(), GETSTRUCT(), GetSysCacheOid2, GetUserId(), InvalidOid, lfirst, makeArrayTypeName(), moveArrayTypeName(), NameListToString(), NIL, object_aclcheck(), OBJECT_FUNCTION, object_ownercheck(), OBJECT_SCHEMA, ObjectAddress::objectId, ObjectIdGetDatum(), OidIsValid, parser_errposition(), pfree(), pg_strcasecmp(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), storage, superuser(), TypeCreate(), typenameType(), typenameTypeId(), TypeShellMake(), and WARNING.

Referenced by ProcessUtilitySlow().

◆ RemoveTypeById()

void RemoveTypeById ( Oid  typeOid)
extern

Definition at line 659 of file typecmds.c.

660{
661 Relation relation;
663
665
667 if (!HeapTupleIsValid(tup))
668 elog(ERROR, "cache lookup failed for type %u", typeOid);
669
670 CatalogTupleDelete(relation, &tup->t_self);
671
672 /*
673 * If it is an enum, delete the pg_enum entries too; we don't bother with
674 * making dependency entries for those, so it has to be done "by hand"
675 * here.
676 */
677 if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_ENUM)
678 EnumValuesDelete(typeOid);
679
680 /*
681 * If it is a range type, delete the pg_range entry too; we don't bother
682 * with making a dependency entry for that, so it has to be done "by hand"
683 * here.
684 */
685 if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_RANGE)
686 RangeDelete(typeOid);
687
689
690 table_close(relation, RowExclusiveLock);
691}
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
void EnumValuesDelete(Oid enumTypeOid)
Definition pg_enum.c:237
void RangeDelete(Oid rangeTypeOid)
Definition pg_range.c:120

References CatalogTupleDelete(), elog, EnumValuesDelete(), ERROR, fb(), Form_pg_type, GETSTRUCT(), HeapTupleIsValid, ObjectIdGetDatum(), RangeDelete(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), table_close(), and table_open().

Referenced by doDeletion().

◆ RenameType()

ObjectAddress RenameType ( RenameStmt stmt)
extern

Definition at line 3791 of file typecmds.c.

3792{
3793 List *names = castNode(List, stmt->object);
3794 const char *newTypeName = stmt->newname;
3795 TypeName *typename;
3796 Oid typeOid;
3797 Relation rel;
3798 HeapTuple tup;
3800 ObjectAddress address;
3801
3802 /* Make a TypeName so we can use standard type lookup machinery */
3803 typename = makeTypeNameFromNameList(names);
3804 typeOid = typenameTypeId(NULL, typename);
3805
3806 /* Look up the type in the type table */
3808
3810 if (!HeapTupleIsValid(tup))
3811 elog(ERROR, "cache lookup failed for type %u", typeOid);
3813
3814 /* check permissions on type */
3815 if (!object_ownercheck(TypeRelationId, typeOid, GetUserId()))
3817
3818 /* ALTER DOMAIN used on a non-domain? */
3819 if (stmt->renameType == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
3820 ereport(ERROR,
3822 errmsg("%s is not a domain",
3823 format_type_be(typeOid))));
3824
3825 /*
3826 * If it's a composite type, we need to check that it really is a
3827 * free-standing composite type, and not a table's rowtype. We want people
3828 * to use ALTER TABLE not ALTER TYPE for that case.
3829 */
3830 if (typTup->typtype == TYPTYPE_COMPOSITE &&
3832 ereport(ERROR,
3834 errmsg("%s is a table's row type",
3835 format_type_be(typeOid)),
3836 /* translator: %s is an SQL ALTER command */
3837 errhint("Use %s instead.",
3838 "ALTER TABLE")));
3839
3840 /* don't allow direct alteration of array types, either */
3842 ereport(ERROR,
3844 errmsg("cannot alter array type %s",
3845 format_type_be(typeOid)),
3846 errhint("You can alter type %s, which will alter the array type as well.",
3847 format_type_be(typTup->typelem))));
3848
3849 /* we do allow separate renaming of multirange types, though */
3850
3851 /*
3852 * If type is composite we need to rename associated pg_class entry too.
3853 * RenameRelationInternal will call RenameTypeInternal automatically.
3854 */
3855 if (typTup->typtype == TYPTYPE_COMPOSITE)
3856 RenameRelationInternal(typTup->typrelid, newTypeName, false, false);
3857 else
3859 typTup->typnamespace);
3860
3861 ObjectAddressSet(address, TypeRelationId, typeOid);
3862 /* Clean up */
3864
3865 return address;
3866}
#define castNode(_type_, nodeptr)
Definition nodes.h:182
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition pg_type.c:763
void RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bool is_index)
Definition tablecmds.c:4327

References aclcheck_error_type(), ACLCHECK_NOT_OWNER, castNode, elog, ereport, errcode(), errhint(), errmsg, ERROR, fb(), Form_pg_type, format_type_be(), get_rel_relkind(), GETSTRUCT(), GetUserId(), HeapTupleIsValid, makeTypeNameFromNameList(), OBJECT_DOMAIN, object_ownercheck(), ObjectAddressSet, ObjectIdGetDatum(), RenameRelationInternal(), RenameTypeInternal(), RowExclusiveLock, SearchSysCacheCopy1, stmt, table_close(), table_open(), and typenameTypeId().

Referenced by ExecRenameStmt().