PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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, 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, 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

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

Definition at line 2540 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 ProcessUtilitySlow().

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

Definition at line 2195 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().

2196 {
2197  TypeName *typename;
2198  Oid domainoid;
2199  HeapTuple tup;
2200  ParseState *pstate;
2201  Relation rel;
2202  char *defaultValue;
2203  Node *defaultExpr = NULL; /* NULL if no default specified */
2204  Datum new_record[Natts_pg_type];
2205  bool new_record_nulls[Natts_pg_type];
2206  bool new_record_repl[Natts_pg_type];
2207  HeapTuple newtuple;
2208  Form_pg_type typTup;
2209  ObjectAddress address;
2210 
2211  /* Make a TypeName so we can use standard type lookup machinery */
2212  typename = makeTypeNameFromNameList(names);
2213  domainoid = typenameTypeId(NULL, typename);
2214 
2215  /* Look up the domain in the type table */
2217 
2218  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2219  if (!HeapTupleIsValid(tup))
2220  elog(ERROR, "cache lookup failed for type %u", domainoid);
2221  typTup = (Form_pg_type) GETSTRUCT(tup);
2222 
2223  /* Check it's a domain and check user has permission for ALTER DOMAIN */
2224  checkDomainOwner(tup);
2225 
2226  /* Setup new tuple */
2227  MemSet(new_record, (Datum) 0, sizeof(new_record));
2228  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
2229  MemSet(new_record_repl, false, sizeof(new_record_repl));
2230 
2231  /* Store the new default into the tuple */
2232  if (defaultRaw)
2233  {
2234  /* Create a dummy ParseState for transformExpr */
2235  pstate = make_parsestate(NULL);
2236 
2237  /*
2238  * Cook the colDef->raw_expr into an expression. Note: Name is
2239  * strictly for error message
2240  */
2241  defaultExpr = cookDefault(pstate, defaultRaw,
2242  typTup->typbasetype,
2243  typTup->typtypmod,
2244  NameStr(typTup->typname));
2245 
2246  /*
2247  * If the expression is just a NULL constant, we treat the command
2248  * like ALTER ... DROP DEFAULT. (But see note for same test in
2249  * DefineDomain.)
2250  */
2251  if (defaultExpr == NULL ||
2252  (IsA(defaultExpr, Const) &&((Const *) defaultExpr)->constisnull))
2253  {
2254  /* Default is NULL, drop it */
2255  new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true;
2256  new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
2257  new_record_nulls[Anum_pg_type_typdefault - 1] = true;
2258  new_record_repl[Anum_pg_type_typdefault - 1] = true;
2259  }
2260  else
2261  {
2262  /*
2263  * Expression must be stored as a nodeToString result, but we also
2264  * require a valid textual representation (mainly to make life
2265  * easier for pg_dump).
2266  */
2267  defaultValue = deparse_expression(defaultExpr,
2268  NIL, false, false);
2269 
2270  /*
2271  * Form an updated tuple with the new default and write it back.
2272  */
2273  new_record[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(nodeToString(defaultExpr));
2274 
2275  new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
2276  new_record[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultValue);
2277  new_record_repl[Anum_pg_type_typdefault - 1] = true;
2278  }
2279  }
2280  else
2281  {
2282  /* ALTER ... DROP DEFAULT */
2283  new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true;
2284  new_record_repl[Anum_pg_type_typdefaultbin - 1] = true;
2285  new_record_nulls[Anum_pg_type_typdefault - 1] = true;
2286  new_record_repl[Anum_pg_type_typdefault - 1] = true;
2287  }
2288 
2289  newtuple = heap_modify_tuple(tup, RelationGetDescr(rel),
2290  new_record, new_record_nulls,
2291  new_record_repl);
2292 
2293  CatalogTupleUpdate(rel, &tup->t_self, newtuple);
2294 
2295  /* Rebuild dependencies */
2296  GenerateTypeDependencies(typTup->typnamespace,
2297  domainoid,
2298  InvalidOid, /* typrelid is n/a */
2299  0, /* relation kind is n/a */
2300  typTup->typowner,
2301  typTup->typinput,
2302  typTup->typoutput,
2303  typTup->typreceive,
2304  typTup->typsend,
2305  typTup->typmodin,
2306  typTup->typmodout,
2307  typTup->typanalyze,
2308  InvalidOid,
2309  false, /* a domain isn't an implicit array */
2310  typTup->typbasetype,
2311  typTup->typcollation,
2312  defaultExpr,
2313  true); /* Rebuild is true */
2314 
2316 
2317  ObjectAddressSet(address, TypeRelationId, domainoid);
2318 
2319  /* Clean up */
2320  heap_close(rel, NoLock);
2321  heap_freetuple(newtuple);
2322 
2323  return address;
2324 }
#define NIL
Definition: pg_list.h:69
#define Anum_pg_type_typdefaultbin
Definition: pg_type.h:267
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, char *attname)
Definition: heap.c:2657
#define RelationGetDescr(relation)
Definition: rel.h:428
Definition: nodes.h:510
#define MemSet(start, val, len)
Definition: c.h:863
#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
#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:2985
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:3038
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:453
#define NameStr(name)
Definition: c.h:493
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4259
#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
ObjectAddress AlterDomainDropConstraint ( List names,
const char *  constrName,
DropBehavior  behavior,
bool  missing_ok 
)

Definition at line 2450 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().

2452 {
2453  TypeName *typename;
2454  Oid domainoid;
2455  HeapTuple tup;
2456  Relation rel;
2457  Relation conrel;
2458  SysScanDesc conscan;
2459  ScanKeyData key[1];
2460  HeapTuple contup;
2461  bool found = false;
2463 
2464  /* Make a TypeName so we can use standard type lookup machinery */
2465  typename = makeTypeNameFromNameList(names);
2466  domainoid = typenameTypeId(NULL, typename);
2467 
2468  /* Look up the domain in the type table */
2470 
2471  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2472  if (!HeapTupleIsValid(tup))
2473  elog(ERROR, "cache lookup failed for type %u", domainoid);
2474 
2475  /* Check it's a domain and check user has permission for ALTER DOMAIN */
2476  checkDomainOwner(tup);
2477 
2478  /* Grab an appropriate lock on the pg_constraint relation */
2480 
2481  /* Use the index to scan only constraints of the target relation */
2482  ScanKeyInit(&key[0],
2484  BTEqualStrategyNumber, F_OIDEQ,
2486 
2487  conscan = systable_beginscan(conrel, ConstraintTypidIndexId, true,
2488  NULL, 1, key);
2489 
2490  /*
2491  * Scan over the result set, removing any matching entries.
2492  */
2493  while ((contup = systable_getnext(conscan)) != NULL)
2494  {
2496 
2497  if (strcmp(NameStr(con->conname), constrName) == 0)
2498  {
2499  ObjectAddress conobj;
2500 
2501  conobj.classId = ConstraintRelationId;
2502  conobj.objectId = HeapTupleGetOid(contup);
2503  conobj.objectSubId = 0;
2504 
2505  performDeletion(&conobj, behavior, 0);
2506  found = true;
2507  }
2508  }
2509 
2510  ObjectAddressSet(address, TypeRelationId, domainoid);
2511 
2512  /* Clean up after the scan */
2513  systable_endscan(conscan);
2514  heap_close(conrel, RowExclusiveLock);
2515 
2516  heap_close(rel, NoLock);
2517 
2518  if (!found)
2519  {
2520  if (!missing_ok)
2521  ereport(ERROR,
2522  (errcode(ERRCODE_UNDEFINED_OBJECT),
2523  errmsg("constraint \"%s\" of domain \"%s\" does not exist",
2524  constrName, TypeNameToString(typename))));
2525  else
2526  ereport(NOTICE,
2527  (errmsg("constraint \"%s\" of domain \"%s\" does not exist, skipping",
2528  constrName, TypeNameToString(typename))));
2529  }
2530 
2531  return address;
2532 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
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:3038
#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:453
#define NameStr(name)
Definition: c.h:493
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:695
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
ObjectAddress AlterDomainNotNull ( List names,
bool  notNull 
)

Definition at line 2334 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().

2335 {
2336  TypeName *typename;
2337  Oid domainoid;
2338  Relation typrel;
2339  HeapTuple tup;
2340  Form_pg_type typTup;
2342 
2343  /* Make a TypeName so we can use standard type lookup machinery */
2344  typename = makeTypeNameFromNameList(names);
2345  domainoid = typenameTypeId(NULL, typename);
2346 
2347  /* Look up the domain in the type table */
2349 
2350  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(domainoid));
2351  if (!HeapTupleIsValid(tup))
2352  elog(ERROR, "cache lookup failed for type %u", domainoid);
2353  typTup = (Form_pg_type) GETSTRUCT(tup);
2354 
2355  /* Check it's a domain and check user has permission for ALTER DOMAIN */
2356  checkDomainOwner(tup);
2357 
2358  /* Is the domain already set to the desired constraint? */
2359  if (typTup->typnotnull == notNull)
2360  {
2361  heap_close(typrel, RowExclusiveLock);
2362  return address;
2363  }
2364 
2365  /* Adding a NOT NULL constraint requires checking existing columns */
2366  if (notNull)
2367  {
2368  List *rels;
2369  ListCell *rt;
2370 
2371  /* Fetch relation list with attributes based on this domain */
2372  /* ShareLock is sufficient to prevent concurrent data changes */
2373 
2374  rels = get_rels_with_domain(domainoid, ShareLock);
2375 
2376  foreach(rt, rels)
2377  {
2378  RelToCheck *rtc = (RelToCheck *) lfirst(rt);
2379  Relation testrel = rtc->rel;
2380  TupleDesc tupdesc = RelationGetDescr(testrel);
2381  HeapScanDesc scan;
2382  HeapTuple tuple;
2383  Snapshot snapshot;
2384 
2385  /* Scan all tuples in this relation */
2386  snapshot = RegisterSnapshot(GetLatestSnapshot());
2387  scan = heap_beginscan(testrel, snapshot, 0, NULL);
2388  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2389  {
2390  int i;
2391 
2392  /* Test attributes that are of the domain */
2393  for (i = 0; i < rtc->natts; i++)
2394  {
2395  int attnum = rtc->atts[i];
2396  Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1);
2397 
2398  if (heap_attisnull(tuple, attnum))
2399  {
2400  /*
2401  * In principle the auxiliary information for this
2402  * error should be errdatatype(), but errtablecol()
2403  * seems considerably more useful in practice. Since
2404  * this code only executes in an ALTER DOMAIN command,
2405  * the client should already know which domain is in
2406  * question.
2407  */
2408  ereport(ERROR,
2409  (errcode(ERRCODE_NOT_NULL_VIOLATION),
2410  errmsg("column \"%s\" of table \"%s\" contains null values",
2411  NameStr(attr->attname),
2412  RelationGetRelationName(testrel)),
2413  errtablecol(testrel, attnum)));
2414  }
2415  }
2416  }
2417  heap_endscan(scan);
2418  UnregisterSnapshot(snapshot);
2419 
2420  /* Close each rel after processing, but keep lock */
2421  heap_close(testrel, NoLock);
2422  }
2423  }
2424 
2425  /*
2426  * Okay to update pg_type row. We can scribble on typTup because it's a
2427  * copy.
2428  */
2429  typTup->typnotnull = notNull;
2430 
2431  CatalogTupleUpdate(typrel, &tup->t_self, tup);
2432 
2434 
2435  ObjectAddressSet(address, TypeRelationId, domainoid);
2436 
2437  /* Clean up */
2438  heap_freetuple(tup);
2439  heap_close(typrel, RowExclusiveLock);
2440 
2441  return address;
2442 }
int * atts
Definition: typecmds.c:81
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:863
#define RelationGetDescr(relation)
Definition: rel.h:428
Relation rel
Definition: typecmds.c:79
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
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:436
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:2869
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:5272
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:3038
#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:453
#define NameStr(name)
Definition: c.h:493
#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
ObjectAddress AlterDomainValidateConstraint ( List names,
char *  constrName 
)

Definition at line 2649 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().

2650 {
2651  TypeName *typename;
2652  Oid domainoid;
2653  Relation typrel;
2654  Relation conrel;
2655  HeapTuple tup;
2656  Form_pg_constraint con = NULL;
2657  Form_pg_constraint copy_con;
2658  char *conbin;
2659  SysScanDesc scan;
2660  Datum val;
2661  bool found = false;
2662  bool isnull;
2663  HeapTuple tuple;
2664  HeapTuple copyTuple;
2665  ScanKeyData key;
2666  ObjectAddress address;
2667 
2668  /* Make a TypeName so we can use standard type lookup machinery */
2669  typename = makeTypeNameFromNameList(names);
2670  domainoid = typenameTypeId(NULL, typename);
2671 
2672  /* Look up the domain in the type table */
2674 
2675  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(domainoid));
2676  if (!HeapTupleIsValid(tup))
2677  elog(ERROR, "cache lookup failed for type %u", domainoid);
2678 
2679  /* Check it's a domain and check user has permission for ALTER DOMAIN */
2680  checkDomainOwner(tup);
2681 
2682  /*
2683  * Find and check the target constraint
2684  */
2686  ScanKeyInit(&key,
2688  BTEqualStrategyNumber, F_OIDEQ,
2689  ObjectIdGetDatum(domainoid));
2691  true, NULL, 1, &key);
2692 
2693  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2694  {
2695  con = (Form_pg_constraint) GETSTRUCT(tuple);
2696  if (strcmp(NameStr(con->conname), constrName) == 0)
2697  {
2698  found = true;
2699  break;
2700  }
2701  }
2702 
2703  if (!found)
2704  ereport(ERROR,
2705  (errcode(ERRCODE_UNDEFINED_OBJECT),
2706  errmsg("constraint \"%s\" of domain \"%s\" does not exist",
2707  constrName, TypeNameToString(typename))));
2708 
2709  if (con->contype != CONSTRAINT_CHECK)
2710  ereport(ERROR,
2711  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2712  errmsg("constraint \"%s\" of domain \"%s\" is not a check constraint",
2713  constrName, TypeNameToString(typename))));
2714 
2715  val = SysCacheGetAttr(CONSTROID, tuple,
2717  &isnull);
2718  if (isnull)
2719  elog(ERROR, "null conbin for constraint %u",
2720  HeapTupleGetOid(tuple));
2721  conbin = TextDatumGetCString(val);
2722 
2723  validateDomainConstraint(domainoid, conbin);
2724 
2725  /*
2726  * Now update the catalog, while we have the door open.
2727  */
2728  copyTuple = heap_copytuple(tuple);
2729  copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
2730  copy_con->convalidated = true;
2731  CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
2732 
2734  HeapTupleGetOid(copyTuple), 0);
2735 
2736  ObjectAddressSet(address, TypeRelationId, domainoid);
2737 
2738  heap_freetuple(copyTuple);
2739 
2740  systable_endscan(scan);
2741 
2742  heap_close(typrel, AccessShareLock);
2743  heap_close(conrel, RowExclusiveLock);
2744 
2745  ReleaseSysCache(tup);
2746 
2747  return address;
2748 }
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:656
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:3038
static void validateDomainConstraint(Oid domainoid, char *ccbin)
Definition: typecmds.c:2751
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:453
#define NameStr(name)
Definition: c.h:493
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:695
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
ObjectAddress AlterEnum ( AlterEnumStmt stmt,
bool  isTopLevel 
)

Definition at line 1276 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().

1277 {
1278  Oid enum_type_oid;
1279  TypeName *typename;
1280  HeapTuple tup;
1281  ObjectAddress address;
1282 
1283  /* Make a TypeName so we can use standard type lookup machinery */
1284  typename = makeTypeNameFromNameList(stmt->typeName);
1285  enum_type_oid = typenameTypeId(NULL, typename);
1286 
1287  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(enum_type_oid));
1288  if (!HeapTupleIsValid(tup))
1289  elog(ERROR, "cache lookup failed for type %u", enum_type_oid);
1290 
1291  /* Check it's an enum and check user has permission to ALTER the enum */
1292  checkEnumOwner(tup);
1293 
1294  if (stmt->oldVal)
1295  {
1296  /* Rename an existing label */
1297  RenameEnumLabel(enum_type_oid, stmt->oldVal, stmt->newVal);
1298  }
1299  else
1300  {
1301  /* Add a new label */
1302 
1303  /*
1304  * Ordinarily we disallow adding values within transaction blocks,
1305  * because we can't cope with enum OID values getting into indexes and
1306  * then having their defining pg_enum entries go away. However, it's
1307  * okay if the enum type was created in the current transaction, since
1308  * then there can be no such indexes that wouldn't themselves go away
1309  * on rollback. (We support this case because pg_dump
1310  * --binary-upgrade needs it.) We test this by seeing if the pg_type
1311  * row has xmin == current XID and is not HEAP_UPDATED. If it is
1312  * HEAP_UPDATED, we can't be sure whether the type was created or only
1313  * modified in this xact. So we are disallowing some cases that could
1314  * theoretically be safe; but fortunately pg_dump only needs the
1315  * simplest case.
1316  */
1318  !(tup->t_data->t_infomask & HEAP_UPDATED))
1319  /* safe to do inside transaction block */ ;
1320  else
1321  PreventTransactionChain(isTopLevel, "ALTER TYPE ... ADD");
1322 
1323  AddEnumLabel(enum_type_oid, stmt->newVal,
1324  stmt->newValNeighbor, stmt->newValIsAfter,
1325  stmt->skipIfNewValExists);
1326  }
1327 
1328  InvokeObjectPostAlterHook(TypeRelationId, enum_type_oid, 0);
1329 
1330  ObjectAddressSet(address, TypeRelationId, enum_type_oid);
1331 
1332  ReleaseSysCache(tup);
1333 
1334  return address;
1335 }
#define HEAP_UPDATED
Definition: htup_details.h:195
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:2982
static void checkEnumOwner(HeapTuple tup)
Definition: typecmds.c:1345
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
List * typeName
Definition: parsenodes.h:2979
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:2984
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
bool newValIsAfter
Definition: parsenodes.h:2983
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:453
#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
ObjectAddress AlterTypeNamespace ( List names,
const char *  newschema,
ObjectType  objecttype,
Oid oldschema 
)

