Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit84b4a0c

Browse files
committed
Fix dependency handling of partitions and inheritance for ON COMMIT
This commit fixes a set of issues with ON COMMIT actions when used onpartitioned tables and tables with inheritance children:- Applying ON COMMIT DROP on a partitioned table with partitions or on atable with inheritance children caused a failure at commit time, withcomplains about the children being already dropped as all relations aredropped one at the same time.- Applying ON COMMIT DELETE on a partition relying on a partitionedtable which uses ON COMMIT DROP would cause the partition truncation tofail as the parent is removed first.The solution to the first problem is to handle the removal of all thedependencies in one go instead of dropping relations one-by-one, basedon a suggestion from Álvaro Herrera. So instead all the relation OIDsto remove are gathered and then processed in one round of multipledeletions.The solution to the second problem is to reorder the actions, withtruncation happening first and relation drop done after. Even if itmeans that a partition could be first truncated, then immediatelydropped if its partitioned table is dropped, this has the merit to keepthe code simple as there is no need to do existence checks on therelations to drop.Contrary to a manual TRUNCATE on a partitioned table, ON COMMIT DELETEdoes not cascade to its partitions. The ON COMMIT action defined oneach partition gets the priority.Author: Michael PaquierReviewed-by: Amit Langote, Álvaro Herrera, Robert HaasDiscussion:https://postgr.es/m/68f17907-ec98-1192-f99f-8011400517f5@lab.ntt.co.jpBackpatch-through: 10
1 parent7b08b4a commit84b4a0c

File tree

4 files changed

+203
-25
lines changed

4 files changed

+203
-25
lines changed

‎doc/src/sgml/ref/create_table.sgml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
11571157
All rows in the temporary table will be deleted at the end
11581158
of each transaction block. Essentially, an automatic <xref
11591159
linkend="sql-truncate"/> is done
1160-
at each commit.
1160+
at each commit. When used on a partitioned table, this
1161+
is not cascaded to its partitions.
11611162
</para>
11621163
</listitem>
11631164
</varlistentry>
@@ -1167,7 +1168,9 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
11671168
<listitem>
11681169
<para>
11691170
The temporary table will be dropped at the end of the current
1170-
transaction block.
1171+
transaction block. When used on a partitioned table, this action
1172+
drops its partitions and when used on tables with inheritance
1173+
children, it drops the dependent children.
11711174
</para>
11721175
</listitem>
11731176
</varlistentry>

‎src/backend/commands/tablecmds.c

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13262,6 +13262,7 @@ PreCommit_on_commit_actions(void)
1326213262
{
1326313263
ListCell*l;
1326413264
List*oids_to_truncate=NIL;
13265+
List*oids_to_drop=NIL;
1326513266

1326613267
foreach(l,on_commits)
1326713268
{
@@ -13288,36 +13289,66 @@ PreCommit_on_commit_actions(void)
1328813289
oids_to_truncate=lappend_oid(oids_to_truncate,oc->relid);
1328913290
break;
1329013291
caseONCOMMIT_DROP:
13291-
{
13292-
ObjectAddressobject;
13293-
13294-
object.classId=RelationRelationId;
13295-
object.objectId=oc->relid;
13296-
object.objectSubId=0;
13297-
13298-
/*
13299-
* Since this is an automatic drop, rather than one
13300-
* directly initiated by the user, we pass the
13301-
* PERFORM_DELETION_INTERNAL flag.
13302-
*/
13303-
performDeletion(&object,
13304-
DROP_CASCADE,PERFORM_DELETION_INTERNAL);
13305-
13306-
/*
13307-
* Note that table deletion will call
13308-
* remove_on_commit_action, so the entry should get marked
13309-
* as deleted.
13310-
*/
13311-
Assert(oc->deleting_subid!=InvalidSubTransactionId);
13312-
break;
13313-
}
13292+
oids_to_drop=lappend_oid(oids_to_drop,oc->relid);
13293+
break;
1331413294
}
1331513295
}
13296+
13297+
/*
13298+
* Truncate relations before dropping so that all dependencies between
13299+
* relations are removed after they are worked on. Doing it like this
13300+
* might be a waste as it is possible that a relation being truncated will
13301+
* be dropped anyway due to its parent being dropped, but this makes the
13302+
* code more robust because of not having to re-check that the relation
13303+
* exists at truncation time.
13304+
*/
1331613305
if (oids_to_truncate!=NIL)
1331713306
{
1331813307
heap_truncate(oids_to_truncate);
1331913308
CommandCounterIncrement();/* XXX needed? */
1332013309
}
13310+
if (oids_to_drop!=NIL)
13311+
{
13312+
ObjectAddresses*targetObjects=new_object_addresses();
13313+
ListCell*l;
13314+
13315+
foreach(l,oids_to_drop)
13316+
{
13317+
ObjectAddressobject;
13318+
13319+
object.classId=RelationRelationId;
13320+
object.objectId=lfirst_oid(l);
13321+
object.objectSubId=0;
13322+
13323+
Assert(!object_address_present(&object,targetObjects));
13324+
13325+
add_exact_object_address(&object,targetObjects);
13326+
}
13327+
13328+
/*
13329+
* Since this is an automatic drop, rather than one directly initiated
13330+
* by the user, we pass the PERFORM_DELETION_INTERNAL flag.
13331+
*/
13332+
performMultipleDeletions(targetObjects,DROP_CASCADE,
13333+
PERFORM_DELETION_INTERNAL |PERFORM_DELETION_QUIETLY);
13334+
13335+
#ifdefUSE_ASSERT_CHECKING
13336+
13337+
/*
13338+
* Note that table deletion will call remove_on_commit_action, so the
13339+
* entry should get marked as deleted.
13340+
*/
13341+
foreach(l,on_commits)
13342+
{
13343+
OnCommitItem*oc= (OnCommitItem*)lfirst(l);
13344+
13345+
if (oc->oncommit!=ONCOMMIT_DROP)
13346+
continue;
13347+
13348+
Assert(oc->deleting_subid!=InvalidSubTransactionId);
13349+
}
13350+
#endif
13351+
}
1332113352
}
1332213353

