PostgreSQL Source Code  git master
typecmds.h File Reference
#include "access/htup.h"
#include "catalog/dependency.h"
#include "nodes/parsenodes.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 (CreateDomainStmt *stmt)
 
ObjectAddress DefineEnum (CreateEnumStmt *stmt)
 
ObjectAddress DefineRange (CreateRangeStmt *stmt)
 
ObjectAddress AlterEnum (AlterEnumStmt *stmt, bool isTopLevel)
 
ObjectAddress DefineCompositeType (RangeVar *typevar, List *coldeflist)
 
Oid AssignTypeArrayOid (void)
 
ObjectAddress AlterDomainDefault (List *names, Node *defaultRaw)
 
ObjectAddress AlterDomainNotNull (List *names, bool notNull)
 
ObjectAddress AlterDomainAddConstraint (List *names, Node *constr, 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, ObjectAddresses *objsMoved)
 
Oid AlterTypeNamespaceInternal (Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
 

Macro Definition Documentation

◆ DEFAULT_TYPDELIM

#define DEFAULT_TYPDELIM   ','

Function Documentation

◆ AlterDomainAddConstraint()

ObjectAddress AlterDomainAddConstraint ( List names,
Node constr,
ObjectAddress constrAddr 
)

Definition at line 2543 of file typecmds.c.

References checkDomainOwner(), CONSTR_ATTR_DEFERRABLE, CONSTR_ATTR_DEFERRED, CONSTR_ATTR_IMMEDIATE, CONSTR_ATTR_NOT_DEFERRABLE, CONSTR_CHECK, CONSTR_EXCLUSION, CONSTR_FOREIGN, CONSTR_PRIMARY, CONSTR_UNIQUE, Constraint::contype, domainAddConstraint(), elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, IsA, makeTypeNameFromNameList(), NameStr, nodeTag, ObjectAddressSet, ObjectIdGetDatum, RowExclusiveLock, SearchSysCacheCopy1, Constraint::skip_validation, typenameTypeId(), TYPEOID, TypeRelationId, and validateDomainConstraint().

Referenced by ATExecCmd(), and ProcessUtilitySlow().

2545 {
2546  TypeName *typename;
2547  Oid domainoid;
2548  Relation typrel;
2549  HeapTuple tup;
2550  Form_pg_type typTup;
2551  Constraint *constr;
2552  char *ccbin;
2553  ObjectAddress address;
2554 
2555  /* Make a TypeName so we can use standard type lookup machinery */
2556  typename = makeTypeNameFromNameList(names);
2557  domainoid = typenameTypeId(NULL, typename);
2558 
2559  /* Look up the domain in the type table */
2561 
2562  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2563  if (!HeapTupleIsValid(tup))
2564  elog(ERROR, "cache lookup failed for type %u", domainoid);
2565  typTup = (Form_pg_type) GETSTRUCT(tup);
2566 
2567  /* Check it's a domain and check user has permission for ALTER DOMAIN */
2568  checkDomainOwner(tup);
2569 
2570  if (!IsA(newConstraint, Constraint))
2571  elog(ERROR, "unrecognized node type: %d",
2572  (int) nodeTag(newConstraint));
2573 
2574  constr = (Constraint *) newConstraint;
2575 
2576  switch (constr->contype)
2577  {
2578  case CONSTR_CHECK:
2579  /* processed below */
2580  break;
2581 
2582  case CONSTR_UNIQUE:
2583  ereport(ERROR,
2584  (errcode(ERRCODE_SYNTAX_ERROR),
2585  errmsg("unique constraints not possible for domains")));
2586  break;
2587 
2588  case CONSTR_PRIMARY:
2589  ereport(ERROR,
2590  (errcode(ERRCODE_SYNTAX_ERROR),
2591  errmsg("primary key constraints not possible for domains")));
2592  break;
2593 
2594  case CONSTR_EXCLUSION:
2595  ereport(ERROR,
2596  (errcode(ERRCODE_SYNTAX_ERROR),
2597  errmsg("exclusion constraints not possible for domains")));
2598  break;
2599 
2600  case CONSTR_FOREIGN:
2601  ereport(ERROR,
2602  (errcode(ERRCODE_SYNTAX_ERROR),
2603  errmsg("foreign key constraints not possible for domains")));
2604  break;
2605 
2608  case CONSTR_ATTR_DEFERRED:
2609  case CONSTR_ATTR_IMMEDIATE:
2610  ereport(ERROR,
2611  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2612  errmsg("specifying constraint deferrability not supported for domains")));
2613  break;
2614 
2615  default:
2616  elog(ERROR, "unrecognized constraint subtype: %d",
2617  (int) constr->contype);
2618  break;
2619  }
2620 
2621  /*
2622  * Since all other constraint types throw errors, this must be a check
2623  * constraint. First, process the constraint expression and add an entry
2624  * to pg_constraint.
2625  */
2626 
2627  ccbin = domainAddConstraint(domainoid, typTup->typnamespace,
2628  typTup->typbasetype, typTup->typtypmod,
2629  constr, NameStr(typTup->typname), constrAddr);
2630 
2631  /*
2632  * If requested to validate the constraint, test all values stored in the
2633  * attributes based on the domain the constraint is being added to.
2634  */
2635  if (!constr->skip_validation)
2636  validateDomainConstraint(domainoid, ccbin);
2637 
2638  ObjectAddressSet(address, TypeRelationId, domainoid);
2639 
2640  /* Clean up */
2641  heap_close(typrel, RowExclusiveLock);
2642 
2643  return address;
2644 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
static char * domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, int typMod, Constraint *constr, const char *domainName, ObjectAddress *constrAddr)
Definition: typecmds.c:3061
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define nodeTag(nodeptr)
Definition: nodes.h:517
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:3041
static void validateDomainConstraint(Oid domainoid, char *ccbin)
Definition: typecmds.c:2754
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
#define NameStr(name)
Definition: c.h:557
ConstrType contype
Definition: parsenodes.h:2092
#define elog
Definition: elog.h:219
bool skip_validation
Definition: parsenodes.h:2132
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ AlterDomainDefault()

ObjectAddress AlterDomainDefault ( List names,
Node defaultRaw 
)

Definition at line 2198 of file typecmds.c.

References Anum_pg_type_typdefault, Anum_pg_type_typdefaultbin, CatalogTupleUpdate(), checkDomainOwner(), cookDefault(), CStringGetTextDatum, deparse_expression(), elog, ERROR, GenerateTypeDependencies(), GETSTRUCT, heap_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, InvalidOid, InvokeObjectPostAlterHook, IsA, make_parsestate(), makeTypeNameFromNameList(), MemSet, NameStr, Natts_pg_type, NIL, nodeToString(), NoLock, ObjectAddressSet, ObjectIdGetDatum, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, typenameTypeId(), TYPEOID, and TypeRelationId.

Referenced by ProcessUtilitySlow().

2199 {
2200  TypeName *typename;
2201  Oid domainoid;
2202  HeapTuple tup;
2203  ParseState *pstate;
2204  Relation rel;
2205  char *defaultValue;
2206  Node *defaultExpr = NULL; /* NULL if no default specified */
2207  Datum new_record[Natts_pg_type];
2208  bool new_record_nulls[Natts_pg_type];
2209  bool new_record_repl[Natts_pg_type];
2210  HeapTuple newtuple;
2211  Form_pg_type typTup;
2212  ObjectAddress address;
2213 
2214  /* Make a TypeName so we can use standard type lookup machinery */
2215  typename = makeTypeNameFromNameList(names);
2216  domainoid = typenameTypeId(NULL, typename);
2217 
2218  /* Look up the domain in the type table */
2220 
2221  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2222  if (!HeapTupleIsValid(tup))
2223  elog(ERROR, "cache lookup failed for type %u", domainoid);
2224  typTup = (Form_pg_type) GETSTRUCT(tup);
2225 
2226  /* Check it's a domain and check user has permission for ALTER DOMAIN */
2227  checkDomainOwner(tup);
2228 
2229  /* Setup new tuple */
2230  MemSet(new_record, (Datum) 0, sizeof(new_record));
2231  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
2232  MemSet(new_record_repl, false, sizeof(new_record_repl));
2233 
2234  /* Store the new default into the tuple */
2235  if (defaultRaw)
2236  {
2237  /* Create a dummy ParseState for transformExpr */
2238  pstate = make_parsestate(NULL);
2239 
2240  /*
2241  * Cook the colDef->raw_expr into an expression. Note: Name is
2242  * strictly for error message
2243  */
2244  defaultExpr = cookDefault(pstate, defaultRaw,
2245  typTup->typbasetype,
2246  typTup->typtypmod,
2247  NameStr(typTup->typname));
2248 
2249  /*
2250  * If the expression is just a NULL constant, we treat the command
2251  * like ALTER ... DROP DEFAULT. (But see note for same test in
2252  * DefineDomain.)
2253  */
2254  if (defaultExpr == NULL ||
2255  (IsA(defaultExpr, Const) &&((Const *) defaultExpr)->constisnull))
2256  {
2257  /* Default is NULL, drop it */
2258  new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true;
2259  new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
2260  new_record_nulls[Anum_pg_type_typdefault - 1] = true;
2261  new_record_repl[Anum_pg_type_typdefault - 1] = true;
2262  }
2263  else
2264  {
2265  /*
2266  * Expression must be stored as a nodeToString result, but we also
2267  * require a valid textual representation (mainly to make life
2268  * easier for pg_dump).
2269  */
2270  defaultValue = deparse_expression(defaultExpr,
2271  NIL, false, false);
2272 
2273  /*
2274  * Form an updated tuple with the new default and write it back.
2275  */
2276  new_record[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(nodeToString(defaultExpr));
2277 
2278  new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
2279  new_record[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultValue);
2280  new_record_repl[Anum_pg_type_typdefault - 1] = true;
2281  }
2282  }
2283  else
2284  {
2285  /* ALTER ... DROP DEFAULT */
2286  new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true;
2287  new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
2288  new_record_nulls[Anum_pg_type_typdefault - 1] = true;
2289  new_record_repl[Anum_pg_type_typdefault - 1] = true;
2290  }
2291 
2292  newtuple = heap_modify_tuple(tup, RelationGetDescr(rel),
2293  new_record, new_record_nulls,
2294  new_record_repl);
2295 
2296  CatalogTupleUpdate(rel, &tup->t_self, newtuple);
2297 
2298  /* Rebuild dependencies */
2299  GenerateTypeDependencies(typTup->typnamespace,
2300  domainoid,
2301  InvalidOid, /* typrelid is n/a */
2302  0, /* relation kind is n/a */
2303  typTup->typowner,
2304  typTup->typinput,
2305  typTup->typoutput,
2306  typTup->typreceive,
2307  typTup->typsend,
2308  typTup->typmodin,
2309  typTup->typmodout,
2310  typTup->typanalyze,
2311  InvalidOid,
2312  false, /* a domain isn't an implicit array */
2313  typTup->typbasetype,
2314  typTup->typcollation,
2315  defaultExpr,
2316  true); /* Rebuild is true */
2317 
2319 
2320  ObjectAddressSet(address, TypeRelationId, domainoid);
2321 
2322  /* Clean up */
2323  heap_close(rel, NoLock);
2324  heap_freetuple(newtuple);
2325 
2326  return address;
2327 }
#define NIL
Definition: pg_list.h:69
#define Anum_pg_type_typdefaultbin
Definition: pg_type.h:267
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Definition: nodes.h:512
#define MemSet(start, val, len)
Definition: c.h:877
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname)
Definition: heap.c:2659
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define Natts_pg_type
Definition: pg_type.h:239
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition: ruleutils.c:3008
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:3041
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
#define NameStr(name)
Definition: c.h:557
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4266
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
void GenerateTypeDependencies(Oid typeNamespace, Oid typeObjectId, Oid relationOid, char relationKind, Oid owner, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, bool isImplicitArray, Oid baseType, Oid typeCollation, Node *defaultExpr, bool rebuild)
Definition: pg_type.c:512
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
#define Anum_pg_type_typdefault
Definition: pg_type.h:268

◆ AlterDomainDropConstraint()

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

Definition at line 2453 of file typecmds.c.

References Anum_pg_constraint_contypid, BTEqualStrategyNumber, checkDomainOwner(), ObjectAddress::classId, ConstraintRelationId, ConstraintTypidIndexId, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvalidObjectAddress, makeTypeNameFromNameList(), NameStr, NoLock, NOTICE, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, performDeletion(), RowExclusiveLock, ScanKeyInit(), SearchSysCacheCopy1, systable_beginscan(), systable_endscan(), systable_getnext(), TypeNameToString(), typenameTypeId(), TYPEOID, and TypeRelationId.

Referenced by ProcessUtilitySlow().

