Support CREATE TABLE .. AS SELECT .. commands for tenant tables (#6998)

Support CREATE TABLE .. AS SELECT .. commands for tenant tables
pull/6957/head
Ahmet Gedemenli 2023-06-13 17:54:09 +03:00 committed by GitHub
parent 772d194357
commit 7b0bc62173
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 18 deletions

View File

@ -4130,10 +4130,13 @@ ConvertNewTableIfNecessary(Node *createStmt)
if (ShouldCreateTenantSchemaTable(createdRelationId)) if (ShouldCreateTenantSchemaTable(createdRelationId))
{ {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* not try to convert the table if it already exists and IF NOT EXISTS syntax is used */
errmsg("cannot create a tenant table using " if (createTableAsStmt->if_not_exists && IsCitusTable(createdRelationId))
"CREATE TABLE AS or SELECT INTO " {
"statements"))); return;
}
CreateTenantSchemaTable(createdRelationId);
} }
/* /*

View File

@ -384,13 +384,36 @@ SELECT EXISTS(
t t
(1 row) (1 row)
-- verify that we don't allow creating tenant tables by using CREATE TABLE AS / SELECT INTO commands -- verify that we allow creating tenant tables by using CREATE TABLE AS / SELECT INTO commands
CREATE TABLE tenant_4.tbl_3 AS SELECT 1 AS a, 'text' as b; CREATE TABLE tenant_4.tbl_3 AS SELECT 1 AS a, 'text' as b;
ERROR: cannot create a tenant table using CREATE TABLE AS or SELECT INTO statements NOTICE: Copying data from local table...
CREATE TABLE IF NOT EXISTS tenant_4.tbl_3 AS SELECT 1 as a, 'text' as b; NOTICE: copying the data has completed
ERROR: cannot create a tenant table using CREATE TABLE AS or SELECT INTO statements DETAIL: The local data in the table is no longer visible, but is still on disk.
SELECT 1 as a, 'text' as b INTO tenant_4.tbl_3; HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$tenant_4.tbl_3$$)
ERROR: cannot create a tenant table using CREATE TABLE AS or SELECT INTO statements CREATE TEMP TABLE IF NOT EXISTS tenant_4.tbl_4 AS SELECT 1 as a, 'text' as b;
ERROR: cannot create temporary relation in non-temporary schema
CREATE UNLOGGED TABLE IF NOT EXISTS tenant_4.tbl_4 AS SELECT 1 as a, 'text' as b WITH NO DATA;
-- the same command, no changes because of IF NOT EXISTS
CREATE UNLOGGED TABLE IF NOT EXISTS tenant_4.tbl_4 AS SELECT 1 as a, 'text' as b WITH NO DATA;
NOTICE: relation "tbl_4" already exists, skipping
SELECT 1 as a, 'text' as b INTO tenant_4.tbl_5;
NOTICE: Copying data from local table...
NOTICE: copying the data has completed
DETAIL: The local data in the table is no longer visible, but is still on disk.
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$tenant_4.tbl_5$$)
-- verify we can query the newly created tenant tables
SELECT * FROM tenant_4.tbl_3;
a | b
---------------------------------------------------------------------
1 | text
(1 row)
SELECT COUNT(*) FROM tenant_4.tbl_5;
count
---------------------------------------------------------------------
1
(1 row)
CREATE TYPE employee_type AS (name text, salary numeric); CREATE TYPE employee_type AS (name text, salary numeric);
-- verify that we don't allow creating tenant tables by using CREATE TABLE OF commands -- verify that we don't allow creating tenant tables by using CREATE TABLE OF commands
CREATE TABLE tenant_4.employees OF employee_type ( CREATE TABLE tenant_4.employees OF employee_type (
@ -399,9 +422,23 @@ CREATE TABLE tenant_4.employees OF employee_type (
); );
ERROR: cannot create a tenant table by using CREATE TABLE OF syntax ERROR: cannot create a tenant table by using CREATE TABLE OF syntax
-- verify that we act accordingly when if not exists is used -- verify that we act accordingly when if not exists is used
CREATE TABLE IF NOT EXISTS tenant_4.tbl_3(a int, b text); CREATE TABLE IF NOT EXISTS tenant_4.tbl_6(a int, b text);
CREATE TABLE IF NOT EXISTS tenant_4.tbl_3(a int, b text); CREATE TABLE IF NOT EXISTS tenant_4.tbl_6(a int, b text);
NOTICE: relation "tbl_3" already exists, skipping NOTICE: relation "tbl_6" already exists, skipping
SELECT logicalrelid, partmethod
FROM pg_dist_partition
WHERE logicalrelid::text LIKE 'tenant_4.tbl%'
ORDER BY logicalrelid;
logicalrelid | partmethod
---------------------------------------------------------------------
tenant_4.tbl_1 | n
tenant_4.tbl_2 | n
tenant_4.tbl_3 | n
tenant_4.tbl_4 | n
tenant_4.tbl_5 | n
tenant_4.tbl_6 | n
(6 rows)
CREATE TABLE regular_schema.local(a int, b text); CREATE TABLE regular_schema.local(a int, b text);
CREATE TABLE regular_schema.citus_local(a int, b text); CREATE TABLE regular_schema.citus_local(a int, b text);
SELECT citus_add_local_table_to_metadata('regular_schema.citus_local'); SELECT citus_add_local_table_to_metadata('regular_schema.citus_local');

View File

@ -273,10 +273,17 @@ SELECT EXISTS(
inhparent = 'tenant_4.parent_attach_test'::regclass inhparent = 'tenant_4.parent_attach_test'::regclass
) AS is_partition; ) AS is_partition;
-- verify that we don't allow creating tenant tables by using CREATE TABLE AS / SELECT INTO commands -- verify that we allow creating tenant tables by using CREATE TABLE AS / SELECT INTO commands
CREATE TABLE tenant_4.tbl_3 AS SELECT 1 AS a, 'text' as b; CREATE TABLE tenant_4.tbl_3 AS SELECT 1 AS a, 'text' as b;
CREATE TABLE IF NOT EXISTS tenant_4.tbl_3 AS SELECT 1 as a, 'text' as b; CREATE TEMP TABLE IF NOT EXISTS tenant_4.tbl_4 AS SELECT 1 as a, 'text' as b;
SELECT 1 as a, 'text' as b INTO tenant_4.tbl_3; CREATE UNLOGGED TABLE IF NOT EXISTS tenant_4.tbl_4 AS SELECT 1 as a, 'text' as b WITH NO DATA;
-- the same command, no changes because of IF NOT EXISTS
CREATE UNLOGGED TABLE IF NOT EXISTS tenant_4.tbl_4 AS SELECT 1 as a, 'text' as b WITH NO DATA;
SELECT 1 as a, 'text' as b INTO tenant_4.tbl_5;
-- verify we can query the newly created tenant tables
SELECT * FROM tenant_4.tbl_3;
SELECT COUNT(*) FROM tenant_4.tbl_5;
CREATE TYPE employee_type AS (name text, salary numeric); CREATE TYPE employee_type AS (name text, salary numeric);
@ -287,8 +294,13 @@ CREATE TABLE tenant_4.employees OF employee_type (
); );
-- verify that we act accordingly when if not exists is used -- verify that we act accordingly when if not exists is used
CREATE TABLE IF NOT EXISTS tenant_4.tbl_3(a int, b text); CREATE TABLE IF NOT EXISTS tenant_4.tbl_6(a int, b text);
CREATE TABLE IF NOT EXISTS tenant_4.tbl_3(a int, b text); CREATE TABLE IF NOT EXISTS tenant_4.tbl_6(a int, b text);
SELECT logicalrelid, partmethod
FROM pg_dist_partition
WHERE logicalrelid::text LIKE 'tenant_4.tbl%'
ORDER BY logicalrelid;
CREATE TABLE regular_schema.local(a int, b text); CREATE TABLE regular_schema.local(a int, b text);