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

Commitf8bbfad

Browse files
committed
Disallow TRUNCATE when there are any pending after-trigger events for
the target relation(s). There might be some cases where we could discardthe pending event instead, but for the moment a conservative approachseems sufficient. Per report from Markus Schiltknecht and subsequentdiscussion.
1 parent395c816 commitf8bbfad

File tree

3 files changed

+79
-4
lines changed

3 files changed

+79
-4
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.201 2006/08/25 04:06:48 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.202 2006/09/04 21:15:55 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -611,6 +611,13 @@ ExecuteTruncate(TruncateStmt *stmt)
611611
heap_truncate_check_FKs(rels, false);
612612
#endif
613613

614+
/*
615+
* Also check for pending AFTER trigger events on the target relations.
616+
* We can't just leave those be, since they will try to fetch tuples
617+
* that the TRUNCATE removes.
618+
*/
619+
AfterTriggerCheckTruncate(relids);
620+
614621
/*
615622
* OK, truncate each table.
616623
*/

‎src/backend/commands/trigger.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.206 2006/08/03 16:04:41 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.207 2006/09/04 21:15:56 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -3117,6 +3117,74 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
31173117
}
31183118
}
31193119

3120+
/* ----------
3121+
* AfterTriggerCheckTruncate()
3122+
*Test deferred-trigger status to see if a TRUNCATE is OK.
3123+
*
3124+
* The argument is a list of OIDs of relations due to be truncated.
3125+
* We raise error if there are any pending after-trigger events for them.
3126+
*
3127+
* In some scenarios it'd be reasonable to remove pending events (more
3128+
* specifically, mark them DONE by the current subxact) but without a lot
3129+
* of knowledge of the trigger semantics we can't do this in general.
3130+
* ----------
3131+
*/
3132+
void
3133+
AfterTriggerCheckTruncate(List*relids)
3134+
{
3135+
AfterTriggerEventevent;
3136+
intdepth;
3137+
3138+
/*
3139+
* Ignore call if we aren't in a transaction. (Shouldn't happen?)
3140+
*/
3141+
if (afterTriggers==NULL)
3142+
return;
3143+
3144+
/* Scan queued events */
3145+
for (event=afterTriggers->events.head;
3146+
event!=NULL;
3147+
event=event->ate_next)
3148+
{
3149+
/*
3150+
* We can ignore completed events. (Even if a DONE flag is rolled
3151+
* back by subxact abort, it's OK because the effects of the
3152+
* TRUNCATE must get rolled back too.)
3153+
*/
3154+
if (event->ate_event&AFTER_TRIGGER_DONE)
3155+
continue;
3156+
3157+
if (list_member_oid(relids,event->ate_relid))
3158+
ereport(ERROR,
3159+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3160+
errmsg("cannot truncate table \"%s\" because it has pending trigger events",
3161+
get_rel_name(event->ate_relid))));
3162+
}
3163+
3164+
/*
3165+
* Also scan events queued by incomplete queries. This could only
3166+
* matter if a TRUNCATE is executed by a function or trigger within
3167+
* an updating query on the same relation, which is pretty perverse,
3168+
* but let's check.
3169+
*/
3170+
for (depth=0;depth <=afterTriggers->query_depth;depth++)
3171+
{
3172+
for (event=afterTriggers->query_stack[depth].head;
3173+
event!=NULL;
3174+
event=event->ate_next)
3175+
{
3176+
if (event->ate_event&AFTER_TRIGGER_DONE)
3177+
continue;
3178+
3179+
if (list_member_oid(relids,event->ate_relid))
3180+
ereport(ERROR,
3181+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3182+
errmsg("cannot truncate table \"%s\" because it has pending trigger events",
3183+
get_rel_name(event->ate_relid))));
3184+
}
3185+
}
3186+
}
3187+
31203188

31213189
/* ----------
31223190
* AfterTriggerSaveEvent()

‎src/include/commands/trigger.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.58 2006/06/16 20:23:45 adunstan Exp $
9+
* $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.59 2006/09/04 21:15:56 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -164,8 +164,8 @@ extern void AfterTriggerFireDeferred(void);
164164
externvoidAfterTriggerEndXact(boolisCommit);
165165
externvoidAfterTriggerBeginSubXact(void);
166166
externvoidAfterTriggerEndSubXact(boolisCommit);
167-
168167
externvoidAfterTriggerSetState(ConstraintsSetStmt*stmt);
168+
externvoidAfterTriggerCheckTruncate(List*relids);
169169

170170

171171
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp