PostgreSQL Source Code  git master
typecmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/heap.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_am.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_constraint_fn.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_enum.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_proc_fn.h"
#include "catalog/pg_range.h"
#include "catalog/pg_type.h"
#include "catalog/pg_type_fn.h"
#include "commands/defrem.h"
#include "commands/tablecmds.h"
#include "commands/typecmds.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "optimizer/var.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/ruleutils.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for typecmds.c:

Go to the source code of this file.

Data Structures

struct  RelToCheck
 

Functions

static void makeRangeConstructors (const char *name, Oid namespace, Oid rangeOid, Oid subtype)
 
static Oid findTypeInputFunction (List *procname, Oid typeOid)
 
static Oid findTypeOutputFunction (List *procname, Oid typeOid)
 
static Oid findTypeReceiveFunction (List *procname, Oid typeOid)
 
static Oid findTypeSendFunction (List *procname, Oid typeOid)
 
static Oid findTypeTypmodinFunction (List *procname)
 
static Oid findTypeTypmodoutFunction (List *procname)
 
static Oid findTypeAnalyzeFunction (List *procname, Oid typeOid)
 
static Oid findRangeSubOpclass (List *opcname, Oid subtype)
 
static Oid findRangeCanonicalFunction (List *procname, Oid typeOid)
 
static Oid findRangeSubtypeDiffFunction (List *procname, Oid subtype)
 
static void validateDomainConstraint (Oid domainoid, char *ccbin)
 
static Listget_rels_with_domain (Oid domainOid, LOCKMODE lockmode)
 
static void checkEnumOwner (HeapTuple tup)
 
static char * domainAddConstraint (Oid domainOid, Oid domainNamespace, Oid baseTypeOid, int typMod, Constraint *constr, const char *domainName, ObjectAddress *constrAddr)
 
static Nodereplace_domain_constraint_value (ParseState *pstate, ColumnRef *cref)
 
ObjectAddress DefineType (ParseState *pstate, List *names, List *parameters)
 
void RemoveTypeById (Oid typeOid)
 
ObjectAddress DefineDomain (CreateDomainStmt *stmt)
 
ObjectAddress DefineEnum (CreateEnumStmt *stmt)
 
ObjectAddress AlterEnum (AlterEnumStmt *stmt, bool isTopLevel)
 
ObjectAddress DefineRange (CreateRangeStmt *stmt)
 
Oid AssignTypeArrayOid (void)
 
ObjectAddress DefineCompositeType (RangeVar *typevar, List *coldeflist)
 
ObjectAddress AlterDomainDefault (List *names, Node *defaultRaw)
 
ObjectAddress AlterDomainNotNull (List *names, bool notNull)
 
ObjectAddress AlterDomainDropConstraint (List *names, const char *constrName, DropBehavior behavior, bool missing_ok)
 
ObjectAddress AlterDomainAddConstraint (List *names, Node *newConstraint, ObjectAddress *constrAddr)
 
ObjectAddress AlterDomainValidateConstraint (List *names, const char *constrName)
 
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)
 

Variables

Oid binary_upgrade_next_array_pg_type_oid = InvalidOid
 

Function Documentation

◆ AlterDomainAddConstraint()

