set_schema.4.patch
text/x-patch
Filename: set_schema.4.patch
Type: text/x-patch
Part: 2
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/catalog/pg_namespace.c | 38 | 0 |
| src/backend/commands/alter.c | 32 | 0 |
| src/backend/commands/conversioncmds.c | 84 | 0 |
| src/backend/commands/functioncmds.c | 19 | 0 |
| src/backend/commands/opclasscmds.c | 215 | 0 |
| src/backend/commands/operatorcmds.c | 90 | 0 |
| src/backend/commands/tsearchcmds.c | 295 | 0 |
| src/backend/parser/gram.y | 67 | 0 |
| src/backend/tcop/utility.c | 12 | 0 |
| src/include/catalog/pg_namespace.h | 2 | 0 |
| src/include/commands/conversioncmds.h | 5 | 0 |
| src/include/commands/defrem.h | 24 | 0 |
*** a/src/backend/catalog/pg_namespace.c
--- b/src/backend/catalog/pg_namespace.c
***************
*** 17,24 ****
--- 17,26 ----
#include "access/heapam.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
+ #include "catalog/namespace.h"
#include "catalog/pg_namespace.h"
#include "utils/builtins.h"
+ #include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
***************
*** 77,79 **** NamespaceCreate(const char *nspName, Oid ownerId)
--- 79,117 ----
return nspoid;
}
+
+ /*
+ * Check new namespace validity in ALTER OBJECT ... SET SCHEMA ... and
+ * ereport(ERROR, ...) in case of any problem.
+ */
+ void
+ CheckSetNamespace(Oid oldNspOid, Oid nspOid,
+ const char *name, const char *objtype)
+ {
+ if (oldNspOid == nspOid)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("%s \"%s\" already exists in schema \"%s\"",
+ objtype, name, get_namespace_name(nspOid))));
+
+ /* disallow renaming into or out of temp schemas */
+ if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot move objects into or out of temporary schemas")));
+
+ /* same for TOAST schema */
+ if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot move objects into or out of TOAST schema")));
+
+ /* check for duplicate name (more friendly than unique-index failure) */
+ if (SearchSysCacheExists2(TYPENAMENSP,
+ CStringGetDatum(name),
+ ObjectIdGetDatum(nspOid)))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("%s \"%s\" already exists in schema \"%s\"",
+ objtype, name, get_namespace_name(nspOid))));
+ }
*** a/src/backend/commands/alter.c
--- b/src/backend/commands/alter.c
***************
*** 182,192 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
--- 182,208 ----
stmt->newschema);
break;
+ case OBJECT_CONVERSION:
+ AlterConversionNamespace(stmt->object, stmt->newschema);
+ break;
+
case OBJECT_FUNCTION:
AlterFunctionNamespace(stmt->object, stmt->objarg, false,
stmt->newschema);
break;
+ case OBJECT_OPERATOR:
+ AlterOperatorNamespace(stmt->object, stmt->objarg, stmt->newschema);
+ break;
+
+ case OBJECT_OPCLASS:
+ AlterOpClassNamespace(stmt->object, stmt->objarg, stmt->newschema);
+ break;
+
+ case OBJECT_OPFAMILY:
+ AlterOpFamilyNamespace(stmt->object, stmt->objarg, stmt->newschema);
+ break;
+
case OBJECT_SEQUENCE:
case OBJECT_TABLE:
case OBJECT_VIEW:
***************
*** 195,200 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
--- 211,232 ----
stmt->objectType, AccessExclusiveLock);
break;
+ case OBJECT_TSPARSER:
+ AlterTSParserNamespace(stmt->object, stmt->newschema);
+ break;
+
+ case OBJECT_TSDICTIONARY:
+ AlterTSDictionaryNamespace(stmt->object, stmt->newschema);
+ break;
+
+ case OBJECT_TSTEMPLATE:
+ AlterTSTemplateNamespace(stmt->object, stmt->newschema);
+ break;
+
+ case OBJECT_TSCONFIGURATION:
+ AlterTSConfigurationNamespace(stmt->object, stmt->newschema);
+ break;
+
case OBJECT_TYPE:
case OBJECT_DOMAIN:
AlterTypeNamespace(stmt->object, stmt->newschema);
*** a/src/backend/commands/conversioncmds.c
--- b/src/backend/commands/conversioncmds.c
***************
*** 19,24 ****
--- 19,25 ----
#include "catalog/indexing.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_conversion_fn.h"
+ #include "catalog/pg_namespace.h"
#include "catalog/pg_type.h"
#include "commands/conversioncmds.h"
#include "mb/pg_wchar.h"
***************
*** 326,328 **** AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid newOwnerId)
--- 327,412 ----
heap_freetuple(tup);
}
+
+ /*
+ * Execute ALTER CONVERSION SET SCHEMA
+ */
+ void
+ AlterConversionNamespace(List *name, const char *newschema)
+ {
+ Oid conversionOid, nspOid;
+ Relation rel;
+
+ rel = heap_open(ConversionRelationId, RowExclusiveLock);
+
+ conversionOid = get_conversion_oid(name, false);
+
+ /* get schema OID */
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterConversionNamespace_internal(rel, conversionOid, nspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ /*
+ * Change conversion owner, by oid
+ */
+ void
+ AlterConversionNamespace_oid(Oid conversionOid, Oid newNspOid)
+ {
+ Relation rel;
+
+ rel = heap_open(ConversionRelationId, RowExclusiveLock);
+
+ AlterConversionNamespace_internal(rel, conversionOid, newNspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterConversionNamespace_internal(Relation rel, Oid conversionOid, Oid nspOid)
+ {
+ Oid oldNspOid;
+ HeapTuple tup;
+ Form_pg_conversion convForm;
+
+ Assert(RelationGetRelid(rel) == ConversionRelationId);
+
+ tup = SearchSysCacheCopy1(CONVOID, ObjectIdGetDatum(conversionOid));
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
+
+ convForm = (Form_pg_conversion) GETSTRUCT(tup);
+ oldNspOid = convForm->connamespace;
+
+ CheckSetNamespace(oldNspOid, nspOid,
+ NameStr(convForm->conname), "conversion");
+
+ /* Superusers can always do it */
+ if (!superuser())
+ {
+ AclResult aclresult;
+
+ /* Otherwise, must be owner of the existing object */
+ if (!pg_conversion_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
+ NameStr(convForm->conname));
+
+ /* owner must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(convForm->connamespace,
+ GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ get_namespace_name(convForm->connamespace));
+ }
+
+ convForm->connamespace = nspOid;
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ /* update dependencies to point to the new schema */
+ changeDependencyFor(ConversionRelationId, conversionOid,
+ NamespaceRelationId, oldNspOid, nspOid);
+ }
*** a/src/backend/commands/functioncmds.c
--- b/src/backend/commands/functioncmds.c
***************
*** 1870,1882 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
const char *newschema)
{
Oid procOid;
- Oid oldNspOid;
Oid nspOid;
- HeapTuple tup;
- Relation procRel;
- Form_pg_proc proc;
-
- procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
/* get function OID */
if (isagg)
--- 1870,1876 ----
***************
*** 1889,1894 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
--- 1883,1903 ----
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
NameListToString(name));
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterFunctionNamespace_oid(procOid, nspOid);
+ }
+
+ void
+ AlterFunctionNamespace_oid(Oid procOid, Oid nspOid)
+ {
+ Oid oldNspOid;
+ HeapTuple tup;
+ Relation procRel;
+ Form_pg_proc proc;
+
+ procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
+
tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid));
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for function %u", procOid);
***************
*** 1896,1910 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
oldNspOid = proc->pronamespace;
- /* get schema OID and check its permissions */
- nspOid = LookupCreationNamespace(newschema);
-
if (oldNspOid == nspOid)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_FUNCTION),
errmsg("function \"%s\" is already in schema \"%s\"",
! NameListToString(name),
! newschema)));
/* disallow renaming into or out of temp schemas */
if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
--- 1905,1916 ----
oldNspOid = proc->pronamespace;
if (oldNspOid == nspOid)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_FUNCTION),
errmsg("function \"%s\" is already in schema \"%s\"",
! NameStr(proc->proname),
! get_namespace_name(nspOid))));
/* disallow renaming into or out of temp schemas */
if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
***************
*** 1927,1933 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
(errcode(ERRCODE_DUPLICATE_FUNCTION),
errmsg("function \"%s\" already exists in schema \"%s\"",
NameStr(proc->proname),
! newschema)));
/* OK, modify the pg_proc row */
--- 1933,1939 ----
(errcode(ERRCODE_DUPLICATE_FUNCTION),
errmsg("function \"%s\" already exists in schema \"%s\"",
NameStr(proc->proname),
! get_namespace_name(nspOid))));
/* OK, modify the pg_proc row */
***************
*** 1941,1947 **** AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
if (changeDependencyFor(ProcedureRelationId, procOid,
NamespaceRelationId, oldNspOid, nspOid) != 1)
elog(ERROR, "failed to change schema dependency for function \"%s\"",
! NameListToString(name));
heap_freetuple(tup);
--- 1947,1953 ----
if (changeDependencyFor(ProcedureRelationId, procOid,
NamespaceRelationId, oldNspOid, nspOid) != 1)
elog(ERROR, "failed to change schema dependency for function \"%s\"",
! NameStr(proc->proname));
heap_freetuple(tup);
*** a/src/backend/commands/opclasscmds.c
--- b/src/backend/commands/opclasscmds.c
***************
*** 1912,1917 **** AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
--- 1912,2007 ----
}
/*
+ * ALTER OPERATOR CLASS any_name USING access_method SET SCHEMA name
+ */
+ void
+ AlterOpClassNamespace(List *name, List *argam, const char *newschema)
+ {
+ Oid amOid;
+ char *access_method = linitial(argam);
+ Relation rel;
+ HeapTuple tup, origtup;
+ Oid nspOid;
+
+ Assert(list_length(argam) == 1);
+
+ amOid = get_am_oid(access_method, false);
+
+ rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
+
+ /* Look up the opclass. */
+ origtup = OpClassCacheLookup(amOid, name, false);
+ tup = heap_copytuple(origtup);
+ ReleaseSysCache(origtup);
+
+ /* get schema OID */
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterOpClassNamespace_internal(rel, tup, nspOid);
+
+ heap_freetuple(tup);
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterOpClassNamespace_oid(Oid opclassOid, Oid newNspOid)
+ {
+ HeapTuple tup;
+ Relation rel;
+
+ rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy1(CLAOID, ObjectIdGetDatum(opclassOid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for opclass %u", opclassOid);
+
+ AlterOpClassOwner_internal(rel, tup, newNspOid);
+
+ heap_freetuple(tup);
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterOpClassNamespace_internal(Relation rel, HeapTuple tup, Oid nspOid)
+ {
+ Oid oldNspOid;
+ Form_pg_opclass opcForm;
+
+ opcForm = (Form_pg_opclass) GETSTRUCT(tup);
+ oldNspOid = opcForm->opcnamespace;
+
+ CheckSetNamespace(oldNspOid, nspOid,
+ NameStr(opcForm->opcname), "operator class");
+
+ /* Superusers can always do it */
+ if (!superuser())
+ {
+ AclResult aclresult;
+
+ /* Otherwise, must be owner of the existing object */
+ if (!pg_opclass_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
+ NameStr(opcForm->opcname));
+
+ /* New owner must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ get_namespace_name(nspOid));
+ }
+
+ /* tup is a copy, so we can scribble directly on it */
+ opcForm->opcnamespace = nspOid;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ /* update dependencies to point to the new schema */
+ changeDependencyFor(OperatorClassRelationId, HeapTupleGetOid(tup),
+ NamespaceRelationId, oldNspOid, nspOid);
+ }
+
+ /*
* Change opfamily owner by name
*/
void
***************
*** 2067,2069 **** get_am_oid(const char *amname, bool missing_ok)
--- 2157,2284 ----
errmsg("access method \"%s\" does not exist", amname)));
return oid;
}
+
+ /*
+ * ALTER OPERATOR FAMILY any_name USING access_method SET SCHEMA name
+ */
+ void
+ AlterOpFamilyNamespace(List *name, List *argam, const char *newschema)
+ {
+ Oid amOid;
+ char *access_method = linitial(argam);
+ Relation rel;
+ HeapTuple tup;
+ char *opfname, *schemaname;
+ Oid nspOid;
+
+ Assert(list_length(argam) == 1);
+ amOid = get_am_oid(access_method, false);
+
+ rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
+
+ /*
+ * Look up the opfamily
+ */
+ DeconstructQualifiedName(name, &schemaname, &opfname);
+
+ if (schemaname)
+ {
+ Oid namespaceOid;
+
+ namespaceOid = LookupExplicitNamespace(schemaname);
+
+ tup = SearchSysCacheCopy3(OPFAMILYAMNAMENSP,
+ ObjectIdGetDatum(amOid),
+ PointerGetDatum(opfname),
+ ObjectIdGetDatum(namespaceOid));
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("operator family \"%s\" does not exist for access method \"%s\"",
+ opfname, access_method)));
+ }
+ else
+ {
+ Oid opfOid;
+
+ opfOid = OpfamilynameGetOpfid(amOid, opfname);
+ if (!OidIsValid(opfOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("operator family \"%s\" does not exist for access method \"%s\"",
+ opfname, access_method)));
+
+ tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfOid));
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for opfamily %u", opfOid);
+ }
+
+ /* get schema OID */
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterOpFamilyNamespace_internal(rel, tup, nspOid);
+
+ heap_freetuple(tup);
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterOpFamilyNamespace_oid(Oid opfamilyOid, Oid newNspOid)
+ {
+ HeapTuple tup;
+ Relation rel;
+
+ rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfamilyOid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for opfamily %u", opfamilyOid);
+
+ AlterOpFamilyOwner_internal(rel, tup, newNspOid);
+
+ heap_freetuple(tup);
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterOpFamilyNamespace_internal(Relation rel, HeapTuple tup, Oid nspOid)
+ {
+ Oid oldNspOid;
+ Form_pg_opfamily opfForm;
+
+ Assert(tup->t_tableOid == OperatorFamilyRelationId);
+ Assert(RelationGetRelid(rel) == OperatorFamilyRelationId);
+
+ opfForm = (Form_pg_opfamily) GETSTRUCT(tup);
+ oldNspOid = opfForm->opfnamespace;
+
+ CheckSetNamespace(oldNspOid, nspOid,
+ NameStr(opfForm->opfname), "operator family");
+
+ /* Superusers can always do it */
+ if (!superuser())
+ {
+ AclResult aclresult;
+
+ /* Otherwise, must be owner of the existing object */
+ if (!pg_opfamily_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
+ NameStr(opfForm->opfname));
+
+ /* owner must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ get_namespace_name(nspOid));
+ }
+
+ /* tup is a copy, so we can scribble directly on it */
+ opfForm->opfnamespace = nspOid;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ /* update dependencies to point to the new schema */
+ changeDependencyFor(OperatorFamilyRelationId, HeapTupleGetOid(tup),
+ NamespaceRelationId, oldNspOid, nspOid);
+ }
*** a/src/backend/commands/operatorcmds.c
--- b/src/backend/commands/operatorcmds.c
***************
*** 39,44 ****
--- 39,45 ----
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_operator.h"
+ #include "catalog/pg_namespace.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "miscadmin.h"
***************
*** 452,454 **** AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId)
--- 453,544 ----
heap_freetuple(tup);
}
+
+ /*
+ * Execute ALTER OPERATOR SET SCHEMA
+ */
+ void
+ AlterOperatorNamespace_oid(Oid operOid, Oid newNspOid)
+ {
+ Relation rel;
+
+ rel = heap_open(OperatorRelationId, RowExclusiveLock);
+
+ AlterOperatorOwner_internal(rel, operOid, newNspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterOperatorNamespace(List *names, List *argtypes, const char *newschema)
+ {
+ List *operatorName = names;
+ TypeName *typeName1 = (TypeName *) linitial(argtypes);
+ TypeName *typeName2 = (TypeName *) lsecond(argtypes);
+ Oid operOid, nspOid;
+ Relation rel;
+
+ rel = heap_open(OperatorRelationId, RowExclusiveLock);
+
+ Assert(list_length(argtypes) == 2);
+ operOid = LookupOperNameTypeNames(NULL, operatorName,
+ typeName1, typeName2,
+ false, -1);
+
+ /* get schema OID */
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterOperatorNamespace_internal(rel, operOid, nspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterOperatorNamespace_internal(Relation rel, Oid operOid, Oid nspOid)
+ {
+ Form_pg_operator oprForm;
+ Oid oldNspOid;
+ HeapTuple tup;
+
+ Assert(RelationGetRelid(rel) == OperatorRelationId);
+
+ tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(operOid));
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for operator %u", operOid);
+
+ oprForm = (Form_pg_operator) GETSTRUCT(tup);
+ oldNspOid = oprForm->oprnamespace;
+
+ CheckSetNamespace(oldNspOid, nspOid, NameStr(oprForm->oprname), "operator");
+
+ /* Superusers can always do it */
+ if (!superuser())
+ {
+ AclResult aclresult;
+
+ /* Otherwise, must be owner of the existing object */
+ if (!pg_oper_ownercheck(operOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
+ NameStr(oprForm->oprname));
+
+ /* owner must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(oprForm->oprnamespace,
+ GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ get_namespace_name(oprForm->oprnamespace));
+ }
+
+ /* tup is a copy, so we can scribble directly on it */
+ oprForm->oprnamespace = nspOid;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ /* update dependencies to point to the new schema */
+ changeDependencyFor(OperatorRelationId, operOid,
+ NamespaceRelationId, oldNspOid, nspOid);
+
+ heap_freetuple(tup);
+ }
*** a/src/backend/commands/tsearchcmds.c
--- b/src/backend/commands/tsearchcmds.c
***************
*** 393,398 **** RenameTSParser(List *oldname, const char *newname)
--- 393,465 ----
heap_freetuple(tup);
}
+ /*
+ * ALTER TEXT SEARCH PARSER any_name SET SCHEMA name
+ */
+ void
+ AlterTSParserNamespace(List *name, const char *newschema)
+ {
+ Oid prsId, nspOid;
+ Relation rel;
+
+ rel = heap_open(TSParserRelationId, RowExclusiveLock);
+
+ prsId = get_ts_parser_oid(name, false);
+
+ /* get schema OID */
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterTSParserNamespace_internal(rel, prsId, nspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterTSParserNamespace_oid(Oid prsId, Oid newNspOid)
+ {
+ Relation rel;
+
+ rel = heap_open(TSParserRelationId, RowExclusiveLock);
+
+ AlterTSParserNamespace_internal(rel, prsId, newNspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterTSParserNamespace_internal(Relation rel, Oid prsId, Oid nspOid)
+ {
+ HeapTuple tup;
+ Oid oldNspOid;
+ Form_pg_ts_parser prs;
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to rename text search parsers")));
+
+ tup = SearchSysCacheCopy1(TSPARSEROID, ObjectIdGetDatum(prsId));
+
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for text search parser %u", prsId);
+
+ prs = (Form_pg_ts_parser) GETSTRUCT(tup);
+ oldNspOid = prs->prsnamespace;
+
+ CheckSetNamespace(oldNspOid, nspOid,
+ NameStr(prs->prsname), "text search parser");
+
+ prs->prsnamespace = nspOid;
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ /* update dependencies to point to the new schema */
+ changeDependencyFor(TSParserRelationId, prsId,
+ NamespaceRelationId, oldNspOid, nspOid);
+
+ heap_freetuple(tup);
+ }
+
/* ---------------------- TS Dictionary commands -----------------------*/
/*
***************
*** 620,625 **** RenameTSDictionary(List *oldname, const char *newname)
--- 687,772 ----
}
/*
+ * ALTER TEXT SEARCH PARSER any_name SET SCHEMA name
+ */
+ void
+ AlterTSDictionaryNamespace(List *name, const char *newschema)
+ {
+ Oid dictId, nspOid;
+ Relation rel;
+
+ rel = heap_open(TSDictionaryRelationId, RowExclusiveLock);
+
+ dictId = get_ts_dict_oid(name, false);
+
+ /* get schema OID */
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterTSDictionaryNamespace_internal(rel, dictId, nspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterTSDictionaryNamespace_oid(Oid dictId, Oid newNspOid)
+ {
+ Relation rel;
+
+ rel = heap_open(TSDictionaryRelationId, RowExclusiveLock);
+
+ AlterTSDictionaryNamespace_internal(rel, dictId, newNspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterTSDictionaryNamespace_internal(Relation rel, Oid dictId, Oid nspOid)
+ {
+ HeapTuple tup;
+ Oid oldNspOid;
+ Form_pg_ts_dict dict;
+
+ tup = SearchSysCacheCopy1(TSDICTOID, ObjectIdGetDatum(dictId));
+
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for text search dictionary %u",
+ dictId);
+
+ dict = ((Form_pg_ts_dict) GETSTRUCT(tup));
+ oldNspOid = dict->dictnamespace;
+
+ CheckSetNamespace(oldNspOid, nspOid,
+ NameStr(dict->dictname), "text search dictionary");
+
+ /* Superusers can always do it */
+ if (!superuser())
+ {
+ AclResult aclresult;
+
+ /* Otherwise, must be owner of the existing object */
+ if (!pg_ts_dict_ownercheck(dictId, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
+ NameStr(dict->dictname));
+
+ /* owner must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(oldNspOid, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ get_namespace_name(oldNspOid));
+ }
+
+ dict->dictnamespace = nspOid;
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ /* update dependencies to point to the new schema */
+ changeDependencyFor(TSDictionaryRelationId, dictId,
+ NamespaceRelationId, oldNspOid, nspOid);
+
+ heap_freetuple(tup);
+ }
+
+ /*
* DROP TEXT SEARCH DICTIONARY
*/
void
***************
*** 1100,1105 **** RenameTSTemplate(List *oldname, const char *newname)
--- 1247,1321 ----
}
/*
+ * ALTER TEXT SEARCH TEMPLATE any_name SET SCHEMA name
+ */
+ void
+ AlterTSTemplateNamespace(List *name, const char *newschema)
+ {
+ Oid tmplId, nspOid;
+ Relation rel;
+
+ rel = heap_open(TSTemplateRelationId, RowExclusiveLock);
+
+ tmplId = get_ts_template_oid(name, false);
+
+ /* get schema OID */
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterTSTemplateNamespace_internal(rel, tmplId, nspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid)
+ {
+ Relation rel;
+
+ rel = heap_open(TSTemplateRelationId, RowExclusiveLock);
+
+ AlterTSTemplateNamespace_internal(rel, tmplId, newNspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterTSTemplateNamespace_internal(Relation rel, Oid tmplId, Oid nspOid)
+ {
+ HeapTuple tup;
+ Oid oldNspOid;
+ Form_pg_ts_template tmpl;
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to rename text search templates")));
+
+ tup = SearchSysCacheCopy1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId));
+
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for text search template %u",
+ tmplId);
+
+ tmpl = (Form_pg_ts_template) GETSTRUCT(tup);
+ oldNspOid = tmpl->tmplnamespace;
+
+ CheckSetNamespace(oldNspOid, nspOid,
+ NameStr(tmpl->tmplname), "text search template");
+
+ tmpl->tmplnamespace = nspOid;
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ /* update dependencies to point to the new schema */
+ changeDependencyFor(TSTemplateRelationId, tmplId,
+ NamespaceRelationId, oldNspOid, nspOid);
+
+ heap_freetuple(tup);
+ }
+
+
+ /*
* DROP TEXT SEARCH TEMPLATE
*/
void
***************
*** 1498,1503 **** RenameTSConfiguration(List *oldname, const char *newname)
--- 1714,1798 ----
}
/*
+ * ALTER TEXT SEARCH CONFIGURATION any_name SET SCHEMA name
+ */
+ void
+ AlterTSConfigurationNamespace(List *name, const char *newschema)
+ {
+ Oid cfgId, nspOid;
+ Relation rel;
+
+ rel = heap_open(TSConfigRelationId, RowExclusiveLock);
+
+ cfgId = get_ts_config_oid(name, false);
+
+ /* get schema OID */
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterTSConfigurationNamespace_internal(rel, cfgId, nspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterTSConfigurationNamespace_oid(Oid cfgId, Oid newNspOid)
+ {
+ Relation rel;
+
+ rel = heap_open(TSConfigRelationId, RowExclusiveLock);
+
+ AlterTSConfigurationNamespace_internal(rel, cfgId, newNspOid);
+
+ heap_close(rel, NoLock);
+ }
+
+ void
+ AlterTSConfigurationNamespace_internal(Relation rel, Oid cfgId, Oid nspOid)
+ {
+ HeapTuple tup;
+ Oid oldNspOid;
+ Form_pg_ts_config cfg;
+
+ tup = SearchSysCacheCopy1(TSCONFIGOID, ObjectIdGetDatum(cfgId));
+
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for text search configuration %u",
+ cfgId);
+
+ cfg = (Form_pg_ts_config) GETSTRUCT(tup);
+ oldNspOid = cfg->cfgnamespace;
+
+ CheckSetNamespace(oldNspOid, nspOid,
+ NameStr(cfg->cfgname), "text search configuration");
+
+ /* Superusers can always do it */
+ if (!superuser())
+ {
+ AclResult aclresult;
+
+ /* Otherwise, must be owner of the existing object */
+ if (!pg_ts_config_ownercheck(cfgId, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
+ NameStr(cfg->cfgname));
+
+ /* owner must have CREATE privilege on namespace */
+ aclresult = pg_namespace_aclcheck(oldNspOid, GetUserId(), ACL_CREATE);
+ aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ get_namespace_name(oldNspOid));
+ }
+
+ cfg->cfgnamespace = nspOid;
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ /* update dependencies to point to the new schema */
+ changeDependencyFor(TSConfigRelationId, cfgId,
+ NamespaceRelationId, oldNspOid, nspOid);
+
+ heap_freetuple(tup);
+ }
+
+ /*
* DROP TEXT SEARCH CONFIGURATION
*/
void
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 6040,6045 **** AlterObjectSchemaStmt:
--- 6040,6053 ----
n->newschema = $7;
$$ = (Node *)n;
}
+ | ALTER CONVERSION_P any_name SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_CONVERSION;
+ n->object = $3;
+ n->newschema = $6;
+ $$ = (Node *)n;
+ }
| ALTER DOMAIN_P any_name SET SCHEMA name
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
***************
*** 6057,6062 **** AlterObjectSchemaStmt:
--- 6065,6097 ----
n->newschema = $6;
$$ = (Node *)n;
}
+ | ALTER OPERATOR any_operator oper_argtypes SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_OPERATOR;
+ n->object = $3;
+ n->objarg = $4;
+ n->newschema = $7;
+ $$ = (Node *)n;
+ }
+ | ALTER OPERATOR CLASS any_name USING access_method SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_OPCLASS;
+ n->object = $4;
+ n->objarg = list_make1($6);
+ n->newschema = $9;
+ $$ = (Node *)n;
+ }
+ | ALTER OPERATOR FAMILY any_name USING access_method SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_OPFAMILY;
+ n->object = $4;
+ n->objarg = list_make1($6);
+ n->newschema = $9;
+ $$ = (Node *)n;
+ }
| ALTER TABLE relation_expr SET SCHEMA name
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
***************
*** 6065,6070 **** AlterObjectSchemaStmt:
--- 6100,6137 ----
n->newschema = $6;
$$ = (Node *)n;
}
+ | ALTER TEXT_P SEARCH PARSER any_name SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_TSPARSER;
+ n->object = $5;
+ n->newschema = $8;
+ $$ = (Node *)n;
+ }
+ | ALTER TEXT_P SEARCH DICTIONARY any_name SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_TSDICTIONARY;
+ n->object = $5;
+ n->newschema = $8;
+ $$ = (Node *)n;
+ }
+ | ALTER TEXT_P SEARCH TEMPLATE any_name SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_TSTEMPLATE;
+ n->object = $5;
+ n->newschema = $8;
+ $$ = (Node *)n;
+ }
+ | ALTER TEXT_P SEARCH CONFIGURATION any_name SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_TSCONFIGURATION;
+ n->object = $5;
+ n->newschema = $8;
+ $$ = (Node *)n;
+ }
| ALTER SEQUENCE qualified_name SET SCHEMA name
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 1694,1702 **** CreateCommandTag(Node *parsetree)
--- 1694,1714 ----
case OBJECT_AGGREGATE:
tag = "ALTER AGGREGATE";
break;
+ case OBJECT_CONVERSION:
+ tag = "ALTER CONVERSION";
+ break;
case OBJECT_DOMAIN:
tag = "ALTER DOMAIN";
break;
+ case OBJECT_OPERATOR:
+ tag = "ALTER OPERATOR";
+ break;
+ case OBJECT_OPCLASS:
+ tag = "ALTER OPERATOR CLASS";
+ break;
+ case OBJECT_OPFAMILY:
+ tag = "ALTER OPERATOR FAMILY";
+ break;
case OBJECT_FUNCTION:
tag = "ALTER FUNCTION";
break;
*** a/src/include/catalog/pg_namespace.h
--- b/src/include/catalog/pg_namespace.h
***************
*** 78,82 **** DESCR("standard public schema");
--- 78,84 ----
* prototypes for functions in pg_namespace.c
*/
extern Oid NamespaceCreate(const char *nspName, Oid ownerId);
+ extern void CheckSetNamespace(Oid oldNspOid, Oid nspOid,
+ const char *name, const char *objtype);
#endif /* PG_NAMESPACE_H */
*** a/src/include/commands/conversioncmds.h
--- b/src/include/commands/conversioncmds.h
***************
*** 16,26 ****
--- 16,31 ----
#define CONVERSIONCMDS_H
#include "nodes/parsenodes.h"
+ #include "utils/relcache.h"
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
extern void DropConversionsCommand(DropStmt *drop);
extern void RenameConversion(List *name, const char *newname);
extern void AlterConversionOwner(List *name, Oid newOwnerId);
extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId);
+ extern void AlterConversionNamespace(List *name, const char *newschema);
+ extern void AlterConversionNamespace_oid(Oid conversionOid, Oid newNspOid);
+ extern void AlterConversionNamespace_internal(Relation rel, Oid conversionOid, Oid nspOid);
+
#endif /* CONVERSIONCMDS_H */
*** a/src/include/commands/defrem.h
--- b/src/include/commands/defrem.h
***************
*** 14,20 ****
--- 14,22 ----
#ifndef DEFREM_H
#define DEFREM_H
+ #include "access/htup.h"
#include "nodes/parsenodes.h"
+ #include "utils/relcache.h"
/* commands/indexcmds.c */
***************
*** 66,71 **** extern void DropCast(DropCastStmt *stmt);
--- 68,74 ----
extern void DropCastById(Oid castOid);
extern void AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
const char *newschema);
+ extern void AlterFunctionNamespace_oid(Oid procOid, Oid nspOid);
extern void ExecuteDoStmt(DoStmt *stmt);
extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok);
***************
*** 78,83 **** extern void AlterOperatorOwner(List *name, TypeName *typeName1,
--- 81,89 ----
extern void AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId);
extern Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok);
extern Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok);
+ extern void AlterOperatorNamespace_oid(Oid operOid, Oid newNspOid);
+ extern void AlterOperatorNamespace(List *names, List *argtypes, const char *newschema);
+ extern void AlterOperatorNamespace_internal(Relation rel, Oid operoid, Oid nspOid);
/* commands/aggregatecmds.c */
extern void DefineAggregate(List *name, List *args, bool oldstyle,
***************
*** 100,114 **** extern void RenameOpClass(List *name, const char *access_method, const char *new
--- 106,129 ----
extern void RenameOpFamily(List *name, const char *access_method, const char *newname);
extern void AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId);
extern void AlterOpClassOwner_oid(Oid opclassOid, Oid newOwnerId);
+ extern void AlterOpClassNamespace(List *name, List *argam, const char *newschema);
+ extern void AlterOpClassNamespace_oid(Oid opclassOid, Oid newNspOid);
+ extern void AlterOpClassNamespace_internal(Relation rel, HeapTuple tup, Oid nspOid);
extern void AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwnerId);
extern void AlterOpFamilyOwner_oid(Oid opfamilyOid, Oid newOwnerId);
extern Oid get_am_oid(const char *amname, bool missing_ok);
+ extern void AlterOpFamilyNamespace(List *name, List *argam, const char *newschema);
+ extern void AlterOpFamilyNamespace_oid(Oid opfamilyOid, Oid newNspOid);
+ extern void AlterOpFamilyNamespace_internal(Relation rel, HeapTuple tup, Oid nspOid);
/* commands/tsearchcmds.c */
extern void DefineTSParser(List *names, List *parameters);
extern void RenameTSParser(List *oldname, const char *newname);
extern void RemoveTSParsers(DropStmt *drop);
extern void RemoveTSParserById(Oid prsId);
+ extern void AlterTSParserNamespace(List *name, const char *newschema);
+ extern void AlterTSParserNamespace_oid(Oid prsId, Oid newNspOid);
+ extern void AlterTSParserNamespace_internal(Relation rel, Oid prsId, Oid nspOid);
extern void DefineTSDictionary(List *names, List *parameters);
extern void RenameTSDictionary(List *oldname, const char *newname);
***************
*** 116,129 **** extern void RemoveTSDictionaries(DropStmt *drop);
--- 131,153 ----
extern void RemoveTSDictionaryById(Oid dictId);
extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId);
+ extern void AlterTSDictionaryNamespace(List *name, const char *newschema);
+ extern void AlterTSDictionaryNamespace_oid(Oid dictId, Oid newNspOid);
+ extern void AlterTSDictionaryNamespace_internal(Relation rel, Oid dictId, Oid nspOid);
extern void DefineTSTemplate(List *names, List *parameters);
extern void RenameTSTemplate(List *oldname, const char *newname);
+ extern void AlterTSTemplateNamespace(List *name, const char *newschema);
+ extern void AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid);
+ extern void AlterTSTemplateNamespace_internal(Relation rel, Oid tmplId, Oid nspOid);
extern void RemoveTSTemplates(DropStmt *stmt);
extern void RemoveTSTemplateById(Oid tmplId);
extern void DefineTSConfiguration(List *names, List *parameters);
extern void RenameTSConfiguration(List *oldname, const char *newname);
+ extern void AlterTSConfigurationNamespace(List *name, const char *newschema);
+ extern void AlterTSConfigurationNamespace_oid(Oid cfgId, Oid newNspOid);
+ extern void AlterTSConfigurationNamespace_internal(Relation rel, Oid cfgId, Oid nspOid);
extern void RemoveTSConfigurations(DropStmt *stmt);
extern void RemoveTSConfigurationById(Oid cfgId);
extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);