Definition at line 3502 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().

3504 {
3505  TypeName *typename;
3506  Oid typeOid;
3507  Oid nspOid;
3508  Oid oldNspOid;
3509  ObjectAddresses *objsMoved;
3510  ObjectAddress myself;
3511 
3512  /* Make a TypeName so we can use standard type lookup machinery */
3513  typename = makeTypeNameFromNameList(names);
3514  typeOid = typenameTypeId(NULL, typename);
3515 
3516  /* Don't allow ALTER DOMAIN on a type */
3517  if (objecttype == OBJECT_DOMAIN && get_typtype(typeOid) != TYPTYPE_DOMAIN)
3518  ereport(ERROR,
3519  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3520  errmsg("%s is not a domain",
3521  format_type_be(typeOid))));
3522 
3523  /* get schema OID and check its permissions */
3524  nspOid = LookupCreationNamespace(newschema);
3525 
3526  objsMoved = new_object_addresses();
3527  oldNspOid = AlterTypeNamespace_oid(typeOid, nspOid, objsMoved);
3528  free_object_addresses(objsMoved);
3529 
3530  if (oldschema)
3531  *oldschema = oldNspOid;
3532 
3533  ObjectAddressSet(myself, TypeRelationId, typeOid);
3534 
3535  return myself;
3536 }
#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:2379
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2055
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2326
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:3539
#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:453
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
Oid AlterTypeNamespace_oid ( Oid  typeOid,
Oid  nspOid,
ObjectAddresses objsMoved 
)

Definition at line 3539 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().

3540 {
3541  Oid elemOid;
3542 
3543  /* check permissions on type */
3544  if (!pg_type_ownercheck(typeOid, GetUserId()))
3546 
3547  /* don't allow direct alteration of array types */
3548  elemOid = get_element_type(typeOid);
3549  if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid)
3550  ereport(ERROR,
3551  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3552  errmsg("cannot alter array type %s",
3553  format_type_be(typeOid)),
3554  errhint("You can alter type %s, which will alter the array type as well.",
3555  format_type_be(elemOid))));
3556 
3557  /* and do the work */
3558  return AlterTypeNamespaceInternal(typeOid, nspOid, false, true, objsMoved);
3559 }
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:2484
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2512
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition: typecmds.c:3577
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:4572
#define OidIsValid(objectId)
Definition: c.h:532
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid AlterTypeNamespaceInternal ( Oid  typeOid,
Oid  nspOid,
bool  isImplicitArray,
bool  errorOnTableType,
ObjectAddresses objsMoved 
)

Definition at line 3577 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().

3581 {
3582  Relation rel;
3583  HeapTuple tup;
3584  Form_pg_type typform;
3585  Oid oldNspOid;
3586  Oid arrayOid;
3587  bool isCompositeType;
3588  ObjectAddress thisobj;
3589 
3590  /*
3591  * Make sure we haven't moved this object previously.
3592  */
3593  thisobj.classId = TypeRelationId;
3594  thisobj.objectId = typeOid;
3595  thisobj.objectSubId = 0;
3596 
3597  if (object_address_present(&thisobj, objsMoved))
3598  return InvalidOid;
3599 
3601 
3602  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
3603  if (!HeapTupleIsValid(tup))
3604  elog(ERROR, "cache lookup failed for type %u", typeOid);
3605  typform = (Form_pg_type) GETSTRUCT(tup);
3606 
3607  oldNspOid = typform->typnamespace;
3608  arrayOid = typform->typarray;
3609 
3610  /* If the type is already there, we scan skip these next few checks. */
3611  if (oldNspOid != nspOid)
3612  {
3613  /* common checks on switching namespaces */
3614  CheckSetNamespace(oldNspOid, nspOid);
3615 
3616  /* check for duplicate name (more friendly than unique-index failure) */
3618  NameGetDatum(&typform->typname),
3619  ObjectIdGetDatum(nspOid)))
3620  ereport(ERROR,
3622  errmsg("type \"%s\" already exists in schema \"%s\"",
3623  NameStr(typform->typname),
3624  get_namespace_name(nspOid))));
3625  }
3626 
3627  /* Detect whether type is a composite type (but not a table rowtype) */
3628  isCompositeType =
3629  (typform->typtype == TYPTYPE_COMPOSITE &&
3630  get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);
3631 
3632  /* Enforce not-table-type if requested */
3633  if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType &&
3634  errorOnTableType)
3635  ereport(ERROR,
3636  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3637  errmsg("%s is a table's row type",
3638  format_type_be(typeOid)),
3639  errhint("Use ALTER TABLE instead.")));
3640 
3641  if (oldNspOid != nspOid)
3642  {
3643  /* OK, modify the pg_type row */
3644 
3645  /* tup is a copy, so we can scribble directly on it */
3646  typform->typnamespace = nspOid;
3647 
3648  CatalogTupleUpdate(rel, &tup->t_self, tup);
3649  }
3650 
3651  /*
3652  * Composite types have pg_class entries.
3653  *
3654  * We need to modify the pg_class tuple as well to reflect the change of
3655  * schema.
3656  */
3657  if (isCompositeType)
3658  {
3659  Relation classRel;
3660 
3662 
3663  AlterRelationNamespaceInternal(classRel, typform->typrelid,
3664  oldNspOid, nspOid,
3665  false, objsMoved);
3666 
3667  heap_close(classRel, RowExclusiveLock);
3668 
3669  /*
3670  * Check for constraints associated with the composite type (we don't
3671  * currently support this, but probably will someday).
3672  */
3673  AlterConstraintNamespaces(typform->typrelid, oldNspOid,
3674  nspOid, false, objsMoved);
3675  }
3676  else
3677  {
3678  /* If it's a domain, it might have constraints */
3679  if (typform->typtype == TYPTYPE_DOMAIN)
3680  AlterConstraintNamespaces(typeOid, oldNspOid, nspOid, true,
3681  objsMoved);
3682  }
3683 
3684  /*
3685  * Update dependency on schema, if any --- a table rowtype has not got
3686  * one, and neither does an implicit array.
3687  */
3688  if (oldNspOid != nspOid &&
3689  (isCompositeType || typform->typtype != TYPTYPE_COMPOSITE) &&
3690  !isImplicitArray)
3691  if (changeDependencyFor(TypeRelationId, typeOid,
3692  NamespaceRelationId, oldNspOid, nspOid) != 1)
3693  elog(ERROR, "failed to change schema dependency for type %s",
3694  format_type_be(typeOid));
3695 
3697 
3698  heap_freetuple(tup);
3699 
3701 
3702  add_exact_object_address(&thisobj, objsMoved);
3703 
3704  /* Recursively alter the associated array type, if any */
3705  if (OidIsValid(arrayOid))
3706  AlterTypeNamespaceInternal(arrayOid, nspOid, true, true, objsMoved);
3707 
3708  return oldNspOid;
3709 }
#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:656
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1801
#define RelationRelationId
Definition: pg_class.h:29
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2170
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition: typecmds.c:3577
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:2110
#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:532
#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:3033
#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:12655
#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:493
#define elog
Definition: elog.h:219
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
ObjectAddress AlterTypeOwner ( List names,
Oid  newOwnerId,
ObjectType  objecttype 
)

Definition at line 3298 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().

