This is an automated email from the ASF dual-hosted git repository.

reshke pushed a commit to branch REL_2_STABLE
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 5bee95685be6a05a108b411ebb1dca5271022fef
Author: Etsuro Fujita <[email protected]>
AuthorDate: Fri Aug 5 17:15:03 2022 +0900

    postgres_fdw: Disable batch insertion when there are WCO constraints.
    
    When inserting a view referencing a foreign table that has WITH CHECK
    OPTION constraints, in single-insert mode postgres_fdw retrieves the
    data that was actually inserted on the remote side so that the WITH
    CHECK OPTION constraints are enforced with the data locally, but in
    batch-insert mode it cannot currently retrieve the data (except for the
    row first inserted through the view), resulting in enforcing the WITH
    CHECK OPTION constraints with the data passed from the core (except for
    the first-inserted row), which led to incorrect results when inserting
    into a view referencing a foreign table in which a remote BEFORE ROW
    INSERT trigger changes the rows inserted through the view so that they
    violate the view's WITH CHECK OPTION constraint.  Also, the query
    inserting into the view caused an assertion failure in assert-enabled
    builds.
    
    Fix these by disabling batch insertion when inserting into such a view.
    
    Back-patch to v14 where batch insertion was added.
    
    Discussion: 
https://postgr.es/m/CAPmGK17LpbTZs4m4a_6THP54UBeK9fHvX8aVVA%2BC6yEZDZwQcg%40mail.gmail.com
---
 contrib/postgres_fdw/expected/postgres_fdw.out | 44 ++++++++++++++++++++++++++
 contrib/postgres_fdw/postgres_fdw.c            |  6 ++--
 contrib/postgres_fdw/sql/postgres_fdw.sql      | 16 ++++++++++
 3 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out 
b/contrib/postgres_fdw/expected/postgres_fdw.out
index 655bdced4f1..2874e69c7e5 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -6486,6 +6486,29 @@ SELECT * FROM foreign_tbl;
  20 | 30
 (1 row)
 
+-- We don't allow batch insert when there are any WCO constraints
+ALTER SERVER loopback OPTIONS (ADD batch_size '10');
+EXPLAIN (VERBOSE, COSTS OFF)
+INSERT INTO rw_view VALUES (0, 15), (0, 5);
+                                   QUERY PLAN                                  
 
+--------------------------------------------------------------------------------
+ Insert on public.foreign_tbl
+   Remote SQL: INSERT INTO public.base_tbl(a, b) VALUES ($1, $2) RETURNING a, b
+   Batch Size: 1
+   ->  Values Scan on "*VALUES*"
+         Output: "*VALUES*".column1, "*VALUES*".column2
+(5 rows)
+
+INSERT INTO rw_view VALUES (0, 15), (0, 5); -- should fail
+ERROR:  new row violates check option for view "rw_view"
+DETAIL:  Failing row contains (10, 5).
+SELECT * FROM foreign_tbl;
+ a  | b  
+----+----
+ 20 | 30
+(1 row)
+
+ALTER SERVER loopback OPTIONS (DROP batch_size);
 DROP FOREIGN TABLE foreign_tbl CASCADE;
 NOTICE:  drop cascades to view rw_view
 DROP TRIGGER row_before_insupd_trigger ON base_tbl;
@@ -6578,6 +6601,27 @@ SELECT * FROM foreign_tbl;
  20 | 30
 (1 row)
 