ObjectAddress AlterDomainAddConstraint ( List names,
Node newConstraint,
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:547
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:853
#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:547
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4265
#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:547
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:5275
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:547
#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:547
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:3153
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:576
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:576
#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:12726
#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:547
#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:576
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:9993
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:576
#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:576
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

◆ checkEnumOwner()

static void checkEnumOwner ( HeapTuple  tup)
static

Definition at line 1348 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_ENUM.

Referenced by AlterEnum().

1349 {
1350  Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
1351 
1352  /* Check that this is actually an enum */
1353  if (typTup->typtype != TYPTYPE_ENUM)
1354  ereport(ERROR,
1355  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1356  errmsg("%s is not an enum",
1358 
1359  /* Permission check: must own type */
1362 }
#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 TYPTYPE_ENUM
Definition: pg_type.h:723
#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:576
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:505
#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:283
#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:576
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:284
#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:949
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:4265
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:576
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:949
#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:283
#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:576
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:949
#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:670
#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:442
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:283
#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:576
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:949
#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:5539
#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:670
#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

◆ domainAddConstraint()

static char * domainAddConstraint ( Oid  domainOid,
Oid  domainNamespace,
Oid  baseTypeOid,
int  typMod,
Constraint constr,
const char *  domainName,
ObjectAddress constrAddr 
)
static

Definition at line 3061 of file typecmds.c.

References assign_expr_collations(), ChooseConstraintName(), coerce_to_boolean(), CoerceToDomainValue::collation, Constraint::conname, CONSTRAINT_CHECK, CONSTRAINT_DOMAIN, ConstraintNameIsUsed(), ConstraintRelationId, contain_var_clause(), CreateConstraintEntry(), deparse_expression(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, EXPR_KIND_DOMAIN_CHECK, get_typcollation(), InvalidOid, list_length(), CoerceToDomainValue::location, make_parsestate(), makeNode, NIL, nodeToString(), ObjectAddressSet, ParseState::p_pre_columnref_hook, ParseState::p_ref_hook_state, ParseState::p_rtable, Constraint::raw_expr, replace_domain_constraint_value(), Constraint::skip_validation, transformExpr(), CoerceToDomainValue::typeId, and CoerceToDomainValue::typeMod.

Referenced by AlterDomainAddConstraint(), and DefineDomain().

3064 {
3065  Node *expr;
3066  char *ccsrc;
3067  char *ccbin;
3068  ParseState *pstate;
3069  CoerceToDomainValue *domVal;
3070  Oid ccoid;
3071 
3072  /*
3073  * Assign or validate constraint name
3074  */
3075  if (constr->conname)
3076  {
3078  domainOid,
3079  domainNamespace,
3080  constr->conname))
3081  ereport(ERROR,
3083  errmsg("constraint \"%s\" for domain \"%s\" already exists",
3084  constr->conname, domainName)));
3085  }
3086  else
3087  constr->conname = ChooseConstraintName(domainName,
3088  NULL,
3089  "check",
3090  domainNamespace,
3091  NIL);
3092 
3093  /*
3094  * Convert the A_EXPR in raw_expr into an EXPR
3095  */
3096  pstate = make_parsestate(NULL);
3097 
3098  /*
3099  * Set up a CoerceToDomainValue to represent the occurrence of VALUE in
3100  * the expression. Note that it will appear to have the type of the base
3101  * type, not the domain. This seems correct since within the check
3102  * expression, we should not assume the input value can be considered a
3103  * member of the domain.
3104  */
3105  domVal = makeNode(CoerceToDomainValue);
3106  domVal->typeId = baseTypeOid;
3107  domVal->typeMod = typMod;
3108  domVal->collation = get_typcollation(baseTypeOid);
3109  domVal->location = -1; /* will be set when/if used */
3110 
3112  pstate->p_ref_hook_state = (void *) domVal;
3113 
3114  expr = transformExpr(pstate, constr->raw_expr, EXPR_KIND_DOMAIN_CHECK);
3115 
3116  /*
3117  * Make sure it yields a boolean result.
3118  */
3119  expr = coerce_to_boolean(pstate, expr, "CHECK");
3120 
3121  /*
3122  * Fix up collation information.
3123  */
3124  assign_expr_collations(pstate, expr);
3125 
3126  /*
3127  * Domains don't allow variables (this is probably dead code now that
3128  * add_missing_from is history, but let's be sure).
3129  */
3130  if (list_length(pstate->p_rtable) != 0 ||
3131  contain_var_clause(expr))
3132  ereport(ERROR,
3133  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
3134  errmsg("cannot use table references in domain check constraint")));
3135 
3136  /*
3137  * Convert to string form for storage.
3138  */
3139  ccbin = nodeToString(expr);
3140 
3141  /*
3142  * Deparse it to produce text for consrc.
3143  */
3144  ccsrc = deparse_expression(expr,
3145  NIL, false, false);
3146 
3147  /*
3148  * Store the constraint in pg_constraint
3149  */
3150  ccoid =
3151  CreateConstraintEntry(constr->conname, /* Constraint Name */
3152  domainNamespace, /* namespace */
3153  CONSTRAINT_CHECK, /* Constraint Type */
3154  false, /* Is Deferrable */
3155  false, /* Is Deferred */
3156  !constr->skip_validation, /* Is Validated */
3157  InvalidOid, /* not a relation constraint */
3158  NULL,
3159  0,
3160  domainOid, /* domain constraint */
3161  InvalidOid, /* no associated index */
3162  InvalidOid, /* Foreign key fields */
3163  NULL,
3164  NULL,
3165  NULL,
3166  NULL,
3167  0,
3168  ' ',
3169  ' ',
3170  ' ',
3171  NULL, /* not an exclusion constraint */
3172  expr, /* Tree form of check constraint */
3173  ccbin, /* Binary form of check constraint */
3174  ccsrc, /* Source form of check constraint */
3175  true, /* is local */
3176  0, /* inhcount */
3177  false, /* connoinherit */
3178  false); /* is_internal */
3179  if (constrAddr)
3180  ObjectAddressSet(*constrAddr, ConstraintRelationId, ccoid);
3181 
3182  /*
3183  * Return the compiled constraint expression so the calling routine can
3184  * perform any additional required tests.
3185  */
3186  return ccbin;
3187 }
#define NIL
Definition: pg_list.h:69
char * ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
static Node * replace_domain_constraint_value(ParseState *pstate, ColumnRef *cref)
Definition: typecmds.c:3191
Node * raw_expr
Definition: parsenodes.h:2102
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:146
Definition: nodes.h:512
int errcode(int sqlerrcode)
Definition: elog.c:575
bool contain_var_clause(Node *node)
Definition: var.c:331
char * conname
Definition: parsenodes.h:2095
unsigned int Oid
Definition: postgres_ext.h:31
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
void assign_expr_collations(ParseState *pstate, Node *expr)
#define CONSTRAINT_CHECK
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidOid
Definition: postgres_ext.h:36
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2814
#define makeNode(_type_)
Definition: nodes.h:560
void * p_ref_hook_state
Definition: parse_node.h:215
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 ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, Oid objNamespace, const char *conname)
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * nodeToString(const void *obj)
Definition: outfuncs.c:4265
#define ConstraintRelationId
Definition: pg_constraint.h:29
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:211
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
bool skip_validation
Definition: parsenodes.h:2132
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid relId, const int16 *constraintKey, int constraintNKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, const char *conSrc, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
Definition: pg_constraint.c:49
List * p_rtable
Definition: parse_node.h:173
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)

◆ findRangeCanonicalFunction()

static Oid findRangeCanonicalFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 2010 of file typecmds.c.

References ACL_EXECUTE, ACL_KIND_PROC, aclcheck_error(), ACLCHECK_OK, ereport, errcode(), errmsg(), ERROR, func_signature_string(), func_volatile(), get_func_name(), get_func_rettype(), GetUserId(), LookupFuncName(), NIL, OidIsValid, pg_proc_aclcheck(), and PROVOLATILE_IMMUTABLE.

Referenced by DefineRange().

2011 {
2012  Oid argList[1];
2013  Oid procOid;
2014  AclResult aclresult;
2015 
2016  /*
2017  * Range canonical functions must take and return the range type, and must
2018  * be immutable.
2019  */
2020  argList[0] = typeOid;
2021 
2022  procOid = LookupFuncName(procname, 1, argList, true);
2023 
2024  if (!OidIsValid(procOid))
2025  ereport(ERROR,
2026  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2027  errmsg("function %s does not exist",
2028  func_signature_string(procname, 1, NIL, argList))));
2029 
2030  if (get_func_rettype(procOid) != typeOid)
2031  ereport(ERROR,
2032  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2033  errmsg("range canonical function %s must return range type",
2034  func_signature_string(procname, 1, NIL, argList))));
2035 
2036  if (func_volatile(procOid) != PROVOLATILE_IMMUTABLE)
2037  ereport(ERROR,
2038  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2039  errmsg("range canonical function %s must be immutable",
2040  func_signature_string(procname, 1, NIL, argList))));
2041 
2042  /* Also, range type's creator must have permission to call function */
2043  aclresult = pg_proc_aclcheck(procOid, GetUserId(), ACL_EXECUTE);
2044  if (aclresult != ACLCHECK_OK)
2045  aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(procOid));
2046 
2047  return procOid;
2048 }
#define NIL
Definition: pg_list.h:69
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5537
Oid GetUserId(void)
Definition: miscinit.c:284
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1459
#define ERROR
Definition: elog.h:43
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1412
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define ereport(elevel, rest)
Definition: elog.h:122
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1931
AclResult
Definition: acl.h:178
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1952
char func_volatile(Oid funcid)
Definition: lsyscache.c:1584
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_EXECUTE
Definition: parsenodes.h:79
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4504