3299 {
3300  TypeName *typename;
3301  Oid typeOid;
3302  Relation rel;
3303  HeapTuple tup;
3304  HeapTuple newtup;
3305  Form_pg_type typTup;
3306  AclResult aclresult;
3307  ObjectAddress address;
3308 
3310 
3311  /* Make a TypeName so we can use standard type lookup machinery */
3312  typename = makeTypeNameFromNameList(names);
3313 
3314  /* Use LookupTypeName here so that shell types can be processed */
3315  tup = LookupTypeName(NULL, typename, NULL, false);
3316  if (tup == NULL)
3317  ereport(ERROR,
3318  (errcode(ERRCODE_UNDEFINED_OBJECT),
3319  errmsg("type \"%s\" does not exist",
3320  TypeNameToString(typename))));
3321  typeOid = typeTypeId(tup);
3322 
3323  /* Copy the syscache entry so we can scribble on it below */
3324  newtup = heap_copytuple(tup);
3325  ReleaseSysCache(tup);
3326  tup = newtup;
3327  typTup = (Form_pg_type) GETSTRUCT(tup);
3328 
3329  /* Don't allow ALTER DOMAIN on a type */
3330  if (objecttype == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN)
3331  ereport(ERROR,
3332  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3333  errmsg("%s is not a domain",
3334  format_type_be(typeOid))));
3335 
3336  /*
3337  * If it's a composite type, we need to check that it really is a
3338  * free-standing composite type, and not a table's rowtype. We want people
3339  * to use ALTER TABLE not ALTER TYPE for that case.
3340  */
3341  if (typTup->typtype == TYPTYPE_COMPOSITE &&
3342  get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)
3343  ereport(ERROR,
3344  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3345  errmsg("%s is a table's row type",
3346  format_type_be(typeOid)),
3347  errhint("Use ALTER TABLE instead.")));
3348 
3349  /* don't allow direct alteration of array types, either */
3350  if (OidIsValid(typTup->typelem) &&
3351  get_array_type(typTup->typelem) == typeOid)
3352  ereport(ERROR,
3353  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3354  errmsg("cannot alter array type %s",
3355  format_type_be(typeOid)),
3356  errhint("You can alter type %s, which will alter the array type as well.",
3357  format_type_be(typTup->typelem))));
3358 
3359  /*
3360  * If the new owner is the same as the existing owner, consider the
3361  * command to have succeeded. This is for dump restoration purposes.
3362  */
3363  if (typTup->typowner != newOwnerId)
3364  {
3365  /* Superusers can always do it */
3366  if (!superuser())
3367  {
3368  /* Otherwise, must be owner of the existing object */
3371 
3372  /* Must be able to become new owner */
3373  check_is_member_of_role(GetUserId(), newOwnerId);
3374 
3375  /* New owner must have CREATE privilege on namespace */
3376  aclresult = pg_namespace_aclcheck(typTup->typnamespace,
3377  newOwnerId,
3378  ACL_CREATE);
3379  if (aclresult != ACLCHECK_OK)
3381  get_namespace_name(typTup->typnamespace));
3382  }
3383 
3384  AlterTypeOwner_oid(typeOid, newOwnerId, true);
3385  }
3386 
3387  ObjectAddressSet(address, TypeRelationId, typeOid);
3388 
3389  /* Clean up */
3391 
3392  return address;
3393 }
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:656
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:2512
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1801
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:4572
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:532
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4484
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
#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:3407
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define RowExclusiveLock
Definition: lockdefs.h:38
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4876
#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:453
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Oid typeTypeId(Type tp)
Definition: parse_type.c:571
void AlterTypeOwner_oid ( Oid  typeOid,
Oid  newOwnerId,
bool  hasDependEntry 
)

Definition at line 3407 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().

