From 4122a93343c442de6b7a68c0611cfb0b6a8f129d Mon Sep 17 00:00:00 2001 From: Zhang Mingli Date: Tue, 6 Aug 2024 21:38:07 +0800 Subject: [PATCH] CREATE FOREIGN TABLE LIKE. Allow user to use LIKE to create foreign tables, ex: CREATE FOREIGN TABLE ft(LIKE t1); Foreign table ft will use t1's column definitions as its own. In CBDB, we usually use foreign tables to import data from outside data source. Each target table usually has an associated foreign table. This is very useful if target table has a lot of columns, making it easy to create a foreign table without defining columns one by one, and avoid mistake. Distribution policy is not inherited for this case because it should be defined with options by users. Authored-by: Zhang Mingli avamingli@gmail.com --- src/backend/parser/parse_utilcmd.c | 11 ++++++ src/test/regress/expected/gp_foreign_data.out | 38 +++++++++++++++++++ src/test/regress/sql/gp_foreign_data.sql | 15 ++++++++ 3 files changed, 64 insertions(+) diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 446af6f3cf0..16d43c82a93 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -396,6 +396,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) likeDistributedBy, bQuiet); } + /* + * CBDB: for a foreign table, do not inherit source table's distribution policy. + * It should be decided by OPTIONS, ex: mpp_execute all segments. + */ +#if 0 if (IsA(stmt, CreateForeignTableStmt)) { DistributedBy *ft_distributedBy = ((CreateForeignTableStmt *)stmt)->distributedBy; @@ -403,6 +408,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) stmt->distributedBy = transformDistributedBy(pstate, &cxt, ft_distributedBy, likeDistributedBy, bQuiet); } +#endif /* * Postprocess check constraints. @@ -1071,11 +1077,16 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("LIKE INCLUDING may not be used with this kind of relation"))); + /* + * CBDB: Support CREATE FOREIGN TABLE LIKE. + */ +#if 0 /* we could support LIKE in many cases, but worry about it another day */ if (cxt->isforeign) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("LIKE is not supported for creating foreign tables"))); +#endif /* Open the relation referenced by the LIKE clause */ relation = relation_openrv(table_like_clause->relation, AccessShareLock); diff --git a/src/test/regress/expected/gp_foreign_data.out b/src/test/regress/expected/gp_foreign_data.out index c4dbd5bea93..04be4318e78 100644 --- a/src/test/regress/expected/gp_foreign_data.out +++ b/src/test/regress/expected/gp_foreign_data.out @@ -39,6 +39,44 @@ CREATE FOREIGN TABLE ft5 ( Server: s1 FDW options: (delimiter ',', mpp_execute 'all segments', num_segments '5') +-- CREATE FOREIGN TABLE LIKE +CREATE TABLE ft_source_table(a INT, b INT, c INT) DISTRIBUTED BY (b); +CREATE FOREIGN TABLE ft_like (LIKE ft_source_table) SERVER s0; +\d+ ft_like + Foreign table "public.ft_like" + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description +--------+---------+-----------+----------+---------+-------------+---------+--------------+------------- + a | integer | | | | | plain | | + b | integer | | | | | plain | | + c | integer | | | | | plain | | +Server: s0 + +-- shoule be null +SELECT * FROM gp_distribution_policy WHERE localoid = 'ft_like'::regclass::oid; + localoid | policytype | numsegments | distkey | distclass +----------+------------+-------------+---------+----------- +(0 rows) + +CREATE FOREIGN TABLE ft_like1 (LIKE ft_source_table) SERVER s0 +OPTIONS (delimiter ',', mpp_execute 'all segments', num_segments '3'); +\d+ ft_like1 + Foreign table "public.ft_like1" + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description +--------+---------+-----------+----------+---------+-------------+---------+--------------+------------- + a | integer | | | | | plain | | + b | integer | | | | | plain | | + c | integer | | | | | plain | | +Server: s0 +FDW options: (delimiter ',', mpp_execute 'all segments', num_segments '3') + +SELECT * FROM gp_distribution_policy WHERE localoid = 'ft_like1'::regclass::oid; + localoid | policytype | numsegments | distkey | distclass +----------+------------+-------------+---------+----------- +(0 rows) + +DROP TABLE ft_source_table; +DROP FOREIGN TABLE ft_like; +DROP FOREIGN TABLE ft_like1; --start_ignore DROP FOREIGN DATA WRAPPER dummy CASCADE; --end_ignore diff --git a/src/test/regress/sql/gp_foreign_data.sql b/src/test/regress/sql/gp_foreign_data.sql index a26f96f9d50..c40eaf5cafd 100644 --- a/src/test/regress/sql/gp_foreign_data.sql +++ b/src/test/regress/sql/gp_foreign_data.sql @@ -28,6 +28,21 @@ CREATE FOREIGN TABLE ft5 ( ) SERVER s1 OPTIONS (delimiter ',', mpp_execute 'all segments', num_segments '5'); \d+ ft5 +-- CREATE FOREIGN TABLE LIKE +CREATE TABLE ft_source_table(a INT, b INT, c INT) DISTRIBUTED BY (b); +CREATE FOREIGN TABLE ft_like (LIKE ft_source_table) SERVER s0; +\d+ ft_like +-- shoule be null +SELECT * FROM gp_distribution_policy WHERE localoid = 'ft_like'::regclass::oid; +CREATE FOREIGN TABLE ft_like1 (LIKE ft_source_table) SERVER s0 +OPTIONS (delimiter ',', mpp_execute 'all segments', num_segments '3'); +\d+ ft_like1 +SELECT * FROM gp_distribution_policy WHERE localoid = 'ft_like1'::regclass::oid; + +DROP TABLE ft_source_table; +DROP FOREIGN TABLE ft_like; +DROP FOREIGN TABLE ft_like1; + --start_ignore DROP FOREIGN DATA WRAPPER dummy CASCADE; --end_ignore