alter_extension.0.patch
text/x-patch
Filename: alter_extension.0.patch
Type: text/x-patch
Part: 1
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_depend.c | 54 | 0 |
| src/backend/commands/alter.c | 5 | 0 |
| src/backend/commands/extension.c | 91 | 0 |
| src/backend/parser/gram.y | 8 | 0 |
| src/backend/tcop/utility.c | 3 | 0 |
| src/include/catalog/dependency.h | 3 | 0 |
| src/include/commands/extension.h | 1 | 0 |
*** a/src/backend/catalog/pg_depend.c
--- b/src/backend/catalog/pg_depend.c
***************
*** 20,25 ****
--- 20,27 ----
#include "catalog/indexing.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
+ #include "catalog/pg_extension.h"
+ #include "catalog/pg_namespace.h"
#include "miscadmin.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
***************
*** 643,645 **** get_index_constraint(Oid indexId)
--- 645,699 ----
return constraintId;
}
+
+ /*
+ * get_extension_namespace
+ * Given the OID of an extension, return the OID of the schema it
+ * depends on, or InvalidOid when not found
+ */
+ Oid
+ get_extension_namespace(Oid extensionId)
+ {
+ Oid nspId = InvalidOid;
+ Relation depRel;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Search the dependency table for the index */
+ depRel = heap_open(DependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(ExtensionRelationId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(extensionId));
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(0));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ SnapshotNow, 3, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (deprec->refclassid == NamespaceRelationId &&
+ deprec->refobjsubid == 0 &&
+ deprec->deptype == DEPENDENCY_NORMAL)
+ {
+ nspId = deprec->refobjid;
+ break;
+ }
+ }
+
+ systable_endscan(scan);
+ heap_close(depRel, AccessShareLock);
+
+ return nspId;
+ }
*** a/src/backend/commands/alter.c
--- b/src/backend/commands/alter.c
***************
*** 20,25 ****
--- 20,26 ----
#include "commands/conversioncmds.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
+ #include "commands/extension.h"
#include "commands/proclang.h"
#include "commands/schemacmds.h"
#include "commands/tablecmds.h"
***************
*** 186,191 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
--- 187,196 ----
AlterConversionNamespace(stmt->object, stmt->newschema);
break;
+ case OBJECT_EXTENSION:
+ AlterExtensionNamespace(stmt->object, stmt->newschema);
+ break;
+
case OBJECT_FUNCTION:
AlterFunctionNamespace(stmt->object, stmt->objarg, false,
stmt->newschema);
*** a/src/backend/commands/extension.c
--- b/src/backend/commands/extension.c
***************
*** 38,48 ****
--- 38,51 ----
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
+ #include "catalog/namespace.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_type.h"
#include "commands/comment.h"
+ #include "commands/conversioncmds.h"
+ #include "commands/defrem.h"
#include "commands/extension.h"
#include "commands/portalcmds.h"
#include "funcapi.h"
***************
*** 1276,1278 **** pg_extension_objects(PG_FUNCTION_ARGS)
--- 1279,1369 ----
releaseDependentObjects(fctx->targetObjects);
SRF_RETURN_DONE(funcctx);
}
+
+ /*
+ * Execute ALTER EXTENSION SET SCHEMA
+ */
+ void
+ AlterExtensionNamespace(List *name, const char *newschema)
+ {
+ Oid extensionOid, nspOid, oldNspOid;
+ ObjectAddress *object;
+ ObjectAddresses *targetObjects;
+ int i;
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to ALTER EXTENSION"))));
+
+ Assert(list_length(name) == 1);
+ extensionOid = get_extension_oid(strVal(linitial(name)), false);
+ nspOid = LookupCreationNamespace(newschema);
+
+ object = (ObjectAddress *)palloc(sizeof(ObjectAddress));
+ object->classId = ExtensionRelationId;
+ object->objectId = extensionOid;
+ object->objectSubId = 0;
+
+ oldNspOid = get_extension_namespace(extensionOid);
+
+ targetObjects = listDependentObjects(object);
+
+ for (i = 0; i < targetObjects->numrefs; i++)
+ {
+ ObjectAddress *thisobj = targetObjects->refs + i;
+
+ /*
+ * Do the SET SCHEMA now.
+ *
+ * We only consider objects that have a namespace and that can exist
+ * without depending on another object (like a table) which will
+ * have its dependencies follow the SET SCHEMA operation.
+ */
+ switch (getObjectClass(thisobj))
+ {
+ case OCLASS_CLASS:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("Relations are not supported.")));
+ break;
+ case OCLASS_PROC:
+ AlterFunctionNamespace_oid(thisobj->objectId, nspOid);
+ break;
+ case OCLASS_TYPE:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("Types are not supported.")));
+ break;
+ case OCLASS_CONVERSION:
+ AlterConversionNamespace_oid(thisobj->objectId, nspOid);
+ break;
+ case OCLASS_OPERATOR:
+ AlterOperatorNamespace_oid(thisobj->objectId, nspOid);
+ break;
+ case OCLASS_OPCLASS:
+ AlterOpClassNamespace_oid(thisobj->objectId, nspOid);
+ break;
+ case OCLASS_OPFAMILY:
+ AlterOpFamilyNamespace_oid(thisobj->objectId, nspOid);
+ break;
+ case OCLASS_TSPARSER:
+ AlterTSParserNamespace_oid(thisobj->objectId, nspOid);
+ break;
+ case OCLASS_TSDICT:
+ AlterTSDictionaryNamespace_oid(thisobj->objectId, nspOid);
+ break;
+ case OCLASS_TSTEMPLATE:
+ AlterTSTemplateNamespace_oid(thisobj->objectId, nspOid);
+ break;
+ case OCLASS_TSCONFIG:
+ AlterTSConfigurationNamespace_oid(thisobj->objectId, nspOid);
+ break;
+ default:
+ break;
+ }
+ }
+ /* update dependencies to point to the new schema */
+ changeDependencyFor(ExtensionRelationId, extensionOid,
+ NamespaceRelationId, oldNspOid, nspOid);
+ }
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 6138,6143 **** AlterObjectSchemaStmt:
--- 6138,6151 ----
n->newschema = $6;
$$ = (Node *)n;
}
+ | ALTER EXTENSION any_name SET SCHEMA name
+ {
+ AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
+ n->objectType = OBJECT_EXTENSION;
+ n->object = $3;
+ n->newschema = $6;
+ $$ = (Node *)n;
+ }
| ALTER FUNCTION function_with_argtypes SET SCHEMA name
{
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 1719,1724 **** CreateCommandTag(Node *parsetree)
--- 1719,1727 ----
case OBJECT_DOMAIN:
tag = "ALTER DOMAIN";
break;
+ case OBJECT_EXTENSION:
+ tag = "ALTER EXTENSION";
+ break;
case OBJECT_OPERATOR:
tag = "ALTER OPERATOR";
break;
*** a/src/include/catalog/dependency.h
--- b/src/include/catalog/dependency.h
***************
*** 238,243 **** extern Oid get_constraint_index(Oid constraintId);
--- 238,246 ----
extern Oid get_index_constraint(Oid indexId);
+ extern Oid get_extension_namespace(Oid extensionId);
+
+
/* in pg_shdepend.c */
extern void recordSharedDependencyOn(ObjectAddress *depender,
*** a/src/include/commands/extension.h
--- b/src/include/commands/extension.h
***************
*** 64,69 **** extern void DropExtension(DropExtensionStmt *stmt);
--- 64,70 ----
extern Oid get_extension_oid(const char *extname, bool missing_ok);
extern char *get_extension_name(Oid ext_oid);
extern void RemoveExtensionById(Oid extId);
+ extern void AlterExtensionNamespace(List *name, const char *newschema);
#endif /* EXTENSION_H */