◆ findRangeSubOpclass()

static Oid findRangeSubOpclass ( List opcname,
Oid  subtype 
)
static

Definition at line 1971 of file typecmds.c.

References BTREE_AM_OID, ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), get_opclass_input_type(), get_opclass_oid(), GetDefaultOpClass(), IsBinaryCoercible(), NameListToString(), NIL, and OidIsValid.

Referenced by DefineRange().

1972 {
1973  Oid opcid;
1974  Oid opInputType;
1975 
1976  if (opcname != NIL)
1977  {
1978  opcid = get_opclass_oid(BTREE_AM_OID, opcname, false);
1979 
1980  /*
1981  * Verify that the operator class accepts this datatype. Note we will
1982  * accept binary compatibility.
1983  */
1984  opInputType = get_opclass_input_type(opcid);
1985  if (!IsBinaryCoercible(subtype, opInputType))
1986  ereport(ERROR,
1987  (errcode(ERRCODE_DATATYPE_MISMATCH),
1988  errmsg("operator class \"%s\" does not accept data type %s",
1989  NameListToString(opcname),
1990  format_type_be(subtype))));
1991  }
1992  else
1993  {
1994  opcid = GetDefaultOpClass(subtype, BTREE_AM_OID);
1995  if (!OidIsValid(opcid))
1996  {
1997  /* We spell the error message identically to GetIndexOpClass */
1998  ereport(ERROR,
1999  (errcode(ERRCODE_UNDEFINED_OBJECT),
2000  errmsg("data type %s has no default operator class for access method \"%s\"",
2001  format_type_be(subtype), "btree"),
2002  errhint("You must specify an operator class for the range type or define a default operator class for the subtype.")));
2003  }
2004  }
2005 
2006  return opcid;
2007 }
#define NIL
Definition: pg_list.h:69
int errhint(const char *fmt,...)
Definition: elog.c:987
Oid GetDefaultOpClass(Oid type_id, Oid am_id)
Definition: indexcmds.c:1407
#define BTREE_AM_OID
Definition: pg_am.h:70
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok)
Definition: opclasscmds.c:221
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool IsBinaryCoercible(Oid srctype, Oid targettype)
char * NameListToString(List *names)
Definition: namespace.c:3063
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid get_opclass_input_type(Oid opclass)
Definition: lsyscache.c:1069

◆ findRangeSubtypeDiffFunction()

static Oid findRangeSubtypeDiffFunction ( List procname,
Oid  subtype 
)
static

Definition at line 2051 of file typecmds.c.

References ACL_EXECUTE, ACL_KIND_PROC, aclcheck_error(), ACLCHECK_OK, ereport, errcode(), errmsg(), ERROR, FLOAT8OID, func_signature_string(), func_volatile(), get_func_name(), get_func_rettype(), GetUserId(), LookupFuncName(), NIL, OidIsValid, pg_proc_aclcheck(), and PROVOLATILE_IMMUTABLE.

Referenced by DefineRange().

2052 {
2053  Oid argList[2];
2054  Oid procOid;
2055  AclResult aclresult;
2056 
2057  /*
2058  * Range subtype diff functions must take two arguments of the subtype,
2059  * must return float8, and must be immutable.
2060  */
2061  argList[0] = subtype;
2062  argList[1] = subtype;
2063 
2064  procOid = LookupFuncName(procname, 2, argList, true);
2065 
2066  if (!OidIsValid(procOid))
2067  ereport(ERROR,
2068  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2069  errmsg("function %s does not exist",
2070  func_signature_string(procname, 2, NIL, argList))));
2071 
2072  if (get_func_rettype(procOid) != FLOAT8OID)
2073  ereport(ERROR,
2074  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2075  errmsg("range subtype diff function %s must return type %s",
2076  func_signature_string(procname, 2, NIL, argList),
2077  "double precision")));
2078 
2079  if (func_volatile(procOid) != PROVOLATILE_IMMUTABLE)
2080  ereport(ERROR,
2081  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2082  errmsg("range subtype diff function %s must be immutable",
2083  func_signature_string(procname, 2, NIL, argList))));
2084 
2085  /* Also, range type's creator must have permission to call function */
2086  aclresult = pg_proc_aclcheck(procOid, GetUserId(), ACL_EXECUTE);
2087  if (aclresult != ACLCHECK_OK)
2088  aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(procOid));
2089 
2090  return procOid;
2091 }
#define NIL
Definition: pg_list.h:69
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5537
Oid GetUserId(void)
Definition: miscinit.c:284
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1459
#define ERROR
Definition: elog.h:43
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1412
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
#define ereport(elevel, rest)
Definition: elog.h:122
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1931
AclResult
Definition: acl.h:178
#define FLOAT8OID
Definition: pg_type.h:419
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1952
char func_volatile(Oid funcid)
Definition: lsyscache.c:1584
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_EXECUTE
Definition: parsenodes.h:79
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4504

◆ findTypeAnalyzeFunction()

static Oid findTypeAnalyzeFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1936 of file typecmds.c.

References BOOLOID, ereport, errcode(), errmsg(), ERROR, func_signature_string(), get_func_rettype(), INTERNALOID, LookupFuncName(), NameListToString(), NIL, and OidIsValid.

Referenced by DefineType().

1937 {
1938  Oid argList[1];
1939  Oid procOid;
1940 
1941  /*
1942  * Analyze functions always take one INTERNAL argument and return bool.
1943  */
1944  argList[0] = INTERNALOID;
1945 
1946  procOid = LookupFuncName(procname, 1, argList, true);
1947  if (!OidIsValid(procOid))
1948  ereport(ERROR,
1949  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1950  errmsg("function %s does not exist",
1951  func_signature_string(procname, 1, NIL, argList))));
1952 
1953  if (get_func_rettype(procOid) != BOOLOID)
1954  ereport(ERROR,
1955  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1956  errmsg("type analyze function %s must return type %s",
1957  NameListToString(procname), "boolean")));
1958 
1959  return procOid;
1960 }
#define NIL
Definition: pg_list.h:69
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1459
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1931
char * NameListToString(List *names)
Definition: namespace.c:3063
#define INTERNALOID
Definition: pg_type.h:698
#define BOOLOID
Definition: pg_type.h:288
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1952
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ findTypeInputFunction()

static Oid findTypeInputFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1710 of file typecmds.c.

References CommandCounterIncrement(), CSTRINGOID, ereport, errcode(), errmsg(), ERROR, func_signature_string(), INT4OID, InvalidOid, LookupFuncName(), NameListToString(), NIL, OidIsValid, OIDOID, OPAQUEOID, SetFunctionArgType(), and WARNING.

Referenced by DefineType().

1711 {
1712  Oid argList[3];
1713  Oid procOid;
1714 
1715  /*
1716  * Input functions can take a single argument of type CSTRING, or three
1717  * arguments (string, typioparam OID, typmod).
1718  *
1719  * For backwards compatibility we allow OPAQUE in place of CSTRING; if we
1720  * see this, we issue a warning and fix up the pg_proc entry.
1721  */
1722  argList[0] = CSTRINGOID;
1723 
1724  procOid = LookupFuncName(procname, 1, argList, true);
1725  if (OidIsValid(procOid))
1726  return procOid;
1727 
1728  argList[1] = OIDOID;
1729  argList[2] = INT4OID;
1730 
1731  procOid = LookupFuncName(procname, 3, argList, true);
1732  if (OidIsValid(procOid))
1733  return procOid;
1734 
1735  /* No luck, try it with OPAQUE */
1736  argList[0] = OPAQUEOID;
1737 
1738  procOid = LookupFuncName(procname, 1, argList, true);
1739 
1740  if (!OidIsValid(procOid))
1741  {
1742  argList[1] = OIDOID;
1743  argList[2] = INT4OID;
1744 
1745  procOid = LookupFuncName(procname, 3, argList, true);
1746  }
1747 
1748  if (OidIsValid(procOid))
1749  {
1750  /* Found, but must complain and fix the pg_proc entry */
1751  ereport(WARNING,
1752  (errmsg("changing argument type of function %s from \"opaque\" to \"cstring\"",
1753  NameListToString(procname))));
1754  SetFunctionArgType(procOid, 0, CSTRINGOID);
1755 
1756  /*
1757  * Need CommandCounterIncrement since DefineType will likely try to
1758  * alter the pg_proc tuple again.
1759  */
1761 
1762  return procOid;
1763  }
1764 
1765  /* Use CSTRING (preferred) in the error message */
1766  argList[0] = CSTRINGOID;
1767 
1768  ereport(ERROR,
1769  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1770  errmsg("function %s does not exist",
1771  func_signature_string(procname, 1, NIL, argList))));
1772 
1773  return InvalidOid; /* keep compiler quiet */
1774 }
#define NIL
Definition: pg_list.h:69
#define OIDOID
Definition: pg_type.h:328
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define OPAQUEOID
Definition: pg_type.h:700
#define ERROR
Definition: elog.h:43
void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
#define ereport(elevel, rest)
Definition: elog.h:122
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1931
#define WARNING
Definition: elog.h:40
char * NameListToString(List *names)
Definition: namespace.c:3063
void CommandCounterIncrement(void)
Definition: xact.c:915
#define InvalidOid
Definition: postgres_ext.h:36
#define CSTRINGOID
Definition: pg_type.h:684
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1952
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ findTypeOutputFunction()

static Oid findTypeOutputFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1777 of file typecmds.c.

References CommandCounterIncrement(), ereport, errcode(), errmsg(), ERROR, format_type_be(), func_signature_string(), InvalidOid, LookupFuncName(), NameListToString(), NIL, OidIsValid, OPAQUEOID, SetFunctionArgType(), and WARNING.

Referenced by DefineType().

1778 {
1779  Oid argList[1];
1780  Oid procOid;
1781 
1782  /*
1783  * Output functions can take a single argument of the type.
1784  *
1785  * For backwards compatibility we allow OPAQUE in place of the actual type
1786  * name; if we see this, we issue a warning and fix up the pg_proc entry.
1787  */
1788  argList[0] = typeOid;
1789 
1790  procOid = LookupFuncName(procname, 1, argList, true);
1791  if (OidIsValid(procOid))
1792  return procOid;
1793 
1794  /* No luck, try it with OPAQUE */
1795  argList[0] = OPAQUEOID;
1796 
1797  procOid = LookupFuncName(procname, 1, argList, true);
1798 
1799  if (OidIsValid(procOid))
1800  {
1801  /* Found, but must complain and fix the pg_proc entry */
1802  ereport(WARNING,
1803  (errmsg("changing argument type of function %s from \"opaque\" to %s",
1804  NameListToString(procname), format_type_be(typeOid))));
1805  SetFunctionArgType(procOid, 0, typeOid);
1806 
1807  /*
1808  * Need CommandCounterIncrement since DefineType will likely try to
1809  * alter the pg_proc tuple again.
1810  */
1812 
1813  return procOid;
1814  }
1815 
1816  /* Use type name, not OPAQUE, in the failure message. */
1817  argList[0] = typeOid;
1818 
1819  ereport(ERROR,
1820  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1821  errmsg("function %s does not exist",
1822  func_signature_string(procname, 1, NIL, argList))));
1823 
1824  return InvalidOid; /* keep compiler quiet */
1825 }
#define NIL
Definition: pg_list.h:69
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define OPAQUEOID
Definition: pg_type.h:700
#define ERROR
Definition: elog.h:43
void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
#define ereport(elevel, rest)
Definition: elog.h:122
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1931
#define WARNING
Definition: elog.h:40
char * NameListToString(List *names)
Definition: namespace.c:3063
void CommandCounterIncrement(void)
Definition: xact.c:915
#define InvalidOid
Definition: postgres_ext.h:36
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1952
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ findTypeReceiveFunction()

static Oid findTypeReceiveFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1828 of file typecmds.c.