3408 {
3409  Relation rel;
3410  HeapTuple tup;
3411  Form_pg_type typTup;
3412 
3414 
3415  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
3416  if (!HeapTupleIsValid(tup))
3417  elog(ERROR, "cache lookup failed for type %u", typeOid);
3418  typTup = (Form_pg_type) GETSTRUCT(tup);
3419 
3420  /*
3421  * If it's a composite type, invoke ATExecChangeOwner so that we fix up
3422  * the pg_class entry properly. That will call back to
3423  * AlterTypeOwnerInternal to take care of the pg_type entry(s).
3424  */
3425  if (typTup->typtype == TYPTYPE_COMPOSITE)
3426  ATExecChangeOwner(typTup->typrelid, newOwnerId, true, AccessExclusiveLock);
3427  else
3428  AlterTypeOwnerInternal(typeOid, newOwnerId);
3429 
3430  /* Update owner dependency reference */
3431  if (hasDependEntry)
3432  changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
3433 
3435 
3436  ReleaseSysCache(tup);
3438 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition: typecmds.c:3447
#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:9922
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
void AlterTypeOwnerInternal ( Oid  typeOid,
Oid  newOwnerId 
)

Definition at line 3447 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().

3448 {
3449  Relation rel;
3450  HeapTuple tup;
3451  Form_pg_type typTup;
3452  Datum repl_val[Natts_pg_type];
3453  bool repl_null[Natts_pg_type];
3454  bool repl_repl[Natts_pg_type];
3455  Acl *newAcl;
3456  Datum aclDatum;
3457  bool isNull;
3458 
3460 
3461  tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
3462  if (!HeapTupleIsValid(tup))
3463  elog(ERROR, "cache lookup failed for type %u", typeOid);
3464  typTup = (Form_pg_type) GETSTRUCT(tup);
3465 
3466  memset(repl_null, false, sizeof(repl_null));
3467  memset(repl_repl, false, sizeof(repl_repl));
3468 
3469  repl_repl[Anum_pg_type_typowner - 1] = true;
3470  repl_val[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(newOwnerId);
3471 
3472  aclDatum = heap_getattr(tup,
3474  RelationGetDescr(rel),
3475  &isNull);
3476  /* Null ACLs do not require changes */
3477  if (!isNull)
3478  {
3479  newAcl = aclnewowner(DatumGetAclP(aclDatum),
3480  typTup->typowner, newOwnerId);
3481  repl_repl[Anum_pg_type_typacl - 1] = true;
3482  repl_val[Anum_pg_type_typacl - 1] = PointerGetDatum(newAcl);
3483  }
3484 
3485  tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
3486  repl_repl);
3487 
3488  CatalogTupleUpdate(rel, &tup->t_self, tup);
3489 
3490  /* If it has an array type, update that too */
3491  if (OidIsValid(typTup->typarray))
3492  AlterTypeOwnerInternal(typTup->typarray, newOwnerId);
3493 
3494  /* Clean up */
3496 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationGetDescr(relation)
Definition: rel.h:428
#define DatumGetAclP(X)
Definition: acl.h:121
#define PointerGetDatum(X)
Definition: postgres.h:562
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition: typecmds.c:3447
#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:532
#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:769
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
Oid AssignTypeArrayOid ( void  )

Definition at line 2096 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().

2097 {
2098  Oid type_array_oid;
2099 
2100  /* Use binary-upgrade override for pg_type.typarray? */
2101  if (IsBinaryUpgrade)
2102  {
2104  ereport(ERROR,
2105  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2106  errmsg("pg_type array OID value not set when in binary upgrade mode")));
2107 
2108  type_array_oid = binary_upgrade_next_array_pg_type_oid;
2110  }
2111  else
2112  {
2114 
2115  type_array_oid = GetNewOid(pg_type);
2116  heap_close(pg_type, AccessShareLock);
2117  }
2118 
2119  return type_array_oid;
2120 }
#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:532
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
void checkDomainOwner ( HeapTuple  tup)

Definition at line 3038 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().

3039 {
3040  Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
3041 
3042  /* Check that this is actually a domain */
3043  if (typTup->typtype != TYPTYPE_DOMAIN)
3044  ereport(ERROR,
3045  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3046  errmsg("%s is not a domain",
3048 
3049  /* Permission check: must own type */
3052 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
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:4572
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
#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:695
static void checkEnumOwner ( HeapTuple  tup)
static

Definition at line 1345 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().

1346 {
1347  Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
1348 
1349  /* Check that this is actually an enum */
1350  if (typTup->typtype != TYPTYPE_ENUM)
1351  ereport(ERROR,
1352  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1353  errmsg("%s is not an enum",
1355 
1356  /* Permission check: must own type */
1359 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
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:4572
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
#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:695
ObjectAddress DefineCompositeType ( RangeVar typevar,
List coldeflist 
)

Definition at line 2137 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().

2138 {
2139  CreateStmt *createStmt = makeNode(CreateStmt);
2140  Oid old_type_oid;
2141  Oid typeNamespace;
2142  ObjectAddress address;
2143 
2144  /*
2145  * now set the parameters for keys/inheritance etc. All of these are
2146  * uninteresting for composite types...
2147  */
2148  createStmt->relation = typevar;
2149  createStmt->tableElts = coldeflist;
2150  createStmt->inhRelations = NIL;
2151  createStmt->constraints = NIL;
2152  createStmt->options = NIL;
2153  createStmt->oncommit = ONCOMMIT_NOOP;
2154  createStmt->tablespacename = NULL;
2155  createStmt->if_not_exists = false;
2156 
2157  /*
2158  * Check for collision with an existing type name. If there is one and
2159  * it's an autogenerated array, we can rename it out of the way. This
2160  * check is here mainly to get a better error message about a "type"
2161  * instead of below about a "relation".
2162  */
2163  typeNamespace = RangeVarGetAndCheckCreationNamespace(createStmt->relation,
2164  NoLock, NULL);
2165  RangeVarAdjustRelationPersistence(createStmt->relation, typeNamespace);
2166  old_type_oid =
2168  CStringGetDatum(createStmt->relation->relname),
2169  ObjectIdGetDatum(typeNamespace));
2170  if (OidIsValid(old_type_oid))
2171  {
2172  if (!moveArrayTypeName(old_type_oid, createStmt->relation->relname, typeNamespace))
2173  ereport(ERROR,
2175  errmsg("type \"%s\" already exists", createStmt->relation->relname)));
2176  }
2177 
2178  /*
2179  * Finally create the relation. This also creates the type.
2180  */
2181  DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid, &address,
2182  NULL);
2183 
2184  return address;
2185 }
RangeVar * relation
Definition: parsenodes.h:2003
#define NIL
Definition: pg_list.h:69
OnCommitAction oncommit
Definition: parsenodes.h:2012
List * inhRelations
Definition: parsenodes.h:2005
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
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:2010
bool if_not_exists
Definition: parsenodes.h:2014
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:2011
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:504
#define ereport(elevel, rest)
Definition: elog.h:122
char * tablespacename
Definition: parsenodes.h:2013
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:2004
#define makeNode(_type_)
Definition: nodes.h:558
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
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_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, another domain, an enum or a range
802  * type. Domains over pseudotypes would create a security hole. Domains
803  * over composite types might be made to work in the future, but not
804  * today.
805  */
806  typtype = baseType->typtype;
807  if (typtype != TYPTYPE_BASE &&
808  typtype != TYPTYPE_DOMAIN &&
809  typtype != TYPTYPE_ENUM &&
810  typtype != TYPTYPE_RANGE)
811  ereport(ERROR,
812  (errcode(ERRCODE_DATATYPE_MISMATCH),
813  errmsg("\"%s\" is not a valid base type for a domain",
814  TypeNameToString(stmt->typeName))));
815 
816  aclresult = pg_type_aclcheck(basetypeoid, GetUserId(), ACL_USAGE);
817  if (aclresult != ACLCHECK_OK)
818  aclcheck_error_type(aclresult, basetypeoid);
819 
820  /*
821  * Identify the collation if any
822  */
823  baseColl = baseType->typcollation;
824  if (stmt->collClause)
825  domaincoll = get_collation_oid(stmt->collClause->collname, false);
826  else
827  domaincoll = baseColl;
828 
829  /* Complain if COLLATE is applied to an uncollatable type */
830  if (OidIsValid(domaincoll) && !OidIsValid(baseColl))
831  ereport(ERROR,
832  (errcode(ERRCODE_DATATYPE_MISMATCH),
833  errmsg("collations are not supported by type %s",
834  format_type_be(basetypeoid))));
835 
836  /* passed by value */
837  byValue = baseType->typbyval;
838 
839  /* Required Alignment */
840  alignment = baseType->typalign;
841 
842  /* TOAST Strategy */
843  storage = baseType->typstorage;
844 
845  /* Storage Length */
846  internalLength = baseType->typlen;
847 
848  /* Type Category */
849  category = baseType->typcategory;
850 
851  /* Array element Delimiter */
852  delimiter = baseType->typdelim;
853 
854  /* I/O Functions */
855  inputProcedure = F_DOMAIN_IN;
856  outputProcedure = baseType->typoutput;
857  receiveProcedure = F_DOMAIN_RECV;
858  sendProcedure = baseType->typsend;
859 
860  /* Domains never accept typmods, so no typmodin/typmodout needed */
861 
862  /* Analysis function */
863  analyzeProcedure = baseType->typanalyze;
864 
865  /* Inherited default value */
866  datum = SysCacheGetAttr(TYPEOID, typeTup,
867  Anum_pg_type_typdefault, &isnull);
868  if (!isnull)
869  defaultValue = TextDatumGetCString(datum);
870 
871  /* Inherited default binary value */
872  datum = SysCacheGetAttr(TYPEOID, typeTup,
873  Anum_pg_type_typdefaultbin, &isnull);
874  if (!isnull)
875  defaultValueBin = TextDatumGetCString(datum);
876 
877  /*
878  * Run through constraints manually to avoid the additional processing
879  * conducted by DefineRelation() and friends.
880  */
881  foreach(listptr, schema)
882  {
883  Constraint *constr = lfirst(listptr);
884 
885  if (!IsA(constr, Constraint))
886  elog(ERROR, "unrecognized node type: %d",
887  (int) nodeTag(constr));
888  switch (constr->contype)
889  {
890  case CONSTR_DEFAULT:
891 
892  /*
893  * The inherited default value may be overridden by the user
894  * with the DEFAULT <expr> clause ... but only once.
895  */
896  if (saw_default)
897  ereport(ERROR,
898  (errcode(ERRCODE_SYNTAX_ERROR),
899  errmsg("multiple default expressions")));
900  saw_default = true;
901 
902  if (constr->raw_expr)
903  {
904  ParseState *pstate;
905  Node *defaultExpr;
906 
907  /* Create a dummy ParseState for transformExpr */
908  pstate = make_parsestate(NULL);
909 
910  /*
911  * Cook the constr->raw_expr into an expression. Note:
912  * name is strictly for error message
913  */
914  defaultExpr = cookDefault(pstate, constr->raw_expr,
915  basetypeoid,
916  basetypeMod,
917  domainName);
918 
919  /*
920  * If the expression is just a NULL constant, we treat it
921  * like not having a default.
922  *
923  * Note that if the basetype is another domain, we'll see
924  * a CoerceToDomain expr here and not discard the default.
925  * This is critical because the domain default needs to be
926  * retained to override any default that the base domain
927  * might have.
928  */
929  if (defaultExpr == NULL ||
930  (IsA(defaultExpr, Const) &&
931  ((Const *) defaultExpr)->constisnull))
932  {
933  defaultValue = NULL;
934  defaultValueBin = NULL;
935  }
936  else
937  {
938  /*
939  * Expression must be stored as a nodeToString result,
940  * but we also require a valid textual representation
941  * (mainly to make life easier for pg_dump).
942  */
943  defaultValue =
944  deparse_expression(defaultExpr,
945  NIL, false, false);
946  defaultValueBin = nodeToString(defaultExpr);
947  }
948  }
949  else
950  {
951  /* No default (can this still happen?) */
952  defaultValue = NULL;
953  defaultValueBin = NULL;
954  }
955  break;
956 
957  case CONSTR_NOTNULL:
958  if (nullDefined && !typNotNull)
959  ereport(ERROR,
960  (errcode(ERRCODE_SYNTAX_ERROR),
961  errmsg("conflicting NULL/NOT NULL constraints")));
962  typNotNull = true;
963  nullDefined = true;
964  break;
965 
966  case CONSTR_NULL:
967  if (nullDefined && typNotNull)
968  ereport(ERROR,
969  (errcode(ERRCODE_SYNTAX_ERROR),
970  errmsg("conflicting NULL/NOT NULL constraints")));
971  typNotNull = false;
972  nullDefined = true;
973  break;
974 
975  case CONSTR_CHECK:
976 
977  /*
978  * Check constraints are handled after domain creation, as
979  * they require the Oid of the domain; at this point we can
980  * only check that they're not marked NO INHERIT, because that
981  * would be bogus.
982  */
983  if (constr->is_no_inherit)
984  ereport(ERROR,
985  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
986  errmsg("check constraints for domains cannot be marked NO INHERIT")));
987  break;
988 
989  /*
990  * All else are error cases
991  */
992  case CONSTR_UNIQUE:
993  ereport(ERROR,
994  (errcode(ERRCODE_SYNTAX_ERROR),
995  errmsg("unique constraints not possible for domains")));
996  break;
997 
998  case CONSTR_PRIMARY:
999  ereport(ERROR,
1000  (errcode(ERRCODE_SYNTAX_ERROR),
1001  errmsg("primary key constraints not possible for domains")));
1002  break;
1003 
1004  case CONSTR_EXCLUSION:
1005  ereport(ERROR,
1006  (errcode(ERRCODE_SYNTAX_ERROR),
1007  errmsg("exclusion constraints not possible for domains")));
1008  break;
1009 
1010  case CONSTR_FOREIGN:
1011  ereport(ERROR,
1012  (errcode(ERRCODE_SYNTAX_ERROR),
1013  errmsg("foreign key constraints not possible for domains")));
1014  break;
1015 
1018  case CONSTR_ATTR_DEFERRED:
1019  case CONSTR_ATTR_IMMEDIATE:
1020  ereport(ERROR,
1021  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1022  errmsg("specifying constraint deferrability not supported for domains")));
1023  break;
1024 
1025  default:
1026  elog(ERROR, "unrecognized constraint subtype: %d",
1027  (int) constr->contype);
1028  break;
1029  }
1030  }
1031 
1032  /* Allocate OID for array type */
1033  domainArrayOid = AssignTypeArrayOid();
1034 
1035  /*
1036  * Have TypeCreate do all the real work.
1037  */
1038  address =
1039  TypeCreate(InvalidOid, /* no predetermined type OID */
1040  domainName, /* type name */
1041  domainNamespace, /* namespace */
1042  InvalidOid, /* relation oid (n/a here) */
1043  0, /* relation kind (ditto) */
1044  GetUserId(), /* owner's ID */
1045  internalLength, /* internal size */
1046  TYPTYPE_DOMAIN, /* type-type (domain type) */
1047  category, /* type-category */
1048  false, /* domain types are never preferred */
1049  delimiter, /* array element delimiter */
1050  inputProcedure, /* input procedure */
1051  outputProcedure, /* output procedure */
1052  receiveProcedure, /* receive procedure */
1053  sendProcedure, /* send procedure */
1054  InvalidOid, /* typmodin procedure - none */
1055  InvalidOid, /* typmodout procedure - none */
1056  analyzeProcedure, /* analyze procedure */
1057  InvalidOid, /* no array element type */
1058  false, /* this isn't an array */
1059  domainArrayOid, /* array type we are about to create */
1060  basetypeoid, /* base type ID */
1061  defaultValue, /* default type value (text) */
1062  defaultValueBin, /* default type value (binary) */
1063  byValue, /* passed by value */
1064  alignment, /* required alignment */
1065  storage, /* TOAST strategy */
1066  basetypeMod, /* typeMod value */
1067  typNDims, /* Array dimensions for base type */
1068  typNotNull, /* Type NOT NULL */
1069  domaincoll); /* type's collation */
1070 
1071  /*
1072  * Create the array type that goes with it.
1073  */
1074  domainArrayName = makeArrayTypeName(domainName, domainNamespace);
1075 
1076  /* alignment must be 'i' or 'd' for arrays */
1077  alignment = (alignment == 'd') ? 'd' : 'i';
1078 
1079  TypeCreate(domainArrayOid, /* force assignment of this type OID */
1080  domainArrayName, /* type name */
1081  domainNamespace, /* namespace */
1082  InvalidOid, /* relation oid (n/a here) */
1083  0, /* relation kind (ditto) */
1084  GetUserId(), /* owner's ID */
1085  -1, /* internal size (always varlena) */
1086  TYPTYPE_BASE, /* type-type (base type) */
1087  TYPCATEGORY_ARRAY, /* type-category (array) */
1088  false, /* array types are never preferred */
1089  delimiter, /* array element delimiter */
1090  F_ARRAY_IN, /* input procedure */
1091  F_ARRAY_OUT, /* output procedure */
1092  F_ARRAY_RECV, /* receive procedure */
1093  F_ARRAY_SEND, /* send procedure */
1094  InvalidOid, /* typmodin procedure - none */
1095  InvalidOid, /* typmodout procedure - none */
1096  F_ARRAY_TYPANALYZE, /* analyze procedure */
1097  address.objectId, /* element type ID */
1098  true, /* yes this is an array type */
1099  InvalidOid, /* no further array type */
1100  InvalidOid, /* base type ID */
1101  NULL, /* never a default type value */
1102  NULL, /* binary default isn't sent either */
1103  false, /* never passed by value */
1104  alignment, /* see above */
1105  'x', /* ARRAY is always toastable */
1106  -1, /* typMod (Domains only) */
1107  0, /* Array dimensions of typbasetype */
1108  false, /* Type NOT NULL */
1109  domaincoll); /* type's collation */
1110 
1111  pfree(domainArrayName);
1112 
1113  /*
1114  * Process constraints which refer to the domain ID returned by TypeCreate
1115  */
1116  foreach(listptr, schema)
1117  {
1118  Constraint *constr = lfirst(listptr);
1119 
1120  /* it must be a Constraint, per check above */
1121 
1122  switch (constr->contype)
1123  {
1124  case CONSTR_CHECK:
1125  domainAddConstraint(address.objectId, domainNamespace,
1126  basetypeoid, basetypeMod,
1127  constr, domainName, NULL);
1128  break;
1129 
1130  /* Other constraint types were fully processed above */
1131 
1132  default:
1133  break;
1134  }
1135 
1136  /* CCI so we can detect duplicate constraint names */
1138  }
1139 
1140  /*
1141  * Now we can clean up.
1142  */
1143  ReleaseSysCache(typeTup);
1144 
1145  return address;
1146 }
signed short int16
Definition: c.h:245
#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:561
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:767
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Type typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
Definition: parse_type.c:247
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, char *attname)
Definition: heap.c:2657
#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
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
Node * raw_expr
Definition: parsenodes.h:2091
Definition: nodes.h:510
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:532
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4484
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
signed int int32
Definition: c.h:246
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
void pfree(void *pointer)
Definition: mcxt.c:949
CollateClause * collClause
Definition: parsenodes.h:2510
#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:3033
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:3399
#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
static char * domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, int typMod, Constraint *constr, char *domainName, ObjectAddress *constrAddr)
Definition: typecmds.c:3058
#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:2090
#define lfirst(lc)
Definition: pg_list.h:106
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition: ruleutils.c:2985
static int list_length(const List *l)
Definition: pg_list.h:89
#define nodeTag(nodeptr)
Definition: nodes.h:515
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2096
TypeName * typeName
Definition: parsenodes.h:2509
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:4259
ConstrType contype
Definition: parsenodes.h:2081
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4534
#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
ObjectAddress DefineEnum ( CreateEnumStmt stmt)