2455 {
2456  TypeName *typename;
2457  Oid domainoid;
2458  HeapTuple tup;
2459  Relation rel;
2460  Relation conrel;
2461  SysScanDesc conscan;
2462  ScanKeyData key[1];
2463  HeapTuple contup;
2464  bool found = false;
2466 
2467  /* Make a TypeName so we can use standard type lookup machinery */
2468  typename = makeTypeNameFromNameList(names);
2469  domainoid = typenameTypeId(NULL, typename);
2470 
2471  /* Look up the domain in the type table */
2473 
2474  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2475  if (!HeapTupleIsValid(tup))
2476  elog(ERROR, "cache lookup failed for type %u", domainoid);
2477 
2478  /* Check it's a domain and check user has permission for ALTER DOMAIN */
2479  checkDomainOwner(tup);
2480 
2481  /* Grab an appropriate lock on the pg_constraint relation */
2483 
2484  /* Use the index to scan only constraints of the target relation */
2485  ScanKeyInit(&key[0],
2487  BTEqualStrategyNumber, F_OIDEQ,
2489 
2490  conscan = systable_beginscan(conrel, ConstraintTypidIndexId, true,
2491  NULL, 1, key);
2492 
2493  /*
2494  * Scan over the result set, removing any matching entries.
2495  */
2496  while ((contup = systable_getnext(conscan)) != NULL)
2497  {
2499 
2500  if (strcmp(NameStr(con->conname), constrName) == 0)
2501  {
2502  ObjectAddress conobj;
2503 
2504  conobj.classId = ConstraintRelationId;
2505  conobj.objectId = HeapTupleGetOid(contup);
2506  conobj.objectSubId = 0;
2507 
2508  performDeletion(&conobj, behavior, 0);
2509  found = true;
2510  }
2511  }
2512 
2513  ObjectAddressSet(address, TypeRelationId, domainoid);
2514 
2515  /* Clean up after the scan */
2516  systable_endscan(conscan);
2517  heap_close(conrel, RowExclusiveLock);
2518 
2519  heap_close(rel, NoLock);
2520 
2521  if (!found)
2522  {
2523  if (!missing_ok)
2524  ereport(ERROR,
2525  (errcode(ERRCODE_UNDEFINED_OBJECT),
2526  errmsg("constraint \"%s\" of domain \"%s\" does not exist",
2527  constrName, TypeNameToString(typename))));
2528  else
2529  ereport(NOTICE,
2530  (errmsg("constraint \"%s\" of domain \"%s\" does not exist, skipping",
2531  constrName, TypeNameToString(typename))));
2532  }
2533 
2534  return address;
2535 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define ConstraintTypidIndexId
Definition: indexing.h:128
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:303
#define ereport(elevel, rest)
Definition: elog.h:122
#define Anum_pg_constraint_contypid
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define NOTICE
Definition: elog.h:37
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:3041
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
#define NameStr(name)
Definition: c.h:557
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ AlterDomainNotNull()

ObjectAddress AlterDomainNotNull ( List names,
bool  notNull 
)

Definition at line 2337 of file typecmds.c.

References RelToCheck::atts, CatalogTupleUpdate(), checkDomainOwner(), elog, ereport, errcode(), errmsg(), ERROR, errtablecol(), ForwardScanDirection, get_rels_with_domain(), GetLatestSnapshot(), GETSTRUCT, heap_attisnull(), heap_beginscan(), heap_close, heap_endscan(), heap_freetuple(), heap_getnext(), heap_open(), HeapTupleIsValid, i, InvalidObjectAddress, InvokeObjectPostAlterHook, lfirst, makeTypeNameFromNameList(), NameStr, RelToCheck::natts, NoLock, ObjectAddressSet, ObjectIdGetDatum, RegisterSnapshot(), RelToCheck::rel, RelationGetDescr, RelationGetRelationName, RowExclusiveLock, SearchSysCacheCopy1, ShareLock, HeapTupleData::t_self, TupleDescAttr, typenameTypeId(), TYPEOID, TypeRelationId, and UnregisterSnapshot().

Referenced by ProcessUtilitySlow().

2338 {
2339  TypeName *typename;
2340  Oid domainoid;
2341  Relation typrel;
2342  HeapTuple tup;
2343  Form_pg_type typTup;
2345 
2346  /* Make a TypeName so we can use standard type lookup machinery */
2347  typename = makeTypeNameFromNameList(names);
2348  domainoid = typenameTypeId(NULL, typename);
2349 
2350  /* Look up the domain in the type table */
2352 
2353  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2354  if (!HeapTupleIsValid(tup))
2355  elog(ERROR, "cache lookup failed for type %u", domainoid);
2356  typTup = (Form_pg_type) GETSTRUCT(tup);
2357 
2358  /* Check it's a domain and check user has permission for ALTER DOMAIN */
2359  checkDomainOwner(tup);
2360 
2361  /* Is the domain already set to the desired constraint? */
2362  if (typTup->typnotnull == notNull)
2363  {
2364  heap_close(typrel, RowExclusiveLock);
2365  return address;
2366  }
2367 
2368  /* Adding a NOT NULL constraint requires checking existing columns */
2369  if (notNull)
2370  {
2371  List *rels;
2372  ListCell *rt;
2373 
2374  /* Fetch relation list with attributes based on this domain */
2375  /* ShareLock is sufficient to prevent concurrent data changes */
2376 
2377  rels = get_rels_with_domain(domainoid, ShareLock);
2378 
2379  foreach(rt, rels)
2380  {
2381  RelToCheck *rtc = (RelToCheck *) lfirst(rt);
2382  Relation testrel = rtc->rel;
2383  TupleDesc tupdesc = RelationGetDescr(testrel);
2384  HeapScanDesc scan;
2385  HeapTuple tuple;
2386  Snapshot snapshot;
2387 
2388  /* Scan all tuples in this relation */
2389  snapshot = RegisterSnapshot(GetLatestSnapshot());
2390  scan = heap_beginscan(testrel, snapshot, 0, NULL);
2391  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2392  {
2393  int i;
2394 
2395  /* Test attributes that are of the domain */
2396  for (i = 0; i < rtc->natts; i++)
2397  {
2398  int attnum = rtc->atts[i];
2399  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
2400 
2401  if (heap_attisnull(tuple, attnum))
2402  {
2403  /*
2404  * In principle the auxiliary information for this
2405  * error should be errdatatype(), but errtablecol()
2406  * seems considerably more useful in practice. Since
2407  * this code only executes in an ALTER DOMAIN command,
2408  * the client should already know which domain is in
2409  * question.
2410  */
2411  ereport(ERROR,
2412  (errcode(ERRCODE_NOT_NULL_VIOLATION),
2413  errmsg("column \"%s\" of table \"%s\" contains null values",
2414  NameStr(attr->attname),
2415  RelationGetRelationName(testrel)),
2416  errtablecol(testrel, attnum)));
2417  }
2418  }
2419  }
2420  heap_endscan(scan);
2421  UnregisterSnapshot(snapshot);
2422 
2423  /* Close each rel after processing, but keep lock */
2424  heap_close(testrel, NoLock);
2425  }
2426  }
2427 
2428  /*
2429  * Okay to update pg_type row. We can scribble on typTup because it's a
2430  * copy.
2431  */
2432  typTup->typnotnull = notNull;
2433 
2434  CatalogTupleUpdate(typrel, &tup->t_self, tup);
2435 
2437 
2438  ObjectAddressSet(address, TypeRelationId, domainoid);
2439 
2440  /* Clean up */
2441  heap_freetuple(tup);
2442  heap_close(typrel, RowExclusiveLock);
2443 
2444  return address;
2445 }
int * atts
Definition: typecmds.c:81
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
#define RelationGetDescr(relation)
Definition: rel.h:437
Relation rel
Definition: typecmds.c:79
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:296
#define RowExclusiveLock
Definition: lockdefs.h:38
#define RelationGetRelationName(relation)
Definition: rel.h:445
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:905
static List * get_rels_with_domain(Oid domainOid, LOCKMODE lockmode)
Definition: typecmds.c:2872
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1808
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define lfirst(lc)
Definition: pg_list.h:106
int errtablecol(Relation rel, int attnum)
Definition: relcache.c:5230
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
Snapshot GetLatestSnapshot(void)
Definition: snapmgr.c:379
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:3041
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ShareLock
Definition: lockdefs.h:41
int i
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
#define NameStr(name)
Definition: c.h:557
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
HeapScanDesc heap_beginscan(Relation relation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: heapam.c:1397
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
int natts
Definition: typecmds.c:80

◆ AlterDomainValidateConstraint()

ObjectAddress AlterDomainValidateConstraint ( List names,
const char *  constrName 
)

Definition at line 2652 of file typecmds.c.

References AccessShareLock, Anum_pg_constraint_conbin, Anum_pg_constraint_contypid, BTEqualStrategyNumber, CatalogTupleUpdate(), checkDomainOwner(), CONSTRAINT_CHECK, ConstraintRelationId, ConstraintTypidIndexId, CONSTROID, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, heap_close, heap_copytuple(), heap_freetuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvokeObjectPostAlterHook, makeTypeNameFromNameList(), NameStr, ObjectAddressSet, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), SysCacheGetAttr(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, TextDatumGetCString, TypeNameToString(), typenameTypeId(), TYPEOID, TypeRelationId, val, and validateDomainConstraint().

Referenced by ProcessUtilitySlow().

2653 {
2654  TypeName *typename;
2655  Oid domainoid;
2656  Relation typrel;
2657  Relation conrel;
2658  HeapTuple tup;
2659  Form_pg_constraint con = NULL;
2660  Form_pg_constraint copy_con;
2661  char *conbin;
2662  SysScanDesc scan;
2663  Datum val;
2664  bool found = false;
2665  bool isnull;
2666  HeapTuple tuple;
2667  HeapTuple copyTuple;
2668  ScanKeyData key;
2669  ObjectAddress address;
2670 
2671  /* Make a TypeName so we can use standard type lookup machinery */
2672  typename = makeTypeNameFromNameList(names);
2673  domainoid = typenameTypeId(NULL, typename);
2674 
2675  /* Look up the domain in the type table */
2677 
2678  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(domainoid));
2679  if (!HeapTupleIsValid(tup))
2680  elog(ERROR, "cache lookup failed for type %u", domainoid);
2681 
2682  /* Check it's a domain and check user has permission for ALTER DOMAIN */
2683  checkDomainOwner(tup);
2684 
2685  /*
2686  * Find and check the target constraint
2687  */
2689  ScanKeyInit(&key,
2691  BTEqualStrategyNumber, F_OIDEQ,
2692  ObjectIdGetDatum(domainoid));
2694  true, NULL, 1, &key);
2695 
2696  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2697  {
2698  con = (Form_pg_constraint) GETSTRUCT(tuple);
2699  if (strcmp(NameStr(con->conname), constrName) == 0)
2700  {
2701  found = true;
2702  break;
2703  }
2704  }
2705 
2706  if (!found)
2707  ereport(ERROR,
2708  (errcode(ERRCODE_UNDEFINED_OBJECT),
2709  errmsg("constraint \"%s\" of domain \"%s\" does not exist",
2710  constrName, TypeNameToString(typename))));
2711 
2712  if (con->contype != CONSTRAINT_CHECK)
2713  ereport(ERROR,
2714  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2715  errmsg("constraint \"%s\" of domain \"%s\" is not a check constraint",
2716  constrName, TypeNameToString(typename))));
2717 
2718  val = SysCacheGetAttr(CONSTROID, tuple,
2720  &isnull);
2721  if (isnull)
2722  elog(ERROR, "null conbin for constraint %u",
2723  HeapTupleGetOid(tuple));
2724  conbin = TextDatumGetCString(val);
2725 
2726  validateDomainConstraint(domainoid, conbin);
2727 
2728  /*
2729  * Now update the catalog, while we have the door open.
2730  */
2731  copyTuple = heap_copytuple(tuple);
2732  copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
2733  copy_con->convalidated = true;
2734  CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
2735 
2737  HeapTupleGetOid(copyTuple), 0);
2738 
2739  ObjectAddressSet(address, TypeRelationId, domainoid);
2740 
2741  heap_freetuple(copyTuple);
2742 
2743  systable_endscan(scan);
2744 
2745  heap_close(typrel, AccessShareLock);
2746  heap_close(conrel, RowExclusiveLock);
2747 
2748  ReleaseSysCache(tup);
2749 
2750  return address;
2751 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define Anum_pg_constraint_conbin
#define ConstraintTypidIndexId
Definition: indexing.h:128
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
#define CONSTRAINT_CHECK
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define Anum_pg_constraint_contypid
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:3041
static void validateDomainConstraint(Oid domainoid, char *ccbin)
Definition: typecmds.c:2754
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
#define NameStr(name)
Definition: c.h:557
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ AlterEnum()

ObjectAddress AlterEnum ( AlterEnumStmt stmt,
bool  isTopLevel 
)

Definition at line 1279 of file typecmds.c.

References AddEnumLabel(), checkEnumOwner(), elog, ERROR, GetCurrentTransactionId(), HEAP_UPDATED, HeapTupleHeaderGetXmin, HeapTupleIsValid, InvokeObjectPostAlterHook, makeTypeNameFromNameList(), AlterEnumStmt::newVal, AlterEnumStmt::newValIsAfter, AlterEnumStmt::newValNeighbor, ObjectAddressSet, ObjectIdGetDatum, AlterEnumStmt::oldVal, PreventTransactionChain(), ReleaseSysCache(), RenameEnumLabel(), SearchSysCache1(), AlterEnumStmt::skipIfNewValExists, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, AlterEnumStmt::typeName, typenameTypeId(), TYPEOID, and TypeRelationId.

Referenced by ProcessUtilitySlow().

1280 {
1281  Oid enum_type_oid;
1282  TypeName *typename;
1283  HeapTuple tup;
1284  ObjectAddress address;
1285 
1286  /* Make a TypeName so we can use standard type lookup machinery */
1287  typename = makeTypeNameFromNameList(stmt->typeName);
1288  enum_type_oid = typenameTypeId(NULL, typename);
1289 
1290  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(enum_type_oid));
1291  if (!HeapTupleIsValid(tup))
1292  elog(ERROR, "cache lookup failed for type %u", enum_type_oid);
1293 
1294  /* Check it's an enum and check user has permission to ALTER the enum */
1295  checkEnumOwner(tup);
1296 
1297  if (stmt->oldVal)
1298  {
1299  /* Rename an existing label */
1300  RenameEnumLabel(enum_type_oid, stmt->oldVal, stmt->newVal);
1301  }
1302  else
1303  {
1304  /* Add a new label */
1305 
1306  /*
1307  * Ordinarily we disallow adding values within transaction blocks,
1308  * because we can't cope with enum OID values getting into indexes and
1309  * then having their defining pg_enum entries go away. However, it's
1310  * okay if the enum type was created in the current transaction, since
1311  * then there can be no such indexes that wouldn't themselves go away
1312  * on rollback. (We support this case because pg_dump
1313  * --binary-upgrade needs it.) We test this by seeing if the pg_type
1314  * row has xmin == current XID and is not HEAP_UPDATED. If it is
1315  * HEAP_UPDATED, we can't be sure whether the type was created or only
1316  * modified in this xact. So we are disallowing some cases that could
1317  * theoretically be safe; but fortunately pg_dump only needs the
1318  * simplest case.
1319  */
1321  !(tup->t_data->t_infomask & HEAP_UPDATED))
1322  /* safe to do inside transaction block */ ;
1323  else
1324  PreventTransactionChain(isTopLevel, "ALTER TYPE ... ADD");
1325 
1326  AddEnumLabel(enum_type_oid, stmt->newVal,
1327  stmt->newValNeighbor, stmt->newValIsAfter,
1328  stmt->skipIfNewValExists);
1329  }
1330 
1331  InvokeObjectPostAlterHook(TypeRelationId, enum_type_oid, 0);
1332 
1333  ObjectAddressSet(address, TypeRelationId, enum_type_oid);
1334 
1335  ReleaseSysCache(tup);
1336 
1337  return address;
1338 }
#define HEAP_UPDATED
Definition: htup_details.h:200
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
HeapTupleHeader t_data
Definition: htup.h:67
char * newValNeighbor
Definition: parsenodes.h:3005
static void checkEnumOwner(HeapTuple tup)
Definition: typecmds.c:1348
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
List * typeName
Definition: parsenodes.h:3002
void AddEnumLabel(Oid enumTypeOid, const char *newVal, const char *neighbor, bool newValIsAfter, bool skipIfExists)
Definition: pg_enum.c:179
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:418
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void RenameEnumLabel(Oid enumTypeOid, const char *oldVal, const char *newVal)
Definition: pg_enum.c:471
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
bool skipIfNewValExists
Definition: parsenodes.h:3007
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
bool newValIsAfter
Definition: parsenodes.h:3006
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
#define elog
Definition: elog.h:219
void PreventTransactionChain(bool isTopLevel, const char *stmtType)
Definition: xact.c:3154
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ AlterTypeNamespace()

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

Definition at line 3505 of file typecmds.c.

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

Referenced by ExecAlterObjectSchemaStmt().

3507 {
3508  TypeName *typename;
3509  Oid typeOid;
3510  Oid nspOid;
3511  Oid oldNspOid;
3512  ObjectAddresses *objsMoved;
3513  ObjectAddress myself;
3514 
3515  /* Make a TypeName so we can use standard type lookup machinery */
3516  typename = makeTypeNameFromNameList(names);
3517  typeOid = typenameTypeId(NULL, typename);
3518 
3519  /* Don't allow ALTER DOMAIN on a type */
3520  if (objecttype == OBJECT_DOMAIN && get_typtype(typeOid) != TYPTYPE_DOMAIN)
3521  ereport(ERROR,
3522  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3523  errmsg("%s is not a domain",
3524  format_type_be(typeOid))));
3525 
3526  /* get schema OID and check its permissions */
3527  nspOid = LookupCreationNamespace(newschema);
3528 
3529  objsMoved = new_object_addresses();
3530  oldNspOid = AlterTypeNamespace_oid(typeOid, nspOid, objsMoved);
3531  free_object_addresses(objsMoved);
3532 
3533  if (oldschema)
3534  *oldschema = oldNspOid;
3535 
3536  ObjectAddressSet(myself, TypeRelationId, typeOid);
3537 
3538  return myself;
3539 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
Oid LookupCreationNamespace(const char *nspname)
Definition: namespace.c:2896
int errcode(int sqlerrcode)
Definition: elog.c:575
char get_typtype(Oid typid)
Definition: lsyscache.c:2398
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2105
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2376
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Oid AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: typecmds.c:3542
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ AlterTypeNamespace_oid()

