>From a0fe2f007420254d908b64c266e8956d042c1c43 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 9 Feb 2015 19:17:21 -0300 Subject: [PATCH 31/44] deparse: support ALTER ... SET SCHEMA --- src/backend/commands/alter.c | 16 ++++++++------ src/backend/commands/extension.c | 6 +++++- src/backend/commands/tablecmds.c | 5 ++++- src/backend/commands/typecmds.c | 9 ++++++-- src/backend/tcop/deparse_utility.c | 44 +++++++++++++++++++++++++++++++++++++- src/backend/tcop/utility.c | 5 +++-- src/include/commands/alter.h | 3 ++- src/include/commands/extension.h | 3 ++- src/include/commands/tablecmds.h | 2 +- src/include/commands/typecmds.h | 3 ++- 10 files changed, 79 insertions(+), 17 deletions(-) diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index c8901be..bdc79c9 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -394,24 +394,24 @@ ExecRenameStmt(RenameStmt *stmt) * type, the function appropriate to that type is executed. */ Oid -ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) +ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt, Oid *oldschema) { switch (stmt->objectType) { case OBJECT_EXTENSION: - return AlterExtensionNamespace(stmt->object, stmt->newschema); + return AlterExtensionNamespace(stmt->object, stmt->newschema, oldschema); case OBJECT_FOREIGN_TABLE: case OBJECT_SEQUENCE: case OBJECT_TABLE: case OBJECT_VIEW: case OBJECT_MATVIEW: - return AlterTableNamespace(stmt); + return AlterTableNamespace(stmt, oldschema); case OBJECT_DOMAIN: case OBJECT_TYPE: return AlterTypeNamespace(stmt->object, stmt->newschema, - stmt->objectType); + stmt->objectType, oldschema); /* generic code path */ case OBJECT_AGGREGATE: @@ -431,6 +431,7 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) Oid classId; Oid nspOid; ObjectAddress address; + Oid oldNspOid; address = get_object_address(stmt->objectType, stmt->object, @@ -443,10 +444,13 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt) catalog = heap_open(classId, RowExclusiveLock); nspOid = LookupCreationNamespace(stmt->newschema); - AlterObjectNamespace_internal(catalog, address.objectId, - nspOid); + oldNspOid = AlterObjectNamespace_internal(catalog, address.objectId, + nspOid); heap_close(catalog, RowExclusiveLock); + if (oldschema) + *oldschema = oldNspOid; + return address.objectId; } break; diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 73f8bea..4b28a8d 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -2400,7 +2400,7 @@ extension_config_remove(Oid extensionoid, Oid tableoid) * Execute ALTER EXTENSION SET SCHEMA */ Oid -AlterExtensionNamespace(List *names, const char *newschema) +AlterExtensionNamespace(List *names, const char *newschema, Oid *oldschema) { char *extensionName; Oid extensionOid; @@ -2557,6 +2557,10 @@ AlterExtensionNamespace(List *names, const char *newschema) get_namespace_name(oldNspOid)))); } + /* report old schema, if caller wants it */ + if (oldschema) + *oldschema = oldNspOid; + systable_endscan(depScan); relation_close(depRel, AccessShareLock); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 43f4018..5be235c 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -11052,7 +11052,7 @@ ATPrepChangePersistence(Relation rel, bool toLogged) * Execute ALTER TABLE SET SCHEMA */ Oid -AlterTableNamespace(AlterObjectSchemaStmt *stmt) +AlterTableNamespace(AlterObjectSchemaStmt *stmt, Oid *oldschema) { Relation rel; Oid relid; @@ -11104,6 +11104,9 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt) AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved); free_object_addresses(objsMoved); + if (oldschema) + *oldschema = oldNspOid; + /* close rel, but keep lock until commit */ relation_close(rel, NoLock); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 1de37eb..1d58b9d 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -3540,11 +3540,13 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId, * Execute ALTER TYPE SET SCHEMA */ Oid -AlterTypeNamespace(List *names, const char *newschema, ObjectType objecttype) +AlterTypeNamespace(List *names, const char *newschema, ObjectType objecttype, + Oid *oldschema) { TypeName *typename; Oid typeOid; Oid nspOid; + Oid oldNspOid; ObjectAddresses *objsMoved; /* Make a TypeName so we can use standard type lookup machinery */ @@ -3562,9 +3564,12 @@ AlterTypeNamespace(List *names, const char *newschema, ObjectType objecttype) nspOid = LookupCreationNamespace(newschema); objsMoved = new_object_addresses(); - AlterTypeNamespace_oid(typeOid, nspOid, objsMoved); + oldNspOid = AlterTypeNamespace_oid(typeOid, nspOid, objsMoved); free_object_addresses(objsMoved); + if (oldschema) + *oldschema = oldNspOid; + return typeOid; } diff --git a/src/backend/tcop/deparse_utility.c b/src/backend/tcop/deparse_utility.c index 5e89514..17e6c08 100644 --- a/src/backend/tcop/deparse_utility.c +++ b/src/backend/tcop/deparse_utility.c @@ -4110,6 +4110,47 @@ deparse_AlterEnumStmt(Oid objectId, Node *parsetree) } static ObjTree * +deparse_AlterObjectSchemaStmt(Oid objectId, Node *parsetree, Oid oldschema) +{ + AlterObjectSchemaStmt *node = (AlterObjectSchemaStmt *) parsetree; + ObjTree *alterStmt; + ObjectAddress addr; + char *fmt; + char *identity; + char *newschema; + char *oldschname; + char *ident; + + newschema = node->newschema; + + fmt = psprintf("ALTER %s %%{identity}s SET SCHEMA %%{newschema}I", + stringify_objtype(node->objectType)); + alterStmt = new_objtree_VA(fmt, 0); + append_string_object(alterStmt, "newschema", newschema); + + /* + * Since the command has already taken place from the point of view of + * catalogs, getObjectIdentity returns the object name with the already + * changed schema. The output of our deparsing must return the original + * schema name however, so we chop the schema name off the identity string + * and then prepend the quoted schema name. + */ + addr.classId = get_objtype_catalog_oid(node->objectType); + addr.objectId = objectId; + addr.objectSubId = 0; + identity = getObjectIdentity(&addr); + oldschname = get_namespace_name(oldschema); + if (!oldschname) + elog(ERROR, "cache lookup failed for schema with OID %u", oldschema); + ident = psprintf("%s%s", + quote_identifier(oldschname), + identity + strlen(quote_identifier(newschema))); + append_string_object(alterStmt, "identity", ident); + + return alterStmt; +} + +static ObjTree * deparse_AlterOwnerStmt(Oid objectId, Node *parsetree) { AlterOwnerStmt *node = (AlterOwnerStmt *) parsetree; @@ -5213,7 +5254,8 @@ deparse_simple_command(StashedCommand *cmd) break; case T_AlterObjectSchemaStmt: - elog(ERROR, "unimplemented deparse of %s", CreateCommandTag(parsetree)); + command = deparse_AlterObjectSchemaStmt(objectId, parsetree, + cmd->d.simple.secondaryOid); break; case T_AlterOwnerStmt: diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index b45965c..f8476d2 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -818,7 +818,7 @@ standard_ProcessUtility(Node *parsetree, context, params, dest, completionTag); else - ExecAlterObjectSchemaStmt(stmt); + ExecAlterObjectSchemaStmt(stmt, NULL); } break; @@ -1448,7 +1448,8 @@ ProcessUtilitySlow(Node *parsetree, break; case T_AlterObjectSchemaStmt: - objectId = ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree); + objectId = ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree, + &secondaryOid); objectType = ((AlterObjectSchemaStmt *) parsetree)->objectType; break; diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h index 5df28d3..7c4dc4b 100644 --- a/src/include/commands/alter.h +++ b/src/include/commands/alter.h @@ -21,7 +21,8 @@ extern ObjectAddress ExecRenameStmt(RenameStmt *stmt); -extern Oid ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt); +extern Oid ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt, + Oid *oldschema); extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, ObjectAddresses *objsMoved); diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h index 965f96b..b3b73cc 100644 --- a/src/include/commands/extension.h +++ b/src/include/commands/extension.h @@ -44,7 +44,8 @@ extern Oid ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt, extern Oid get_extension_oid(const char *extname, bool missing_ok); extern char *get_extension_name(Oid ext_oid); -extern Oid AlterExtensionNamespace(List *names, const char *newschema); +extern Oid AlterExtensionNamespace(List *names, const char *newschema, + Oid *oldschema); extern void AlterExtensionOwner_oid(Oid extensionOid, Oid newOwnerId); diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index 876fbfd..73e9cf1 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -38,7 +38,7 @@ extern void AlterTableInternal(Oid relid, List *cmds, bool recurse); extern Oid AlterTableMoveAll(AlterTableMoveAllStmt *stmt); -extern Oid AlterTableNamespace(AlterObjectSchemaStmt *stmt); +extern Oid AlterTableNamespace(AlterObjectSchemaStmt *stmt, Oid *oldschema); extern void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, ObjectAddresses *objsMoved); diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h index a9e1449..19f7afc 100644 --- a/src/include/commands/typecmds.h +++ b/src/include/commands/typecmds.h @@ -46,7 +46,8 @@ extern ObjectAddress RenameType(RenameStmt *stmt); extern Oid AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype); extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId, bool hasDependEntry); -extern Oid AlterTypeNamespace(List *names, const char *newschema, ObjectType objecttype); +extern Oid AlterTypeNamespace(List *names, const char *newschema, + ObjectType objecttype, Oid *oldschema); extern Oid AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses *objsMoved); extern Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, -- 2.1.4