+-- We don't allow batch insert when there are any WCO constraints
+ALTER SERVER loopback OPTIONS (ADD batch_size '10');
+EXPLAIN (VERBOSE, COSTS OFF)
+INSERT INTO rw_view VALUES (0, 15), (0, 5);
+                       QUERY PLAN                       
+--------------------------------------------------------
+ Insert on public.parent_tbl
+   ->  Values Scan on "*VALUES*"
+         Output: "*VALUES*".column1, "*VALUES*".column2
+(3 rows)
+
+INSERT INTO rw_view VALUES (0, 15), (0, 5); -- should fail
+ERROR:  new row violates check option for view "rw_view"
+DETAIL:  Failing row contains (10, 5).
+SELECT * FROM foreign_tbl;
+ a  | b  
+----+----
+ 20 | 30
+(1 row)
+
+ALTER SERVER loopback OPTIONS (DROP batch_size);
 DROP FOREIGN TABLE foreign_tbl CASCADE;
 DROP TRIGGER row_before_insupd_trigger ON child_tbl;
 DROP TABLE parent_tbl CASCADE;
diff --git a/contrib/postgres_fdw/postgres_fdw.c 
b/contrib/postgres_fdw/postgres_fdw.c
index 58599c7aeaa..b5adcb86c09 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -2046,8 +2046,9 @@ postgresGetForeignModifyBatchSize(ResultRelInfo 
*resultRelInfo)
                batch_size = 
get_batch_size_option(resultRelInfo->ri_RelationDesc);
 
        /*
-        * Disable batching when we have to use RETURNING or there are any
-        * BEFORE/AFTER ROW INSERT triggers on the foreign table.
+        * Disable batching when we have to use RETURNING, there are any
+        * BEFORE/AFTER ROW INSERT triggers on the foreign table, or there are 
any
+        * WITH CHECK OPTION constraints from parent views.
         *
         * When there are any BEFORE ROW INSERT triggers on the table, we can't
         * support it, because such triggers might query the table we're 
inserting
@@ -2055,6 +2056,7 @@ postgresGetForeignModifyBatchSize(ResultRelInfo 
*resultRelInfo)
         * and prepared for insertion are not there.
         */
        if (resultRelInfo->ri_projectReturning != NULL ||
+               resultRelInfo->ri_WithCheckOptions != NIL ||
                (resultRelInfo->ri_TrigDesc &&
                 (resultRelInfo->ri_TrigDesc->trig_insert_before_row ||
                  resultRelInfo->ri_TrigDesc->trig_insert_after_row)))
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql 
b/contrib/postgres_fdw/sql/postgres_fdw.sql
index 724c1802b28..3663ca3bdf4 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -1442,6 +1442,14 @@ UPDATE rw_view SET b = b + 15;
 UPDATE rw_view SET b = b + 15; -- ok
 SELECT * FROM foreign_tbl;
 
+-- We don't allow batch insert when there are any WCO constraints
+ALTER SERVER loopback OPTIONS (ADD batch_size '10');
+EXPLAIN (VERBOSE, COSTS OFF)
+INSERT INTO rw_view VALUES (0, 15), (0, 5);
+INSERT INTO rw_view VALUES (0, 15), (0, 5); -- should fail
+SELECT * FROM foreign_tbl;
+ALTER SERVER loopback OPTIONS (DROP batch_size);
+
 DROP FOREIGN TABLE foreign_tbl CASCADE;
 DROP TRIGGER row_before_insupd_trigger ON base_tbl;
 DROP TABLE base_tbl;
@@ -1480,6 +1488,14 @@ UPDATE rw_view SET b = b + 15;
 UPDATE rw_view SET b = b + 15; -- ok
 SELECT * FROM foreign_tbl;
 
+-- We don't allow batch insert when there are any WCO constraints
+ALTER SERVER loopback OPTIONS (ADD batch_size '10');
+EXPLAIN (VERBOSE, COSTS OFF)
+INSERT INTO rw_view VALUES (0, 15), (0, 5);
+INSERT INTO rw_view VALUES (0, 15), (0, 5); -- should fail
+SELECT * FROM foreign_tbl;
+ALTER SERVER loopback OPTIONS (DROP batch_size);
+
 DROP FOREIGN TABLE foreign_tbl CASCADE;
 DROP TRIGGER row_before_insupd_trigger ON child_tbl;
 DROP TABLE parent_tbl CASCADE;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to