diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index ab39649a600b7af7aac4180ee7a3c8c8b361de8c..0f9f7c78679563f81e4f98967d5fd50bd72250d8 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -5453,6 +5453,7 @@ static RenameStmt* _copyRenameStmt(const RenameStmt* from) COPY_NODE_FIELD(objarg); COPY_STRING_FIELD(subname); COPY_STRING_FIELD(newname); + COPY_STRING_FIELD(newschema); COPY_SCALAR_FIELD(behavior); COPY_SCALAR_FIELD(missing_ok); COPY_NODE_FIELD(renameTargetList); diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index 8bc36be1e3c4f1aca7a311f9a6cc8ee3de55dff2..6eceb5f94694e20ddb0dad7e9cf77963e76b5ba0 100644 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -1579,6 +1579,7 @@ static bool _equalRenameStmt(const RenameStmt* a, const RenameStmt* b) COMPARE_NODE_FIELD(objarg); COMPARE_STRING_FIELD(subname); COMPARE_STRING_FIELD(newname); + COMPARE_STRING_FIELD(newschema); COMPARE_SCALAR_FIELD(behavior); COMPARE_SCALAR_FIELD(missing_ok); COMPARE_NODE_FIELD(renameTargetList); diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index e1ab544eb688102349c5d7dd2e600b10ff279bfc..bf6b1e1512b4d03ed55c8da5c41eb315c576b47a 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -17433,23 +17433,25 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->missing_ok = true; $$ = (Node *)n; } - | ALTER TABLE relation_expr RENAME TO name + | ALTER TABLE relation_expr RENAME TO qualified_name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_TABLE; n->relation = $3; n->subname = NULL; - n->newname = $6; + n->newname = $6->relname; + n->newschema = $6->schemaname; n->missing_ok = false; $$ = (Node *)n; } - | ALTER TABLE IF_P EXISTS relation_expr RENAME TO name + | ALTER TABLE IF_P EXISTS relation_expr RENAME TO qualified_name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_TABLE; n->relation = $5; n->subname = NULL; - n->newname = $8; + n->newname = $8->relname; + n->newschema = $8->schemaname; n->missing_ok = true; $$ = (Node *)n; } diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index 05e6ddfbe3f77423f6f4faa1bb0151de5d7d0761..34569d05a747053a05e1e0bc4f3a7e2ed3fd907e 100755 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -841,6 +841,8 @@ static void ATAlterCheckModifiyColumnRepeatedly(const AlterTableCmd* cmd, const static int128 EvaluateAutoIncrement(Relation rel, TupleDesc desc, AttrNumber attnum, Datum* value, bool* is_null); static void SetRelAutoIncrement(Relation rel, TupleDesc desc, int128 autoinc); static Node* RecookAutoincAttrDefault(Relation rel, int attrno, Oid targettype, int targettypmod); +static void AlterTableNamespaceDependentProcess(Relation classRel ,Relation rel, Oid oldNspOid, + Oid nspOid, ObjectAddresses* objsMoved, char* newrelname); inline static bool CStoreSupportATCmd(AlterTableType cmdtype) { @@ -6586,7 +6588,7 @@ ObjectAddress RenameRelation(RenameStmt* stmt) #endif /* Do the work */ - RenameRelationInternal(relid, stmt->newname); + RenameRelationInternal(relid, stmt->newname, stmt->newschema); /* * Record the changecsn of the table that defines the index */ @@ -6611,13 +6613,22 @@ ObjectAddress RenameRelation(RenameStmt* stmt) * the sequence name should probably be removed from the * sequence, AFAIK there's no need for it to be there. */ -void RenameRelationInternal(Oid myrelid, const char* newrelname) +void RenameRelationInternal(Oid myrelid, const char* newrelname, char* newschema) { Relation targetrelation; Relation relrelation; /* for RELATION relation */ HeapTuple reltup; Form_pg_class relform; Oid namespaceId; + Oid oldNspOid = InvalidOid; + bool needChangeNsp = false; + ObjectAddresses* objsMoved = NULL; + ObjectAddress thisobj; + bool is_present = false; + + thisobj.classId = RelationRelationId; + thisobj.objectId = myrelid; + thisobj.objectSubId = 0; /* * Grab an exclusive lock on the target table, index, sequence or view, @@ -6625,6 +6636,26 @@ void RenameRelationInternal(Oid myrelid, const char* newrelname) */ targetrelation = relation_open(myrelid, AccessExclusiveLock); + if (newschema != NULL) { + if (targetrelation->rd_mlogoid != InvalidOid) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + (errmsg("Un-support feature"), + errdetail("table owning matview doesn't support this ALTER yet.")))); + } + + if (targetrelation->rd_rel->relkind == RELKIND_MATVIEW) { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("ALTER MATERIALIZED VIEW is not yet supported."))); + } + + /* Permission check */ + if (!pg_class_ownercheck(RelationGetRelid(targetrelation), GetUserId())) { + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, RelationGetRelationName(targetrelation)); + } + } + if (RelationIsSubPartitioned(targetrelation)) { ereport( ERROR, @@ -6656,7 +6687,24 @@ void RenameRelationInternal(Oid myrelid, const char* newrelname) relform = (Form_pg_class)GETSTRUCT(reltup); - /* + oldNspOid = namespaceId; + if (newschema != NULL) { + /* Get and lock schema OID and check its permissions. */ + RangeVar* newrv = makeRangeVar(newschema, (char*)newrelname, -1); + Oid newNspOid = RangeVarGetAndCheckCreationNamespace(newrv, NoLock, NULL, '\0'); + + needChangeNsp = (newNspOid != namespaceId); + if (needChangeNsp) { + /* common checks on switching namespaces */ + CheckSetNamespace(namespaceId, newNspOid, RelationRelationId, myrelid); + ledger_check_switch_schema(namespaceId, newNspOid); + objsMoved = new_object_addresses(); + namespaceId = newNspOid; + is_present = object_address_present(&thisobj, objsMoved); + } + } + + /* * Check relation name to ensure that it doesn't conflict with existing synonym. */ if (!IsInitdb && GetSynonymOid(newrelname, namespaceId, true) != InvalidOid) { @@ -6665,8 +6713,17 @@ void RenameRelationInternal(Oid myrelid, const char* newrelname) get_namespace_name(namespaceId)))); } - if (get_relname_relid(newrelname, namespaceId) != InvalidOid) - ereport(ERROR, (errcode(ERRCODE_DUPLICATE_TABLE), errmsg("relation \"%s\" already exists", newrelname))); + if (get_relname_relid(newrelname, namespaceId) != InvalidOid) { + if (newschema != NULL) { + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_TABLE), + errmsg("relation \"%s\" already exists in schema \"%s\"", + newrelname, + newschema))); + } else { + ereport(ERROR, (errcode(ERRCODE_DUPLICATE_TABLE), errmsg("relation \"%s\" already exists", newrelname))); + } + } #ifdef ENABLE_MULTIPLE_NODES if (RelationIsTsStore(targetrelation)) { @@ -6693,6 +6750,9 @@ void RenameRelationInternal(Oid myrelid, const char* newrelname) */ (void)namestrcpy(&(relform->relname), newrelname); + /* Update pg_class tuple with new nsp. */ + relform->relnamespace = namespaceId; + simple_heap_update(relrelation, &reltup->t_self, reltup); /* keep the system catalog indexes current */ @@ -6709,14 +6769,33 @@ void RenameRelationInternal(Oid myrelid, const char* newrelname) renamePartitionedTable(myrelid, newrelname); } + if (needChangeNsp && !is_present) { + if (changeDependencyFor(RelationRelationId, myrelid, NamespaceRelationId, oldNspOid, namespaceId) != 1) { + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("failed to change schema dependency for relation \"%s\"", NameStr(relform->relname)))); + } + + add_exact_object_address(&thisobj, objsMoved); + } + tableam_tops_free_tuple(reltup); heap_close(relrelation, RowExclusiveLock); - /* - * Also rename the associated type, if any. - */ - if (OidIsValid(targetrelation->rd_rel->reltype)) - RenameTypeInternal(targetrelation->rd_rel->reltype, newrelname, namespaceId); + if (needChangeNsp && !is_present) { + AlterTableNamespaceDependentProcess(relrelation, targetrelation, oldNspOid, namespaceId, objsMoved, + (char*)newrelname); + if (targetrelation->rd_isblockchain) { + rename_hist_by_newnsp(myrelid, newschema); + } + free_object_addresses(objsMoved); + } else { + /* + * Also rename the associated type, if any. + */ + if (OidIsValid(targetrelation->rd_rel->reltype)) + RenameTypeInternal(targetrelation->rd_rel->reltype, newrelname, oldNspOid); + } /* * Also rename the associated constraint, if any. @@ -21277,8 +21356,16 @@ void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, Object AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid, nspOid, true, objsMoved); + AlterTableNamespaceDependentProcess(classRel, rel, oldNspOid, nspOid, objsMoved, NULL); + + heap_close(classRel, RowExclusiveLock); +} + +static void AlterTableNamespaceDependentProcess(Relation classRel ,Relation rel, Oid oldNspOid, + Oid nspOid, ObjectAddresses* objsMoved, char* newrelname) +{ /* Fix the table's row type too */ - (void)AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false, false, objsMoved); + (void)AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false, false, objsMoved, newrelname); /* Change the table's set type too */ TupleDesc tupDesc = rel->rd_att; @@ -21295,8 +21382,6 @@ void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, Object AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved, AccessExclusiveLock); AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid, false, objsMoved); } - - heap_close(classRel, RowExclusiveLock); } /* diff --git a/src/gausskernel/optimizer/commands/typecmds.cpp b/src/gausskernel/optimizer/commands/typecmds.cpp index 1554b61549d875e2fe2040df73b84a50e4d7fdcd..024479dedd386997c744235a69abef729690c7df 100644 --- a/src/gausskernel/optimizer/commands/typecmds.cpp +++ b/src/gausskernel/optimizer/commands/typecmds.cpp @@ -3649,7 +3649,7 @@ Oid AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses* objsMoved) * Returns the type's old namespace OID. */ Oid AlterTypeNamespaceInternal( - Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses* objsMoved) + Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses* objsMoved, char* newTypeName) { Relation rel; HeapTuple tup; @@ -3683,7 +3683,8 @@ Oid AlterTypeNamespaceInternal( CheckSetNamespace(oldNspOid, nspOid, TypeRelationId, typeOid); /* check for duplicate name (more friendly than unique-index failure) */ - if (SearchSysCacheExists2(TYPENAMENSP, CStringGetDatum(NameStr(typform->typname)), ObjectIdGetDatum(nspOid))) + char* checkTypeName = (newTypeName == NULL) ? NameStr(typform->typname) : newTypeName; + if (SearchSysCacheExists2(TYPENAMENSP, CStringGetDatum(checkTypeName), ObjectIdGetDatum(nspOid))) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("type \"%s\" already exists in schema \"%s\"", @@ -3705,6 +3706,9 @@ Oid AlterTypeNamespaceInternal( * tup is a copy, so we can scribble directly on it */ typform->typnamespace = nspOid; + if (newTypeName != NULL) { + (void)namestrcpy(&(typform->typname), newTypeName); + } simple_heap_update(rel, &tup->t_self, tup); CatalogUpdateIndexes(rel, tup); @@ -3752,8 +3756,10 @@ Oid AlterTypeNamespaceInternal( add_exact_object_address(&thisobj, objsMoved); /* Recursively alter the associated array type, if any */ - if (OidIsValid(arrayOid)) - AlterTypeNamespaceInternal(arrayOid, nspOid, true, true, objsMoved); + if (OidIsValid(arrayOid)) { + AlterTypeNamespaceInternal(arrayOid, nspOid, true, true, objsMoved, + (newTypeName == NULL) ? NULL : makeArrayTypeName(newTypeName, nspOid)); + } return oldNspOid; } diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index 14ab73ce23a7cedcd98e6431f92e6886c952d89b..ac3ada51637c5948ad92e065859eaa8565d784cb 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -90,7 +90,7 @@ extern ObjectAddress RenameConstraint(RenameStmt* stmt); extern ObjectAddress RenameRelation(RenameStmt* stmt); -extern void RenameRelationInternal(Oid myrelid, const char* newrelname); +extern void RenameRelationInternal(Oid myrelid, const char* newrelname, char* newschema = NULL); extern void find_composite_type_dependencies(Oid typeOid, Relation origRelation, const char* origTypeName); diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h index ecfdec760a1fcaab9adcf4ff68fe311296e356a1..4a0e2b644f06bbd91cf9598da6c1f2156a73ae3f 100644 --- a/src/include/commands/typecmds.h +++ b/src/include/commands/typecmds.h @@ -47,7 +47,8 @@ extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId, bool hasDependEn extern ObjectAddress AlterTypeNamespace(List* names, const char* newschema, ObjectType objecttype); extern Oid AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses* objsMoved); extern Oid AlterTypeNamespaceInternal( - Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses* objsMoved); + Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses* objsMoved, + char* newTypeName = NULL); extern void AlterTypeOwnerByPkg(Oid pkgOid, Oid newOwnerId); extern void AlterTypeOwnerByFunc(Oid funcOid, Oid newOwnerId); diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index 1061f6ff3d7b838c55dfab94b850d036e8cf6af1..90fd738f47a68d56b56a543ac8e5669a4d9725f0 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -2349,6 +2349,7 @@ typedef struct RenameStmt { char* subname; /* name of contained object (column, rule, * trigger, etc) */ char* newname; /* the new name */ + char* newschema; /* the new schema name */ DropBehavior behavior; /* RESTRICT or CASCADE behavior */ bool missing_ok; /* skip error if missing? */ List* renameTargetList = NULL; diff --git a/src/test/regress/expected/alter_table_003.out b/src/test/regress/expected/alter_table_003.out index ac5bb0fbc03dd9e83ab3855f8fce1b49a5ff0229..a57a6fa715113cb12085c76720fdb336a67e91f8 100644 --- a/src/test/regress/expected/alter_table_003.out +++ b/src/test/regress/expected/alter_table_003.out @@ -8796,5 +8796,293 @@ SELECT pg_get_tabledef('t1'); (1 row) drop table if exists t1 cascade; +-- test about setting schema by RenameStmt +CREATE SCHEMA test1; +CREATE SCHEMA test2; +CREATE TABLE test1.test(a int primary key, b int not null); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test" +CREATE INDEX ON test1.test using btree(b); +INSERT INTO test1.test VALUES (1, 1); +\d+ test1.test + Table "test1.test" + Column | Type | Modifiers | Storage | Stats target | Description +--------+---------+-----------+---------+--------------+------------- + a | integer | not null | plain | | + b | integer | not null | plain | | +Indexes: + "test_pkey" PRIMARY KEY, btree (a) TABLESPACE pg_default + "test_b_idx" btree (b) TABLESPACE pg_default +Has OIDs: no +Options: orientation=row, compression=no + +SELECT n.nspname, c.relname from pg_class c, pg_namespace n where n.oid = c.relnamespace and c.relname in ('test', 'test_pkey', 'test_b_idx', 'tttt'); + nspname | relname +---------+------------ + test1 | test + test1 | test_pkey + test1 | test_b_idx +(3 rows) + +SELECT * FROM test1.test; + a | b +---+--- + 1 | 1 +(1 row) + +-- check about type +SELECT n.nspname, t.typname FROM pg_type t, pg_namespace n where t.typnamespace = n.oid and t.typname in ('test','tttt'); + nspname | typname +---------+--------- + test1 | test +(1 row) + +ALTER TABLE test1.test RENAME TO test2.tttt; +\d+ test1.test +\d+ test2.tttt + Table "test2.tttt" + Column | Type | Modifiers | Storage | Stats target | Description +--------+---------+-----------+---------+--------------+------------- + a | integer | not null | plain | | + b | integer | not null | plain | | +Indexes: + "test_pkey" PRIMARY KEY, btree (a) TABLESPACE pg_default + "test_b_idx" btree (b) TABLESPACE pg_default +Has OIDs: no +Options: orientation=row, compression=no + +SELECT n.nspname, c.relname from pg_class c, pg_namespace n where n.oid = c.relnamespace and c.relname in ('test', 'test_pkey', 'test_b_idx', 'tttt'); + nspname | relname +---------+------------ + test2 | tttt + test2 | test_pkey + test2 | test_b_idx +(3 rows) + +INSERT INTO test2.tttt VALUES (2, 2); +SELECT * FROM test1.test; +ERROR: relation "test1.test" does not exist on datanode1 +LINE 1: SELECT * FROM test1.test; + ^ +SELECT * FROM test2.tttt; + a | b +---+--- + 1 | 1 + 2 | 2 +(2 rows) + +-- check about type +SELECT n.nspname, t.typname FROM pg_type t, pg_namespace n where t.typnamespace = n.oid and t.typname in ('test','tttt'); + nspname | typname +---------+--------- + test2 | tttt +(1 row) + +-- just rename +ALTER TABLE test2.tttt RENAME TO test2.ttt; +SELECT * FROM test2.tttt; +ERROR: relation "test2.tttt" does not exist on datanode1 +LINE 1: SELECT * FROM test2.tttt; + ^ +SELECT * FROM test2.ttt; + a | b +---+--- + 1 | 1 + 2 | 2 +(2 rows) + +-- check about type +SELECT n.nspname, t.typname FROM pg_type t, pg_namespace n where t.typnamespace = n.oid and t.typname = 'ttt'; + nspname | typname +---------+--------- + test2 | ttt +(1 row) + +-- just move to other schema +CREATE TABLE test1.t1 (a int); +\d+ test1.t1 + Table "test1.t1" + Column | Type | Modifiers | Storage | Stats target | Description +--------+---------+-----------+---------+--------------+------------- + a | integer | | plain | | +Has OIDs: no +Options: orientation=row, compression=no + +ALTER TABLE test1.t1 RENAME TO test2.t1; +\d+ test1.t1 +\d+ test2.t1 + Table "test2.t1" + Column | Type | Modifiers | Storage | Stats target | Description +--------+---------+-----------+---------+--------------+------------- + a | integer | | plain | | +Has OIDs: no +Options: orientation=row, compression=no + +-- check about type +SELECT n.nspname, t.typname FROM pg_type t, pg_namespace n where t.typnamespace = n.oid and t.typname = 't1'; + nspname | typname +---------+--------- + test2 | t1 +(1 row) + +-- test about partition table +CREATE TABLE test1.sales_table1 +( + order_no INTEGER NOT NULL, + goods_name CHAR(20) NOT NULL, + sales_date DATE NOT NULL, + sales_volume INTEGER, + sales_store CHAR(20) +) +PARTITION BY RANGE(sales_date) +( + PARTITION sales_table1_season1 VALUES LESS THAN('2021-04-01 00:00:00'), + PARTITION sales_table1_season2 VALUES LESS THAN('2021-07-01 00:00:00'), + PARTITION sales_table1_season3 VALUES LESS THAN('2021-10-01 00:00:00'), + PARTITION sales_table1_season4 VALUES LESS THAN(MAXVALUE) +); +CREATE TABLE test1.sales_table2 +( + order_no INTEGER NOT NULL, + goods_name CHAR(20) NOT NULL, + sales_date DATE NOT NULL, + sales_volume INTEGER, + sales_store CHAR(20) +) +PARTITION BY RANGE(sales_date) +( + PARTITION sales_table2_season1 VALUES LESS THAN('2021-04-01 00:00:00'), + PARTITION sales_table2_season2 VALUES LESS THAN('2021-07-01 00:00:00'), + PARTITION sales_table2_season3 VALUES LESS THAN('2021-10-01 00:00:00'), + PARTITION sales_table2_season4 VALUES LESS THAN(MAXVALUE) +); +CREATE TABLE test1.sales_table3 +( + order_no INTEGER NOT NULL, + goods_name CHAR(20) NOT NULL, + sales_date DATE NOT NULL, + sales_volume INTEGER, + sales_store CHAR(20) +) +PARTITION BY RANGE(sales_date) +( + PARTITION sales_table3_season1 VALUES LESS THAN('2021-04-01 00:00:00'), + PARTITION sales_table3_season2 VALUES LESS THAN('2021-07-01 00:00:00'), + PARTITION sales_table3_season3 VALUES LESS THAN('2021-10-01 00:00:00'), + PARTITION sales_table3_season4 VALUES LESS THAN(MAXVALUE) +); +SELECT n.nspname, c.relname, p.relname AS partition_name +FROM pg_class c, pg_namespace n, pg_partition p +WHERE n.oid = c.relnamespace and c.oid = p.parentid and c.relname like '%sales_table%' ORDER BY 1, 2, 3; + nspname | relname | partition_name +---------+--------------+---------------------- + test1 | sales_table1 | sales_table1 + test1 | sales_table1 | sales_table1_season1 + test1 | sales_table1 | sales_table1_season2 + test1 | sales_table1 | sales_table1_season3 + test1 | sales_table1 | sales_table1_season4 + test1 | sales_table2 | sales_table2 + test1 | sales_table2 | sales_table2_season1 + test1 | sales_table2 | sales_table2_season2 + test1 | sales_table2 | sales_table2_season3 + test1 | sales_table2 | sales_table2_season4 + test1 | sales_table3 | sales_table3 + test1 | sales_table3 | sales_table3_season1 + test1 | sales_table3 | sales_table3_season2 + test1 | sales_table3 | sales_table3_season3 + test1 | sales_table3 | sales_table3_season4 +(15 rows) + +ALTER TABLE test1.sales_table1 RENAME TO test2.sales_table1; +ALTER TABLE test1.sales_table2 RENAME TO test2.sales_table3; +ALTER TABLE test1.sales_table3 RENAME TO test1.sales_table4; +SELECT n.nspname, c.relname, p.relname AS partition_name +FROM pg_class c, pg_namespace n, pg_partition p +WHERE n.oid = c.relnamespace and c.oid = p.parentid and c.relname like '%sales_table%' ORDER BY 1, 2, 3; + nspname | relname | partition_name +---------+--------------+---------------------- + test1 | sales_table4 | sales_table3_season1 + test1 | sales_table4 | sales_table3_season2 + test1 | sales_table4 | sales_table3_season3 + test1 | sales_table4 | sales_table3_season4 + test1 | sales_table4 | sales_table4 + test2 | sales_table1 | sales_table1 + test2 | sales_table1 | sales_table1_season1 + test2 | sales_table1 | sales_table1_season2 + test2 | sales_table1 | sales_table1_season3 + test2 | sales_table1 | sales_table1_season4 + test2 | sales_table3 | sales_table2_season1 + test2 | sales_table3 | sales_table2_season2 + test2 | sales_table3 | sales_table2_season3 + test2 | sales_table3 | sales_table2_season4 + test2 | sales_table3 | sales_table3 +(15 rows) + +-- rename table with view or matview +CREATE TABLE test1.test_table_view1 (a int); +CREATE TABLE test1.test_table_view2 (a int); +CREATE TABLE test1.test_table_matview1 (a int); +CREATE TABLE test1.test_table_matview2 (a int); +CREATE VIEW test1.test_view1 AS SELECT * FROM test1.test_table_view1; +CREATE VIEW test1.test_view2 AS SELECT * FROM test1.test_table_view2; +CREATE MATERIALIZED VIEW test1.test_matview1 AS SELECT * FROM test1.test_table_matview1; +CREATE MATERIALIZED VIEW test1.test_matview2 AS SELECT * FROM test1.test_table_matview2; +ALTER TABLE test1.test_table_view1 RENAME TO test2.test_table_view1; -- just move to other schema +ALTER TABLE test1.test_table_view2 RENAME TO test2.test_table_view3; -- rename and move to other schema +SELECT * FROM test1.test_view1; + a +--- +(0 rows) + +SELECT pg_get_viewdef('test1.test_view1'); + pg_get_viewdef +---------------------------------------- + SELECT * FROM test2.test_table_view1; +(1 row) + +SELECT * FROM test1.test_view2; + a +--- +(0 rows) + +SELECT pg_get_viewdef('test1.test_view2'); + pg_get_viewdef +--------------------------------------------------------- + SELECT * FROM test2.test_table_view3 test_table_view2; +(1 row) + +ALTER TABLE test1.test_table_matview1 RENAME TO test2.test_table_matview1; -- just move to other schema +ALTER TABLE test1.test_table_matview2 RENAME TO test2.test_table_matview3; -- rename and move to other schema +SELECT * FROM test1.test_matview1; + a +--- +(0 rows) + +SELECT pg_get_viewdef('test1.test_matview1'); + pg_get_viewdef +------------------------------------------- + SELECT * FROM test2.test_table_matview1; +(1 row) + +SELECT * FROM test1.test_matview2; + a +--- +(0 rows) + +SELECT pg_get_viewdef('test1.test_matview2'); + pg_get_viewdef +--------------------------------------------------------------- + SELECT * FROM test2.test_table_matview3 test_table_matview2; +(1 row) + +-- rename to a existed table +CREATE TABLE test1.name1 (a int); +CREATE TABLE test2.name1 (a int); +CREATE TABLE test2.name2 (a int); +ALTER TABLE test1.name1 RENAME TO test2.name1; +ERROR: relation "name1" already exists in schema "test2" +ALTER TABLE test1.name1 RENAME TO test2.name2; +ERROR: relation "name2" already exists in schema "test2" +ALTER TABLE test2.name1 RENAME TO test2.name2; +ERROR: relation "name2" already exists in schema "test2" \c postgres drop database test_first_after_B; diff --git a/src/test/regress/sql/alter_table_003.sql b/src/test/regress/sql/alter_table_003.sql index 68aba791e377ca8f0f5ca3ae89d0864b84308b4a..e9f53884f52bbd36289ae74529e14d7a6286767e 100644 --- a/src/test/regress/sql/alter_table_003.sql +++ b/src/test/regress/sql/alter_table_003.sql @@ -3256,5 +3256,133 @@ alter table t1 modify f1 int after f3, modify f5 bool first, modify f3 timestamp SELECT pg_get_tabledef('t1'); drop table if exists t1 cascade; +-- test about setting schema by RenameStmt +CREATE SCHEMA test1; +CREATE SCHEMA test2; +CREATE TABLE test1.test(a int primary key, b int not null); +CREATE INDEX ON test1.test using btree(b); +INSERT INTO test1.test VALUES (1, 1); +\d+ test1.test +SELECT n.nspname, c.relname from pg_class c, pg_namespace n where n.oid = c.relnamespace and c.relname in ('test', 'test_pkey', 'test_b_idx', 'tttt'); +SELECT * FROM test1.test; +-- check about type +SELECT n.nspname, t.typname FROM pg_type t, pg_namespace n where t.typnamespace = n.oid and t.typname in ('test','tttt'); +ALTER TABLE test1.test RENAME TO test2.tttt; +\d+ test1.test +\d+ test2.tttt +SELECT n.nspname, c.relname from pg_class c, pg_namespace n where n.oid = c.relnamespace and c.relname in ('test', 'test_pkey', 'test_b_idx', 'tttt'); +INSERT INTO test2.tttt VALUES (2, 2); +SELECT * FROM test1.test; +SELECT * FROM test2.tttt; +-- check about type +SELECT n.nspname, t.typname FROM pg_type t, pg_namespace n where t.typnamespace = n.oid and t.typname in ('test','tttt'); + +-- just rename +ALTER TABLE test2.tttt RENAME TO test2.ttt; +SELECT * FROM test2.tttt; +SELECT * FROM test2.ttt; +-- check about type +SELECT n.nspname, t.typname FROM pg_type t, pg_namespace n where t.typnamespace = n.oid and t.typname = 'ttt'; + +-- just move to other schema +CREATE TABLE test1.t1 (a int); +\d+ test1.t1 +ALTER TABLE test1.t1 RENAME TO test2.t1; +\d+ test1.t1 +\d+ test2.t1 +-- check about type +SELECT n.nspname, t.typname FROM pg_type t, pg_namespace n where t.typnamespace = n.oid and t.typname = 't1'; + +-- test about partition table +CREATE TABLE test1.sales_table1 +( + order_no INTEGER NOT NULL, + goods_name CHAR(20) NOT NULL, + sales_date DATE NOT NULL, + sales_volume INTEGER, + sales_store CHAR(20) +) +PARTITION BY RANGE(sales_date) +( + PARTITION sales_table1_season1 VALUES LESS THAN('2021-04-01 00:00:00'), + PARTITION sales_table1_season2 VALUES LESS THAN('2021-07-01 00:00:00'), + PARTITION sales_table1_season3 VALUES LESS THAN('2021-10-01 00:00:00'), + PARTITION sales_table1_season4 VALUES LESS THAN(MAXVALUE) +); + +CREATE TABLE test1.sales_table2 +( + order_no INTEGER NOT NULL, + goods_name CHAR(20) NOT NULL, + sales_date DATE NOT NULL, + sales_volume INTEGER, + sales_store CHAR(20) +) +PARTITION BY RANGE(sales_date) +( + PARTITION sales_table2_season1 VALUES LESS THAN('2021-04-01 00:00:00'), + PARTITION sales_table2_season2 VALUES LESS THAN('2021-07-01 00:00:00'), + PARTITION sales_table2_season3 VALUES LESS THAN('2021-10-01 00:00:00'), + PARTITION sales_table2_season4 VALUES LESS THAN(MAXVALUE) +); + +CREATE TABLE test1.sales_table3 +( + order_no INTEGER NOT NULL, + goods_name CHAR(20) NOT NULL, + sales_date DATE NOT NULL, + sales_volume INTEGER, + sales_store CHAR(20) +) +PARTITION BY RANGE(sales_date) +( + PARTITION sales_table3_season1 VALUES LESS THAN('2021-04-01 00:00:00'), + PARTITION sales_table3_season2 VALUES LESS THAN('2021-07-01 00:00:00'), + PARTITION sales_table3_season3 VALUES LESS THAN('2021-10-01 00:00:00'), + PARTITION sales_table3_season4 VALUES LESS THAN(MAXVALUE) +); +SELECT n.nspname, c.relname, p.relname AS partition_name +FROM pg_class c, pg_namespace n, pg_partition p +WHERE n.oid = c.relnamespace and c.oid = p.parentid and c.relname like '%sales_table%' ORDER BY 1, 2, 3; +ALTER TABLE test1.sales_table1 RENAME TO test2.sales_table1; +ALTER TABLE test1.sales_table2 RENAME TO test2.sales_table3; +ALTER TABLE test1.sales_table3 RENAME TO test1.sales_table4; +SELECT n.nspname, c.relname, p.relname AS partition_name +FROM pg_class c, pg_namespace n, pg_partition p +WHERE n.oid = c.relnamespace and c.oid = p.parentid and c.relname like '%sales_table%' ORDER BY 1, 2, 3; + +-- rename table with view or matview +CREATE TABLE test1.test_table_view1 (a int); +CREATE TABLE test1.test_table_view2 (a int); +CREATE TABLE test1.test_table_matview1 (a int); +CREATE TABLE test1.test_table_matview2 (a int); + +CREATE VIEW test1.test_view1 AS SELECT * FROM test1.test_table_view1; +CREATE VIEW test1.test_view2 AS SELECT * FROM test1.test_table_view2; +CREATE MATERIALIZED VIEW test1.test_matview1 AS SELECT * FROM test1.test_table_matview1; +CREATE MATERIALIZED VIEW test1.test_matview2 AS SELECT * FROM test1.test_table_matview2; + +ALTER TABLE test1.test_table_view1 RENAME TO test2.test_table_view1; -- just move to other schema +ALTER TABLE test1.test_table_view2 RENAME TO test2.test_table_view3; -- rename and move to other schema +SELECT * FROM test1.test_view1; +SELECT pg_get_viewdef('test1.test_view1'); +SELECT * FROM test1.test_view2; +SELECT pg_get_viewdef('test1.test_view2'); + +ALTER TABLE test1.test_table_matview1 RENAME TO test2.test_table_matview1; -- just move to other schema +ALTER TABLE test1.test_table_matview2 RENAME TO test2.test_table_matview3; -- rename and move to other schema +SELECT * FROM test1.test_matview1; +SELECT pg_get_viewdef('test1.test_matview1'); +SELECT * FROM test1.test_matview2; +SELECT pg_get_viewdef('test1.test_matview2'); + +-- rename to a existed table +CREATE TABLE test1.name1 (a int); +CREATE TABLE test2.name1 (a int); +CREATE TABLE test2.name2 (a int); +ALTER TABLE test1.name1 RENAME TO test2.name1; +ALTER TABLE test1.name1 RENAME TO test2.name2; +ALTER TABLE test2.name1 RENAME TO test2.name2; + \c postgres drop database test_first_after_B; \ No newline at end of file