Definition at line 1154 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().

1155 {
1156  char *enumName;
1157  char *enumArrayName;
1158  Oid enumNamespace;
1159  AclResult aclresult;
1160  Oid old_type_oid;
1161  Oid enumArrayOid;
1162  ObjectAddress enumTypeAddr;
1163 
1164  /* Convert list of names to a name and namespace */
1165  enumNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
1166  &enumName);
1167 
1168  /* Check we have creation rights in target namespace */
1169  aclresult = pg_namespace_aclcheck(enumNamespace, GetUserId(), ACL_CREATE);
1170  if (aclresult != ACLCHECK_OK)
1172  get_namespace_name(enumNamespace));
1173 
1174  /*
1175  * Check for collision with an existing type name. If there is one and
1176  * it's an autogenerated array, we can rename it out of the way.
1177  */
1178  old_type_oid = GetSysCacheOid2(TYPENAMENSP,
1179  CStringGetDatum(enumName),
1180  ObjectIdGetDatum(enumNamespace));
1181  if (OidIsValid(old_type_oid))
1182  {
1183  if (!moveArrayTypeName(old_type_oid, enumName, enumNamespace))
1184  ereport(ERROR,
1186  errmsg("type \"%s\" already exists", enumName)));
1187  }
1188 
1189  /* Allocate OID for array type */
1190  enumArrayOid = AssignTypeArrayOid();
1191 
1192  /* Create the pg_type entry */
1193  enumTypeAddr =
1194  TypeCreate(InvalidOid, /* no predetermined type OID */
1195  enumName, /* type name */
1196  enumNamespace, /* namespace */
1197  InvalidOid, /* relation oid (n/a here) */
1198  0, /* relation kind (ditto) */
1199  GetUserId(), /* owner's ID */
1200  sizeof(Oid), /* internal size */
1201  TYPTYPE_ENUM, /* type-type (enum type) */
1202  TYPCATEGORY_ENUM, /* type-category (enum type) */
1203  false, /* enum types are never preferred */
1204  DEFAULT_TYPDELIM, /* array element delimiter */
1205  F_ENUM_IN, /* input procedure */
1206  F_ENUM_OUT, /* output procedure */
1207  F_ENUM_RECV, /* receive procedure */
1208  F_ENUM_SEND, /* send procedure */
1209  InvalidOid, /* typmodin procedure - none */
1210  InvalidOid, /* typmodout procedure - none */
1211  InvalidOid, /* analyze procedure - default */
1212  InvalidOid, /* element type ID */
1213  false, /* this is not an array type */
1214  enumArrayOid, /* array type we are about to create */
1215  InvalidOid, /* base type ID (only for domains) */
1216  NULL, /* never a default type value */
1217  NULL, /* binary default isn't sent either */
1218  true, /* always passed by value */
1219  'i', /* int alignment */
1220  'p', /* TOAST strategy always plain */
1221  -1, /* typMod (Domains only) */
1222  0, /* Array dimensions of typbasetype */
1223  false, /* Type NOT NULL */
1224  InvalidOid); /* type's collation */
1225 
1226  /* Enter the enum's values into pg_enum */
1227  EnumValuesCreate(enumTypeAddr.objectId, stmt->vals);
1228 
1229  /*
1230  * Create the array type that goes with it.
1231  */
1232  enumArrayName = makeArrayTypeName(enumName, enumNamespace);
1233 
1234  TypeCreate(enumArrayOid, /* force assignment of this type OID */
1235  enumArrayName, /* type name */
1236  enumNamespace, /* namespace */
1237  InvalidOid, /* relation oid (n/a here) */
1238  0, /* relation kind (ditto) */
1239  GetUserId(), /* owner's ID */
1240  -1, /* internal size (always varlena) */
1241  TYPTYPE_BASE, /* type-type (base type) */
1242  TYPCATEGORY_ARRAY, /* type-category (array) */
1243  false, /* array types are never preferred */
1244  DEFAULT_TYPDELIM, /* array element delimiter */
1245  F_ARRAY_IN, /* input procedure */
1246  F_ARRAY_OUT, /* output procedure */
1247  F_ARRAY_RECV, /* receive procedure */
1248  F_ARRAY_SEND, /* send procedure */
1249  InvalidOid, /* typmodin procedure - none */
1250  InvalidOid, /* typmodout procedure - none */
1251  F_ARRAY_TYPANALYZE, /* analyze procedure */
1252  enumTypeAddr.objectId, /* element type ID */
1253  true, /* yes this is an array type */
1254  InvalidOid, /* no further array type */
1255  InvalidOid, /* base type ID */
1256  NULL, /* never a default type value */
1257  NULL, /* binary default isn't sent either */
1258  false, /* never passed by value */
1259  'i', /* enums have align i, so do their arrays */
1260  'x', /* ARRAY is always toastable */
1261  -1, /* typMod (Domains only) */
1262  0, /* Array dimensions of typbasetype */
1263  false, /* Type NOT NULL */
1264  InvalidOid); /* type's collation */
1265 
1266  pfree(enumArrayName);
1267 
1268  return enumTypeAddr;
1269 }
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:532
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4484
#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:3033
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:3399
#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:2096
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
ObjectAddress DefineRange ( CreateRangeStmt stmt)

