mirror of
https://github.com/postgres/postgres.git
synced 2025-07-26 01:22:12 +03:00
Add support for renaming domain constraints
This commit is contained in:
@ -31,6 +31,8 @@ ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
|||||||
ADD <replaceable class="PARAMETER">domain_constraint</replaceable> [ NOT VALID ]
|
ADD <replaceable class="PARAMETER">domain_constraint</replaceable> [ NOT VALID ]
|
||||||
ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
||||||
DROP CONSTRAINT [ IF EXISTS ] <replaceable class="PARAMETER">constraint_name</replaceable> [ RESTRICT | CASCADE ]
|
DROP CONSTRAINT [ IF EXISTS ] <replaceable class="PARAMETER">constraint_name</replaceable> [ RESTRICT | CASCADE ]
|
||||||
|
ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
||||||
|
RENAME CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> TO <replaceable class="PARAMETER">new_constraint_name</replaceable>
|
||||||
ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
||||||
VALIDATE CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable>
|
VALIDATE CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable>
|
||||||
ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
||||||
@ -102,6 +104,15 @@ ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>RENAME CONSTRAINT</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
This form changes the name of a constraint on a domain.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>VALIDATE CONSTRAINT</term>
|
<term>VALIDATE CONSTRAINT</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -182,7 +193,7 @@ ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
|||||||
<term><replaceable class="PARAMETER">constraint_name</replaceable></term>
|
<term><replaceable class="PARAMETER">constraint_name</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Name of an existing constraint to drop.
|
Name of an existing constraint to drop or rename.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -225,6 +236,15 @@ ALTER DOMAIN <replaceable class="PARAMETER">name</replaceable>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="PARAMETER">new_constraint_name</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The new name for the constraint.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><replaceable class="PARAMETER">new_owner</replaceable></term>
|
<term><replaceable class="PARAMETER">new_owner</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -288,6 +308,13 @@ ALTER DOMAIN zipcode DROP CONSTRAINT zipchk;
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
To rename a check constraint on a domain:
|
||||||
|
<programlisting>
|
||||||
|
ALTER DOMAIN zipcode RENAME CONSTRAINT zipchk TO zip_check;
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To move the domain into a different schema:
|
To move the domain into a different schema:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
|
@ -753,7 +753,7 @@ get_object_address_relobject(ObjectType objtype, List *objname,
|
|||||||
case OBJECT_CONSTRAINT:
|
case OBJECT_CONSTRAINT:
|
||||||
address.classId = ConstraintRelationId;
|
address.classId = ConstraintRelationId;
|
||||||
address.objectId =
|
address.objectId =
|
||||||
get_constraint_oid(reloid, depname, missing_ok);
|
get_relation_constraint_oid(reloid, depname, missing_ok);
|
||||||
address.objectSubId = 0;
|
address.objectSubId = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -736,12 +736,12 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_constraint_oid
|
* get_relation_constraint_oid
|
||||||
* Find a constraint on the specified relation with the specified name.
|
* Find a constraint on the specified relation with the specified name.
|
||||||
* Returns constraint's OID.
|
* Returns constraint's OID.
|
||||||
*/
|
*/
|
||||||
Oid
|
Oid
|
||||||
get_constraint_oid(Oid relid, const char *conname, bool missing_ok)
|
get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok)
|
||||||
{
|
{
|
||||||
Relation pg_constraint;
|
Relation pg_constraint;
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
@ -793,6 +793,64 @@ get_constraint_oid(Oid relid, const char *conname, bool missing_ok)
|
|||||||
return conOid;
|
return conOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_domain_constraint_oid
|
||||||
|
* Find a constraint on the specified domain with the specified name.
|
||||||
|
* Returns constraint's OID.
|
||||||
|
*/
|
||||||
|
Oid
|
||||||
|
get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok)
|
||||||
|
{
|
||||||
|
Relation pg_constraint;
|
||||||
|
HeapTuple tuple;
|
||||||
|
SysScanDesc scan;
|
||||||
|
ScanKeyData skey[1];
|
||||||
|
Oid conOid = InvalidOid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetch the constraint tuple from pg_constraint. There may be more than
|
||||||
|
* one match, because constraints are not required to have unique names;
|
||||||
|
* if so, error out.
|
||||||
|
*/
|
||||||
|
pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
|
||||||
|
|
||||||
|
ScanKeyInit(&skey[0],
|
||||||
|
Anum_pg_constraint_contypid,
|
||||||
|
BTEqualStrategyNumber, F_OIDEQ,
|
||||||
|
ObjectIdGetDatum(typid));
|
||||||
|
|
||||||
|
scan = systable_beginscan(pg_constraint, ConstraintTypidIndexId, true,
|
||||||
|
SnapshotNow, 1, skey);
|
||||||
|
|
||||||
|
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
|
||||||
|
{
|
||||||
|
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
|
||||||
|
|
||||||
|
if (strcmp(NameStr(con->conname), conname) == 0)
|
||||||
|
{
|
||||||
|
if (OidIsValid(conOid))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||||
|
errmsg("domain \"%s\" has multiple constraints named \"%s\"",
|
||||||
|
format_type_be(typid), conname)));
|
||||||
|
conOid = HeapTupleGetOid(tuple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
systable_endscan(scan);
|
||||||
|
|
||||||
|
/* If no such constraint exists, complain */
|
||||||
|
if (!OidIsValid(conOid) && !missing_ok)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||||
|
errmsg("constraint \"%s\" for domain \"%s\" does not exist",
|
||||||
|
conname, format_type_be(typid))));
|
||||||
|
|
||||||
|
heap_close(pg_constraint, AccessShareLock);
|
||||||
|
|
||||||
|
return conOid;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine whether a relation can be proven functionally dependent on
|
* Determine whether a relation can be proven functionally dependent on
|
||||||
* a set of grouping columns. If so, return TRUE and add the pg_constraint
|
* a set of grouping columns. If so, return TRUE and add the pg_constraint
|
||||||
|
@ -2333,22 +2333,32 @@ renameatt(RenameStmt *stmt)
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
rename_constraint_internal(Oid myrelid,
|
rename_constraint_internal(Oid myrelid,
|
||||||
|
Oid mytypid,
|
||||||
const char *oldconname,
|
const char *oldconname,
|
||||||
const char *newconname,
|
const char *newconname,
|
||||||
bool recurse,
|
bool recurse,
|
||||||
bool recursing,
|
bool recursing,
|
||||||
int expected_parents)
|
int expected_parents)
|
||||||
{
|
{
|
||||||
Relation targetrelation;
|
Relation targetrelation = NULL;
|
||||||
Oid constraintOid;
|
Oid constraintOid;
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
Form_pg_constraint con;
|
Form_pg_constraint con;
|
||||||
|
|
||||||
targetrelation = relation_open(myrelid, AccessExclusiveLock);
|
AssertArg(!myrelid || !mytypid);
|
||||||
/* don't tell it whether we're recursing; we allow changing typed tables here */
|
|
||||||
renameatt_check(myrelid, RelationGetForm(targetrelation), false);
|
|
||||||
|
|
||||||
constraintOid = get_constraint_oid(myrelid, oldconname, false);
|
if (mytypid)
|
||||||
|
{
|
||||||
|
constraintOid = get_domain_constraint_oid(mytypid, oldconname, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetrelation = relation_open(myrelid, AccessExclusiveLock);
|
||||||
|
/* don't tell it whether we're recursing; we allow changing typed tables here */
|
||||||
|
renameatt_check(myrelid, RelationGetForm(targetrelation), false);
|
||||||
|
|
||||||
|
constraintOid = get_relation_constraint_oid(myrelid, oldconname, false);
|
||||||
|
}
|
||||||
|
|
||||||
tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintOid));
|
tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintOid));
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
@ -2356,7 +2366,7 @@ rename_constraint_internal(Oid myrelid,
|
|||||||
constraintOid);
|
constraintOid);
|
||||||
con = (Form_pg_constraint) GETSTRUCT(tuple);
|
con = (Form_pg_constraint) GETSTRUCT(tuple);
|
||||||
|
|
||||||
if (con->contype == CONSTRAINT_CHECK && !con->conisonly)
|
if (myrelid && con->contype == CONSTRAINT_CHECK && !con->conisonly)
|
||||||
{
|
{
|
||||||
if (recurse)
|
if (recurse)
|
||||||
{
|
{
|
||||||
@ -2376,7 +2386,7 @@ rename_constraint_internal(Oid myrelid,
|
|||||||
if (childrelid == myrelid)
|
if (childrelid == myrelid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rename_constraint_internal(childrelid, oldconname, newconname, false, true, numparents);
|
rename_constraint_internal(childrelid, InvalidOid, oldconname, newconname, false, true, numparents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2407,24 +2417,43 @@ rename_constraint_internal(Oid myrelid,
|
|||||||
|
|
||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
|
|
||||||
relation_close(targetrelation, NoLock); /* close rel but keep lock */
|
if (targetrelation)
|
||||||
|
relation_close(targetrelation, NoLock); /* close rel but keep lock */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RenameConstraint(RenameStmt *stmt)
|
RenameConstraint(RenameStmt *stmt)
|
||||||
{
|
{
|
||||||
Oid relid;
|
Oid relid = InvalidOid;
|
||||||
|
Oid typid = InvalidOid;
|
||||||
|
|
||||||
/* lock level taken here should match rename_constraint_internal */
|
if (stmt->relationType == OBJECT_DOMAIN)
|
||||||
relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
|
{
|
||||||
false, false,
|
Relation rel;
|
||||||
RangeVarCallbackForRenameAttribute,
|
HeapTuple tup;
|
||||||
NULL);
|
|
||||||
|
|
||||||
rename_constraint_internal(relid,
|
typid = typenameTypeId(NULL, makeTypeNameFromNameList(stmt->object));
|
||||||
|
rel = heap_open(TypeRelationId, RowExclusiveLock);
|
||||||
|
tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
|
||||||
|
if (!HeapTupleIsValid(tup))
|
||||||
|
elog(ERROR, "cache lookup failed for type %u", typid);
|
||||||
|
checkDomainOwner(tup);
|
||||||
|
ReleaseSysCache(tup);
|
||||||
|
heap_close(rel, NoLock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* lock level taken here should match rename_constraint_internal */
|
||||||
|
relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
|
||||||
|
false, false,
|
||||||
|
RangeVarCallbackForRenameAttribute,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
rename_constraint_internal(relid, typid,
|
||||||
stmt->subname,
|
stmt->subname,
|
||||||
stmt->newname,
|
stmt->newname,
|
||||||
interpretInhOption(stmt->relation->inhOpt), /* recursive? */
|
stmt->relation ? interpretInhOption(stmt->relation->inhOpt) : false, /* recursive? */
|
||||||
false, /* recursing? */
|
false, /* recursing? */
|
||||||
0 /* expected inhcount */);
|
0 /* expected inhcount */);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,6 @@ static Oid findRangeCanonicalFunction(List *procname, Oid typeOid);
|
|||||||
static Oid findRangeSubtypeDiffFunction(List *procname, Oid subtype);
|
static Oid findRangeSubtypeDiffFunction(List *procname, Oid subtype);
|
||||||
static void validateDomainConstraint(Oid domainoid, char *ccbin);
|
static void validateDomainConstraint(Oid domainoid, char *ccbin);
|
||||||
static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode);
|
static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode);
|
||||||
static void checkDomainOwner(HeapTuple tup);
|
|
||||||
static void checkEnumOwner(HeapTuple tup);
|
static void checkEnumOwner(HeapTuple tup);
|
||||||
static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
|
static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
|
||||||
Oid baseTypeOid,
|
Oid baseTypeOid,
|
||||||
@ -2794,7 +2793,7 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode)
|
|||||||
* Check that the type is actually a domain and that the current user
|
* Check that the type is actually a domain and that the current user
|
||||||
* has permission to do ALTER DOMAIN on it. Throw an error if not.
|
* has permission to do ALTER DOMAIN on it. Throw an error if not.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
checkDomainOwner(HeapTuple tup)
|
checkDomainOwner(HeapTuple tup)
|
||||||
{
|
{
|
||||||
Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
|
Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup);
|
||||||
|
@ -6529,6 +6529,16 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
|
|||||||
n->missing_ok = false;
|
n->missing_ok = false;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
|
| ALTER DOMAIN_P any_name RENAME CONSTRAINT name TO name
|
||||||
|
{
|
||||||
|
RenameStmt *n = makeNode(RenameStmt);
|
||||||
|
n->renameType = OBJECT_CONSTRAINT;
|
||||||
|
n->relationType = OBJECT_DOMAIN;
|
||||||
|
n->object = $3;
|
||||||
|
n->subname = $6;
|
||||||
|
n->newname = $8;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
| ALTER FOREIGN DATA_P WRAPPER name RENAME TO name
|
| ALTER FOREIGN DATA_P WRAPPER name RENAME TO name
|
||||||
{
|
{
|
||||||
RenameStmt *n = makeNode(RenameStmt);
|
RenameStmt *n = makeNode(RenameStmt);
|
||||||
|
@ -802,7 +802,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
|
|||||||
|
|
||||||
/* Copy comment on constraint */
|
/* Copy comment on constraint */
|
||||||
if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
|
if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
|
||||||
(comment = GetComment(get_constraint_oid(RelationGetRelid(relation),
|
(comment = GetComment(get_relation_constraint_oid(RelationGetRelid(relation),
|
||||||
n->conname, false),
|
n->conname, false),
|
||||||
ConstraintRelationId,
|
ConstraintRelationId,
|
||||||
0)) != NULL)
|
0)) != NULL)
|
||||||
|
@ -244,7 +244,8 @@ extern char *ChooseConstraintName(const char *name1, const char *name2,
|
|||||||
|
|
||||||
extern void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
|
extern void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
|
||||||
Oid newNspId, bool isType);
|
Oid newNspId, bool isType);
|
||||||
extern Oid get_constraint_oid(Oid relid, const char *conname, bool missing_ok);
|
extern Oid get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok);
|
||||||
|
extern Oid get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok);
|
||||||
|
|
||||||
extern bool check_functional_grouping(Oid relid,
|
extern bool check_functional_grouping(Oid relid,
|
||||||
Index varno, Index varlevelsup,
|
Index varno, Index varlevelsup,
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#ifndef TYPECMDS_H
|
#ifndef TYPECMDS_H
|
||||||
#define TYPECMDS_H
|
#define TYPECMDS_H
|
||||||
|
|
||||||
|
#include "access/htup.h"
|
||||||
#include "nodes/parsenodes.h"
|
#include "nodes/parsenodes.h"
|
||||||
|
|
||||||
|
|
||||||
@ -35,6 +36,8 @@ extern void AlterDomainValidateConstraint(List *names, char *constrName);
|
|||||||
extern void AlterDomainDropConstraint(List *names, const char *constrName,
|
extern void AlterDomainDropConstraint(List *names, const char *constrName,
|
||||||
DropBehavior behavior, bool missing_ok);
|
DropBehavior behavior, bool missing_ok);
|
||||||
|
|
||||||
|
extern void checkDomainOwner(HeapTuple tup);
|
||||||
|
|
||||||
extern List *GetDomainConstraints(Oid typeOid);
|
extern List *GetDomainConstraints(Oid typeOid);
|
||||||
|
|
||||||
extern void RenameType(RenameStmt *stmt);
|
extern void RenameType(RenameStmt *stmt);
|
||||||
|
@ -659,3 +659,10 @@ create domain testdomain1 as int;
|
|||||||
alter domain testdomain1 rename to testdomain2;
|
alter domain testdomain1 rename to testdomain2;
|
||||||
alter type testdomain2 rename to testdomain3; -- alter type also works
|
alter type testdomain2 rename to testdomain3; -- alter type also works
|
||||||
drop domain testdomain3;
|
drop domain testdomain3;
|
||||||
|
--
|
||||||
|
-- Renaming domain constraints
|
||||||
|
--
|
||||||
|
create domain testdomain1 as int constraint unsigned check (value > 0);
|
||||||
|
alter domain testdomain1 rename constraint unsigned to unsigned_foo;
|
||||||
|
alter domain testdomain1 drop constraint unsigned_foo;
|
||||||
|
drop domain testdomain1;
|
||||||
|
@ -496,3 +496,13 @@ create domain testdomain1 as int;
|
|||||||
alter domain testdomain1 rename to testdomain2;
|
alter domain testdomain1 rename to testdomain2;
|
||||||
alter type testdomain2 rename to testdomain3; -- alter type also works
|
alter type testdomain2 rename to testdomain3; -- alter type also works
|
||||||
drop domain testdomain3;
|
drop domain testdomain3;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Renaming domain constraints
|
||||||
|
--
|
||||||
|
|
||||||
|
create domain testdomain1 as int constraint unsigned check (value > 0);
|
||||||
|
alter domain testdomain1 rename constraint unsigned to unsigned_foo;
|
||||||
|
alter domain testdomain1 drop constraint unsigned_foo;
|
||||||
|
drop domain testdomain1;
|
||||||
|
Reference in New Issue
Block a user