]> granicus.if.org Git - postgresql/commitdiff
Disable WAL-skipping optimization for COPY on views and foreign tables
authorMichael Paquier <michael@paquier.xyz>
Sun, 23 Dec 2018 07:43:47 +0000 (16:43 +0900)
committerMichael Paquier <michael@paquier.xyz>
Sun, 23 Dec 2018 07:43:47 +0000 (16:43 +0900)
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.

contrib/postgres_fdw/expected/postgres_fdw.out
contrib/postgres_fdw/sql/postgres_fdw.sql
src/backend/commands/copy.c
src/test/regress/expected/copy2.out
src/test/regress/sql/copy2.sql

index 97de293f838eb8900d04cca1576c9e4358cc7c51..5d60ead91cc97ec9281b3d586c9b7017de55be6f 100644 (file)
@@ -7883,6 +7883,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
 -- ===================================================================
index 88b9f5c42d61cd151a30f468f564b1deb0efec5e..cef42d26f1944fb3fbccab0809a7dc162ebf4887 100644 (file)
@@ -2085,6 +2085,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
 -- ===================================================================
index 25d19a51182935c9d1539139a3644859a0b770cd..f4653485e2bd081ddad9ccd4be2caf291d2bc8c1 100644 (file)
@@ -2423,10 +2423,17 @@ 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 (cstate->rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+               cstate->rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE &&
+               cstate->rel->rd_rel->relkind != RELKIND_VIEW &&
                (cstate->rel->rd_createSubid != InvalidSubTransactionId ||
                 cstate->rel->rd_newRelfilenodeSubid != InvalidSubTransactionId))
        {
index e606a5fda47e3f1cfac8ae47631a03d618bacd3e..063522e6629ae0ac26b5049ca77e83ab110314ed 100644 (file)
@@ -557,6 +557,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;
@@ -569,4 +586,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();
index f3a6d228fae0ae6827d288f267340197204285f1..3022a07d3c20b1be00b7a10afa505875dac24a23 100644 (file)
@@ -411,6 +411,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;
@@ -424,4 +439,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();