Oid AlterTypeNamespace_oid ( Oid  typeOid,
Oid  nspOid,
ObjectAddresses objsMoved 
)

Definition at line 3542 of file typecmds.c.

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

Referenced by AlterObjectNamespace_oid(), and AlterTypeNamespace().

3543 {
3544  Oid elemOid;
3545 
3546  /* check permissions on type */
3547  if (!pg_type_ownercheck(typeOid, GetUserId()))
3549 
3550  /* don't allow direct alteration of array types */
3551  elemOid = get_element_type(typeOid);
3552  if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid)
3553  ereport(ERROR,
3554  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3555  errmsg("cannot alter array type %s",
3556  format_type_be(typeOid)),
3557  errhint("You can alter type %s, which will alter the array type as well.",
3558  format_type_be(elemOid))));
3559 
3560  /* and do the work */
3561  return AlterTypeNamespaceInternal(typeOid, nspOid, false, true, objsMoved);
3562 }
int errhint(const char *fmt,...)
Definition: elog.c:987
Oid GetUserId(void)
Definition: miscinit.c:284
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2517
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2545
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition: typecmds.c:3580
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4630
#define OidIsValid(objectId)
Definition: c.h:586
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3515
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ AlterTypeNamespaceInternal()

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

Definition at line 3580 of file typecmds.c.

References add_exact_object_address(), AlterConstraintNamespaces(), AlterRelationNamespaceInternal(), AlterTypeNamespaceInternal(), CatalogTupleUpdate(), changeDependencyFor(), CheckSetNamespace(), ObjectAddress::classId, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg(), ERROR, format_type_be(), get_namespace_name(), get_rel_relkind(), GETSTRUCT, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, InvalidOid, InvokeObjectPostAlterHook, NameGetDatum, NamespaceRelationId, NameStr, object_address_present(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, RelationRelationId, RELKIND_COMPOSITE_TYPE, RowExclusiveLock, SearchSysCacheCopy1, SearchSysCacheExists2, HeapTupleData::t_self, TYPENAMENSP, TYPEOID, TypeRelationId, TYPTYPE_COMPOSITE, and TYPTYPE_DOMAIN.

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

3584 {
3585  Relation rel;
3586  HeapTuple tup;
3587  Form_pg_type typform;
3588  Oid oldNspOid;
3589  Oid arrayOid;
3590  bool isCompositeType;
3591  ObjectAddress thisobj;
3592 
3593  /*
3594  * Make sure we haven't moved this object previously.
3595  */
3596  thisobj.classId = TypeRelationId;
3597  thisobj.objectId = typeOid;
3598  thisobj.objectSubId = 0;
3599 
3600  if (object_address_present(&thisobj, objsMoved))
3601  return InvalidOid;
3602 
3604 
3605  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
3606  if (!HeapTupleIsValid(tup))
3607  elog(ERROR, "cache lookup failed for type %u", typeOid);
3608  typform = (Form_pg_type) GETSTRUCT(tup);
3609 
3610  oldNspOid = typform->typnamespace;
3611  arrayOid = typform->typarray;
3612 
3613  /* If the type is already there, we scan skip these next few checks. */
3614  if (oldNspOid != nspOid)
3615  {
3616  /* common checks on switching namespaces */
3617  CheckSetNamespace(oldNspOid, nspOid);
3618 
3619  /* check for duplicate name (more friendly than unique-index failure) */
3621  NameGetDatum(&typform->typname),
3622  ObjectIdGetDatum(nspOid)))
3623  ereport(ERROR,
3625  errmsg("type \"%s\" already exists in schema \"%s\"",
3626  NameStr(typform->typname),
3627  get_namespace_name(nspOid))));
3628  }
3629 
3630  /* Detect whether type is a composite type (but not a table rowtype) */
3631  isCompositeType =
3632  (typform->typtype == TYPTYPE_COMPOSITE &&
3633  get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);
3634 
3635  /* Enforce not-table-type if requested */
3636  if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType &&
3637  errorOnTableType)
3638  ereport(ERROR,
3639  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3640  errmsg("%s is a table's row type",
3641  format_type_be(typeOid)),
3642  errhint("Use ALTER TABLE instead.")));
3643 
3644  if (oldNspOid != nspOid)
3645  {
3646  /* OK, modify the pg_type row */
3647 
3648  /* tup is a copy, so we can scribble directly on it */
3649  typform->typnamespace = nspOid;
3650 
3651  CatalogTupleUpdate(rel, &tup->t_self, tup);
3652  }
3653 
3654  /*
3655  * Composite types have pg_class entries.
3656  *
3657  * We need to modify the pg_class tuple as well to reflect the change of
3658  * schema.
3659  */
3660  if (isCompositeType)
3661  {
3662  Relation classRel;
3663 
3665 
3666  AlterRelationNamespaceInternal(classRel, typform->typrelid,
3667  oldNspOid, nspOid,
3668  false, objsMoved);
3669 
3670  heap_close(classRel, RowExclusiveLock);
3671 
3672  /*
3673  * Check for constraints associated with the composite type (we don't
3674  * currently support this, but probably will someday).
3675  */
3676  AlterConstraintNamespaces(typform->typrelid, oldNspOid,
3677  nspOid, false, objsMoved);
3678  }
3679  else
3680  {
3681  /* If it's a domain, it might have constraints */
3682  if (typform->typtype == TYPTYPE_DOMAIN)
3683  AlterConstraintNamespaces(typeOid, oldNspOid, nspOid, true,
3684  objsMoved);
3685  }
3686 
3687  /*
3688  * Update dependency on schema, if any --- a table rowtype has not got
3689  * one, and neither does an implicit array.
3690  */
3691  if (oldNspOid != nspOid &&
3692  (isCompositeType || typform->typtype != TYPTYPE_COMPOSITE) &&
3693  !isImplicitArray)
3694  if (changeDependencyFor(TypeRelationId, typeOid,
3695  NamespaceRelationId, oldNspOid, nspOid) != 1)
3696  elog(ERROR, "failed to change schema dependency for type %s",
3697  format_type_be(typeOid));
3698 
3700 
3701  heap_freetuple(tup);
3702 
3704 
3705  add_exact_object_address(&thisobj, objsMoved);
3706 
3707  /* Recursively alter the associated array type, if any */
3708  if (OidIsValid(arrayOid))
3709  AlterTypeNamespaceInternal(arrayOid, nspOid, true, true, objsMoved);
3710 
3711  return oldNspOid;
3712 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define NameGetDatum(X)
Definition: postgres.h:601
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1820
#define RelationRelationId
Definition: pg_class.h:29
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2220
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition: typecmds.c:3580
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2160
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:586
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId, Oid newNspId, bool isType, ObjectAddresses *objsMoved)
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3066
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void CheckSetNamespace(Oid oldNspOid, Oid nspOid)
Definition: namespace.c:2928
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:184
void AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid, bool hasDependEntry, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12667
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:295
#define NameStr(name)
Definition: c.h:557
#define elog
Definition: elog.h:219
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30

◆ AlterTypeOwner()

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

Definition at line 3301 of file typecmds.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, AlterTypeOwner_oid(), check_is_member_of_role(), ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), get_array_type(), get_namespace_name(), get_rel_relkind(), GETSTRUCT, GetUserId(), heap_close, heap_copytuple(), heap_open(), HeapTupleGetOid, LookupTypeName(), makeTypeNameFromNameList(), OBJECT_DOMAIN, ObjectAddressSet, OidIsValid, pg_namespace_aclcheck(), pg_type_ownercheck(), ReleaseSysCache(), RELKIND_COMPOSITE_TYPE, RowExclusiveLock, superuser(), TypeNameToString(), TypeRelationId, typeTypeId(), TYPTYPE_COMPOSITE, and TYPTYPE_DOMAIN.

Referenced by ExecAlterOwnerStmt().

3302 {
3303  TypeName *typename;
3304  Oid typeOid;
3305  Relation rel;
3306  HeapTuple tup;
3307  HeapTuple newtup;
3308  Form_pg_type typTup;
3309  AclResult aclresult;
3310  ObjectAddress address;
3311 
3313 
3314  /* Make a TypeName so we can use standard type lookup machinery */
3315  typename = makeTypeNameFromNameList(names);
3316 
3317  /* Use LookupTypeName here so that shell types can be processed */
3318  tup = LookupTypeName(NULL, typename, NULL, false);
3319  if (tup == NULL)
3320  ereport(ERROR,
3321  (errcode(ERRCODE_UNDEFINED_OBJECT),
3322  errmsg("type \"%s\" does not exist",
3323  TypeNameToString(typename))));
3324  typeOid = typeTypeId(tup);
3325 
3326  /* Copy the syscache entry so we can scribble on it below */
3327  newtup = heap_copytuple(tup);
3328  ReleaseSysCache(tup);
3329  tup = newtup;
3330  typTup = (Form_pg_type) GETSTRUCT(tup);
3331 
3332  /* Don't allow ALTER DOMAIN on a type */
3333  if (objecttype == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
3334  ereport(ERROR,
3335  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3336  errmsg("%s is not a domain",
3337  format_type_be(typeOid))));
3338 
3339  /*
3340  * If it's a composite type, we need to check that it really is a
3341  * free-standing composite type, and not a table's rowtype. We want people
3342  * to use ALTER TABLE not ALTER TYPE for that case.
3343  */
3344  if (typTup->typtype == TYPTYPE_COMPOSITE &&
3345  get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)
3346  ereport(ERROR,
3347  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3348  errmsg("%s is a table's row type",
3349  format_type_be(typeOid)),
3350  errhint("Use ALTER TABLE instead.")));
3351 
3352  /* don't allow direct alteration of array types, either */
3353  if (OidIsValid(typTup->typelem) &&
3354  get_array_type(typTup->typelem) == typeOid)
3355  ereport(ERROR,
3356  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3357  errmsg("cannot alter array type %s",
3358  format_type_be(typeOid)),
3359  errhint("You can alter type %s, which will alter the array type as well.",
3360  format_type_be(typTup->typelem))));
3361 
3362  /*
3363  * If the new owner is the same as the existing owner, consider the
3364  * command to have succeeded. This is for dump restoration purposes.
3365  */
3366  if (typTup->typowner != newOwnerId)
3367  {
3368  /* Superusers can always do it */
3369  if (!superuser())
3370  {
3371  /* Otherwise, must be owner of the existing object */
3374 
3375  /* Must be able to become new owner */
3376  check_is_member_of_role(GetUserId(), newOwnerId);
3377 
3378  /* New owner must have CREATE privilege on namespace */
3379  aclresult = pg_namespace_aclcheck(typTup->typnamespace,
3380  newOwnerId,
3381  ACL_CREATE);
3382  if (aclresult != ACLCHECK_OK)
3384  get_namespace_name(typTup->typnamespace));
3385  }
3386 
3387  AlterTypeOwner_oid(typeOid, newOwnerId, true);
3388  }
3389 
3390  ObjectAddressSet(address, TypeRelationId, typeOid);
3391 
3392  /* Clean up */
3394 
3395  return address;
3396 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:57
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
Oid GetUserId(void)
Definition: miscinit.c:284
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2545
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1820
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4630
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:586
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4542
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3515
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3410
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3066
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define RowExclusiveLock
Definition: lockdefs.h:38
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4879
#define ereport(elevel, rest)
Definition: elog.h:122
AclResult
Definition: acl.h:178
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
Oid typeTypeId(Type tp)
Definition: parse_type.c:571

◆ AlterTypeOwner_oid()

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

Definition at line 3410 of file typecmds.c.

References AccessExclusiveLock, AlterTypeOwnerInternal(), ATExecChangeOwner(), changeDependencyOnOwner(), elog, ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, InvokeObjectPostAlterHook, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), TYPEOID, TypeRelationId, and TYPTYPE_COMPOSITE.

Referenced by AlterTypeOwner(), and shdepReassignOwned().

3411 {
3412  Relation rel;
3413  HeapTuple tup;
3414  Form_pg_type typTup;
3415 
3417 
3418  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
3419  if (!HeapTupleIsValid(tup))
3420  elog(ERROR, "cache lookup failed for type %u", typeOid);
3421  typTup = (Form_pg_type) GETSTRUCT(tup);
3422 
3423  /*
3424  * If it's a composite type, invoke ATExecChangeOwner so that we fix up
3425  * the pg_class entry properly. That will call back to
3426  * AlterTypeOwnerInternal to take care of the pg_type entry(s).
3427  */
3428  if (typTup->typtype == TYPTYPE_COMPOSITE)
3429  ATExecChangeOwner(typTup->typrelid, newOwnerId, true, AccessExclusiveLock);
3430  else
3431  AlterTypeOwnerInternal(typeOid, newOwnerId);
3432 
3433  /* Update owner dependency reference */
3434  if (hasDependEntry)
3435  changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
3436 
3438 
3439  ReleaseSysCache(tup);
3441 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition: typecmds.c:3450
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
#define TypeRelationId
Definition: pg_type.h:34
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:304
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
Definition: tablecmds.c:9934
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define elog
Definition: elog.h:219

◆ AlterTypeOwnerInternal()

void AlterTypeOwnerInternal ( Oid  typeOid,
Oid  newOwnerId 
)

Definition at line 3450 of file typecmds.c.

References aclnewowner(), AlterTypeOwnerInternal(), Anum_pg_type_typacl, Anum_pg_type_typowner, CatalogTupleUpdate(), DatumGetAclP, elog, ERROR, GETSTRUCT, heap_close, heap_getattr, heap_modify_tuple(), heap_open(), HeapTupleIsValid, Natts_pg_type, ObjectIdGetDatum, OidIsValid, PointerGetDatum, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, TYPEOID, and TypeRelationId.

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

3451 {
3452  Relation rel;
3453  HeapTuple tup;
3454  Form_pg_type typTup;
3455  Datum repl_val[Natts_pg_type];
3456  bool repl_null[Natts_pg_type];
3457  bool repl_repl[Natts_pg_type];
3458  Acl *newAcl;
3459  Datum aclDatum;
3460  bool isNull;
3461 
3463 
3464  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
3465  if (!HeapTupleIsValid(tup))
3466  elog(ERROR, "cache lookup failed for type %u", typeOid);
3467  typTup = (Form_pg_type) GETSTRUCT(tup);
3468 
3469  memset(repl_null, false, sizeof(repl_null));
3470  memset(repl_repl, false, sizeof(repl_repl));
3471 
3472  repl_repl[Anum_pg_type_typowner - 1] = true;
3473  repl_val[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(newOwnerId);
3474 
3475  aclDatum = heap_getattr(tup,
3477  RelationGetDescr(rel),
3478  &isNull);
3479  /* Null ACLs do not require changes */
3480  if (!isNull)
3481  {
3482  newAcl = aclnewowner(DatumGetAclP(aclDatum),
3483  typTup->typowner, newOwnerId);
3484  repl_repl[Anum_pg_type_typacl - 1] = true;
3485  repl_val[Anum_pg_type_typacl - 1] = PointerGetDatum(newAcl);
3486  }
3487 
3488  tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
3489  repl_repl);
3490 
3491  CatalogTupleUpdate(rel, &tup->t_self, tup);
3492 
3493  /* If it has an array type, update that too */
3494  if (OidIsValid(typTup->typarray))
3495  AlterTypeOwnerInternal(typTup->typarray, newOwnerId);
3496 
3497  /* Clean up */
3499 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
#define DatumGetAclP(X)
Definition: acl.h:121
#define PointerGetDatum(X)
Definition: postgres.h:562
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition: typecmds.c:3450
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:586
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Natts_pg_type
Definition: pg_type.h:239
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Anum_pg_type_typacl
Definition: pg_type.h:269
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1052
#define Anum_pg_type_typowner
Definition: pg_type.h:242

◆ AssignTypeArrayOid()

Oid AssignTypeArrayOid ( void  )

Definition at line 2099 of file typecmds.c.

References AccessShareLock, binary_upgrade_next_array_pg_type_oid, ereport, errcode(), errmsg(), ERROR, GetNewOid(), heap_close, heap_open(), InvalidOid, IsBinaryUpgrade, OidIsValid, and TypeRelationId.

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

2100 {
2101  Oid type_array_oid;
2102 
2103  /* Use binary-upgrade override for pg_type.typarray? */
2104  if (IsBinaryUpgrade)
2105  {
2107  ereport(ERROR,
2108  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2109  errmsg("pg_type array OID value not set when in binary upgrade mode")));
2110 
2111  type_array_oid = binary_upgrade_next_array_pg_type_oid;
2113  }
2114  else
2115  {
2117 
2118  type_array_oid = GetNewOid(pg_type);
2119  heap_close(pg_type, AccessShareLock);
2120  }
2121 
2122  return type_array_oid;
2123 }
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:586
bool IsBinaryUpgrade
Definition: globals.c:102
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Oid GetNewOid(Relation relation)
Definition: catalog.c:289
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
Oid binary_upgrade_next_array_pg_type_oid
Definition: typecmds.c:86
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ checkDomainOwner()

void checkDomainOwner ( HeapTuple  tup)

Definition at line 3041 of file typecmds.c.

References aclcheck_error_type(), ACLCHECK_NOT_OWNER, ereport, errcode(), errmsg(), ERROR, format_type_be(), GETSTRUCT, GetUserId(), HeapTupleGetOid, pg_type_ownercheck(), and TYPTYPE_DOMAIN.

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

3042 {
3043  Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
3044 
3045  /* Check that this is actually a domain */
3046  if (typTup->typtype != TYPTYPE_DOMAIN)
3047  ereport(ERROR,
3048  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3049  errmsg("%s is not a domain",
3051 
3052  /* Permission check: must own type */
3055 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
Oid GetUserId(void)
Definition: miscinit.c:284
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4630
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3515
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700

◆ DefineCompositeType()

ObjectAddress DefineCompositeType ( RangeVar typevar,
List coldeflist 
)

Definition at line 2140 of file typecmds.c.

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

Referenced by ProcessUtilitySlow().

2141 {
2142  CreateStmt *createStmt = makeNode(CreateStmt);
2143  Oid old_type_oid;
2144  Oid typeNamespace;
2145  ObjectAddress address;
2146 
2147  /*
2148  * now set the parameters for keys/inheritance etc. All of these are
2149  * uninteresting for composite types...
2150  */
2151  createStmt->relation = typevar;
2152  createStmt->tableElts = coldeflist;
2153  createStmt->inhRelations = NIL;
2154  createStmt->constraints = NIL;
2155  createStmt->options = NIL;
2156  createStmt->oncommit = ONCOMMIT_NOOP;
2157  createStmt->tablespacename = NULL;
2158  createStmt->if_not_exists = false;
2159 
2160  /*
2161  * Check for collision with an existing type name. If there is one and
2162  * it's an autogenerated array, we can rename it out of the way. This
2163  * check is here mainly to get a better error message about a "type"
2164  * instead of below about a "relation".
2165  */
2166  typeNamespace = RangeVarGetAndCheckCreationNamespace(createStmt->relation,
2167  NoLock, NULL);
2168  RangeVarAdjustRelationPersistence(createStmt->relation, typeNamespace);
2169  old_type_oid =
2171  CStringGetDatum(createStmt->relation->relname),
2172  ObjectIdGetDatum(typeNamespace));
2173  if (OidIsValid(old_type_oid))
2174  {
2175  if (!moveArrayTypeName(old_type_oid, createStmt->relation->relname, typeNamespace))
2176  ereport(ERROR,
2178  errmsg("type \"%s\" already exists", createStmt->relation->relname)));
2179  }
2180 
2181  /*
2182  * Finally create the relation. This also creates the type.
2183  */
2184  DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid, &address,
2185  NULL);
2186 
2187  return address;
2188 }
RangeVar * relation
Definition: parsenodes.h:2014
#define NIL
Definition: pg_list.h:69
OnCommitAction oncommit
Definition: parsenodes.h:2023
List * inhRelations
Definition: parsenodes.h:2016
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
void RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
Definition: namespace.c:615
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
List * constraints
Definition: parsenodes.h:2021
bool if_not_exists
Definition: parsenodes.h:2025
char * relname
Definition: primnodes.h:68
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:833
#define NoLock
Definition: lockdefs.h:34
#define CStringGetDatum(X)
Definition: postgres.h:584
List * options
Definition: parsenodes.h:2022
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:504
#define ereport(elevel, rest)
Definition: elog.h:122
char * tablespacename
Definition: parsenodes.h:2024
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:508
#define InvalidOid
Definition: postgres_ext.h:36
List * tableElts
Definition: parsenodes.h:2015
#define makeNode(_type_)
Definition: nodes.h:560
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30

◆ DefineDomain()

ObjectAddress DefineDomain ( CreateDomainStmt stmt)

Definition at line 729 of file typecmds.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_OK, Anum_pg_type_typdefault, Anum_pg_type_typdefaultbin, TypeName::arrayBounds, AssignTypeArrayOid(), CreateDomainStmt::collClause, CollateClause::collname, CommandCounterIncrement(), CONSTR_ATTR_DEFERRABLE, CONSTR_ATTR_DEFERRED, CONSTR_ATTR_IMMEDIATE, CONSTR_ATTR_NOT_DEFERRABLE, CONSTR_CHECK, CONSTR_DEFAULT, CONSTR_EXCLUSION, CONSTR_FOREIGN, CONSTR_NOTNULL, CONSTR_NULL, CONSTR_PRIMARY, CONSTR_UNIQUE, CreateDomainStmt::constraints, Constraint::contype, cookDefault(), CStringGetDatum, deparse_expression(), domainAddConstraint(), CreateDomainStmt::domainname, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, format_type_be(), get_collation_oid(), get_namespace_name(), GETSTRUCT, GetSysCacheOid2, GetUserId(), HeapTupleGetOid, InvalidOid, Constraint::is_no_inherit, IsA, lfirst, list_length(), make_parsestate(), makeArrayTypeName(), moveArrayTypeName(), NIL, nodeTag, nodeToString(), ObjectAddress::objectId, ObjectIdGetDatum, OidIsValid, pfree(), pg_namespace_aclcheck(), pg_type_aclcheck(), QualifiedNameGetCreationNamespace(), Constraint::raw_expr, ReleaseSysCache(), SysCacheGetAttr(), TextDatumGetCString, TYPCATEGORY_ARRAY, TypeCreate(), CreateDomainStmt::typeName, TYPENAMENSP, TypeNameToString(), typenameType(), TYPEOID, TYPTYPE_BASE, TYPTYPE_COMPOSITE, TYPTYPE_DOMAIN, TYPTYPE_ENUM, and TYPTYPE_RANGE.

Referenced by ProcessUtilitySlow().

730 {
731  char *domainName;
732  char *domainArrayName;
733  Oid domainNamespace;
734  AclResult aclresult;
735  int16 internalLength;
736  Oid inputProcedure;
737  Oid outputProcedure;
738  Oid receiveProcedure;
739  Oid sendProcedure;
740  Oid analyzeProcedure;
741  bool byValue;
742  char category;
743  char delimiter;
744  char alignment;
745  char storage;
746  char typtype;
747  Datum datum;
748  bool isnull;
749  char *defaultValue = NULL;
750  char *defaultValueBin = NULL;
751  bool saw_default = false;
752  bool typNotNull = false;
753  bool nullDefined = false;
754  int32 typNDims = list_length(stmt->typeName->arrayBounds);
755  HeapTuple typeTup;
756  List *schema = stmt->constraints;
757  ListCell *listptr;
758  Oid basetypeoid;
759  Oid old_type_oid;
760  Oid domaincoll;
761  Oid domainArrayOid;
762  Form_pg_type baseType;
763  int32 basetypeMod;
764  Oid baseColl;
765  ObjectAddress address;
766 
767  /* Convert list of names to a name and namespace */
768  domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
769  &domainName);
770 
771  /* Check we have creation rights in target namespace */
772  aclresult = pg_namespace_aclcheck(domainNamespace, GetUserId(),
773  ACL_CREATE);
774  if (aclresult != ACLCHECK_OK)
776  get_namespace_name(domainNamespace));
777 
778  /*
779  * Check for collision with an existing type name. If there is one and
780  * it's an autogenerated array, we can rename it out of the way.
781  */
782  old_type_oid = GetSysCacheOid2(TYPENAMENSP,
783  CStringGetDatum(domainName),
784  ObjectIdGetDatum(domainNamespace));
785  if (OidIsValid(old_type_oid))
786  {
787  if (!moveArrayTypeName(old_type_oid, domainName, domainNamespace))
788  ereport(ERROR,
790  errmsg("type \"%s\" already exists", domainName)));
791  }
792 
793  /*
794  * Look up the base type.
795  */
796  typeTup = typenameType(NULL, stmt->typeName, &basetypeMod);
797  baseType = (Form_pg_type) GETSTRUCT(typeTup);
798  basetypeoid = HeapTupleGetOid(typeTup);
799 
800  /*
801  * Base type must be a plain base type, a composite type, another domain,
802  * an enum or a range type. Domains over pseudotypes would create a
803  * security hole. (It would be shorter to code this to just check for
804  * pseudotypes; but it seems safer to call out the specific typtypes that
805  * are supported, rather than assume that all future typtypes would be
806  * automatically supported.)
807  */
808  typtype = baseType->typtype;
809  if (typtype != TYPTYPE_BASE &&
810  typtype != TYPTYPE_COMPOSITE &&
811  typtype != TYPTYPE_DOMAIN &&
812  typtype != TYPTYPE_ENUM &&
813  typtype != TYPTYPE_RANGE)
814  ereport(ERROR,
815  (errcode(ERRCODE_DATATYPE_MISMATCH),
816  errmsg("\"%s\" is not a valid base type for a domain",
817  TypeNameToString(stmt->typeName))));
818 
819  aclresult = pg_type_aclcheck(basetypeoid, GetUserId(), ACL_USAGE);
820  if (aclresult != ACLCHECK_OK)
821  aclcheck_error_type(aclresult, basetypeoid);
822 
823  /*
824  * Identify the collation if any
825  */
826  baseColl = baseType->typcollation;
827  if (stmt->collClause)
828  domaincoll = get_collation_oid(stmt->collClause->collname, false);
829  else
830  domaincoll = baseColl;
831 
832  /* Complain if COLLATE is applied to an uncollatable type */
833  if (OidIsValid(domaincoll) && !OidIsValid(baseColl))
834  ereport(ERROR,
835  (errcode(ERRCODE_DATATYPE_MISMATCH),
836  errmsg("collations are not supported by type %s",
837  format_type_be(basetypeoid))));
838 
839  /* passed by value */
840  byValue = baseType->typbyval;
841 
842  /* Required Alignment */
843  alignment = baseType->typalign;
844 
845  /* TOAST Strategy */
846  storage = baseType->typstorage;
847 
848  /* Storage Length */
849  internalLength = baseType->typlen;
850 
851  /* Type Category */
852  category = baseType->typcategory;
853 
854  /* Array element Delimiter */
855  delimiter = baseType->typdelim;
856 
857  /* I/O Functions */
858  inputProcedure = F_DOMAIN_IN;
859  outputProcedure = baseType->typoutput;
860  receiveProcedure = F_DOMAIN_RECV;
861  sendProcedure = baseType->typsend;
862 
863  /* Domains never accept typmods, so no typmodin/typmodout needed */
864 
865  /* Analysis function */
866  analyzeProcedure = baseType->typanalyze;
867 
868  /* Inherited default value */
869  datum = SysCacheGetAttr(TYPEOID, typeTup,
870  Anum_pg_type_typdefault, &isnull);
871  if (!isnull)
872  defaultValue = TextDatumGetCString(datum);
873 
874  /* Inherited default binary value */
875  datum = SysCacheGetAttr(TYPEOID, typeTup,
876  Anum_pg_type_typdefaultbin, &isnull);
877  if (!isnull)
878  defaultValueBin = TextDatumGetCString(datum);
879 
880  /*
881  * Run through constraints manually to avoid the additional processing
882  * conducted by DefineRelation() and friends.
883  */
884  foreach(listptr, schema)
885  {
886  Constraint *constr = lfirst(listptr);
887 
888  if (!IsA(constr, Constraint))
889  elog(ERROR, "unrecognized node type: %d",
890  (int) nodeTag(constr));
891  switch (constr->contype)
892  {
893  case CONSTR_DEFAULT:
894 
895  /*
896  * The inherited default value may be overridden by the user
897  * with the DEFAULT <expr> clause ... but only once.
898  */
899  if (saw_default)
900  ereport(ERROR,
901  (errcode(ERRCODE_SYNTAX_ERROR),
902  errmsg("multiple default expressions")));
903  saw_default = true;
904 
905  if (constr->raw_expr)
906  {
907  ParseState *pstate;
908  Node *defaultExpr;
909 
910  /* Create a dummy ParseState for transformExpr */
911  pstate = make_parsestate(NULL);
912 
913  /*
914  * Cook the constr->raw_expr into an expression. Note:
915  * name is strictly for error message
916  */
917  defaultExpr = cookDefault(pstate, constr->raw_expr,
918  basetypeoid,
919  basetypeMod,
920  domainName);
921 
922  /*
923  * If the expression is just a NULL constant, we treat it
924  * like not having a default.
925  *
926  * Note that if the basetype is another domain, we'll see
927  * a CoerceToDomain expr here and not discard the default.
928  * This is critical because the domain default needs to be
929  * retained to override any default that the base domain
930  * might have.
931  */
932  if (defaultExpr == NULL ||
933  (IsA(defaultExpr, Const) &&
934  ((Const *) defaultExpr)->constisnull))
935  {
936  defaultValue = NULL;
937  defaultValueBin = NULL;
938  }
939  else
940  {
941  /*
942  * Expression must be stored as a nodeToString result,
943  * but we also require a valid textual representation
944  * (mainly to make life easier for pg_dump).
945  */
946  defaultValue =
947  deparse_expression(defaultExpr,
948  NIL, false, false);
949  defaultValueBin = nodeToString(defaultExpr);
950  }
951  }
952  else
953  {
954  /* No default (can this still happen?) */
955  defaultValue = NULL;
956  defaultValueBin = NULL;
957  }
958  break;
959 
960  case CONSTR_NOTNULL:
961  if (nullDefined && !typNotNull)
962  ereport(ERROR,
963  (errcode(ERRCODE_SYNTAX_ERROR),
964  errmsg("conflicting NULL/NOT NULL constraints")));
965  typNotNull = true;
966  nullDefined = true;
967  break;
968 
969  case CONSTR_NULL:
970  if (nullDefined && typNotNull)
971  ereport(ERROR,
972  (errcode(ERRCODE_SYNTAX_ERROR),
973  errmsg("conflicting NULL/NOT NULL constraints")));
974  typNotNull = false;
975  nullDefined = true;
976  break;
977 
978  case CONSTR_CHECK:
979 
980  /*
981  * Check constraints are handled after domain creation, as
982  * they require the Oid of the domain; at this point we can
983  * only check that they're not marked NO INHERIT, because that
984  * would be bogus.
985  */
986  if (constr->is_no_inherit)
987  ereport(ERROR,
988  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
989  errmsg("check constraints for domains cannot be marked NO INHERIT")));
990  break;
991 
992  /*
993  * All else are error cases
994  */
995  case CONSTR_UNIQUE:
996  ereport(ERROR,
997  (errcode(ERRCODE_SYNTAX_ERROR),
998  errmsg("unique constraints not possible for domains")));
999  break;
1000 
1001  case CONSTR_PRIMARY:
1002  ereport(ERROR,
1003  (errcode(ERRCODE_SYNTAX_ERROR),
1004  errmsg("primary key constraints not possible for domains")));
1005  break;
1006 
1007  case CONSTR_EXCLUSION:
1008  ereport(ERROR,
1009  (errcode(ERRCODE_SYNTAX_ERROR),
1010  errmsg("exclusion constraints not possible for domains")));
1011  break;
1012 
1013  case CONSTR_FOREIGN:
1014  ereport(ERROR,
1015  (errcode(ERRCODE_SYNTAX_ERROR),
1016  errmsg("foreign key constraints not possible for domains")));
1017  break;
1018 
1021  case CONSTR_ATTR_DEFERRED:
1022  case CONSTR_ATTR_IMMEDIATE:
1023  ereport(ERROR,
1024  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1025  errmsg("specifying constraint deferrability not supported for domains")));
1026  break;
1027 
1028  default:
1029  elog(ERROR, "unrecognized constraint subtype: %d",
1030  (int) constr->contype);
1031  break;
1032  }
1033  }
1034 
1035  /* Allocate OID for array type */
1036  domainArrayOid = AssignTypeArrayOid();
1037 
1038  /*
1039  * Have TypeCreate do all the real work.
1040  */
1041  address =
1042  TypeCreate(InvalidOid, /* no predetermined type OID */
1043  domainName, /* type name */
1044  domainNamespace, /* namespace */
1045  InvalidOid, /* relation oid (n/a here) */
1046  0, /* relation kind (ditto) */
1047  GetUserId(), /* owner's ID */
1048  internalLength, /* internal size */
1049  TYPTYPE_DOMAIN, /* type-type (domain type) */
1050  category, /* type-category */
1051  false, /* domain types are never preferred */
1052  delimiter, /* array element delimiter */
1053  inputProcedure, /* input procedure */
1054  outputProcedure, /* output procedure */
1055  receiveProcedure, /* receive procedure */
1056  sendProcedure, /* send procedure */
1057  InvalidOid, /* typmodin procedure - none */
1058  InvalidOid, /* typmodout procedure - none */
1059  analyzeProcedure, /* analyze procedure */
1060  InvalidOid, /* no array element type */
1061  false, /* this isn't an array */
1062  domainArrayOid, /* array type we are about to create */
1063  basetypeoid, /* base type ID */
1064  defaultValue, /* default type value (text) */
1065  defaultValueBin, /* default type value (binary) */
1066  byValue, /* passed by value */
1067  alignment, /* required alignment */
1068  storage, /* TOAST strategy */
1069  basetypeMod, /* typeMod value */
1070  typNDims, /* Array dimensions for base type */
1071  typNotNull, /* Type NOT NULL */
1072  domaincoll); /* type's collation */
1073 
1074  /*
1075  * Create the array type that goes with it.
1076  */
1077  domainArrayName = makeArrayTypeName(domainName, domainNamespace);
1078 
1079  /* alignment must be 'i' or 'd' for arrays */
1080  alignment = (alignment == 'd') ? 'd' : 'i';
1081 
1082  TypeCreate(domainArrayOid, /* force assignment of this type OID */
1083  domainArrayName, /* type name */
1084  domainNamespace, /* namespace */
1085  InvalidOid, /* relation oid (n/a here) */
1086  0, /* relation kind (ditto) */
1087  GetUserId(), /* owner's ID */
1088  -1, /* internal size (always varlena) */
1089  TYPTYPE_BASE, /* type-type (base type) */
1090  TYPCATEGORY_ARRAY, /* type-category (array) */
1091  false, /* array types are never preferred */
1092  delimiter, /* array element delimiter */
1093  F_ARRAY_IN, /* input procedure */
1094  F_ARRAY_OUT, /* output procedure */
1095  F_ARRAY_RECV, /* receive procedure */
1096  F_ARRAY_SEND, /* send procedure */
1097  InvalidOid, /* typmodin procedure - none */
1098  InvalidOid, /* typmodout procedure - none */
1099  F_ARRAY_TYPANALYZE, /* analyze procedure */
1100  address.objectId, /* element type ID */
1101  true, /* yes this is an array type */
1102  InvalidOid, /* no further array type */
1103  InvalidOid, /* base type ID */
1104  NULL, /* never a default type value */
1105  NULL, /* binary default isn't sent either */
1106  false, /* never passed by value */
1107  alignment, /* see above */
1108  'x', /* ARRAY is always toastable */
1109  -1, /* typMod (Domains only) */
1110  0, /* Array dimensions of typbasetype */
1111  false, /* Type NOT NULL */
1112  domaincoll); /* type's collation */
1113 
1114  pfree(domainArrayName);
1115 
1116  /*
1117  * Process constraints which refer to the domain ID returned by TypeCreate
1118  */
1119  foreach(listptr, schema)
1120  {
1121  Constraint *constr = lfirst(listptr);
1122 
1123  /* it must be a Constraint, per check above */
1124 
1125  switch (constr->contype)
1126  {
1127  case CONSTR_CHECK:
1128  domainAddConstraint(address.objectId, domainNamespace,
1129  basetypeoid, basetypeMod,
1130  constr, domainName, NULL);
1131  break;
1132 
1133  /* Other constraint types were fully processed above */
1134 
1135  default:
1136  break;
1137  }
1138 
1139  /* CCI so we can detect duplicate constraint names */
1141  }
1142 
1143  /*
1144  * Now we can clean up.
1145  */
1146  ReleaseSysCache(typeTup);
1147 
1148  return address;
1149 }
signed short int16
Definition: c.h:293
#define NIL
Definition: pg_list.h:69
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
#define Anum_pg_type_typdefaultbin
Definition: pg_type.h:267
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:767
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
Type typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
Definition: parse_type.c:247
#define TYPTYPE_BASE
Definition: pg_type.h:720
Oid GetUserId(void)
Definition: miscinit.c:284
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2956
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
Node * raw_expr
Definition: parsenodes.h:2102
Definition: nodes.h:512
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4542
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3515
signed int int32
Definition: c.h:294
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname)
Definition: heap.c:2659
static char * domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, int typMod, Constraint *constr, const char *domainName, ObjectAddress *constrAddr)
Definition: typecmds.c:3061
void pfree(void *pointer)
Definition: mcxt.c:936
CollateClause * collClause
Definition: parsenodes.h:2521
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
#define TYPCATEGORY_ARRAY
Definition: pg_type.h:728
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3066
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:833
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ACL_USAGE
Definition: parsenodes.h:80
#define ereport(elevel, rest)
Definition: elog.h:122
#define TYPTYPE_RANGE
Definition: pg_type.h:725
#define TextDatumGetCString(d)
Definition: builtins.h:92
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
#define InvalidOid
Definition: postgres_ext.h:36
bool is_no_inherit
Definition: parsenodes.h:2101
#define lfirst(lc)
Definition: pg_list.h:106
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition: ruleutils.c:3008
static int list_length(const List *l)
Definition: pg_list.h:89
#define nodeTag(nodeptr)
Definition: nodes.h:517
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2099
TypeName * typeName
Definition: parsenodes.h:2520
List * collname
Definition: parsenodes.h:309
List * arrayBounds
Definition: parsenodes.h:214
int errmsg(const char *fmt,...)
Definition: elog.c:797
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 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
#define TYPTYPE_ENUM
Definition: pg_type.h:723
char * nodeToString(const void *obj)
Definition: outfuncs.c:4266
ConstrType contype
Definition: parsenodes.h:2092
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4592
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3493
Definition: pg_list.h:45
#define Anum_pg_type_typdefault
Definition: pg_type.h:268