1332313354
/*

‎src/test/regress/expected/temp.out

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,88 @@ select * from temp_parted_oncommit;
216216
(0 rows)
217217

218218
drop table temp_parted_oncommit;
219+
-- Check dependencies between ON COMMIT actions with a partitioned
220+
-- table and its partitions. Using ON COMMIT DROP on a parent removes
221+
-- the whole set.
222+
begin;
223+
create temp table temp_parted_oncommit_test (a int)
224+
partition by list (a) on commit drop;
225+
create temp table temp_parted_oncommit_test1
226+
partition of temp_parted_oncommit_test
227+
for values in (1) on commit delete rows;
228+
create temp table temp_parted_oncommit_test2
229+
partition of temp_parted_oncommit_test
230+
for values in (2) on commit drop;
231+
insert into temp_parted_oncommit_test values (1), (2);
232+
commit;
233+
-- no relations remain in this case.
234+
select relname from pg_class where relname like 'temp_parted_oncommit_test%';
235+
relname
236+
---------
237+
(0 rows)
238+
239+
-- Using ON COMMIT DELETE on a partitioned table does not remove
240+
-- all rows if partitions preserve their data.
241+
begin;
242+
create temp table temp_parted_oncommit_test (a int)
243+
partition by list (a) on commit delete rows;
244+
create temp table temp_parted_oncommit_test1
245+
partition of temp_parted_oncommit_test
246+
for values in (1) on commit preserve rows;
247+
create temp table temp_parted_oncommit_test2
248+
partition of temp_parted_oncommit_test
249+
for values in (2) on commit drop;
250+
insert into temp_parted_oncommit_test values (1), (2);
251+
commit;
252+
-- Data from the remaining partition is still here as its rows are
253+
-- preserved.
254+
select * from temp_parted_oncommit_test;
255+
a
256+
---
257+
1
258+
(1 row)
259+
260+
-- two relations remain in this case.
261+
select relname from pg_class where relname like 'temp_parted_oncommit_test%';
262+
relname
263+
----------------------------
264+
temp_parted_oncommit_test
265+
temp_parted_oncommit_test1
266+
(2 rows)
267+
268+
drop table temp_parted_oncommit_test;
269+
-- Check dependencies between ON COMMIT actions with inheritance trees.
270+
-- Using ON COMMIT DROP on a parent removes the whole set.
271+
begin;
272+
create temp table temp_inh_oncommit_test (a int) on commit drop;
273+
create temp table temp_inh_oncommit_test1 ()
274+
inherits(temp_inh_oncommit_test) on commit delete rows;
275+
insert into temp_inh_oncommit_test1 values (1);
276+
commit;
277+
-- no relations remain in this case
278+
select relname from pg_class where relname like 'temp_inh_oncommit_test%';
279+
relname
280+
---------
281+
(0 rows)
282+
283+
-- Data on the parent is removed, and the child goes away.
284+
begin;
285+
create temp table temp_inh_oncommit_test (a int) on commit delete rows;
286+
create temp table temp_inh_oncommit_test1 ()
287+
inherits(temp_inh_oncommit_test) on commit drop;
288+
insert into temp_inh_oncommit_test1 values (1);
289+
insert into temp_inh_oncommit_test values (1);
290+
commit;
291+
select * from temp_inh_oncommit_test;
292+
a
293+
---
294+
(0 rows)
295+
296+
-- one relation remains
297+
select relname from pg_class where relname like 'temp_inh_oncommit_test%';
298+
relname
299+
------------------------
300+
temp_inh_oncommit_test
301+
(1 row)
302+
303+
drop table temp_inh_oncommit_test;

‎src/test/regress/sql/temp.sql

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,62 @@ commit;
165165
-- partitions are emptied by the previous commit
166166
select*from temp_parted_oncommit;
167167
droptable temp_parted_oncommit;
168+
169+
-- Check dependencies between ON COMMIT actions with a partitioned
170+
-- table and its partitions. Using ON COMMIT DROP on a parent removes
171+
-- the whole set.
172+
begin;
173+
create temp table temp_parted_oncommit_test (aint)
174+
partition by list (a)oncommit drop;
175+
create temp table temp_parted_oncommit_test1
176+
partition of temp_parted_oncommit_test
177+
forvaluesin (1)oncommitdelete rows;
178+
create temp table temp_parted_oncommit_test2
179+
partition of temp_parted_oncommit_test
180+
forvaluesin (2)oncommit drop;
181+
insert into temp_parted_oncommit_testvalues (1), (2);
182+
commit;
183+
-- no relations remain in this case.
184+
select relnamefrom pg_classwhere relnamelike'temp_parted_oncommit_test%';
185+
-- Using ON COMMIT DELETE on a partitioned table does not remove
186+
-- all rows if partitions preserve their data.
187+
begin;
188+
create temp table temp_parted_oncommit_test (aint)
189+
partition by list (a)oncommitdelete rows;
190+
create temp table temp_parted_oncommit_test1
191+
partition of temp_parted_oncommit_test
192+
forvaluesin (1)oncommit preserve rows;
193+
create temp table temp_parted_oncommit_test2
194+
partition of temp_parted_oncommit_test
195+
forvaluesin (2)oncommit drop;
196+
insert into temp_parted_oncommit_testvalues (1), (2);
197+
commit;
198+
-- Data from the remaining partition is still here as its rows are
199+
-- preserved.
200+
select*from temp_parted_oncommit_test;
201+
-- two relations remain in this case.
202+
select relnamefrom pg_classwhere relnamelike'temp_parted_oncommit_test%';
203+
droptable temp_parted_oncommit_test;
204+
205+
-- Check dependencies between ON COMMIT actions with inheritance trees.
206+
-- Using ON COMMIT DROP on a parent removes the whole set.
207+
begin;
208+
create temp table temp_inh_oncommit_test (aint)oncommit drop;
209+
create temp table temp_inh_oncommit_test1 ()
210+
inherits(temp_inh_oncommit_test)oncommitdelete rows;
211+
insert into temp_inh_oncommit_test1values (1);
212+
commit;
213+
-- no relations remain in this case
214+
select relnamefrom pg_classwhere relnamelike'temp_inh_oncommit_test%';
215+
-- Data on the parent is removed, and the child goes away.
216+
begin;
217+
create temp table temp_inh_oncommit_test (aint)oncommitdelete rows;
218+
create temp table temp_inh_oncommit_test1 ()
219+
inherits(temp_inh_oncommit_test)oncommit drop;
220+
insert into temp_inh_oncommit_test1values (1);
221+
insert into temp_inh_oncommit_testvalues (1);
222+
commit;
223+
select*from temp_inh_oncommit_test;
224+
-- one relation remains
225+
select relnamefrom pg_classwhere relnamelike'temp_inh_oncommit_test%';
226+
droptable temp_inh_oncommit_test;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp