aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/tablecmds.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2018-12-27 10:16:19 +0900
committerMichael Paquier <michael@paquier.xyz>2018-12-27 10:16:19 +0900
commit1e504f01da11db0181d7b28bb30cb5eeb0767184 (patch)
tree5d5a1a3bfbb085b9f9bdd3291b39b26b7c6a96c7 /src/backend/commands/tablecmds.c
parent8528e3d849a896f8711c56fb41eae56f8c986729 (diff)
downloadpostgresql-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.c23
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);