aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2018-12-23 16:42:22 +0900
committerMichael Paquier <michael@paquier.xyz>2018-12-23 16:42:22 +0900
commitbf491a9073e12ce1fc3e6facd0ae1308534df570 (patch)
tree9cd8cd5ce2f5e21d32227592d82dd0fa830e37d2
parent11a60d496147a1e1bbf6932bda53941c5a62ee1a (diff)
downloadpostgresql-bf491a9073e12ce1fc3e6facd0ae1308534df570.tar.gz
postgresql-bf491a9073e12ce1fc3e6facd0ae1308534df570.zip
Disable WAL-skipping optimization for COPY on views and foreign tables
COPY can skip writing WAL when loading data on a table which has been created in the same transaction as the one loading the data, however this cannot work on views or foreign table as this would result in trying to flush relation files which do not exist. So disable the optimization so as commands are able to work the same way with any configuration of wal_level. Tests are added to cover the different cases, which need to have wal_level set to minimal to allow the problem to show up, and that is not the default configuration. Reported-by: Luis M. Carril, Etsuro Fujita Author: Amit Langote, Michael Paquier Reviewed-by: Etsuro Fujita Discussion: https://postgr.es/m/15552-c64aa14c5c22f63c@postgresql.org Backpatch-through: 10, where support for COPY on views has been added, while v11 has added support for COPY on foreign tables.
-rw-r--r--contrib/postgres_fdw/expected/postgres_fdw.out16
-rw-r--r--contrib/postgres_fdw/sql/postgres_fdw.sql14
-rw-r--r--src/backend/commands/copy.c7
-rw-r--r--src/test/regress/expected/copy2.out18
-rw-r--r--src/test/regress/sql/copy2.sql16
5 files changed, 70 insertions, 1 deletions
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 666548ba696..bb92d9d37ab 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -7981,6 +7981,22 @@ drop trigger rem2_trig_row_before on rem2;
drop trigger rem2_trig_row_after on rem2;
drop trigger loc2_trig_row_before_insert on loc2;
delete from rem2;
+-- test COPY FROM with foreign table created in the same transaction
+create table loc3 (f1 int, f2 text);
+begin;
+create foreign table rem3 (f1 int, f2 text)
+ server loopback options(table_name 'loc3');
+copy rem3 from stdin;
+commit;
+select * from rem3;
+ f1 | f2
+----+-----
+ 1 | foo
+ 2 | bar
+(2 rows)
+
+drop foreign table rem3;
+drop table loc3;
-- ===================================================================
-- test IMPORT FOREIGN SCHEMA
-- ===================================================================
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index f963e99ab63..f438165650c 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -2124,6 +2124,20 @@ drop trigger loc2_trig_row_before_insert on loc2;
delete from rem2;
+-- test COPY FROM with foreign table created in the same transaction
+create table loc3 (f1 int, f2 text);
+begin;
+create foreign table rem3 (f1 int, f2 text)
+ server loopback options(table_name 'loc3');
+copy rem3 from stdin;
+1 foo
+2 bar
+\.
+commit;
+select * from rem3;
+drop foreign table rem3;
+drop table loc3;
+
-- ===================================================================
-- test IMPORT FOREIGN SCHEMA
-- ===================================================================
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 4311e160076..faa3f6357ae 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2397,10 +2397,15 @@ CopyFrom(CopyState cstate)
* possible to improve on this, but it does mean maintaining heap insert
* option flags per partition and setting them when we first open the
* partition.
+ *
+ * This optimization is not supported for relation types which do not
+ * have any physical storage, with foreign tables and views using
+ * INSTEAD OF triggers entering in this category. Partitioned tables
+ * are not supported as per the description above.
*----------
*/
/* createSubid is creation check, newRelfilenodeSubid is truncation check */
- if (cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
+ if (RELKIND_CAN_HAVE_STORAGE(cstate->rel->rd_rel->relkind) &&
(cstate->rel->rd_createSubid != InvalidSubTransactionId ||
cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId))
{
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index 19bb5384110..1d5bed5cc56 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -545,6 +545,23 @@ SELECT * FROM instead_of_insert_tbl;
1 | test1
(1 row)
+-- Test of COPY optimization with view using INSTEAD OF INSERT
+-- trigger when relation is created in the same transaction as
+-- when COPY is executed.
+BEGIN;
+CREATE VIEW instead_of_insert_tbl_view_2 as select ''::text as str;
+CREATE TRIGGER trig_instead_of_insert_tbl_view_2
+ INSTEAD OF INSERT ON instead_of_insert_tbl_view_2
+ FOR EACH ROW EXECUTE PROCEDURE fun_instead_of_insert_tbl();
+COPY instead_of_insert_tbl_view_2 FROM stdin;
+SELECT * FROM instead_of_insert_tbl;
+ id | name
+----+-------
+ 1 | test1
+ 2 | test1
+(2 rows)
+
+COMMIT;
-- clean up
DROP TABLE forcetest;
DROP TABLE vistest;
@@ -557,4 +574,5 @@ DROP FUNCTION fn_x_before();
DROP FUNCTION fn_x_after();
DROP TABLE instead_of_insert_tbl;
DROP VIEW instead_of_insert_tbl_view;
+DROP VIEW instead_of_insert_tbl_view_2;
DROP FUNCTION fun_instead_of_insert_tbl();
diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql
index e36df8858eb..a35f455fb5a 100644
--- a/src/test/regress/sql/copy2.sql
+++ b/src/test/regress/sql/copy2.sql
@@ -398,6 +398,21 @@ test1
SELECT * FROM instead_of_insert_tbl;
+-- Test of COPY optimization with view using INSTEAD OF INSERT
+-- trigger when relation is created in the same transaction as
+-- when COPY is executed.
+BEGIN;
+CREATE VIEW instead_of_insert_tbl_view_2 as select ''::text as str;
+CREATE TRIGGER trig_instead_of_insert_tbl_view_2
+ INSTEAD OF INSERT ON instead_of_insert_tbl_view_2
+ FOR EACH ROW EXECUTE PROCEDURE fun_instead_of_insert_tbl();
+
+COPY instead_of_insert_tbl_view_2 FROM stdin;
+test1
+\.
+
+SELECT * FROM instead_of_insert_tbl;
+COMMIT;
-- clean up
DROP TABLE forcetest;
@@ -411,4 +426,5 @@ DROP FUNCTION fn_x_before();
DROP FUNCTION fn_x_after();
DROP TABLE instead_of_insert_tbl;
DROP VIEW instead_of_insert_tbl_view;
+DROP VIEW instead_of_insert_tbl_view_2;
DROP FUNCTION fun_instead_of_insert_tbl();