◆ DefineEnum()

ObjectAddress DefineEnum ( CreateEnumStmt stmt)

Definition at line 1157 of file typecmds.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_OK, AssignTypeArrayOid(), CStringGetDatum, DEFAULT_TYPDELIM, EnumValuesCreate(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, get_namespace_name(), GetSysCacheOid2, GetUserId(), InvalidOid, makeArrayTypeName(), moveArrayTypeName(), ObjectAddress::objectId, ObjectIdGetDatum, OidIsValid, pfree(), pg_namespace_aclcheck(), QualifiedNameGetCreationNamespace(), TYPCATEGORY_ARRAY, TYPCATEGORY_ENUM, TypeCreate(), CreateEnumStmt::typeName, TYPENAMENSP, TYPTYPE_BASE, TYPTYPE_ENUM, and CreateEnumStmt::vals.

Referenced by ProcessUtilitySlow().

1158 {
1159  char *enumName;
1160  char *enumArrayName;
1161  Oid enumNamespace;
1162  AclResult aclresult;
1163  Oid old_type_oid;
1164  Oid enumArrayOid;
1165  ObjectAddress enumTypeAddr;
1166 
1167  /* Convert list of names to a name and namespace */
1168  enumNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
1169  &enumName);
1170 
1171  /* Check we have creation rights in target namespace */
1172  aclresult = pg_namespace_aclcheck(enumNamespace, GetUserId(), ACL_CREATE);
1173  if (aclresult != ACLCHECK_OK)
1175  get_namespace_name(enumNamespace));
1176 
1177  /*
1178  * Check for collision with an existing type name. If there is one and
1179  * it's an autogenerated array, we can rename it out of the way.
1180  */
1181  old_type_oid = GetSysCacheOid2(TYPENAMENSP,
1182  CStringGetDatum(enumName),
1183  ObjectIdGetDatum(enumNamespace));
1184  if (OidIsValid(old_type_oid))
1185  {
1186  if (!moveArrayTypeName(old_type_oid, enumName, enumNamespace))
1187  ereport(ERROR,
1189  errmsg("type \"%s\" already exists", enumName)));
1190  }
1191 
1192  /* Allocate OID for array type */
1193  enumArrayOid = AssignTypeArrayOid();
1194 
1195  /* Create the pg_type entry */
1196  enumTypeAddr =
1197  TypeCreate(InvalidOid, /* no predetermined type OID */
1198  enumName, /* type name */
1199  enumNamespace, /* namespace */
1200  InvalidOid, /* relation oid (n/a here) */
1201  0, /* relation kind (ditto) */
1202  GetUserId(), /* owner's ID */
1203  sizeof(Oid), /* internal size */
1204  TYPTYPE_ENUM, /* type-type (enum type) */
1205  TYPCATEGORY_ENUM, /* type-category (enum type) */
1206  false, /* enum types are never preferred */
1207  DEFAULT_TYPDELIM, /* array element delimiter */
1208  F_ENUM_IN, /* input procedure */
1209  F_ENUM_OUT, /* output procedure */
1210  F_ENUM_RECV, /* receive procedure */
1211  F_ENUM_SEND, /* send procedure */
1212  InvalidOid, /* typmodin procedure - none */
1213  InvalidOid, /* typmodout procedure - none */
1214  InvalidOid, /* analyze procedure - default */
1215  InvalidOid, /* element type ID */
1216  false, /* this is not an array type */
1217  enumArrayOid, /* array type we are about to create */
1218  InvalidOid, /* base type ID (only for domains) */
1219  NULL, /* never a default type value */
1220  NULL, /* binary default isn't sent either */
1221  true, /* always passed by value */
1222  'i', /* int alignment */
1223  'p', /* TOAST strategy always plain */
1224  -1, /* typMod (Domains only) */
1225  0, /* Array dimensions of typbasetype */
1226  false, /* Type NOT NULL */
1227  InvalidOid); /* type's collation */
1228 
1229  /* Enter the enum's values into pg_enum */
1230  EnumValuesCreate(enumTypeAddr.objectId, stmt->vals);
1231 
1232  /*
1233  * Create the array type that goes with it.
1234  */
1235  enumArrayName = makeArrayTypeName(enumName, enumNamespace);
1236 
1237  TypeCreate(enumArrayOid, /* force assignment of this type OID */
1238  enumArrayName, /* type name */
1239  enumNamespace, /* namespace */
1240  InvalidOid, /* relation oid (n/a here) */
1241  0, /* relation kind (ditto) */
1242  GetUserId(), /* owner's ID */
1243  -1, /* internal size (always varlena) */
1244  TYPTYPE_BASE, /* type-type (base type) */
1245  TYPCATEGORY_ARRAY, /* type-category (array) */
1246  false, /* array types are never preferred */
1247  DEFAULT_TYPDELIM, /* array element delimiter */
1248  F_ARRAY_IN, /* input procedure */
1249  F_ARRAY_OUT, /* output procedure */
1250  F_ARRAY_RECV, /* receive procedure */
1251  F_ARRAY_SEND, /* send procedure */
1252  InvalidOid, /* typmodin procedure - none */
1253  InvalidOid, /* typmodout procedure - none */
1254  F_ARRAY_TYPANALYZE, /* analyze procedure */
1255  enumTypeAddr.objectId, /* element type ID */
1256  true, /* yes this is an array type */
1257  InvalidOid, /* no further array type */
1258  InvalidOid, /* base type ID */
1259  NULL, /* never a default type value */
1260  NULL, /* binary default isn't sent either */
1261  false, /* never passed by value */
1262  'i', /* enums have align i, so do their arrays */
1263  'x', /* ARRAY is always toastable */
1264  -1, /* typMod (Domains only) */
1265  0, /* Array dimensions of typbasetype */
1266  false, /* Type NOT NULL */
1267  InvalidOid); /* type's collation */
1268 
1269  pfree(enumArrayName);
1270 
1271  return enumTypeAddr;
1272 }
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:767
#define TYPTYPE_BASE
Definition: pg_type.h:720
Oid GetUserId(void)
Definition: miscinit.c:284
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2956
int errcode(int sqlerrcode)
Definition: elog.c:575
void EnumValuesCreate(Oid enumTypeOid, List *vals)
Definition: pg_enum.c:49
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:586
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4542
#define TYPCATEGORY_ENUM
Definition: pg_type.h:732
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
void pfree(void *pointer)
Definition: mcxt.c:936
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
#define TYPCATEGORY_ARRAY
Definition: pg_type.h:728
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3066
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:833
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
AclResult
Definition: acl.h:178
#define InvalidOid
Definition: postgres_ext.h:36
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2099
int errmsg(const char *fmt,...)
Definition: elog.c:797
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 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
#define TYPTYPE_ENUM
Definition: pg_type.h:723
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30

