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

Commited98b48

Browse files
committed
Fix failure to ignore leftover temp tables after a server crash.
During crash recovery, we remove disk files belonging to temporary tables,but the system catalog entries for such tables are intentionally notcleaned up right away. Instead, the first backend that uses a temp schemais expected to clean out any leftover objects therein. This approachrequires that we be careful to ignore leftover temp tables (since anyactual access attempt would fail), *even if their BackendId matches oursession*, if we have not yet established use of the session's correspondingtemp schema. That worked fine in the past, but was broken by commitdebcec7 which incorrectly removed therd_islocaltemp relcache flag. Put it back, and undo various changesthat substituted tests like "rel->rd_backend == MyBackendId" for useof a state-aware flag. Per trouble report from Heikki Linnakangas.Back-patch to 9.1 where the erroneous change was made. In the backbranches, be careful to add rd_islocaltemp in a spot in the struct thatwas alignment padding before, so as not to break existing add-on code.
1 parent9d39e94 commited98b48

File tree

7 files changed

+63
-23
lines changed

7 files changed

+63
-23
lines changed

‎src/backend/catalog/toasting.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio
199199
* Toast tables for regular relations go in pg_toast; those for temp
200200
* relations go into the per-backend temp-toast-table namespace.
201201
*/
202-
if (RelationUsesTempNamespace(rel))
202+
if (isTempOrToastNamespace(rel->rd_rel->relnamespace))
203203
namespaceid=GetTempToastNamespace();
204204
else
205205
namespaceid=PG_TOAST_NAMESPACE;

‎src/backend/commands/copy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
790790
if (is_from)
791791
{
792792
/* check read-only transaction */
793-
if (XactReadOnly&&rel->rd_backend!=MyBackendId)
793+
if (XactReadOnly&&!rel->rd_islocaltemp)
794794
PreventCommandIfReadOnly("COPY FROM");
795795

796796
cstate=BeginCopyFrom(rel,stmt->filename,

‎src/backend/commands/sequence.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ nextval_internal(Oid relid)
538538
RelationGetRelationName(seqrel))));
539539

540540
/* read-only transactions may only modify temp sequences */
541-
if (seqrel->rd_backend!=MyBackendId)
541+
if (!seqrel->rd_islocaltemp)
542542
PreventCommandIfReadOnly("nextval()");
543543

544544
if (elm->last!=elm->cached)/* some numbers were cached */
@@ -831,7 +831,7 @@ do_setval(Oid relid, int64 next, bool iscalled)
831831
RelationGetRelationName(seqrel))));
832832

833833
/* read-only transactions may only modify temp sequences */
834-
if (seqrel->rd_backend!=MyBackendId)
834+
if (!seqrel->rd_islocaltemp)
835835
PreventCommandIfReadOnly("setval()");
836836

837837
/* lock page' buffer and read tuple */

‎src/backend/commands/tablecmds.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,13 +1362,20 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
13621362
errmsg("inherited relation \"%s\" is not a table",
13631363
parent->relname)));
13641364
/* Permanent rels cannot inherit from temporary ones */
1365-
if (relpersistence!=RELPERSISTENCE_TEMP
1366-
&&RelationUsesTempNamespace(relation))
1365+
if (relpersistence!=RELPERSISTENCE_TEMP&&
1366+
relation->rd_rel->relpersistence==RELPERSISTENCE_TEMP)
13671367
ereport(ERROR,
13681368
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
13691369
errmsg("cannot inherit from temporary relation \"%s\"",
13701370
parent->relname)));
13711371

1372+
/* If existing rel is temp, it must belong to this session */
1373+
if (relation->rd_rel->relpersistence==RELPERSISTENCE_TEMP&&
1374+
!relation->rd_islocaltemp)
1375+
ereport(ERROR,
1376+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1377+
errmsg("cannot inherit from temporary relation of another session")));
1378+
13721379
/*
13731380
* We should have an UNDER permission flag for this, but for now,
13741381
* demand that creator of a child table own the parent.
@@ -5504,6 +5511,10 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
55045511
ereport(ERROR,
55055512
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
55065513
errmsg("constraints on temporary tables may reference only temporary tables")));
5514+
if (!pkrel->rd_islocaltemp|| !rel->rd_islocaltemp)
5515+
ereport(ERROR,
5516+
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5517+
errmsg("constraints on temporary tables must involve temporary tables of this session")));
55075518
break;
55085519
}
55095520

@@ -8146,13 +8157,27 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
81468157
ATSimplePermissions(parent_rel,ATT_TABLE);
81478158

81488159
/* Permanent rels cannot inherit from temporary ones */
8149-
if (RelationUsesTempNamespace(parent_rel)
8150-
&& !RelationUsesTempNamespace(child_rel))
8160+
if (parent_rel->rd_rel->relpersistence==RELPERSISTENCE_TEMP&&
8161+
child_rel->rd_rel->relpersistence!=RELPERSISTENCE_TEMP)
81518162
ereport(ERROR,
81528163
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
81538164
errmsg("cannot inherit from temporary relation \"%s\"",
81548165
RelationGetRelationName(parent_rel))));
81558166