Definition at line 1367 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().

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

Definition at line 3058 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().

3061 {
3062  Node *expr;
3063  char *ccsrc;
3064  char *ccbin;
3065  ParseState *pstate;
3066  CoerceToDomainValue *domVal;
3067  Oid ccoid;
3068 
3069  /*
3070  * Assign or validate constraint name
3071  */
3072  if (constr->conname)
3073  {
3075  domainOid,
3076  domainNamespace,
3077  constr->conname))
3078  ereport(ERROR,
3080  errmsg("constraint \"%s\" for domain \"%s\" already exists",
3081  constr->conname, domainName)));
3082  }
3083  else
3084  constr->conname = ChooseConstraintName(domainName,
3085  NULL,
3086  "check",
3087  domainNamespace,
3088  NIL);
3089 
3090  /*
3091  * Convert the A_EXPR in raw_expr into an EXPR
3092  */
3093  pstate = make_parsestate(NULL);
3094 
3095  /*
3096  * Set up a CoerceToDomainValue to represent the occurrence of VALUE in
3097  * the expression. Note that it will appear to have the type of the base
3098  * type, not the domain. This seems correct since within the check
3099  * expression, we should not assume the input value can be considered a
3100  * member of the domain.
3101  */
3102  domVal = makeNode(CoerceToDomainValue);
3103  domVal->typeId = baseTypeOid;
3104  domVal->typeMod = typMod;
3105  domVal->collation = get_typcollation(baseTypeOid);
3106  domVal->location = -1; /* will be set when/if used */
3107 
3109  pstate->p_ref_hook_state = (void *) domVal;
3110 
3111  expr = transformExpr(pstate, constr->raw_expr, EXPR_KIND_DOMAIN_CHECK);
3112 
3113  /*
3114  * Make sure it yields a boolean result.
3115  */
3116  expr = coerce_to_boolean(pstate, expr, "CHECK");
3117 
3118  /*
3119  * Fix up collation information.
3120  */
3121  assign_expr_collations(pstate, expr);
3122 
3123  /*
3124  * Domains don't allow variables (this is probably dead code now that
3125  * add_missing_from is history, but let's be sure).
3126  */
3127  if (list_length(pstate->p_rtable) != 0 ||
3128  contain_var_clause(expr))
3129  ereport(ERROR,
3130  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
3131  errmsg("cannot use table references in domain check constraint")));
3132 
3133  /*
3134  * Convert to string form for storage.
3135  */
3136  ccbin = nodeToString(expr);
3137 
3138  /*
3139  * Deparse it to produce text for consrc.
3140  */
3141  ccsrc = deparse_expression(expr,
3142  NIL, false, false);
3143 
3144  /*
3145  * Store the constraint in pg_constraint
3146  */
3147  ccoid =
3148  CreateConstraintEntry(constr->conname, /* Constraint Name */
3149  domainNamespace, /* namespace */
3150  CONSTRAINT_CHECK, /* Constraint Type */
3151  false, /* Is Deferrable */
3152  false, /* Is Deferred */
3153  !constr->skip_validation, /* Is Validated */
3154  InvalidOid, /* not a relation constraint */
3155  NULL,
3156  0,
3157  domainOid, /* domain constraint */
3158  InvalidOid, /* no associated index */
3159  InvalidOid, /* Foreign key fields */
3160  NULL,
3161  NULL,
3162  NULL,
3163  NULL,
3164  0,
3165  ' ',
3166  ' ',
3167  ' ',
3168  NULL, /* not an exclusion constraint */
3169  expr, /* Tree form of check constraint */
3170  ccbin, /* Binary form of check constraint */
3171  ccsrc, /* Source form of check constraint */
3172  true, /* is local */
3173  0, /* inhcount */
3174  false, /* connoinherit */
3175  false); /* is_internal */
3176  if (constrAddr)
3177  ObjectAddressSet(*constrAddr, ConstraintRelationId, ccoid);
3178 
3179  /*
3180  * Return the compiled constraint expression so the calling routine can
3181  * perform any additional required tests.
3182  */
3183  return ccbin;
3184 }
#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:3188
Node * raw_expr
Definition: parsenodes.h:2091
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:146
Definition: nodes.h:510
int errcode(int sqlerrcode)
Definition: elog.c:575
bool contain_var_clause(Node *node)
Definition: var.c:331
char * conname
Definition: parsenodes.h:2084
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:2781
#define makeNode(_type_)
Definition: nodes.h:558
void * p_ref_hook_state
Definition: parse_node.h:214
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition: ruleutils.c:2985
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:4259
#define ConstraintRelationId
Definition: pg_constraint.h:29
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:210
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
bool skip_validation
Definition: parsenodes.h:2121
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:172
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)
static Oid findRangeCanonicalFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 2007 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().

2008 {
2009  Oid argList[1];
2010  Oid procOid;
2011  AclResult aclresult;
2012 
2013  /*
2014  * Range canonical functions must take and return the range type, and must
2015  * be immutable.
2016  */
2017  argList[0] = typeOid;
2018 
2019  procOid = LookupFuncName(procname, 1, argList, true);
2020 
2021  if (!OidIsValid(procOid))
2022  ereport(ERROR,
2023  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2024  errmsg("function %s does not exist",
2025  func_signature_string(procname, 1, NIL, argList))));
2026 
2027  if (get_func_rettype(procOid) != typeOid)
2028  ereport(ERROR,
2029  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2030  errmsg("range canonical function %s must return range type",
2031  func_signature_string(procname, 1, NIL, argList))));
2032 
2033  if (func_volatile(procOid) != PROVOLATILE_IMMUTABLE)
2034  ereport(ERROR,
2035  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2036  errmsg("range canonical function %s must be immutable",
2037  func_signature_string(procname, 1, NIL, argList))));
2038 
2039  /* Also, range type's creator must have permission to call function */
2040  aclresult = pg_proc_aclcheck(procOid, GetUserId(), ACL_EXECUTE);
2041  if (aclresult != ACLCHECK_OK)
2042  aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(procOid));
2043 
2044  return procOid;
2045 }
#define NIL
Definition: pg_list.h:69
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5533
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:532
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:3399
#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:1908
AclResult
Definition: acl.h:178
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1929
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:4446
static Oid findRangeSubOpclass ( List opcname,
Oid  subtype 
)
static

Definition at line 1968 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().

1969 {
1970  Oid opcid;
1971  Oid opInputType;
1972 
1973  if (opcname != NIL)
1974  {
1975  opcid = get_opclass_oid(BTREE_AM_OID, opcname, false);
1976 
1977  /*
1978  * Verify that the operator class accepts this datatype. Note we will
1979  * accept binary compatibility.
1980  */
1981  opInputType = get_opclass_input_type(opcid);
1982  if (!IsBinaryCoercible(subtype, opInputType))
1983  ereport(ERROR,
1984  (errcode(ERRCODE_DATATYPE_MISMATCH),
1985  errmsg("operator class \"%s\" does not accept data type %s",
1986  NameListToString(opcname),
1987  format_type_be(subtype))));
1988  }
1989  else
1990  {
1991  opcid = GetDefaultOpClass(subtype, BTREE_AM_OID);
1992  if (!OidIsValid(opcid))
1993  {
1994  /* We spell the error message identically to GetIndexOpClass */
1995  ereport(ERROR,
1996  (errcode(ERRCODE_UNDEFINED_OBJECT),
1997  errmsg("data type %s has no default operator class for access method \"%s\"",
1998  format_type_be(subtype), "btree"),
1999  errhint("You must specify an operator class for the range type or define a default operator class for the subtype.")));
2000  }
2001  }
2002 
2003  return opcid;
2004 }
#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:1390
#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:532
#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
static Oid findRangeSubtypeDiffFunction ( List procname,
Oid  subtype 
)
static

Definition at line 2048 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().

2049 {
2050  Oid argList[2];
2051  Oid procOid;
2052  AclResult aclresult;
2053 
2054  /*
2055  * Range subtype diff functions must take two arguments of the subtype,
2056  * must return float8, and must be immutable.
2057  */
2058  argList[0] = subtype;
2059  argList[1] = subtype;
2060 
2061  procOid = LookupFuncName(procname, 2, argList, true);
2062 
2063  if (!OidIsValid(procOid))
2064  ereport(ERROR,
2065  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2066  errmsg("function %s does not exist",
2067  func_signature_string(procname, 2, NIL, argList))));
2068 
2069  if (get_func_rettype(procOid) != FLOAT8OID)
2070  ereport(ERROR,
2071  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2072  errmsg("range subtype diff function %s must return type %s",
2073  func_signature_string(procname, 2, NIL, argList),
2074  "double precision")));
2075 
2076  if (func_volatile(procOid) != PROVOLATILE_IMMUTABLE)
2077  ereport(ERROR,
2078  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2079  errmsg("range subtype diff function %s must be immutable",
2080  func_signature_string(procname, 2, NIL, argList))));
2081 
2082  /* Also, range type's creator must have permission to call function */
2083  aclresult = pg_proc_aclcheck(procOid, GetUserId(), ACL_EXECUTE);
2084  if (aclresult != ACLCHECK_OK)
2085  aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(procOid));
2086 
2087  return procOid;
2088 }
#define NIL
Definition: pg_list.h:69
#define PROVOLATILE_IMMUTABLE
Definition: pg_proc.h:5533
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:532
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:3399
#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:1908
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:1929
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:4446
static Oid findTypeAnalyzeFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1933 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().