◆ DefineRange()

ObjectAddress DefineRange ( CreateRangeStmt stmt)

Definition at line 1370 of file typecmds.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_OK, Assert, AssignTypeArrayOid(), CommandCounterIncrement(), CStringGetDatum, DEFAULT_TYPDELIM, defGetQualifiedName(), defGetTypeName(), DefElem::defname, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, 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(), makeRangeConstructors(), moveArrayTypeName(), NIL, ObjectAddress::objectId, ObjectIdGetDatum, OidIsValid, CreateRangeStmt::params, pfree(), pg_namespace_aclcheck(), pg_strcasecmp(), QualifiedNameGetCreationNamespace(), RangeCreate(), TYPCATEGORY_ARRAY, TYPCATEGORY_RANGE, type_is_collatable(), TypeCreate(), CreateRangeStmt::typeName, TYPENAMENSP, typenameTypeId(), TypeShellMake(), TYPTYPE_BASE, TYPTYPE_PSEUDO, and TYPTYPE_RANGE.

Referenced by ProcessUtilitySlow().

1371 {
1372  char *typeName;
1373  Oid typeNamespace;
1374  Oid typoid;
1375  char *rangeArrayName;
1376  Oid rangeArrayOid;
1377  Oid rangeSubtype = InvalidOid;
1378  List *rangeSubOpclassName = NIL;
1379  List *rangeCollationName = NIL;
1380  List *rangeCanonicalName = NIL;
1381  List *rangeSubtypeDiffName = NIL;
1382  Oid rangeSubOpclass;
1383  Oid rangeCollation;
1384  regproc rangeCanonical;
1385  regproc rangeSubtypeDiff;
1386  int16 subtyplen;
1387  bool subtypbyval;
1388  char subtypalign;
1389  char alignment;
1390  AclResult aclresult;
1391  ListCell *lc;
1392  ObjectAddress address;
1393 
1394  /* Convert list of names to a name and namespace */
1395  typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
1396  &typeName);
1397 
1398  /* Check we have creation rights in target namespace */
1399  aclresult = pg_namespace_aclcheck(typeNamespace, GetUserId(), ACL_CREATE);
1400  if (aclresult != ACLCHECK_OK)
1402  get_namespace_name(typeNamespace));
1403 
1404  /*
1405  * Look to see if type already exists.
1406  */
1407  typoid = GetSysCacheOid2(TYPENAMENSP,
1408  CStringGetDatum(typeName),
1409  ObjectIdGetDatum(typeNamespace));
1410 
1411  /*
1412  * If it's not a shell, see if it's an autogenerated array type, and if so
1413  * rename it out of the way.
1414  */
1415  if (OidIsValid(typoid) && get_typisdefined(typoid))
1416  {
1417  if (moveArrayTypeName(typoid, typeName, typeNamespace))
1418  typoid = InvalidOid;
1419  else
1420  ereport(ERROR,
1422  errmsg("type \"%s\" already exists", typeName)));
1423  }
1424 
1425  /*
1426  * If it doesn't exist, create it as a shell, so that the OID is known for
1427  * use in the range function definitions.
1428  */
1429  if (!OidIsValid(typoid))
1430  {
1431  address = TypeShellMake(typeName, typeNamespace, GetUserId());
1432  typoid = address.objectId;
1433  /* Make new shell type visible for modification below */
1435  }
1436 
1437  /* Extract the parameters from the parameter list */
1438  foreach(lc, stmt->params)
1439  {
1440  DefElem *defel = (DefElem *) lfirst(lc);
1441 
1442  if (pg_strcasecmp(defel->defname, "subtype") == 0)
1443  {
1444  if (OidIsValid(rangeSubtype))
1445  ereport(ERROR,
1446  (errcode(ERRCODE_SYNTAX_ERROR),
1447  errmsg("conflicting or redundant options")));
1448  /* we can look up the subtype name immediately */
1449  rangeSubtype = typenameTypeId(NULL, defGetTypeName(defel));
1450  }
1451  else if (pg_strcasecmp(defel->defname, "subtype_opclass") == 0)
1452  {
1453  if (rangeSubOpclassName != NIL)
1454  ereport(ERROR,
1455  (errcode(ERRCODE_SYNTAX_ERROR),
1456  errmsg("conflicting or redundant options")));
1457  rangeSubOpclassName = defGetQualifiedName(defel);
1458  }
1459  else if (pg_strcasecmp(defel->defname, "collation") == 0)
1460  {
1461  if (rangeCollationName != NIL)
1462  ereport(ERROR,
1463  (errcode(ERRCODE_SYNTAX_ERROR),
1464  errmsg("conflicting or redundant options")));
1465  rangeCollationName = defGetQualifiedName(defel);
1466  }
1467  else if (pg_strcasecmp(defel->defname, "canonical") == 0)
1468  {
1469  if (rangeCanonicalName != NIL)
1470  ereport(ERROR,
1471  (errcode(ERRCODE_SYNTAX_ERROR),
1472  errmsg("conflicting or redundant options")));
1473  rangeCanonicalName = defGetQualifiedName(defel);
1474  }
1475  else if (pg_strcasecmp(defel->defname, "subtype_diff") == 0)
1476  {
1477  if (rangeSubtypeDiffName != NIL)
1478  ereport(ERROR,
1479  (errcode(ERRCODE_SYNTAX_ERROR),
1480  errmsg("conflicting or redundant options")));
1481  rangeSubtypeDiffName = defGetQualifiedName(defel);
1482  }
1483  else
1484  ereport(ERROR,
1485  (errcode(ERRCODE_SYNTAX_ERROR),
1486  errmsg("type attribute \"%s\" not recognized",
1487  defel->defname)));
1488  }
1489 
1490  /* Must have a subtype */
1491  if (!OidIsValid(rangeSubtype))
1492  ereport(ERROR,
1493  (errcode(ERRCODE_SYNTAX_ERROR),
1494  errmsg("type attribute \"subtype\" is required")));
1495  /* disallow ranges of pseudotypes */
1496  if (get_typtype(rangeSubtype) == TYPTYPE_PSEUDO)
1497  ereport(ERROR,
1498  (errcode(ERRCODE_DATATYPE_MISMATCH),
1499  errmsg("range subtype cannot be %s",
1500  format_type_be(rangeSubtype))));
1501 
1502  /* Identify subopclass */
1503  rangeSubOpclass = findRangeSubOpclass(rangeSubOpclassName, rangeSubtype);
1504 
1505  /* Identify collation to use, if any */
1506  if (type_is_collatable(rangeSubtype))
1507  {
1508  if (rangeCollationName != NIL)
1509  rangeCollation = get_collation_oid(rangeCollationName, false);
1510  else
1511  rangeCollation = get_typcollation(rangeSubtype);
1512  }
1513  else
1514  {
1515  if (rangeCollationName != NIL)
1516  ereport(ERROR,
1517  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1518  errmsg("range collation specified but subtype does not support collation")));
1519  rangeCollation = InvalidOid;
1520  }
1521 
1522  /* Identify support functions, if provided */
1523  if (rangeCanonicalName != NIL)
1524  rangeCanonical = findRangeCanonicalFunction(rangeCanonicalName,
1525  typoid);
1526  else
1527  rangeCanonical = InvalidOid;
1528 
1529  if (rangeSubtypeDiffName != NIL)
1530  rangeSubtypeDiff = findRangeSubtypeDiffFunction(rangeSubtypeDiffName,
1531  rangeSubtype);
1532  else
1533  rangeSubtypeDiff = InvalidOid;
1534 
1535  get_typlenbyvalalign(rangeSubtype,
1536  &subtyplen, &subtypbyval, &subtypalign);
1537 
1538  /* alignment must be 'i' or 'd' for ranges */
1539  alignment = (subtypalign == 'd') ? 'd' : 'i';
1540 
1541  /* Allocate OID for array type */
1542  rangeArrayOid = AssignTypeArrayOid();
1543 
1544  /* Create the pg_type entry */
1545  address =
1546  TypeCreate(InvalidOid, /* no predetermined type OID */
1547  typeName, /* type name */
1548  typeNamespace, /* namespace */
1549  InvalidOid, /* relation oid (n/a here) */
1550  0, /* relation kind (ditto) */
1551  GetUserId(), /* owner's ID */
1552  -1, /* internal size (always varlena) */
1553  TYPTYPE_RANGE, /* type-type (range type) */
1554  TYPCATEGORY_RANGE, /* type-category (range type) */
1555  false, /* range types are never preferred */
1556  DEFAULT_TYPDELIM, /* array element delimiter */
1557  F_RANGE_IN, /* input procedure */
1558  F_RANGE_OUT, /* output procedure */
1559  F_RANGE_RECV, /* receive procedure */
1560  F_RANGE_SEND, /* send procedure */
1561  InvalidOid, /* typmodin procedure - none */
1562  InvalidOid, /* typmodout procedure - none */
1563  F_RANGE_TYPANALYZE, /* analyze procedure */
1564  InvalidOid, /* element type ID - none */
1565  false, /* this is not an array type */
1566  rangeArrayOid, /* array type we are about to create */
1567  InvalidOid, /* base type ID (only for domains) */
1568  NULL, /* never a default type value */
1569  NULL, /* no binary form available either */
1570  false, /* never passed by value */
1571  alignment, /* alignment */
1572  'x', /* TOAST strategy (always extended) */
1573  -1, /* typMod (Domains only) */
1574  0, /* Array dimensions of typbasetype */
1575  false, /* Type NOT NULL */
1576  InvalidOid); /* type's collation (ranges never have one) */
1577  Assert(typoid == address.objectId);
1578 
1579  /* Create the entry in pg_range */
1580  RangeCreate(typoid, rangeSubtype, rangeCollation, rangeSubOpclass,
1581  rangeCanonical, rangeSubtypeDiff);
1582 
1583  /*
1584  * Create the array type that goes with it.
1585  */
1586  rangeArrayName = makeArrayTypeName(typeName, typeNamespace);
1587 
1588  TypeCreate(rangeArrayOid, /* force assignment of this type OID */
1589  rangeArrayName, /* type name */
1590  typeNamespace, /* namespace */
1591  InvalidOid, /* relation oid (n/a here) */
1592  0, /* relation kind (ditto) */
1593  GetUserId(), /* owner's ID */
1594  -1, /* internal size (always varlena) */
1595  TYPTYPE_BASE, /* type-type (base type) */
1596  TYPCATEGORY_ARRAY, /* type-category (array) */
1597  false, /* array types are never preferred */
1598  DEFAULT_TYPDELIM, /* array element delimiter */
1599  F_ARRAY_IN, /* input procedure */
1600  F_ARRAY_OUT, /* output procedure */
1601  F_ARRAY_RECV, /* receive procedure */
1602  F_ARRAY_SEND, /* send procedure */
1603  InvalidOid, /* typmodin procedure - none */
1604  InvalidOid, /* typmodout procedure - none */
1605  F_ARRAY_TYPANALYZE, /* analyze procedure */
1606  typoid, /* element type ID */
1607  true, /* yes this is an array type */
1608  InvalidOid, /* no further array type */
1609  InvalidOid, /* base type ID */
1610  NULL, /* never a default type value */
1611  NULL, /* binary default isn't sent either */
1612  false, /* never passed by value */
1613  alignment, /* alignment - same as range's */
1614  'x', /* ARRAY is always toastable */
1615  -1, /* typMod (Domains only) */
1616  0, /* Array dimensions of typbasetype */
1617  false, /* Type NOT NULL */
1618  InvalidOid); /* typcollation */
1619 
1620  pfree(rangeArrayName);
1621 
1622  /* And create the constructor functions for this range type */
1623  makeRangeConstructors(typeName, typeNamespace, typoid, rangeSubtype);
1624 
1625  return address;
1626 }
signed short int16
Definition: c.h:293
#define NIL
Definition: pg_list.h:69
static void makeRangeConstructors(const char *name, Oid namespace, Oid rangeOid, Oid subtype)
Definition: typecmds.c:1638
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:767
#define TYPTYPE_BASE
Definition: pg_type.h:720
Oid GetUserId(void)
Definition: miscinit.c:284
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2956
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2040
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:1942
int errcode(int sqlerrcode)
Definition: elog.c:575
char get_typtype(Oid typid)
Definition: lsyscache.c:2398
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
unsigned int Oid
Definition: postgres_ext.h:31
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:56
#define OidIsValid(objectId)
Definition: c.h:586
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4542
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
static Oid findRangeSubtypeDiffFunction(List *procname, Oid subtype)
Definition: typecmds.c:2051
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:255
#define TYPCATEGORY_RANGE
Definition: pg_type.h:737
void pfree(void *pointer)
Definition: mcxt.c:936
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
#define TYPCATEGORY_ARRAY
Definition: pg_type.h:728
void RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation, Oid rangeSubOpclass, RegProcedure rangeCanonical, RegProcedure rangeSubDiff)
Definition: pg_range.c:37
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3066
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:833
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define CStringGetDatum(X)
Definition: postgres.h:584
#define ereport(elevel, rest)
Definition: elog.h:122
#define TYPTYPE_RANGE
Definition: pg_type.h:725
AclResult
Definition: acl.h:178
void CommandCounterIncrement(void)
Definition: xact.c:915
#define InvalidOid
Definition: postgres_ext.h:36
static Oid findRangeSubOpclass(List *opcname, Oid subtype)
Definition: typecmds.c:1971
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2814
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
#define Assert(condition)
Definition: c.h:680
#define lfirst(lc)
Definition: pg_list.h:106
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2099
#define TYPTYPE_PSEUDO
Definition: pg_type.h:724
Oid regproc
Definition: c.h:452
int errmsg(const char *fmt,...)
Definition: elog.c:797
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 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 * defname
Definition: parsenodes.h:719
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:2839
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3493
Definition: pg_list.h:45
static Oid findRangeCanonicalFunction(List *procname, Oid typeOid)
Definition: typecmds.c:2010
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ DefineType()

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

Definition at line 116 of file typecmds.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, ACL_KIND_PROC, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, Assert, AssignTypeArrayOid(), BYTEAOID, CommandCounterIncrement(), CStringGetDatum, CSTRINGOID, DEFAULT_COLLATION_OID, DEFAULT_TYPDELIM, defGetBoolean(), defGetQualifiedName(), defGetString(), defGetTypeLength(), defGetTypeName(), DefElem::defname, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, findTypeAnalyzeFunction(), findTypeInputFunction(), findTypeOutputFunction(), findTypeReceiveFunction(), findTypeSendFunction(), findTypeTypmodinFunction(), findTypeTypmodoutFunction(), format_type_be(), func_volatile(), get_func_rettype(), get_namespace_name(), get_typisdefined(), get_typtype(), GETSTRUCT, GetSysCacheOid2, GetUserId(), InvalidOid, lfirst, DefElem::location, makeArrayTypeName(), moveArrayTypeName(), NameListToString(), NIL, ObjectAddress::objectId, ObjectIdGetDatum, OidIsValid, OPAQUEOID, parser_errposition(), pfree(), pg_namespace_aclcheck(), pg_proc_ownercheck(), pg_strcasecmp(), PROVOLATILE_VOLATILE, QualifiedNameGetCreationNamespace(), ReleaseSysCache(), SetFunctionReturnType(), superuser(), TYPCATEGORY_ARRAY, TYPCATEGORY_USER, TypeCreate(), TYPENAMENSP, typenameType(), typenameTypeId(), TypeShellMake(), TYPTYPE_BASE, TYPTYPE_PSEUDO, and WARNING.

Referenced by ProcessUtilitySlow().

117 {
118  char *typeName;
119  Oid typeNamespace;
120  int16 internalLength = -1; /* default: variable-length */
121  List *inputName = NIL;
122  List *outputName = NIL;
123  List *receiveName = NIL;
124  List *sendName = NIL;
125  List *typmodinName = NIL;
126  List *typmodoutName = NIL;
127  List *analyzeName = NIL;
128  char category = TYPCATEGORY_USER;
129  bool preferred = false;
130  char delimiter = DEFAULT_TYPDELIM;
131  Oid elemType = InvalidOid;
132  char *defaultValue = NULL;
133  bool byValue = false;
134  char alignment = 'i'; /* default alignment */
135  char storage = 'p'; /* default TOAST storage method */
136  Oid collation = InvalidOid;
137  DefElem *likeTypeEl = NULL;
138  DefElem *internalLengthEl = NULL;
139  DefElem *inputNameEl = NULL;
140  DefElem *outputNameEl = NULL;
141  DefElem *receiveNameEl = NULL;
142  DefElem *sendNameEl = NULL;
143  DefElem *typmodinNameEl = NULL;
144  DefElem *typmodoutNameEl = NULL;
145  DefElem *analyzeNameEl = NULL;
146  DefElem *categoryEl = NULL;
147  DefElem *preferredEl = NULL;
148  DefElem *delimiterEl = NULL;
149  DefElem *elemTypeEl = NULL;
150  DefElem *defaultValueEl = NULL;
151  DefElem *byValueEl = NULL;
152  DefElem *alignmentEl = NULL;
153  DefElem *storageEl = NULL;
154  DefElem *collatableEl = NULL;
155  Oid inputOid;
156  Oid outputOid;
157  Oid receiveOid = InvalidOid;
158  Oid sendOid = InvalidOid;
159  Oid typmodinOid = InvalidOid;
160  Oid typmodoutOid = InvalidOid;
161  Oid analyzeOid = InvalidOid;
162  char *array_type;
163  Oid array_oid;
164  Oid typoid;
165  Oid resulttype;
166  ListCell *pl;
167  ObjectAddress address;
168 
169  /*
170  * As of Postgres 8.4, we require superuser privilege to create a base
171  * type. This is simple paranoia: there are too many ways to mess up the
172  * system with an incorrect type definition (for instance, representation
173  * parameters that don't match what the C code expects). In practice it
174  * takes superuser privilege to create the I/O functions, and so the
175  * former requirement that you own the I/O functions pretty much forced
176  * superuserness anyway. We're just making doubly sure here.
177  *
178  * XXX re-enable NOT_USED code sections below if you remove this test.
179  */
180  if (!superuser())
181  ereport(ERROR,
182  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
183  errmsg("must be superuser to create a base type")));
184 
185  /* Convert list of names to a name and namespace */
186  typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
187 
188 #ifdef NOT_USED
189  /* XXX this is unnecessary given the superuser check above */
190  /* Check we have creation rights in target namespace */
191  aclresult = pg_namespace_aclcheck(typeNamespace, GetUserId(), ACL_CREATE);
192  if (aclresult != ACLCHECK_OK)
194  get_namespace_name(typeNamespace));
195 #endif
196 
197  /*
198  * Look to see if type already exists (presumably as a shell; if not,
199  * TypeCreate will complain).
200  */
201  typoid = GetSysCacheOid2(TYPENAMENSP,
202  CStringGetDatum(typeName),
203  ObjectIdGetDatum(typeNamespace));
204 
205  /*
206  * If it's not a shell, see if it's an autogenerated array type, and if so
207  * rename it out of the way.
208  */
209  if (OidIsValid(typoid) && get_typisdefined(typoid))
210  {
211  if (moveArrayTypeName(typoid, typeName, typeNamespace))
212  typoid = InvalidOid;
213  }
214 
215  /*
216  * If it doesn't exist, create it as a shell, so that the OID is known for
217  * use in the I/O function definitions.
218  */
219  if (!OidIsValid(typoid))
220  {
221  address = TypeShellMake(typeName, typeNamespace, GetUserId());
222  typoid = address.objectId;
223  /* Make new shell type visible for modification below */
225 
226  /*
227  * If the command was a parameterless CREATE TYPE, we're done ---
228  * creating the shell type was all we're supposed to do.
229  */
230  if (parameters == NIL)
231  return address;
232  }
233  else
234  {
235  /* Complain if dummy CREATE TYPE and entry already exists */
236  if (parameters == NIL)
237  ereport(ERROR,
239  errmsg("type \"%s\" already exists", typeName)));
240  }
241 
242  /* Extract the parameters from the parameter list */
243  foreach(pl, parameters)
244  {
245  DefElem *defel = (DefElem *) lfirst(pl);
246  DefElem **defelp;
247 
248  if (pg_strcasecmp(defel->defname, "like") == 0)
249  defelp = &likeTypeEl;
250  else if (pg_strcasecmp(defel->defname, "internallength") == 0)
251  defelp = &internalLengthEl;
252  else if (pg_strcasecmp(defel->defname, "input") == 0)
253  defelp = &inputNameEl;
254  else if (pg_strcasecmp(defel->defname, "output") == 0)
255  defelp = &outputNameEl;
256  else if (pg_strcasecmp(defel->defname, "receive") == 0)
257  defelp = &receiveNameEl;
258  else if (pg_strcasecmp(defel->defname, "send") == 0)
259  defelp = &sendNameEl;
260  else if (pg_strcasecmp(defel->defname, "typmod_in") == 0)
261  defelp = &typmodinNameEl;
262  else if (pg_strcasecmp(defel->defname, "typmod_out") == 0)
263  defelp = &typmodoutNameEl;
264  else if (pg_strcasecmp(defel->defname, "analyze") == 0 ||
265  pg_strcasecmp(defel->defname, "analyse") == 0)
266  defelp = &analyzeNameEl;
267  else if (pg_strcasecmp(defel->defname, "category") == 0)
268  defelp = &categoryEl;
269  else if (pg_strcasecmp(defel->defname, "preferred") == 0)
270  defelp = &preferredEl;
271  else if (pg_strcasecmp(defel->defname, "delimiter") == 0)
272  defelp = &delimiterEl;
273  else if (pg_strcasecmp(defel->defname, "element") == 0)
274  defelp = &elemTypeEl;
275  else if (pg_strcasecmp(defel->defname, "default") == 0)
276  defelp = &defaultValueEl;
277  else if (pg_strcasecmp(defel->defname, "passedbyvalue") == 0)
278  defelp = &byValueEl;
279  else if (pg_strcasecmp(defel->defname, "alignment") == 0)
280  defelp = &alignmentEl;
281  else if (pg_strcasecmp(defel->defname, "storage") == 0)
282  defelp = &storageEl;
283  else if (pg_strcasecmp(defel->defname, "collatable") == 0)
284  defelp = &collatableEl;
285  else
286  {
287  /* WARNING, not ERROR, for historical backwards-compatibility */
289  (errcode(ERRCODE_SYNTAX_ERROR),
290  errmsg("type attribute \"%s\" not recognized",
291  defel->defname),
292  parser_errposition(pstate, defel->location)));
293  continue;
294  }
295  if (*defelp != NULL)
296  ereport(ERROR,
297  (errcode(ERRCODE_SYNTAX_ERROR),
298  errmsg("conflicting or redundant options"),
299  parser_errposition(pstate, defel->location)));
300  *defelp = defel;
301  }
302 
303  /*
304  * Now interpret the options; we do this separately so that LIKE can be
305  * overridden by other options regardless of the ordering in the parameter
306  * list.
307  */
308  if (likeTypeEl)
309  {
310  Type likeType;
311  Form_pg_type likeForm;
312 
313  likeType = typenameType(NULL, defGetTypeName(likeTypeEl), NULL);
314  likeForm = (Form_pg_type) GETSTRUCT(likeType);
315  internalLength = likeForm->typlen;
316  byValue = likeForm->typbyval;
317  alignment = likeForm->typalign;
318  storage = likeForm->typstorage;
319  ReleaseSysCache(likeType);
320  }
321  if (internalLengthEl)
322  internalLength = defGetTypeLength(internalLengthEl);
323  if (inputNameEl)
324  inputName = defGetQualifiedName(inputNameEl);
325  if (outputNameEl)
326  outputName = defGetQualifiedName(outputNameEl);
327  if (receiveNameEl)
328  receiveName = defGetQualifiedName(receiveNameEl);
329  if (sendNameEl)
330  sendName = defGetQualifiedName(sendNameEl);
331  if (typmodinNameEl)
332  typmodinName = defGetQualifiedName(typmodinNameEl);
333  if (typmodoutNameEl)
334  typmodoutName = defGetQualifiedName(typmodoutNameEl);
335  if (analyzeNameEl)
336  analyzeName = defGetQualifiedName(analyzeNameEl);
337  if (categoryEl)
338  {
339  char *p = defGetString(categoryEl);
340 
341  category = p[0];
342  /* restrict to non-control ASCII */
343  if (category < 32 || category > 126)
344  ereport(ERROR,
345  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
346  errmsg("invalid type category \"%s\": must be simple ASCII",
347  p)));
348  }
349  if (preferredEl)
350  preferred = defGetBoolean(preferredEl);
351  if (delimiterEl)
352  {
353  char *p = defGetString(delimiterEl);
354 
355  delimiter = p[0];
356  /* XXX shouldn't we restrict the delimiter? */
357  }
358  if (elemTypeEl)
359  {
360  elemType = typenameTypeId(NULL, defGetTypeName(elemTypeEl));
361  /* disallow arrays of pseudotypes */
362  if (get_typtype(elemType) == TYPTYPE_PSEUDO)
363  ereport(ERROR,
364  (errcode(ERRCODE_DATATYPE_MISMATCH),
365  errmsg("array element type cannot be %s",
366  format_type_be(elemType))));
367  }
368  if (defaultValueEl)
369  defaultValue = defGetString(defaultValueEl);
370  if (byValueEl)
371  byValue = defGetBoolean(byValueEl);
372  if (alignmentEl)
373  {
374  char *a = defGetString(alignmentEl);
375 
376  /*
377  * Note: if argument was an unquoted identifier, parser will have
378  * applied translations to it, so be prepared to recognize translated
379  * type names as well as the nominal form.
380  */
381  if (pg_strcasecmp(a, "double") == 0 ||
382  pg_strcasecmp(a, "float8") == 0 ||
383  pg_strcasecmp(a, "pg_catalog.float8") == 0)
384  alignment = 'd';
385  else if (pg_strcasecmp(a, "int4") == 0 ||
386  pg_strcasecmp(a, "pg_catalog.int4") == 0)
387  alignment = 'i';
388  else if (pg_strcasecmp(a, "int2") == 0 ||
389  pg_strcasecmp(a, "pg_catalog.int2") == 0)
390  alignment = 's';
391  else if (pg_strcasecmp(a, "char") == 0 ||
392  pg_strcasecmp(a, "pg_catalog.bpchar") == 0)
393  alignment = 'c';
394  else
395  ereport(ERROR,
396  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
397  errmsg("alignment \"%s\" not recognized", a)));
398  }
399  if (storageEl)
400  {
401  char *a = defGetString(storageEl);
402 
403  if (pg_strcasecmp(a, "plain") == 0)
404  storage = 'p';
405  else if (pg_strcasecmp(a, "external") == 0)
406  storage = 'e';
407  else if (pg_strcasecmp(a, "extended") == 0)
408  storage = 'x';
409  else if (pg_strcasecmp(a, "main") == 0)
410  storage = 'm';
411  else
412  ereport(ERROR,
413  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
414  errmsg("storage \"%s\" not recognized", a)));
415  }
416  if (collatableEl)
417  collation = defGetBoolean(collatableEl) ? DEFAULT_COLLATION_OID : InvalidOid;
418 
419  /*
420  * make sure we have our required definitions
421  */
422  if (inputName == NIL)
423  ereport(ERROR,
424  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
425  errmsg("type input function must be specified")));
426  if (outputName == NIL)
427  ereport(ERROR,
428  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
429  errmsg("type output function must be specified")));
430 
431  if (typmodinName == NIL && typmodoutName != NIL)
432  ereport(ERROR,
433  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
434  errmsg("type modifier output function is useless without a type modifier input function")));
435 
436  /*
437  * Convert I/O proc names to OIDs
438  */
439  inputOid = findTypeInputFunction(inputName, typoid);
440  outputOid = findTypeOutputFunction(outputName, typoid);
441  if (receiveName)
442  receiveOid = findTypeReceiveFunction(receiveName, typoid);
443  if (sendName)
444  sendOid = findTypeSendFunction(sendName, typoid);
445 
446  /*
447  * Verify that I/O procs return the expected thing. If we see OPAQUE,
448  * complain and change it to the correct type-safe choice.
449  */
450  resulttype = get_func_rettype(inputOid);
451  if (resulttype != typoid)
452  {
453  if (resulttype == OPAQUEOID)
454  {
455  /* backwards-compatibility hack */
457  (errmsg("changing return type of function %s from %s to %s",
458  NameListToString(inputName), "opaque", typeName)));
459  SetFunctionReturnType(inputOid, typoid);
460  }
461  else
462  ereport(ERROR,
463  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
464  errmsg("type input function %s must return type %s",
465  NameListToString(inputName), typeName)));
466  }
467  resulttype = get_func_rettype(outputOid);
468  if (resulttype != CSTRINGOID)
469  {
470  if (resulttype == OPAQUEOID)
471  {
472  /* backwards-compatibility hack */
474  (errmsg("changing return type of function %s from %s to %s",
475  NameListToString(outputName), "opaque", "cstring")));
476  SetFunctionReturnType(outputOid, CSTRINGOID);
477  }
478  else
479  ereport(ERROR,
480  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
481  errmsg("type output function %s must return type %s",
482  NameListToString(outputName), "cstring")));
483  }
484  if (receiveOid)
485  {
486  resulttype = get_func_rettype(receiveOid);
487  if (resulttype != typoid)
488  ereport(ERROR,
489  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
490  errmsg("type receive function %s must return type %s",
491  NameListToString(receiveName), typeName)));
492  }
493  if (sendOid)
494  {
495  resulttype = get_func_rettype(sendOid);
496  if (resulttype != BYTEAOID)
497  ereport(ERROR,
498  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
499  errmsg("type send function %s must return type %s",
500  NameListToString(sendName), "bytea")));
501  }
502 
503  /*
504  * Convert typmodin/out function proc names to OIDs.
505  */
506  if (typmodinName)
507  typmodinOid = findTypeTypmodinFunction(typmodinName);
508  if (typmodoutName)
509  typmodoutOid = findTypeTypmodoutFunction(typmodoutName);
510 
511  /*
512  * Convert analysis function proc name to an OID. If no analysis function
513  * is specified, we'll use zero to select the built-in default algorithm.
514  */
515  if (analyzeName)
516  analyzeOid = findTypeAnalyzeFunction(analyzeName, typoid);
517 
518  /*
519  * Check permissions on functions. We choose to require the creator/owner
520  * of a type to also own the underlying functions. Since creating a type
521  * is tantamount to granting public execute access on the functions, the
522  * minimum sane check would be for execute-with-grant-option. But we
523  * don't have a way to make the type go away if the grant option is
524  * revoked, so ownership seems better.
525  */
526 #ifdef NOT_USED
527  /* XXX this is unnecessary given the superuser check above */
528  if (inputOid && !pg_proc_ownercheck(inputOid, GetUserId()))
530  NameListToString(inputName));
531  if (outputOid && !pg_proc_ownercheck(outputOid, GetUserId()))
533  NameListToString(outputName));
534  if (receiveOid && !pg_proc_ownercheck(receiveOid, GetUserId()))
536  NameListToString(receiveName));
537  if (sendOid && !pg_proc_ownercheck(sendOid, GetUserId()))
539  NameListToString(sendName));
540  if (typmodinOid && !pg_proc_ownercheck(typmodinOid, GetUserId()))
542  NameListToString(typmodinName));
543  if (typmodoutOid && !pg_proc_ownercheck(typmodoutOid, GetUserId()))
545  NameListToString(typmodoutName));
546  if (analyzeOid && !pg_proc_ownercheck(analyzeOid, GetUserId()))
548  NameListToString(analyzeName));
549 #endif
550 
551  /*
552  * Print warnings if any of the type's I/O functions are marked volatile.
553  * There is a general assumption that I/O functions are stable or
554  * immutable; this allows us for example to mark record_in/record_out
555  * stable rather than volatile. Ideally we would throw errors not just
556  * warnings here; but since this check is new as of 9.5, and since the
557  * volatility marking might be just an error-of-omission and not a true
558  * indication of how the function behaves, we'll let it pass as a warning
559  * for now.
560  */
561  if (inputOid && func_volatile(inputOid) == PROVOLATILE_VOLATILE)
563  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
564  errmsg("type input function %s should not be volatile",
565  NameListToString(inputName))));
566  if (outputOid && func_volatile(outputOid) == PROVOLATILE_VOLATILE)
568  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
569  errmsg("type output function %s should not be volatile",
570  NameListToString(outputName))));
571  if (receiveOid && func_volatile(receiveOid) == PROVOLATILE_VOLATILE)
573  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
574  errmsg("type receive function %s should not be volatile",
575  NameListToString(receiveName))));
576  if (sendOid && func_volatile(sendOid) == PROVOLATILE_VOLATILE)
578  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
579  errmsg("type send function %s should not be volatile",
580  NameListToString(sendName))));
581  if (typmodinOid && func_volatile(typmodinOid) == PROVOLATILE_VOLATILE)
583  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
584  errmsg("type modifier input function %s should not be volatile",
585  NameListToString(typmodinName))));
586  if (typmodoutOid && func_volatile(typmodoutOid) == PROVOLATILE_VOLATILE)
588  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
589  errmsg("type modifier output function %s should not be volatile",
590  NameListToString(typmodoutName))));
591 
592  /*
593  * OK, we're done checking, time to make the type. We must assign the
594  * array type OID ahead of calling TypeCreate, since the base type and
595  * array type each refer to the other.
596  */
597  array_oid = AssignTypeArrayOid();
598 
599  /*
600  * now have TypeCreate do all the real work.
601  *
602  * Note: the pg_type.oid is stored in user tables as array elements (base
603  * types) in ArrayType and in composite types in DatumTupleFields. This
604  * oid must be preserved by binary upgrades.
605  */
606  address =
607  TypeCreate(InvalidOid, /* no predetermined type OID */
608  typeName, /* type name */
609  typeNamespace, /* namespace */
610  InvalidOid, /* relation oid (n/a here) */
611  0, /* relation kind (ditto) */
612  GetUserId(), /* owner's ID */
613  internalLength, /* internal size */
614  TYPTYPE_BASE, /* type-type (base type) */
615  category, /* type-category */
616  preferred, /* is it a preferred type? */
617  delimiter, /* array element delimiter */
618  inputOid, /* input procedure */
619  outputOid, /* output procedure */
620  receiveOid, /* receive procedure */
621  sendOid, /* send procedure */
622  typmodinOid, /* typmodin procedure */
623  typmodoutOid, /* typmodout procedure */
624  analyzeOid, /* analyze procedure */
625  elemType, /* element type ID */
626  false, /* this is not an array type */
627  array_oid, /* array type we are about to create */
628  InvalidOid, /* base type ID (only for domains) */
629  defaultValue, /* default type value */
630  NULL, /* no binary form available */
631  byValue, /* passed by value */
632  alignment, /* required alignment */
633  storage, /* TOAST strategy */
634  -1, /* typMod (Domains only) */
635  0, /* Array Dimensions of typbasetype */
636  false, /* Type NOT NULL */
637  collation); /* type's collation */
638  Assert(typoid == address.objectId);
639 
640  /*
641  * Create the array type that goes with it.
642  */
643  array_type = makeArrayTypeName(typeName, typeNamespace);
644 
645  /* alignment must be 'i' or 'd' for arrays */
646  alignment = (alignment == 'd') ? 'd' : 'i';
647 
648  TypeCreate(array_oid, /* force assignment of this type OID */
649  array_type, /* type name */
650  typeNamespace, /* namespace */
651  InvalidOid, /* relation oid (n/a here) */
652  0, /* relation kind (ditto) */
653  GetUserId(), /* owner's ID */
654  -1, /* internal size (always varlena) */
655  TYPTYPE_BASE, /* type-type (base type) */
656  TYPCATEGORY_ARRAY, /* type-category (array) */
657  false, /* array types are never preferred */
658  delimiter, /* array element delimiter */
659  F_ARRAY_IN, /* input procedure */
660  F_ARRAY_OUT, /* output procedure */
661  F_ARRAY_RECV, /* receive procedure */
662  F_ARRAY_SEND, /* send procedure */
663  typmodinOid, /* typmodin procedure */
664  typmodoutOid, /* typmodout procedure */
665  F_ARRAY_TYPANALYZE, /* analyze procedure */
666  typoid, /* element type ID */
667  true, /* yes this is an array type */
668  InvalidOid, /* no further array type */
669  InvalidOid, /* base type ID */
670  NULL, /* never a default type value */
671  NULL, /* binary default isn't sent either */
672  false, /* never passed by value */
673  alignment, /* see above */
674  'x', /* ARRAY is always toastable */
675  -1, /* typMod (Domains only) */
676  0, /* Array dimensions of typbasetype */
677  false, /* Type NOT NULL */
678  collation); /* type's collation */
679 
680  pfree(array_type);
681 
682  return address;
683 }
signed short int16
Definition: c.h:293
#define NIL
Definition: pg_list.h:69
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:767
static Oid findTypeOutputFunction(List *procname, Oid typeOid)
Definition: typecmds.c:1777
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
Type typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
Definition: parse_type.c:247
static Oid findTypeReceiveFunction(List *procname, Oid typeOid)
Definition: typecmds.c:1828
#define TYPTYPE_BASE
Definition: pg_type.h:720
Oid GetUserId(void)
Definition: miscinit.c:284
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2956
static Oid findTypeTypmodinFunction(List *procname)
Definition: typecmds.c:1882
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:1942
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
char get_typtype(Oid typid)
Definition: lsyscache.c:2398
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define TYPCATEGORY_USER
Definition: pg_type.h:740
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:56
#define OidIsValid(objectId)
Definition: c.h:586
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4542
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1459
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
int defGetTypeLength(DefElem *def)
Definition: define.c:283
bool defGetBoolean(DefElem *def)
Definition: define.c:111
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:255
void pfree(void *pointer)
Definition: mcxt.c:936
#define OPAQUEOID
Definition: pg_type.h:700
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
char * defGetString(DefElem *def)
Definition: define.c:49
#define TYPCATEGORY_ARRAY
Definition: pg_type.h:728
static Oid findTypeAnalyzeFunction(List *procname, Oid typeOid)
Definition: typecmds.c:1936
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3066
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:833
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
int location
Definition: parsenodes.h:722
#define CStringGetDatum(X)
Definition: postgres.h:584
static Oid findTypeTypmodoutFunction(List *procname)
Definition: typecmds.c:1909
#define ereport(elevel, rest)
Definition: elog.h:122
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5544
#define WARNING
Definition: elog.h:40
char * NameListToString(List *names)
Definition: namespace.c:3063
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
void SetFunctionReturnType(Oid funcOid, Oid newRetType)
#define InvalidOid
Definition: postgres_ext.h:36
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
#define CSTRINGOID
Definition: pg_type.h:684
#define Assert(condition)
Definition: c.h:680
#define lfirst(lc)
Definition: pg_list.h:106
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2099
#define TYPTYPE_PSEUDO
Definition: pg_type.h:724
#define BYTEAOID
Definition: pg_type.h:292
static Oid findTypeInputFunction(List *procname, Oid typeOid)
Definition: typecmds.c:1710
char func_volatile(Oid funcid)
Definition: lsyscache.c:1584
int errmsg(const char *fmt,...)
Definition: elog.c:797
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 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 * defname
Definition: parsenodes.h:719
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
Definition: pg_list.h:45
bool pg_proc_ownercheck(Oid proc_oid, Oid roleid)
Definition: aclchk.c:4682
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
static Oid findTypeSendFunction(List *procname, Oid typeOid)
Definition: typecmds.c:1859

