mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
Fix state reversal after partition tuple routing
We make some changes to ModifyTableState and the EState it uses whenever we route tuples to partitions; but we weren't restoring properly in all cases, possibly causing crashes when partitions with different tuple descriptors are targeted by tuples inserted in the same command. Refactor some code, creating ExecPrepareTupleRouting, to encapsulate the needed state changing logic, and have it invoked one level above its current place (ie. put it in ExecModifyTable instead of ExecInsert); this makes it all more readable. Add a test case to exercise this. We don't support having views as partitions; and since only views can have INSTEAD OF triggers, there is no point in testing for INSTEAD OF when processing insertions into a partitioned table. Remove code that appears to support this (but which is actually never relevant.) In passing, fix location of some very confusing comments in ModifyTableState. Reported-by: Amit Langote Author: Etsuro Fujita, Amit Langote Discussion: https://postgr/es/m/0473bf5c-57b1-f1f7-3d58-455c2230bc5f@lab.ntt.co.jp
This commit is contained in:
@ -748,6 +748,32 @@ drop role regress_coldesc_role;
|
||||
drop table inserttest3;
|
||||
drop table brtrigpartcon;
|
||||
drop function brtrigpartcon1trigf();
|
||||
-- check that "do nothing" BR triggers work with tuple-routing (this checks
|
||||
-- that estate->es_result_relation_info is appropriately set/reset for each
|
||||
-- routed tuple)
|
||||
create table donothingbrtrig_test (a int, b text) partition by list (a);
|
||||
create table donothingbrtrig_test1 (b text, a int);
|
||||
create table donothingbrtrig_test2 (c text, b text, a int);
|
||||
alter table donothingbrtrig_test2 drop column c;
|
||||
create or replace function donothingbrtrig_func() returns trigger as $$begin raise notice 'b: %', new.b; return NULL; end$$ language plpgsql;
|
||||
create trigger donothingbrtrig1 before insert on donothingbrtrig_test1 for each row execute procedure donothingbrtrig_func();
|
||||
create trigger donothingbrtrig2 before insert on donothingbrtrig_test2 for each row execute procedure donothingbrtrig_func();
|
||||
alter table donothingbrtrig_test attach partition donothingbrtrig_test1 for values in (1);
|
||||
alter table donothingbrtrig_test attach partition donothingbrtrig_test2 for values in (2);
|
||||
insert into donothingbrtrig_test values (1, 'foo'), (2, 'bar');
|
||||
NOTICE: b: foo
|
||||
NOTICE: b: bar
|
||||
copy donothingbrtrig_test from stdout;
|
||||
NOTICE: b: baz
|
||||
NOTICE: b: qux
|
||||
select tableoid::regclass, * from donothingbrtrig_test;
|
||||
tableoid | a | b
|
||||
----------+---+---
|
||||
(0 rows)
|
||||
|
||||
-- cleanup
|
||||
drop table donothingbrtrig_test;
|
||||
drop function donothingbrtrig_func();
|
||||
-- check multi-column range partitioning with minvalue/maxvalue constraints
|
||||
create table mcrparted (a text, b int) partition by range(a, b);
|
||||
create table mcrparted1_lt_b partition of mcrparted for values from (minvalue, minvalue) to ('b', minvalue);
|
||||
|
@ -489,6 +489,29 @@ drop table inserttest3;
|
||||
drop table brtrigpartcon;
|
||||
drop function brtrigpartcon1trigf();
|
||||
|
||||
-- check that "do nothing" BR triggers work with tuple-routing (this checks
|
||||
-- that estate->es_result_relation_info is appropriately set/reset for each
|
||||
-- routed tuple)
|
||||
create table donothingbrtrig_test (a int, b text) partition by list (a);
|
||||
create table donothingbrtrig_test1 (b text, a int);
|
||||
create table donothingbrtrig_test2 (c text, b text, a int);
|
||||
alter table donothingbrtrig_test2 drop column c;
|
||||
create or replace function donothingbrtrig_func() returns trigger as $$begin raise notice 'b: %', new.b; return NULL; end$$ language plpgsql;
|
||||
create trigger donothingbrtrig1 before insert on donothingbrtrig_test1 for each row execute procedure donothingbrtrig_func();
|
||||
create trigger donothingbrtrig2 before insert on donothingbrtrig_test2 for each row execute procedure donothingbrtrig_func();
|
||||
alter table donothingbrtrig_test attach partition donothingbrtrig_test1 for values in (1);
|
||||
alter table donothingbrtrig_test attach partition donothingbrtrig_test2 for values in (2);
|
||||
insert into donothingbrtrig_test values (1, 'foo'), (2, 'bar');
|
||||
copy donothingbrtrig_test from stdout;
|
||||
1 baz
|
||||
2 qux
|
||||
\.
|
||||
select tableoid::regclass, * from donothingbrtrig_test;
|
||||
|
||||
-- cleanup
|
||||
drop table donothingbrtrig_test;
|
||||
drop function donothingbrtrig_func();
|
||||
|
||||
-- check multi-column range partitioning with minvalue/maxvalue constraints
|
||||
create table mcrparted (a text, b int) partition by range(a, b);
|
||||
create table mcrparted1_lt_b partition of mcrparted for values from (minvalue, minvalue) to ('b', minvalue);
|
||||
|
Reference in New Issue
Block a user