diff --git a/src/gausskernel/optimizer/commands/copy.cpp b/src/gausskernel/optimizer/commands/copy.cpp index 4a6cf6a5b..c75eabbf8 100644 --- a/src/gausskernel/optimizer/commands/copy.cpp +++ b/src/gausskernel/optimizer/commands/copy.cpp @@ -4282,7 +4282,7 @@ uint64 CopyFrom(CopyState cstate) */ if ((resultRelInfo->ri_TrigDesc != NULL && (resultRelInfo->ri_TrigDesc->trig_insert_before_row || resultRelInfo->ri_TrigDesc->trig_insert_instead_row)) || - cstate->volatile_defexprs) { + cstate->volatile_defexprs || isForeignTbl) { useHeapMultiInsert = false; } else { useHeapMultiInsert = true; @@ -4819,6 +4819,8 @@ uint64 CopyFrom(CopyState cstate) if (!skip_tuple && isForeignTbl) { resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate, resultRelInfo, slot, NULL); + Assert(!useHeapMultiInsert); + resetPerTupCxt = true; processed++; } else if (!skip_tuple) { /* @@ -5004,6 +5006,14 @@ uint64 CopyFrom(CopyState cstate) * tuples inserted by an INSERT command. */ processed++; + } else {/*skip_tupe == true*/ + /* + * only the before row insert trigget would make skip_tupe==true + * which useHeapMultiInsert must be false + * so we can safely reset the per-tuple memory context in next iteration + */ + Assert(useHeapMultiInsert == false); + resetPerTupCxt = true; } #ifdef PGXC } diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out index 3de840c38..68f2fdb3b 100644 --- a/src/test/regress/expected/copy2.out +++ b/src/test/regress/expected/copy2.out @@ -321,3 +321,45 @@ DROP TABLE x; DROP TABLE y; DROP FUNCTION fn_x_before(); DROP FUNCTION fn_x_after(); +CREATE TABLE measurement ( +city_id int not null, +logdate int not null, +peaktemp int, +unitsales int +); +CREATE TABLE measurement_movement ( +city_id int not null, +logdate int not null, +peaktemp int, +unitsales int +); +CREATE OR REPLACE FUNCTION measurement_insert_trigger() +RETURNS TRIGGER AS $$ +BEGIN +INSERT INTO measurement_movement VALUES (NEW.*); +RETURN NULL; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER insert_measurement_trigger +BEFORE INSERT ON measurement +FOR EACH ROW EXECUTE PROCEDURE measurement_insert_trigger(); +COPY measurement from stdin; +select * from measurement_movement order by city_id; + city_id | logdate | peaktemp | unitsales +---------+---------+----------+----------- + 10001 | 22 | 32 | 42 + 10002 | 23 | 33 | 43 + 10003 | 24 | 34 | 44 + 10004 | 25 | 35 | 45 + 10005 | 26 | 36 | 46 +(5 rows) + +select * from measurement order by city_id; + city_id | logdate | peaktemp | unitsales +---------+---------+----------+----------- +(0 rows) + +drop trigger insert_measurement_trigger on measurement; +drop function measurement_insert_trigger; +drop table measurement; +drop table measurement_movement; diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql index 15007aa82..df3ad4292 100644 --- a/src/test/regress/sql/copy2.sql +++ b/src/test/regress/sql/copy2.sql @@ -228,3 +228,46 @@ DROP TABLE x; DROP TABLE y; DROP FUNCTION fn_x_before(); DROP FUNCTION fn_x_after(); + + +CREATE TABLE measurement ( +city_id int not null, +logdate int not null, +peaktemp int, +unitsales int +); + +CREATE TABLE measurement_movement ( +city_id int not null, +logdate int not null, +peaktemp int, +unitsales int +); + +CREATE OR REPLACE FUNCTION measurement_insert_trigger() +RETURNS TRIGGER AS $$ +BEGIN +INSERT INTO measurement_movement VALUES (NEW.*); +RETURN NULL; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER insert_measurement_trigger +BEFORE INSERT ON measurement +FOR EACH ROW EXECUTE PROCEDURE measurement_insert_trigger(); + +COPY measurement from stdin; +10001 22 32 42 +10002 23 33 43 +10003 24 34 44 +10004 25 35 45 +10005 26 36 46 +\. + +select * from measurement_movement order by city_id; +select * from measurement order by city_id; + +drop trigger insert_measurement_trigger on measurement; +drop function measurement_insert_trigger; +drop table measurement; +drop table measurement_movement;