Skip to content

Commit

Permalink
[#23114] YSQL: Implement ALTER TABLE.. SET SCHEMA..
Browse files Browse the repository at this point in the history
Summary:
The diff implements the syntax:
* `ALTER TABLE t SET SCHEMA s`
* `ALTER TABLE IF EXISTS t SET SCHEMA s`
PG side:
* Fixed `AlterObjectSchemaStmt` handling in the grammar.
* Updated `AlterRelationNamespaceInternal` handler.
* New function `YBCAlterTableNamespace`.
YB side:
* New `YBCPgAlterTableSetSchema` function.
* New `PgApiImpl::AlterTableSetSchema` wrapper.
* New `PgAlterTable::SetSchema` method.
* Added `string schema_name` into `PgRenameTablePB` proto-buffer.
* Updated `YBTableAlterer::ToRequest`.
* Updated `CatalogManager::AlterTable`.
* Added `YBTableName::YBTableName(YQLDatabase db_type)` constructor.

**Upgrade/Rollback safety:**
The changed `PgRenameTablePB` is only used for communications between
PG & TS processes. The processes should be always in sync, so the change
does not need `AutoFlag` or any other special handling for the upgrade safety.

Jira: DB-12047

Test Plan:
Updated tests for SET SCHEMA:
./yb_build.sh --java-test org.yb.pgsql.TestPgRegressTable#testPgRegressTable
./yb_build.sh --java-test org.yb.pgsql.TestPgRegressMisc#testPgRegressMiscSerial
./yb_build.sh --java-test org.yb.pgsql.TestPgRegressThirdPartyExtensionsPgaudit#schedule

New C++ tests for SET SCHEMA:
./yb_build.sh --cxx-test pg_mini-test --gtest_filter PgMiniTest.AlterTableSetSchema
./yb_build.sh --cxx-test pg_mini-test --gtest_filter PgMiniTest.AlterPartitionedTableSetSchema

Other related tests:
./yb_build.sh --java-test org.yb.pgsql.TestPgRegressMatview#testPgRegressMatview

Reviewers: mihnea, fizaa, myang, xCluster, hsunder

Reviewed By: myang

Subscribers: jason, ybase, yql

Differential Revision: https://phorge.dev.yugabyte.com/D36474
  • Loading branch information
OlegLoginov committed Aug 6, 2024
1 parent ef62972 commit 34f9741
Show file tree
Hide file tree
Showing 23 changed files with 354 additions and 59 deletions.
10 changes: 10 additions & 0 deletions src/postgres/src/backend/commands/tablecmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -14721,6 +14721,16 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,

CatalogTupleUpdate(classRel, &classTup->t_self, classTup);

/*
* Call SetSchema handler for the related internal YB DocDB table.
* No YB DocDB table for a primary key dummy index.
*/
const Relation rel = RelationIdGetRelation(relOid);
if (IsYBRelation(rel) && !(rel->rd_index && rel->rd_index->indisprimary))
YBCAlterTableNamespace(classForm, relOid);

RelationClose(rel);

/* Update dependency on schema if caller said so */
if (hasDependEntry &&
changeDependencyFor(RelationRelationId,
Expand Down
27 changes: 27 additions & 0 deletions src/postgres/src/backend/commands/ybccmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -1690,6 +1690,33 @@ YBCRename(RenameStmt *stmt, Oid relationId)
YBCExecAlterTable(handle, relationId);
}

void
YBCAlterTableNamespace(Form_pg_class classForm, Oid relationId)
{
YBCPgStatement handle = NULL;
Oid databaseId = YBCGetDatabaseOidByRelid(relationId);

switch (classForm->relkind)
{
case RELKIND_MATVIEW: /* materialized view */
case RELKIND_RELATION: /* ordinary table */
case RELKIND_INDEX: /* secondary index */
case RELKIND_PARTITIONED_TABLE: /* partitioned table */
case RELKIND_PARTITIONED_INDEX: /* partitioned index */
HandleYBStatus(
YBCPgNewAlterTable(databaseId, YbGetRelfileNodeIdFromRelId(relationId), &handle));
HandleYBStatus(
YBCPgAlterTableSetSchema(handle, get_namespace_name(classForm->relnamespace)));
break;

default:
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Schema altering for this object is not yet supported.")));
}

YBCExecAlterTable(handle, relationId);
}

void
YBCDropIndex(Relation index)
{
Expand Down
2 changes: 0 additions & 2 deletions src/postgres/src/backend/parser/gram.y
Original file line number Diff line number Diff line change
Expand Up @@ -10062,7 +10062,6 @@ AlterObjectSchemaStmt:
}
| ALTER TABLE relation_expr SET SCHEMA name
{
parser_ybc_not_support(@1, "ALTER TABLE SET SCHEMA");
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_TABLE;
n->relation = $3;
Expand All @@ -10072,7 +10071,6 @@ AlterObjectSchemaStmt:
}
| ALTER TABLE IF_P EXISTS relation_expr SET SCHEMA name
{
parser_ybc_not_support(@1, "ALTER TABLE SET SCHEMA");
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
n->objectType = OBJECT_TABLE;
n->relation = $5;
Expand Down
2 changes: 2 additions & 0 deletions src/postgres/src/include/commands/ybccmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ extern void YBCExecAlterTable(YBCPgStatement handle, Oid relationId);

extern void YBCRename(RenameStmt* stmt, Oid relationId);

extern void YBCAlterTableNamespace(Form_pg_class classForm, Oid relationId);

extern void YbBackfillIndex(BackfillIndexStmt *stmt, DestReceiver *dest);

extern TupleDesc YbBackfillIndexResultDesc(BackfillIndexStmt *stmt);
Expand Down
8 changes: 6 additions & 2 deletions src/postgres/src/test/regress/expected/yb_pg_alter_table.out
Original file line number Diff line number Diff line change
Expand Up @@ -440,14 +440,18 @@ rollback;
--
create schema alter1;
create schema alter2;
create table alter1.t1(f1 serial primary key, f2 int check (f2 > 0));
create text search parser alter1.prs(start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype);
create text search configuration alter1.cfg(parser = alter1.prs);
alter table alter1.t1 set schema alter1; -- no-op, same schema
alter table alter1.t1 set schema alter2;
alter text search parser alter1.prs set schema alter2;
alter text search configuration alter1.cfg set schema alter2;
-- clean up
drop schema alter2 cascade;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to text search configuration alter2.cfg
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to table alter2.t1
drop cascades to text search configuration alter2.cfg
drop cascades to text search parser alter2.prs
--
-- typed tables: OF / NOT OF
Expand Down
82 changes: 82 additions & 0 deletions src/postgres/src/test/regress/expected/yb_schema.out
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,88 @@ SELECT * FROM S2.TBL;
(1 row)

DROP TABLE S2.TBL;
-- Test ALTER TABLE [IF EXISTS].. SET SCHEMA..
CREATE TABLE S1.TBL2 (a1 int PRIMARY KEY, a2 int);
CREATE INDEX IDX2 ON S1.TBL2(a2);
INSERT INTO S1.TBL2 VALUES (2, 2);
SELECT * FROM S1.TBL2;
a1 | a2
----+----
2 | 2
(1 row)

\d S1.TBL2;
Table "s1.tbl2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
a1 | integer | | not null |
a2 | integer | | |
Indexes:
"tbl2_pkey" PRIMARY KEY, lsm (a1 HASH)
"idx2" lsm (a2 HASH)

ALTER TABLE S1.TBL2 SET SCHEMA S2;
SELECT * FROM S1.TBL2;
ERROR: relation "s1.tbl2" does not exist
LINE 1: SELECT * FROM S1.TBL2;
^
SELECT * FROM S2.TBL2;
a1 | a2
----+----
2 | 2
(1 row)

\d S2.TBL2;
Table "s2.tbl2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
a1 | integer | | not null |
a2 | integer | | |
Indexes:
"tbl2_pkey" PRIMARY KEY, lsm (a1 HASH)
"idx2" lsm (a2 HASH)

\d S2.IDX2;
Index "s2.idx2"
Column | Type | Key? | Definition
--------+---------+------+------------
a2 | integer | yes | a2
lsm, for table "s2.tbl2"

DROP TABLE S2.TBL2;
SELECT * FROM S2.TBL2;
ERROR: relation "s2.tbl2" does not exist
LINE 1: SELECT * FROM S2.TBL2;
^
ALTER TABLE S2.TBL2 SET SCHEMA S1; -- the table was deleted
ERROR: relation "s2.tbl2" does not exist
ALTER TABLE IF EXISTS S2.TBL2 SET SCHEMA S1; -- OK
NOTICE: relation "tbl2" does not exist, skipping
-- for partitioned table
CREATE TABLE S1.P_TBL (k INT PRIMARY KEY, value TEXT) PARTITION BY RANGE(k);
CREATE TABLE S1.P_TBL_1 PARTITION OF S1.P_TBL FOR VALUES FROM (1) TO (3);
CREATE TABLE S1.P_TBL_DEFAULT PARTITION OF S1.P_TBL DEFAULT;
CREATE INDEX P_TBL_K_IDX on S1.P_TBL(k);
ALTER TABLE S1.P_TBL SET SCHEMA S2;
\d+ S2.P_TBL
Table "s2.p_tbl"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+----------+--------------+-------------
k | integer | | not null | | plain | |
value | text | | | | extended | |
Partition key: RANGE (k)
Indexes:
"p_tbl_pkey" PRIMARY KEY, lsm (k HASH)
"p_tbl_k_idx" lsm (k HASH)
Partitions: s1.p_tbl_1 FOR VALUES FROM (1) TO (3),
s1.p_tbl_default DEFAULT

DROP TABLE S2.P_TBL;
-- for temp table
CREATE TEMP TABLE TMP_TBL (a INT PRIMARY KEY);
ALTER TABLE TMP_TBL SET SCHEMA S2;
ERROR: cannot move objects into or out of temporary schemas
DROP TABLE TMP_TBL;
-- verify yb_db_admin role can manage schemas like a superuser
CREATE SCHEMA test_ns_schema_other;
CREATE ROLE test_regress_user1;
Expand Down
4 changes: 4 additions & 0 deletions src/postgres/src/test/regress/sql/yb_pg_alter_table.sql
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 +410,13 @@ rollback;
create schema alter1;
create schema alter2;

create table alter1.t1(f1 serial primary key, f2 int check (f2 > 0));

create text search parser alter1.prs(start = prsd_start, gettoken = prsd_nexttoken, end = prsd_end, lextypes = prsd_lextype);
create text search configuration alter1.cfg(parser = alter1.prs);

alter table alter1.t1 set schema alter1; -- no-op, same schema
alter table alter1.t1 set schema alter2;
alter text search parser alter1.prs set schema alter2;
alter text search configuration alter1.cfg set schema alter2;

Expand Down
38 changes: 38 additions & 0 deletions src/postgres/src/test/regress/sql/yb_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,44 @@ SELECT * FROM S2.TBL;

DROP TABLE S2.TBL;

-- Test ALTER TABLE [IF EXISTS].. SET SCHEMA..
CREATE TABLE S1.TBL2 (a1 int PRIMARY KEY, a2 int);
CREATE INDEX IDX2 ON S1.TBL2(a2);

INSERT INTO S1.TBL2 VALUES (2, 2);
SELECT * FROM S1.TBL2;
\d S1.TBL2;

ALTER TABLE S1.TBL2 SET SCHEMA S2;
SELECT * FROM S1.TBL2;
SELECT * FROM S2.TBL2;
\d S2.TBL2;
\d S2.IDX2;

DROP TABLE S2.TBL2;
SELECT * FROM S2.TBL2;

ALTER TABLE S2.TBL2 SET SCHEMA S1; -- the table was deleted
ALTER TABLE IF EXISTS S2.TBL2 SET SCHEMA S1; -- OK

-- for partitioned table
CREATE TABLE S1.P_TBL (k INT PRIMARY KEY, value TEXT) PARTITION BY RANGE(k);
CREATE TABLE S1.P_TBL_1 PARTITION OF S1.P_TBL FOR VALUES FROM (1) TO (3);
CREATE TABLE S1.P_TBL_DEFAULT PARTITION OF S1.P_TBL DEFAULT;
CREATE INDEX P_TBL_K_IDX on S1.P_TBL(k);

ALTER TABLE S1.P_TBL SET SCHEMA S2;
\d+ S2.P_TBL

DROP TABLE S2.P_TBL;

-- for temp table
CREATE TEMP TABLE TMP_TBL (a INT PRIMARY KEY);

ALTER TABLE TMP_TBL SET SCHEMA S2;

DROP TABLE TMP_TBL;

-- verify yb_db_admin role can manage schemas like a superuser
CREATE SCHEMA test_ns_schema_other;
CREATE ROLE test_regress_user1;
Expand Down
Loading

0 comments on commit 34f9741

Please sign in to comment.