◆ RemoveTypeById()

void RemoveTypeById ( Oid  typeOid)

Definition at line 689 of file typecmds.c.

References CatalogTupleDelete(), elog, EnumValuesDelete(), ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, RangeDelete(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, TYPEOID, TypeRelationId, TYPTYPE_ENUM, and TYPTYPE_RANGE.

Referenced by doDeletion().

690 {
691  Relation relation;
692  HeapTuple tup;
693 
695 
696  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
697  if (!HeapTupleIsValid(tup))
698  elog(ERROR, "cache lookup failed for type %u", typeOid);
699 
700  CatalogTupleDelete(relation, &tup->t_self);
701 
702  /*
703  * If it is an enum, delete the pg_enum entries too; we don't bother with
704  * making dependency entries for those, so it has to be done "by hand"
705  * here.
706  */
707  if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_ENUM)
708  EnumValuesDelete(typeOid);
709 
710  /*
711  * If it is a range type, delete the pg_range entry too; we don't bother
712  * with making a dependency entry for that, so it has to be done "by hand"
713  * here.
714  */
715  if (((Form_pg_type) GETSTRUCT(tup))->typtype == TYPTYPE_RANGE)
716  RangeDelete(typeOid);
717 
718  ReleaseSysCache(tup);
719 
720  heap_close(relation, RowExclusiveLock);
721 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
#define TypeRelationId
Definition: pg_type.h:34
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void EnumValuesDelete(Oid enumTypeOid)
Definition: pg_enum.c:144
#define TYPTYPE_RANGE
Definition: pg_type.h:725
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define TYPTYPE_ENUM
Definition: pg_type.h:723
#define elog
Definition: elog.h:219
void RangeDelete(Oid rangeTypeOid)
Definition: pg_range.c:113

◆ RenameType()

ObjectAddress RenameType ( RenameStmt stmt)

Definition at line 3223 of file typecmds.c.

References aclcheck_error_type(), ACLCHECK_NOT_OWNER, castNode, elog, ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), get_array_type(), get_rel_relkind(), GETSTRUCT, GetUserId(), heap_close, heap_open(), HeapTupleIsValid, makeTypeNameFromNameList(), RenameStmt::newname, RenameStmt::object, OBJECT_DOMAIN, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, pg_type_ownercheck(), RELKIND_COMPOSITE_TYPE, RenameRelationInternal(), RenameStmt::renameType, RenameTypeInternal(), RowExclusiveLock, SearchSysCacheCopy1, typenameTypeId(), TYPEOID, TypeRelationId, TYPTYPE_COMPOSITE, and TYPTYPE_DOMAIN.

Referenced by ExecRenameStmt().

3224 {
3225  List *names = castNode(List, stmt->object);
3226  const char *newTypeName = stmt->newname;
3227  TypeName *typename;
3228  Oid typeOid;
3229  Relation rel;
3230  HeapTuple tup;
3231  Form_pg_type typTup;
3232  ObjectAddress address;
3233 
3234  /* Make a TypeName so we can use standard type lookup machinery */
3235  typename = makeTypeNameFromNameList(names);
3236  typeOid = typenameTypeId(NULL, typename);
3237 
3238  /* Look up the type in the type table */
3240 
3241  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
3242  if (!HeapTupleIsValid(tup))
3243  elog(ERROR, "cache lookup failed for type %u", typeOid);
3244  typTup = (Form_pg_type) GETSTRUCT(tup);
3245 
3246  /* check permissions on type */
3247  if (!pg_type_ownercheck(typeOid, GetUserId()))
3249 
3250  /* ALTER DOMAIN used on a non-domain? */
3251  if (stmt->renameType == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
3252  ereport(ERROR,
3253  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3254  errmsg("%s is not a domain",
3255  format_type_be(typeOid))));
3256 
3257  /*
3258  * If it's a composite type, we need to check that it really is a
3259  * free-standing composite type, and not a table's rowtype. We want people
3260  * to use ALTER TABLE not ALTER TYPE for that case.
3261  */
3262  if (typTup->typtype == TYPTYPE_COMPOSITE &&
3263  get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)
3264  ereport(ERROR,
3265  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3266  errmsg("%s is a table's row type",
3267  format_type_be(typeOid)),
3268  errhint("Use ALTER TABLE instead.")));
3269 
3270  /* don't allow direct alteration of array types, either */
3271  if (OidIsValid(typTup->typelem) &&
3272  get_array_type(typTup->typelem) == typeOid)
3273  ereport(ERROR,
3274  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3275  errmsg("cannot alter array type %s",
3276  format_type_be(typeOid)),
3277  errhint("You can alter type %s, which will alter the array type as well.",
3278  format_type_be(typTup->typelem))));
3279 
3280  /*
3281  * If type is composite we need to rename associated pg_class entry too.
3282  * RenameRelationInternal will call RenameTypeInternal automatically.
3283  */
3284  if (typTup->typtype == TYPTYPE_COMPOSITE)
3285  RenameRelationInternal(typTup->typrelid, newTypeName, false);
3286  else
3287  RenameTypeInternal(typeOid, newTypeName,
3288  typTup->typnamespace);
3289 
3290  ObjectAddressSet(address, TypeRelationId, typeOid);
3291  /* Clean up */
3293 
3294  return address;
3295 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
void RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
Definition: tablecmds.c:2966
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
ObjectType renameType
Definition: parsenodes.h:2825
Oid GetUserId(void)
Definition: miscinit.c:284
#define castNode(_type_, nodeptr)
Definition: nodes.h:581
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2545
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1820
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
char * newname
Definition: parsenodes.h:2831
unsigned int Oid
Definition: postgres_ext.h:31
bool pg_type_ownercheck(Oid type_oid, Oid roleid)
Definition: aclchk.c:4630
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:586
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3515
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
Node * object
Definition: parsenodes.h:2828
#define ereport(elevel, rest)
Definition: elog.h:122
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:692
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274