Skip to content

Commit 44475e7

Browse files
committed
Centralize some ALTER <whatever> .. SET SCHEMA checks.
Any flavor of ALTER <whatever> .. SET SCHEMA fails if (1) the object is already in the new schema, (2) either the old or new schema is a temp schema, or (3) either the old or new schema is the TOAST schema. Extraced from a patch by Dimitri Fontaine, with additional hacking by me.
1 parent 5272d79 commit 44475e7

File tree

7 files changed

+58
-54
lines changed

7 files changed

+58
-54
lines changed

src/backend/catalog/dependency.c

+15
Original file line numberDiff line numberDiff line change
@@ -2684,6 +2684,21 @@ getObjectDescription(const ObjectAddress *object)
26842684
return buffer.data;
26852685
}
26862686

2687+
/*
2688+
* getObjectDescriptionOids: as above, except the object is specified by Oids
2689+
*/
2690+
char *
2691+
getObjectDescriptionOids(Oid classid, Oid objid)
2692+
{
2693+
ObjectAddress address;
2694+
2695+
address.classId = classid;
2696+
address.objectId = objid;
2697+
address.objectSubId = 0;
2698+
2699+
return getObjectDescription(&address);
2700+
}
2701+
26872702
/*
26882703
* subroutine for getObjectDescription: describe a relation
26892704
*/

src/backend/catalog/namespace.c

+34
Original file line numberDiff line numberDiff line change
@@ -2339,6 +2339,40 @@ LookupCreationNamespace(const char *nspname)
23392339
return namespaceId;
23402340
}
23412341

2342+
/*
2343+
* Common checks on switching namespaces.
2344+
*
2345+
* We complain if (1) the old and new namespaces are the same, (2) either the
2346+
* old or new namespaces is a temporary schema (or temporary toast schema), or
2347+
* (3) either the old or new namespaces is the TOAST schema.
2348+
*/
2349+
void
2350+
CheckSetNamespace(Oid oldNspOid, Oid nspOid, Oid classid, Oid objid)
2351+
{
2352+
if (oldNspOid == nspOid)
2353+
ereport(ERROR,
2354+
(classid == RelationRelationId ?
2355+
errcode(ERRCODE_DUPLICATE_TABLE) :
2356+
classid == ProcedureRelationId ?
2357+
errcode(ERRCODE_DUPLICATE_FUNCTION) :
2358+
errcode(ERRCODE_DUPLICATE_OBJECT),
2359+
errmsg("%s is already in schema \"%s\"",
2360+
getObjectDescriptionOids(classid, objid),
2361+
get_namespace_name(nspOid))));
2362+
2363+
/* disallow renaming into or out of temp schemas */
2364+
if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
2365+
ereport(ERROR,
2366+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2367+
errmsg("cannot move objects into or out of temporary schemas")));
2368+
2369+
/* same for TOAST schema */
2370+
if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
2371+
ereport(ERROR,
2372+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2373+
errmsg("cannot move objects into or out of TOAST schema")));
2374+
}
2375+
23422376
/*
23432377
* QualifiedNameGetCreationNamespace
23442378
* Given a possibly-qualified name for an object (in List-of-Values

src/backend/commands/functioncmds.c

+2-18
Original file line numberDiff line numberDiff line change
@@ -1899,24 +1899,8 @@ AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
18991899
/* get schema OID and check its permissions */
19001900
nspOid = LookupCreationNamespace(newschema);
19011901

1902-
if (oldNspOid == nspOid)
1903-
ereport(ERROR,
1904-
(errcode(ERRCODE_DUPLICATE_FUNCTION),
1905-
errmsg("function \"%s\" is already in schema \"%s\"",
1906-
NameListToString(name),
1907-
newschema)));
1908-
1909-
/* disallow renaming into or out of temp schemas */
1910-
if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
1911-
ereport(ERROR,
1912-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1913-
errmsg("cannot move objects into or out of temporary schemas")));
1914-
1915-
/* same for TOAST schema */
1916-
if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
1917-
ereport(ERROR,
1918-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1919-
errmsg("cannot move objects into or out of TOAST schema")));
1902+
/* common checks on switching namespaces */
1903+
CheckSetNamespace(oldNspOid, nspOid, ProcedureRelationId, procOid);
19201904