8167+
/* If parent rel is temp, it must belong to this session */
8168+
if (parent_rel->rd_rel->relpersistence==RELPERSISTENCE_TEMP&&
8169+
!parent_rel->rd_islocaltemp)
8170+
ereport(ERROR,
8171+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
8172+
errmsg("cannot inherit from temporary relation of another session")));
8173+
8174+
/* Ditto for the child */
8175+
if (child_rel->rd_rel->relpersistence==RELPERSISTENCE_TEMP&&
8176+
!child_rel->rd_islocaltemp)
8177+
ereport(ERROR,
8178+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
8179+
errmsg("cannot inherit to temporary relation of another session")));
8180+
81568181
/*
81578182
* Check for duplicates in the list of parents, and determine the highest
81588183
* inhseqno already present; we'll use the next one for the new parent.

‎src/backend/utils/adt/dbsize.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ pg_tablespace_size_name(PG_FUNCTION_ARGS)
242242

243243
/*
244244
* calculate size of (one fork of) a relation
245+
*
246+
* Note: we can safely apply this to temp tables of other sessions, so there
247+
* is no check here or at the call sites for that.
245248
*/
246249
staticint64
247250
calculate_relation_size(RelFileNode*rfn,BackendIdbackend,ForkNumberforknum)

‎src/backend/utils/cache/relcache.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -854,20 +854,33 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
854854
caseRELPERSISTENCE_UNLOGGED:
855855
caseRELPERSISTENCE_PERMANENT:
856856
relation->rd_backend=InvalidBackendId;
857+
relation->rd_islocaltemp= false;
857858
break;
858859
caseRELPERSISTENCE_TEMP:
859860
if (isTempOrToastNamespace(relation->rd_rel->relnamespace))
861+
{
860862
relation->rd_backend=MyBackendId;
863+
relation->rd_islocaltemp= true;
864+
}
861865
else
862866
{
863867
/*
864-
* If it's a local temp table, but not one of ours, we have to
865-
* use the slow, grotty method to figure out the owning
866-
* backend.
868+
* If it's a temp table, but not one of ours, we have to use
869+
* the slow, grotty method to figure out the owning backend.
870+
*
871+
* Note: it's possible that rd_backend gets set to MyBackendId
872+
* here, in case we are looking at a pg_class entry left over
873+
* from a crashed backend that coincidentally had the same
874+
* BackendId we're using. We should *not* consider such a
875+
* table to be "ours"; this is why we need the separate
876+
* rd_islocaltemp flag. The pg_class entry will get flushed
877+
* if/when we clean out the corresponding temp table namespace
878+
* in preparation for using it.
867879
*/
868880
relation->rd_backend=
869881
GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
870882
Assert(relation->rd_backend!=InvalidBackendId);
883+
relation->rd_islocaltemp= false;
871884
}
872885
break;
873886
default:
@@ -1388,6 +1401,7 @@ formrdesc(const char *relationName, Oid relationReltype,
13881401
relation->rd_createSubid=InvalidSubTransactionId;
13891402
relation->rd_newRelfilenodeSubid=InvalidSubTransactionId;
13901403
relation->rd_backend=InvalidBackendId;
1404+
relation->rd_islocaltemp= false;
13911405

13921406
/*
13931407
* initialize relation tuple form
@@ -2535,16 +2549,19 @@ RelationBuildLocalRelation(const char *relname,
25352549
/* needed when bootstrapping: */
25362550
rel->rd_rel->relowner=BOOTSTRAP_SUPERUSERID;
25372551

2538-
/* set up persistence; rd_backend is a function of persistence type */
2552+
/* set up persistence and relcache fields dependent on it */
25392553
rel->rd_rel->relpersistence=relpersistence;
25402554
switch (relpersistence)
25412555
{
25422556
caseRELPERSISTENCE_UNLOGGED:
25432557
caseRELPERSISTENCE_PERMANENT:
25442558
rel->rd_backend=InvalidBackendId;
2559+
rel->rd_islocaltemp= false;
25452560
break;
25462561
caseRELPERSISTENCE_TEMP:
2562+
Assert(isTempOrToastNamespace(relnamespace));
25472563
rel->rd_backend=MyBackendId;
2564+
rel->rd_islocaltemp= true;
25482565
break;
25492566
default:
25502567
elog(ERROR,"invalid relpersistence: %c",relpersistence);

‎src/include/utils/rel.h

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ typedef struct RelationData
137137
boolrd_isvalid;/* relcache entry is valid */
138138
charrd_indexvalid;/* state of rd_indexlist: 0 = not valid, 1 =
139139
* valid, 2 = temporarily forced */
140+
boolrd_islocaltemp;/* rel is a temp rel of this session */
140141

141142
/*
142143
* rd_createSubid is the ID of the highest subtransaction the rel has
@@ -405,22 +406,16 @@ typedef struct StdRdOptions
405406
#defineRelationUsesLocalBuffers(relation) \
406407
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
407408

408-
/*
409-
* RelationUsesTempNamespace
410-
*True if relation's catalog entries live in a private namespace.
411-
*/
412-
#defineRelationUsesTempNamespace(relation) \
413-
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
414-
415409
/*
416410
* RELATION_IS_LOCAL
417411
*If a rel is either temp or newly created in the current transaction,
418-
*it can be assumed to be visible only to the current backend.
412+
*it can be assumed to be accessible only to the current backend.
413+
*This is typically used to decide that we can skip acquiring locks.
419414
*
420415
* Beware of multiple eval of argument
421416
*/
422417
#defineRELATION_IS_LOCAL(relation) \
423-
((relation)->rd_backend == MyBackendId || \
418+
((relation)->rd_islocaltemp || \
424419
(relation)->rd_createSubid != InvalidSubTransactionId)
425420

426421
/*
@@ -430,8 +425,8 @@ typedef struct StdRdOptions
430425
* Beware of multiple eval of argument
431426
*/
432427
#defineRELATION_IS_OTHER_TEMP(relation) \
433-
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP \
434-
&&(relation)->rd_backend != MyBackendId)
428+
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP&&\
429+
!(relation)->rd_islocaltemp)
435430

436431
/* routines in utils/cache/relcache.c */
437432
externvoidRelationIncrementReferenceCount(Relationrel);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp