diff options
author | Michael Paquier <michael@paquier.xyz> | 2018-12-27 10:16:19 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2018-12-27 10:16:19 +0900 |
commit | 1e504f01da11db0181d7b28bb30cb5eeb0767184 (patch) | |
tree | 5d5a1a3bfbb085b9f9bdd3291b39b26b7c6a96c7 /src/backend/commands/tablecmds.c | |
parent | 8528e3d849a896f8711c56fb41eae56f8c986729 (diff) | |
download | postgresql-1e504f01da11db0181d7b28bb30cb5eeb0767184.tar.gz postgresql-1e504f01da11db0181d7b28bb30cb5eeb0767184.zip |
Ignore inherited temp relations from other sessions when truncating
Inheritance trees can include temporary tables if the parent is
permanent, which makes possible the presence of multiple temporary
children from different sessions. Trying to issue a TRUNCATE on the
parent in this scenario causes a failure, so similarly to any other
queries just ignore such cases, which makes TRUNCATE work
transparently.
This makes truncation behave similarly to any other DML query working on
the parent table with queries which need to be work on the children. A
set of isolation tests is added to cover basic cases.
Reported-by: Zhou Digoal
Author: Amit Langote, Michael Paquier
Discussion: https://postgr.es/m/15565-ce67a48d0244436a@postgresql.org
Backpatch-through: 9.4
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 588c1ec5365..936d7aa611e 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1373,8 +1373,9 @@ ExecuteTruncate(TruncateStmt *stmt) Relation rel; bool recurse = rv->inh; Oid myrelid; + LOCKMODE lockmode = AccessExclusiveLock; - myrelid = RangeVarGetRelidExtended(rv, AccessExclusiveLock, + myrelid = RangeVarGetRelidExtended(rv, lockmode, 0, RangeVarCallbackForTruncate, NULL); @@ -1384,7 +1385,7 @@ ExecuteTruncate(TruncateStmt *stmt) /* don't throw error for "TRUNCATE foo, foo" */ if (list_member_oid(relids, myrelid)) { - heap_close(rel, AccessExclusiveLock); + heap_close(rel, lockmode); continue; } @@ -1405,7 +1406,7 @@ ExecuteTruncate(TruncateStmt *stmt) ListCell *child; List *children; - children = find_all_inheritors(myrelid, AccessExclusiveLock, NULL); + children = find_all_inheritors(myrelid, lockmode, NULL); foreach(child, children) { @@ -1416,6 +1417,22 @@ ExecuteTruncate(TruncateStmt *stmt) /* find_all_inheritors already got lock */ rel = heap_open(childrelid, NoLock); + + /* + * It is possible that the parent table has children that are + * temp tables of other backends. We cannot safely access + * such tables (because of buffering issues), and the best + * thing to do is to silently ignore them. Note that this + * check is the same as one of the checks done in + * truncate_check_activity() called below, still it is kept + * here for simplicity. + */ + if (RELATION_IS_OTHER_TEMP(rel)) + { + heap_close(rel, lockmode); + continue; + } + truncate_check_rel(RelationGetRelid(rel), rel->rd_rel); truncate_check_activity(rel); |