1934 {
1935  Oid argList[1];
1936  Oid procOid;
1937 
1938  /*
1939  * Analyze functions always take one INTERNAL argument and return bool.
1940  */
1941  argList[0] = INTERNALOID;
1942 
1943  procOid = LookupFuncName(procname, 1, argList, true);
1944  if (!OidIsValid(procOid))
1945  ereport(ERROR,
1946  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1947  errmsg("function %s does not exist",
1948  func_signature_string(procname, 1, NIL, argList))));
1949 
1950  if (get_func_rettype(procOid) != BOOLOID)
1951  ereport(ERROR,
1952  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1953  errmsg("type analyze function %s must return type %s",
1954  NameListToString(procname), "boolean")));
1955 
1956  return procOid;
1957 }
#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:532
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:1908
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:1929
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Oid findTypeInputFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1707 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().

1708 {
1709  Oid argList[3];
1710  Oid procOid;
1711 
1712  /*
1713  * Input functions can take a single argument of type CSTRING, or three
1714  * arguments (string, typioparam OID, typmod).
1715  *
1716  * For backwards compatibility we allow OPAQUE in place of CSTRING; if we
1717  * see this, we issue a warning and fix up the pg_proc entry.
1718  */
1719  argList[0] = CSTRINGOID;
1720 
1721  procOid = LookupFuncName(procname, 1, argList, true);
1722  if (OidIsValid(procOid))
1723  return procOid;
1724 
1725  argList[1] = OIDOID;
1726  argList[2] = INT4OID;
1727 
1728  procOid = LookupFuncName(procname, 3, argList, true);
1729  if (OidIsValid(procOid))
1730  return procOid;
1731 
1732  /* No luck, try it with OPAQUE */
1733  argList[0] = OPAQUEOID;
1734 
1735  procOid = LookupFuncName(procname, 1, argList, true);
1736 
1737  if (!OidIsValid(procOid))
1738  {
1739  argList[1] = OIDOID;
1740  argList[2] = INT4OID;
1741 
1742  procOid = LookupFuncName(procname, 3, argList, true);
1743  }
1744 
1745  if (OidIsValid(procOid))
1746  {
1747  /* Found, but must complain and fix the pg_proc entry */
1748  ereport(WARNING,
1749  (errmsg("changing argument type of function %s from \"opaque\" to \"cstring\"",
1750  NameListToString(procname))));
1751  SetFunctionArgType(procOid, 0, CSTRINGOID);
1752 
1753  /*
1754  * Need CommandCounterIncrement since DefineType will likely try to
1755  * alter the pg_proc tuple again.
1756  */
1758 
1759  return procOid;
1760  }
1761 
1762  /* Use CSTRING (preferred) in the error message */
1763  argList[0] = CSTRINGOID;
1764 
1765  ereport(ERROR,
1766  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1767  errmsg("function %s does not exist",
1768  func_signature_string(procname, 1, NIL, argList))));
1769 
1770  return InvalidOid; /* keep compiler quiet */
1771 }
#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:532
#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:1908
#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:1929
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Oid findTypeOutputFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1774 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().

1775 {
1776  Oid argList[1];
1777  Oid procOid;
1778 
1779  /*
1780  * Output functions can take a single argument of the type.
1781  *
1782  * For backwards compatibility we allow OPAQUE in place of the actual type
1783  * name; if we see this, we issue a warning and fix up the pg_proc entry.
1784  */
1785  argList[0] = typeOid;
1786 
1787  procOid = LookupFuncName(procname, 1, argList, true);
1788  if (OidIsValid(procOid))
1789  return procOid;
1790 
1791  /* No luck, try it with OPAQUE */
1792  argList[0] = OPAQUEOID;
1793 
1794  procOid = LookupFuncName(procname, 1, argList, true);
1795 
1796  if (OidIsValid(procOid))
1797  {
1798  /* Found, but must complain and fix the pg_proc entry */
1799  ereport(WARNING,
1800  (errmsg("changing argument type of function %s from \"opaque\" to %s",
1801  NameListToString(procname), format_type_be(typeOid))));
1802  SetFunctionArgType(procOid, 0, typeOid);
1803 
1804  /*
1805  * Need CommandCounterIncrement since DefineType will likely try to
1806  * alter the pg_proc tuple again.
1807  */
1809 
1810  return procOid;
1811  }
1812 
1813  /* Use type name, not OPAQUE, in the failure message. */
1814  argList[0] = typeOid;
1815 
1816  ereport(ERROR,
1817  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1818  errmsg("function %s does not exist",
1819  func_signature_string(procname, 1, NIL, argList))));
1820 
1821  return InvalidOid; /* keep compiler quiet */
1822 }
#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:532
#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:1908
#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:1929
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Oid findTypeReceiveFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1825 of file typecmds.c.

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

Referenced by DefineType().

1826 {
1827  Oid argList[3];
1828  Oid procOid;
1829 
1830  /*
1831  * Receive functions can take a single argument of type INTERNAL, or three
1832  * arguments (internal, typioparam OID, typmod).
1833  */
1834  argList[0] = INTERNALOID;
1835 
1836  procOid = LookupFuncName(procname, 1, argList, true);
1837  if (OidIsValid(procOid))
1838  return procOid;
1839 
1840  argList[1] = OIDOID;
1841  argList[2] = INT4OID;
1842 
1843  procOid = LookupFuncName(procname, 3, argList, true);
1844  if (OidIsValid(procOid))
1845  return procOid;
1846 
1847  ereport(ERROR,
1848  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1849  errmsg("function %s does not exist",
1850  func_signature_string(procname, 1, NIL, argList))));
1851 
1852  return InvalidOid; /* keep compiler quiet */
1853 }
#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:532
#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:1908
#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:1929
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Oid findTypeSendFunction ( List procname,
Oid  typeOid 
)
static

Definition at line 1856 of file typecmds.c.

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

Referenced by DefineType().

1857 {
1858  Oid argList[1];
1859  Oid procOid;
1860 
1861  /*
1862  * Send functions can take a single argument of the type.
1863  */
1864  argList[0] = typeOid;
1865 
1866  procOid = LookupFuncName(procname, 1, argList, true);
1867  if (OidIsValid(procOid))
1868  return procOid;
1869 
1870  ereport(ERROR,
1871  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1872  errmsg("function %s does not exist",
1873  func_signature_string(procname, 1, NIL, argList))));
1874 
1875  return InvalidOid; /* keep compiler quiet */
1876 }
#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:532
#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:1908
#define InvalidOid
Definition: postgres_ext.h:36
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1929
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Oid findTypeTypmodinFunction ( List procname)
static

Definition at line 1879 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().

1880 {
1881  Oid argList[1];
1882  Oid procOid;
1883 
1884  /*
1885  * typmodin functions always take one cstring[] argument and return int4.
1886  */
1887  argList[0] = CSTRINGARRAYOID;
1888 
1889  procOid = LookupFuncName(procname, 1, argList, true);
1890  if (!OidIsValid(procOid))
1891  ereport(ERROR,
1892  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1893  errmsg("function %s does not exist",
1894  func_signature_string(procname, 1, NIL, argList))));
1895 
1896  if (get_func_rettype(procOid) != INT4OID)
1897  ereport(ERROR,
1898  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1899  errmsg("typmod_in function %s must return type %s",
1900  NameListToString(procname), "integer")));
1901 
1902  return procOid;
1903 }
#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:532
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:1908
char * NameListToString(List *names)
Definition: namespace.c:3063
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1929
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Oid findTypeTypmodoutFunction ( List procname)
static

Definition at line 1906 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().

1907 {
1908  Oid argList[1];
1909  Oid procOid;
1910 
1911  /*
1912  * typmodout functions always take one int4 argument and return cstring.
1913  */
1914  argList[0] = INT4OID;
1915 
1916  procOid = LookupFuncName(procname, 1, argList, true);
1917  if (!OidIsValid(procOid))
1918  ereport(ERROR,
1919  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1920  errmsg("function %s does not exist",
1921  func_signature_string(procname, 1, NIL, argList))));
1922 
1923  if (get_func_rettype(procOid) != CSTRINGOID)
1924  ereport(ERROR,
1925  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1926  errmsg("typmod_out function %s must return type %s",
1927  NameListToString(procname), "cstring")));
1928 
1929  return procOid;
1930 }
#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:532
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:1908
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:1929
int errmsg(const char *fmt,...)
Definition: elog.c:797
static List * get_rels_with_domain ( Oid  domainOid,
LOCKMODE  lockmode 
)
static

Definition at line 2869 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().

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