References ereport, errcode(), errmsg(), ERROR, func_signature_string(), INT4OID, INTERNALOID, InvalidOid, LookupFuncName(), NIL, OidIsValid, and OIDOID.

Referenced by DefineType().

1829 {
1830  Oid argList[3];
1831  Oid procOid;
1832 
1833  /*
1834  * Receive functions can take a single argument of type INTERNAL, or three
1835  * arguments (internal, typioparam OID, typmod).
1836  */
1837  argList[0] = INTERNALOID;
1838 
1839  procOid = LookupFuncName(procname, 1, argList, true);
1840  if (OidIsValid(procOid))
1841  return procOid;
1842 
1843  argList[1] = OIDOID;
1844  argList[2] = INT4OID;
1845 
1846  procOid = LookupFuncName(procname, 3, argList, true);
1847  if (OidIsValid(procOid))
1848  return procOid;
1849 
1850  ereport(ERROR,
1851  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1852  errmsg("function %s does not exist",
1853  func_signature_string(procname, 1, NIL, argList))));
1854 
1855  return InvalidOid; /* keep compiler quiet */
1856 }
#define NIL
Definition: pg_list.h:69
#define OIDOID
Definition: pg_type.h:328
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1931
#define InvalidOid
Definition: postgres_ext.h:36
#define INTERNALOID
Definition: pg_type.h:698
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1952
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ findTypeSendFunction()

static Oid findTypeSendFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1859 of file typecmds.c.

References ereport, errcode(), errmsg(), ERROR, func_signature_string(), InvalidOid, LookupFuncName(), NIL, and OidIsValid.

Referenced by DefineType().

1860 {
1861  Oid argList[1];
1862  Oid procOid;
1863 
1864  /*
1865  * Send functions can take a single argument of the type.
1866  */
1867  argList[0] = typeOid;
1868 
1869  procOid = LookupFuncName(procname, 1, argList, true);
1870  if (OidIsValid(procOid))
1871  return procOid;
1872 
1873  ereport(ERROR,
1874  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1875  errmsg("function %s does not exist",
1876  func_signature_string(procname, 1, NIL, argList))));
1877 
1878  return InvalidOid; /* keep compiler quiet */
1879 }
#define NIL
Definition: pg_list.h:69
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1931
#define InvalidOid
Definition: postgres_ext.h:36
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1952
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ findTypeTypmodinFunction()

static Oid findTypeTypmodinFunction ( List procname)
static

Definition at line 1882 of file typecmds.c.

References CSTRINGARRAYOID, ereport, errcode(), errmsg(), ERROR, func_signature_string(), get_func_rettype(), INT4OID, LookupFuncName(), NameListToString(), NIL, and OidIsValid.

Referenced by DefineType().

1883 {
1884  Oid argList[1];
1885  Oid procOid;
1886 
1887  /*
1888  * typmodin functions always take one cstring[] argument and return int4.
1889  */
1890  argList[0] = CSTRINGARRAYOID;
1891 
1892  procOid = LookupFuncName(procname, 1, argList, true);
1893  if (!OidIsValid(procOid))
1894  ereport(ERROR,
1895  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1896  errmsg("function %s does not exist",
1897  func_signature_string(procname, 1, NIL, argList))));
1898 
1899  if (get_func_rettype(procOid) != INT4OID)
1900  ereport(ERROR,
1901  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1902  errmsg("typmod_in function %s must return type %s",
1903  NameListToString(procname), "integer")));
1904 
1905  return procOid;
1906 }
#define NIL
Definition: pg_list.h:69
#define CSTRINGARRAYOID
Definition: pg_type.h:500
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1459
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1931
char * NameListToString(List *names)
Definition: namespace.c:3063
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1952
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ findTypeTypmodoutFunction()

static Oid findTypeTypmodoutFunction ( List procname)
static

Definition at line 1909 of file typecmds.c.

References CSTRINGOID, ereport, errcode(), errmsg(), ERROR, func_signature_string(), get_func_rettype(), INT4OID, LookupFuncName(), NameListToString(), NIL, and OidIsValid.

Referenced by DefineType().

