aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2017-09-07 10:55:45 -0400
committerRobert Haas <rhaas@postgresql.org>2017-09-07 10:59:28 -0400
commit08cb36417aa22436647a1831a7d1ff6b41232280 (patch)
tree4e418b9bcae6ff672a0d5bd692fd6dea6bc0143b
parenta6c678f018d3a30a88440d3c20cf8e7cd6592a32 (diff)
downloadpostgresql-08cb36417aa22436647a1831a7d1ff6b41232280.tar.gz
postgresql-08cb36417aa22436647a1831a7d1ff6b41232280.zip
Even if some partitions are foreign, allow tuple routing.
This doesn't allow routing tuple to the foreign partitions themselves, but it permits tuples to be routed to regular partitions despite the presence of foreign partitions in the same inheritance hierarchy. Etsuro Fujita, reviewed by Amit Langote and by me. Discussion: http://postgr.es/m/bc3db4c1-1693-3b8a-559f-33ad2b50b7ad@lab.ntt.co.jp
-rw-r--r--contrib/file_fdw/data/list1.csv2
-rw-r--r--contrib/file_fdw/data/list2.bad2
-rw-r--r--contrib/file_fdw/data/list2.csv2
-rw-r--r--contrib/file_fdw/input/file_fdw.source21
-rw-r--r--contrib/file_fdw/output/file_fdw.source81
-rw-r--r--src/backend/executor/execMain.c25
-rw-r--r--src/backend/executor/nodeModifyTable.c2
-rw-r--r--src/include/executor/executor.h2
8 files changed, 126 insertions, 11 deletions
diff --git a/contrib/file_fdw/data/list1.csv b/contrib/file_fdw/data/list1.csv
new file mode 100644
index 00000000000..203f3b2324e
--- /dev/null
+++ b/contrib/file_fdw/data/list1.csv
@@ -0,0 +1,2 @@
+1,foo
+1,bar
diff --git a/contrib/file_fdw/data/list2.bad b/contrib/file_fdw/data/list2.bad
new file mode 100644
index 00000000000..00af47f5ef6
--- /dev/null
+++ b/contrib/file_fdw/data/list2.bad
@@ -0,0 +1,2 @@
+2,baz
+1,qux
diff --git a/contrib/file_fdw/data/list2.csv b/contrib/file_fdw/data/list2.csv
new file mode 100644
index 00000000000..2fb133d0046
--- /dev/null
+++ b/contrib/file_fdw/data/list2.csv
@@ -0,0 +1,2 @@
+2,baz
+2,qux
diff --git a/contrib/file_fdw/input/file_fdw.source b/contrib/file_fdw/input/file_fdw.source
index 685561fc2a0..e6821d64d44 100644
--- a/contrib/file_fdw/input/file_fdw.source
+++ b/contrib/file_fdw/input/file_fdw.source
@@ -162,6 +162,27 @@ SELECT tableoid::regclass, * FROM agg FOR UPDATE;
ALTER FOREIGN TABLE agg_csv NO INHERIT agg;
DROP TABLE agg;
+-- declarative partitioning tests
+SET ROLE regress_file_fdw_superuser;
+CREATE TABLE pt (a int, b text) partition by list (a);
+CREATE FOREIGN TABLE p1 partition of pt for values in (1) SERVER file_server
+OPTIONS (format 'csv', filename '@abs_srcdir@/data/list1.csv', delimiter ',');
+CREATE TABLE p2 partition of pt for values in (2);
+SELECT tableoid::regclass, * FROM pt;
+SELECT tableoid::regclass, * FROM p1;
+SELECT tableoid::regclass, * FROM p2;
+COPY pt FROM '@abs_srcdir@/data/list2.bad' with (format 'csv', delimiter ','); -- ERROR
+COPY pt FROM '@abs_srcdir@/data/list2.csv' with (format 'csv', delimiter ',');
+SELECT tableoid::regclass, * FROM pt;
+SELECT tableoid::regclass, * FROM p1;
+SELECT tableoid::regclass, * FROM p2;
+INSERT INTO pt VALUES (1, 'xyzzy'); -- ERROR
+INSERT INTO pt VALUES (2, 'xyzzy');
+SELECT tableoid::regclass, * FROM pt;
+SELECT tableoid::regclass, * FROM p1;
+SELECT tableoid::regclass, * FROM p2;
+DROP TABLE pt;
+
-- privilege tests
SET ROLE regress_file_fdw_superuser;
SELECT * FROM agg_text ORDER BY a;
diff --git a/contrib/file_fdw/output/file_fdw.source b/contrib/file_fdw/output/file_fdw.source
index 01e2690a825..709c43ec804 100644
--- a/contrib/file_fdw/output/file_fdw.source
+++ b/contrib/file_fdw/output/file_fdw.source
@@ -289,6 +289,87 @@ SELECT tableoid::regclass, * FROM agg FOR UPDATE;
ALTER FOREIGN TABLE agg_csv NO INHERIT agg;
DROP TABLE agg;
+-- declarative partitioning tests
+SET ROLE regress_file_fdw_superuser;
+CREATE TABLE pt (a int, b text) partition by list (a);
+CREATE FOREIGN TABLE p1 partition of pt for values in (1) SERVER file_server
+OPTIONS (format 'csv', filename '@abs_srcdir@/data/list1.csv', delimiter ',');
+CREATE TABLE p2 partition of pt for values in (2);
+SELECT tableoid::regclass, * FROM pt;
+ tableoid | a | b
+----------+---+-----
+ p1 | 1 | foo
+ p1 | 1 | bar
+(2 rows)
+
+SELECT tableoid::regclass, * FROM p1;
+ tableoid | a | b
+----------+---+-----
+ p1 | 1 | foo
+ p1 | 1 | bar
+(2 rows)
+
+SELECT tableoid::regclass, * FROM p2;
+ tableoid | a | b
+----------+---+---
+(0 rows)
+
+COPY pt FROM '@abs_srcdir@/data/list2.bad' with (format 'csv', delimiter ','); -- ERROR
+ERROR: cannot route inserted tuples to a foreign table
+CONTEXT: COPY pt, line 2: "1,qux"
+COPY pt FROM '@abs_srcdir@/data/list2.csv' with (format 'csv', delimiter ',');
+SELECT tableoid::regclass, * FROM pt;
+ tableoid | a | b
+----------+---+-----
+ p1 | 1 | foo
+ p1 | 1 | bar
+ p2 | 2 | baz
+ p2 | 2 | qux
+(4 rows)
+
+SELECT tableoid::regclass, * FROM p1;
+ tableoid | a | b
+----------+---+-----
+ p1 | 1 | foo
+ p1 | 1 | bar
+(2 rows)
+
+SELECT tableoid::regclass, * FROM p2;
+ tableoid | a | b
+----------+---+-----
+ p2 | 2 | baz
+ p2 | 2 | qux
+(2 rows)
+
+INSERT INTO pt VALUES (1, 'xyzzy'); -- ERROR
+ERROR: cannot route inserted tuples to a foreign table
+INSERT INTO pt VALUES (2, 'xyzzy');
+SELECT tableoid::regclass, * FROM pt;
+ tableoid | a | b
+----------+---+-------
+ p1 | 1 | foo
+ p1 | 1 | bar
+ p2 | 2 | baz
+ p2 | 2 | qux
+ p2 | 2 | xyzzy
+(5 rows)
+
+SELECT tableoid::regclass, * FROM p1;
+ tableoid | a | b
+----------+---+-----
+ p1 | 1 | foo
+ p1 | 1 | bar
+(2 rows)
+
+SELECT tableoid::regclass, * FROM p2;
+ tableoid | a | b
+----------+---+-------
+ p2 | 2 | baz
+ p2 | 2 | qux
+ p2 | 2 | xyzzy
+(3 rows)
+
+DROP TABLE pt;
-- privilege tests
SET ROLE regress_file_fdw_superuser;
SELECT * FROM agg_text ORDER BY a;
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 4582a3caa00..9dcc358ec27 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1097,8 +1097,9 @@ InitPlan(QueryDesc *queryDesc, int eflags)
* CheckValidRowMarkRel.
*/
void
-CheckValidResultRel(Relation resultRel, CmdType operation)
+CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
{
+ Relation resultRel = resultRelInfo->ri_RelationDesc;
TriggerDesc *trigDesc = resultRel->trigdesc;
FdwRoutine *fdwroutine;
@@ -1169,10 +1170,16 @@ CheckValidResultRel(Relation resultRel, CmdType operation)
break;
case RELKIND_FOREIGN_TABLE:
/* Okay only if the FDW supports it */
- fdwroutine = GetFdwRoutineForRelation(resultRel, false);
+ fdwroutine = resultRelInfo->ri_FdwRoutine;
switch (operation)
{
case CMD_INSERT:
+ /*
+ * If foreign partition to do tuple-routing for, skip the
+ * check; it's disallowed elsewhere.
+ */
+ if (resultRelInfo->ri_PartitionRoot)
+ break;
if (fdwroutine->ExecForeignInsert == NULL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -3306,11 +3313,6 @@ ExecSetupPartitionTupleRouting(Relation rel,
part_tupdesc = RelationGetDescr(partrel);
/*
- * Verify result relation is a valid target for the current operation.
- */
- CheckValidResultRel(partrel, CMD_INSERT);
-
- /*
* Save a tuple conversion map to convert a tuple routed to this
* partition from the parent's type to the partition's.
*/
@@ -3323,8 +3325,10 @@ ExecSetupPartitionTupleRouting(Relation rel,
rel,
estate->es_instrument);
- estate->es_leaf_result_relations =
- lappend(estate->es_leaf_result_relations, leaf_part_rri);
+ /*
+ * Verify result relation is a valid target for INSERT.
+ */
+ CheckValidResultRel(leaf_part_rri, CMD_INSERT);
/*
* Open partition indices (remember we do not support ON CONFLICT in
@@ -3335,6 +3339,9 @@ ExecSetupPartitionTupleRouting(Relation rel,
leaf_part_rri->ri_IndexRelationDescs == NULL)
ExecOpenIndices(leaf_part_rri, false);
+ estate->es_leaf_result_relations =
+ lappend(estate->es_leaf_result_relations, leaf_part_rri);
+
leaf_part_rri++;
i++;
}
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 70a6b847a0e..83267580a35 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1853,7 +1853,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
/*
* Verify result relation is a valid target for the current operation
*/
- CheckValidResultRel(resultRelInfo->ri_RelationDesc, operation);
+ CheckValidResultRel(resultRelInfo, operation);
/*
* If there are indices on the result relation, open them and save
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index eacbea3c365..379e7c77a18 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -177,7 +177,7 @@ extern void ExecutorEnd(QueryDesc *queryDesc);
extern void standard_ExecutorEnd(QueryDesc *queryDesc);
extern void ExecutorRewind(QueryDesc *queryDesc);
extern bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation);
-extern void CheckValidResultRel(Relation resultRel, CmdType operation);
+extern void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation);
extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
Relation resultRelationDesc,
Index resultRelationIndex,