19211905
/* check for duplicate name (more friendly than unique-index failure) */
19221906
if (SearchSysCacheExists3(PROCNAMEARGSNSP,

src/backend/commands/tablecmds.c

+2-18
Original file line numberDiff line numberDiff line change
@@ -8114,24 +8114,8 @@ AlterTableNamespace(RangeVar *relation, const char *newschema,
81148114
/* get schema OID and check its permissions */
81158115
nspOid = LookupCreationNamespace(newschema);
81168116

8117-
if (oldNspOid == nspOid)
8118-
ereport(ERROR,
8119-
(errcode(ERRCODE_DUPLICATE_TABLE),
8120-
errmsg("relation \"%s\" is already in schema \"%s\"",
8121-
RelationGetRelationName(rel),
8122-
newschema)));
8123-
8124-
/* disallow renaming into or out of temp schemas */
8125-
if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
8126-
ereport(ERROR,
8127-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8128-
errmsg("cannot move objects into or out of temporary schemas")));
8129-
8130-
/* same for TOAST schema */
8131-
if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
8132-
ereport(ERROR,
8133-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8134-
errmsg("cannot move objects into or out of TOAST schema")));
8117+
/* common checks on switching namespaces */
8118+
CheckSetNamespace(oldNspOid, nspOid, RelationRelationId, relid);
81358119

81368120
/* OK, modify the pg_class row and pg_depend entry */
81378121
classRel = heap_open(RelationRelationId, RowExclusiveLock);

src/backend/commands/typecmds.c

+2-18
Original file line numberDiff line numberDiff line change
@@ -2828,24 +2828,8 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
28282828
oldNspOid = typform->typnamespace;
28292829
arrayOid = typform->typarray;
28302830

2831-
if (oldNspOid == nspOid)
2832-
ereport(ERROR,
2833-
(errcode(ERRCODE_DUPLICATE_OBJECT),
2834-
errmsg("type %s is already in schema \"%s\"",
2835-
format_type_be(typeOid),
2836-
get_namespace_name(nspOid))));
2837-
2838-
/* disallow renaming into or out of temp schemas */
2839-
if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
2840-
ereport(ERROR,
2841-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2842-
errmsg("cannot move objects into or out of temporary schemas")));
2843-
2844-
/* same for TOAST schema */
2845-
if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
2846-
ereport(ERROR,
2847-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2848-
errmsg("cannot move objects into or out of TOAST schema")));
2831+
/* common checks on switching namespaces */
2832+
CheckSetNamespace(oldNspOid, nspOid, TypeRelationId, typeOid);
28492833

28502834
/* check for duplicate name (more friendly than unique-index failure) */
28512835
if (SearchSysCacheExists2(TYPENAMENSP,

src/include/catalog/dependency.h

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ extern void recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
165165
extern ObjectClass getObjectClass(const ObjectAddress *object);
166166

167167
extern char *getObjectDescription(const ObjectAddress *object);
168+
extern char *getObjectDescriptionOids(Oid classid, Oid objid);
168169

169170
extern ObjectAddresses *new_object_addresses(void);
170171

src/include/catalog/namespace.h

+2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ extern Oid LookupExplicitNamespace(const char *nspname);
9494
extern Oid get_namespace_oid(const char *nspname, bool missing_ok);
9595

9696
extern Oid LookupCreationNamespace(const char *nspname);
97+
extern void CheckSetNamespace(Oid oldNspOid, Oid nspOid, Oid classid,
98+
Oid objid);
9799
extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
98100
extern RangeVar *makeRangeVarFromNameList(List *names);
99101
extern char *NameListToString(List *names);

0 commit comments

Comments
 (0)