1910 {
1911  Oid argList[1];
1912  Oid procOid;
1913 
1914  /*
1915  * typmodout functions always take one int4 argument and return cstring.
1916  */
1917  argList[0] = INT4OID;
1918 
1919  procOid = LookupFuncName(procname, 1, argList, true);
1920  if (!OidIsValid(procOid))
1921  ereport(ERROR,
1922  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1923  errmsg("function %s does not exist",
1924  func_signature_string(procname, 1, NIL, argList))));
1925 
1926  if (get_func_rettype(procOid) != CSTRINGOID)
1927  ereport(ERROR,
1928  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1929  errmsg("typmod_out function %s must return type %s",
1930  NameListToString(procname), "cstring")));
1931 
1932  return procOid;
1933 }
#define NIL
Definition: pg_list.h:69
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:576
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1459
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1931
char * NameListToString(List *names)
Definition: namespace.c:3063
#define CSTRINGOID
Definition: pg_type.h:684
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1952
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ get_rels_with_domain()

static List * get_rels_with_domain ( Oid  domainOid,
LOCKMODE  lockmode 
)
static

Definition at line 2872 of file typecmds.c.

References AccessShareLock, Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, Assert, RelToCheck::atts, BTEqualStrategyNumber, check_stack_depth(), DependReferenceIndexId, DependRelationId, find_composite_type_dependencies(), format_type_be(), get_typtype(), GETSTRUCT, heap_open(), HeapTupleIsValid, lcons(), lfirst, list_concat(), RelToCheck::natts, NIL, NoLock, ObjectIdGetDatum, OidIsValid, palloc(), RelationData::rd_att, RelationData::rd_rel, RelToCheck::rel, relation_close(), relation_open(), RelationGetNumberOfAttributes, RelationGetRelid, RelationRelationId, RELKIND_MATVIEW, RELKIND_RELATION, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), TupleDescAttr, TypeRelationId, and TYPTYPE_DOMAIN.

Referenced by AlterDomainNotNull(), and validateDomainConstraint().

2873 {
2874  List *result = NIL;
2875  char *domainTypeName = format_type_be(domainOid);
2876  Relation depRel;
2877  ScanKeyData key[2];
2878  SysScanDesc depScan;
2879  HeapTuple depTup;
2880 
2881  Assert(lockmode != NoLock);
2882 
2883  /* since this function recurses, it could be driven to stack overflow */
2885 
2886  /*
2887  * We scan pg_depend to find those things that depend on the domain. (We
2888  * assume we can ignore refobjsubid for a domain.)
2889  */
2891 
2892  ScanKeyInit(&key[0],
2894  BTEqualStrategyNumber, F_OIDEQ,
2896  ScanKeyInit(&key[1],
2898  BTEqualStrategyNumber, F_OIDEQ,
2899  ObjectIdGetDatum(domainOid));
2900 
2901  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
2902  NULL, 2, key);
2903 
2904  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2905  {
2906  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2907  RelToCheck *rtc = NULL;
2908  ListCell *rellist;
2909  Form_pg_attribute pg_att;
2910  int ptr;
2911 
2912  /* Check for directly dependent types */
2913  if (pg_depend->classid == TypeRelationId)
2914  {
2915  if (get_typtype(pg_depend->objid) == TYPTYPE_DOMAIN)
2916  {
2917  /*
2918  * This is a sub-domain, so recursively add dependent columns
2919  * to the output list. This is a bit inefficient since we may
2920  * fail to combine RelToCheck entries when attributes of the
2921  * same rel have different derived domain types, but it's
2922  * probably not worth improving.
2923  */
2924  result = list_concat(result,
2925  get_rels_with_domain(pg_depend->objid,
2926  lockmode));
2927  }
2928  else
2929  {
2930  /*
2931  * Otherwise, it is some container type using the domain, so
2932  * fail if there are any columns of this type.
2933  */
2934  find_composite_type_dependencies(pg_depend->objid,
2935  NULL,
2936  domainTypeName);
2937  }
2938  continue;
2939  }
2940 
2941  /* Else, ignore dependees that aren't user columns of relations */
2942  /* (we assume system columns are never of domain types) */
2943  if (pg_depend->classid != RelationRelationId ||
2944  pg_depend->objsubid <= 0)