diff --git a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp index fc0dc4d69e8c87b38ad5d769f9d964c9f43a1335..4f8fa3f0cbbdd0962924b206dcd9059b643c3ac3 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp @@ -406,9 +406,10 @@ bool InsertFusion::execute(long max_rows, char* completionTag) refreshParameterIfNecessary(); ModifyTable* node = (ModifyTable*)(m_global->m_planstmt->planTree); + PlanState* ps = NULL; if (node->withCheckOptionLists != NIL) { Plan* plan = (Plan*)linitial(node->plans); - PlanState* ps = ExecInitNode(plan, m_c_local.m_estate, 0); + ps = ExecInitNode(plan, m_c_local.m_estate, 0); List* wcoList = (List*)linitial(node->withCheckOptionLists); List* wcoExprs = NIL; ListCell* ll = NULL; @@ -433,6 +434,9 @@ bool InsertFusion::execute(long max_rows, char* completionTag) /**************** * step 3: done * ****************/ + if (ps != NULL) { + ExecEndNode(ps); + } success = true; m_local.m_isCompleted = true; if (m_local.m_ledger_hash_exist && !IsConnFromApp()) { diff --git a/src/gausskernel/runtime/opfusion/opfusion_update.cpp b/src/gausskernel/runtime/opfusion/opfusion_update.cpp index a04c7ee698df44fb38d4a6e4ea611cbbbd1e67b8..8404b1dd400abaaaaa999b38ca8ba2d56bf5c976 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_update.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_update.cpp @@ -554,13 +554,16 @@ lreplace: m_local.m_ledger_hash_exist = true; m_local.m_ledger_relhash += res_hash; } + + /* Check any WITH CHECK OPTION constraints */ + if (result_rel_info->ri_WithCheckOptions != NIL) { + ExecWithCheckOptions(result_rel_info, m_local.m_reslot, m_c_local.m_estate); + } + bms_free(modifiedIdxAttrs); list_free_ext(recheck_indexes); } - if (result_rel_info->ri_WithCheckOptions != NIL) - ExecWithCheckOptions(result_rel_info, m_local.m_reslot, m_c_local.m_estate); - tableam_tops_free_tuple(tup); (void)ExecClearTuple(m_local.m_reslot); @@ -607,9 +610,10 @@ bool UpdateFusion::execute(long max_rows, char *completionTag) } ModifyTable* node = (ModifyTable*)(m_global->m_planstmt->planTree); + PlanState* ps = NULL; if (node->withCheckOptionLists != NIL) { Plan* plan = (Plan*)linitial(node->plans); - PlanState* ps = ExecInitNode(plan, m_c_local.m_estate, 0); + ps = ExecInitNode(plan, m_c_local.m_estate, 0); List* wcoList = (List*)linitial(node->withCheckOptionLists); List* wcoExprs = NIL; ListCell* ll = NULL; @@ -632,6 +636,9 @@ bool UpdateFusion::execute(long max_rows, char *completionTag) /* *************** * step 3: done * * ************** */ + if (ps != NULL) { + ExecEndNode(ps); + } success = true; if (m_local.m_ledger_hash_exist && !IsConnFromApp()) { errorno = snprintf_s(completionTag, COMPLETION_TAG_BUFSIZE, COMPLETION_TAG_BUFSIZE - 1, diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out index ae07c665a10e253df9c20e6ef532f30cf3bd0208..3404210b772d0f114f834aeaaecda81b0e819a5c 100644 --- a/src/test/regress/expected/updatable_views.out +++ b/src/test/regress/expected/updatable_views.out @@ -2437,5 +2437,40 @@ DETAIL: Failing row contains (0, null). insert into rw_view2 values (10); -- fail ERROR: new row violates WITH CHECK OPTION for view "rw_view2" DETAIL: Failing row contains (10, null). +CREATE TABLE base_tbl (a int primary key, b int DEFAULT 10); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "base_tbl_pkey" for table "base_tbl" +INSERT INTO base_tbl VALUES (1,2), (2,3); +CREATE VIEW ro_view1 AS SELECT * FROM base_tbl WHERE a < 10 WITH CHECK OPTION; +INSERT INTO ro_view1 VALUES(3,4); +explain (costs off) UPDATE ro_view1 SET b = 5 WHERE a = 3; + QUERY PLAN +-------------------------------------------------- + [Bypass] + Update on base_tbl + -> Index Scan using base_tbl_pkey on base_tbl + Index Cond: ((a < 10) AND (a = 3)) +(4 rows) + +UPDATE ro_view1 SET b = 5 WHERE a = 3; +drop table if exists base_tbl cascade; +NOTICE: drop cascades to view ro_view1 +CREATE TABLE base_tbl (a int primary key, b int DEFAULT 10); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "base_tbl_pkey" for table "base_tbl" +INSERT INTO base_tbl VALUES (1,2), (8,2), (9,0); +CREATE VIEW ro_view1 AS SELECT * FROM base_tbl WHERE a < 10 WITH CHECK OPTION; +set enable_seqscan = off; +set enable_bitmapscan = off; +explain (costs off) UPDATE ro_view1 SET a = a + b; + QUERY PLAN +-------------------------------------------------- + [Bypass] + Update on base_tbl + -> Index Scan using base_tbl_pkey on base_tbl + Index Cond: (a < 10) +(4 rows) + +UPDATE ro_view1 SET a = a + b; +ERROR: new row violates WITH CHECK OPTION for view "ro_view1" +DETAIL: Failing row contains (10, 2). \c regression drop database updatable_views_db; diff --git a/src/test/regress/sql/updatable_views.sql b/src/test/regress/sql/updatable_views.sql index d38b0a0a101503d97315f1d6c4d13898ef0e838f..f97fce2c9a08b26e8be6954d4efb158798f44668 100644 --- a/src/test/regress/sql/updatable_views.sql +++ b/src/test/regress/sql/updatable_views.sql @@ -1246,5 +1246,23 @@ alter view rw_view2 as select * from rw_view1 where id < 10 with cascaded check insert into rw_view2 values (0); -- fail insert into rw_view2 values (10); -- fail +CREATE TABLE base_tbl (a int primary key, b int DEFAULT 10); +INSERT INTO base_tbl VALUES (1,2), (2,3); +CREATE VIEW ro_view1 AS SELECT * FROM base_tbl WHERE a < 10 WITH CHECK OPTION; +INSERT INTO ro_view1 VALUES(3,4); + +explain (costs off) UPDATE ro_view1 SET b = 5 WHERE a = 3; +UPDATE ro_view1 SET b = 5 WHERE a = 3; + +drop table if exists base_tbl cascade; +CREATE TABLE base_tbl (a int primary key, b int DEFAULT 10); +INSERT INTO base_tbl VALUES (1,2), (8,2), (9,0); +CREATE VIEW ro_view1 AS SELECT * FROM base_tbl WHERE a < 10 WITH CHECK OPTION; + +set enable_seqscan = off; +set enable_bitmapscan = off; +explain (costs off) UPDATE ro_view1 SET a = a + b; +UPDATE ro_view1 SET a = a + b; + \c regression drop database updatable_views_db; \ No newline at end of file