diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2012-12-17 20:15:39 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2012-12-17 20:15:39 -0500 |
commit | fe2ef429a19b25903438b882ce16617a6e700d0f (patch) | |
tree | bed25c0944bd41575589fbd7573cc667d2196ac8 /src/backend/commands/tablecmds.c | |
parent | d93c01f16854e655dd69b614747d3432a39f0385 (diff) | |
download | postgresql-fe2ef429a19b25903438b882ce16617a6e700d0f.tar.gz postgresql-fe2ef429a19b25903438b882ce16617a6e700d0f.zip |
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 not
cleaned up right away. Instead, the first backend that uses a temp schema
is expected to clean out any leftover objects therein. This approach
requires that we be careful to ignore leftover temp tables (since any
actual access attempt would fail), *even if their BackendId matches our
session*, if we have not yet established use of the session's corresponding
temp schema. That worked fine in the past, but was broken by commit
debcec7dc31a992703911a9953e299c8d730c778 which incorrectly removed the
rd_islocaltemp relcache flag. Put it back, and undo various changes
that substituted tests like "rel->rd_backend == MyBackendId" for use
of a state-aware flag. Per trouble report from Heikki Linnakangas.
Back-patch to 9.1 where the erroneous change was made. In the back
branches, be careful to add rd_islocaltemp in a spot in the struct that
was alignment padding before, so as not to break existing add-on code.
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index ab5ab940ade..5d64461cdaa 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1450,13 +1450,20 @@ MergeAttributes(List *schema, List *supers, char relpersistence, errmsg("inherited relation \"%s\" is not a table", parent->relname))); /* Permanent rels cannot inherit from temporary ones */ - if (relpersistence != RELPERSISTENCE_TEMP - && RelationUsesTempNamespace(relation)) + if (relpersistence != RELPERSISTENCE_TEMP && + relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot inherit from temporary relation \"%s\"", parent->relname))); + /* If existing rel is temp, it must belong to this session */ + if (relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP && + !relation->rd_islocaltemp) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot inherit from temporary relation of another session"))); + /* * We should have an UNDER permission flag for this, but for now, * demand that creator of a child table own the parent. @@ -5767,6 +5774,10 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("constraints on temporary tables may reference only temporary tables"))); + if (!pkrel->rd_islocaltemp || !rel->rd_islocaltemp) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("constraints on temporary tables must involve temporary tables of this session"))); break; } @@ -8905,13 +8916,27 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode) ATSimplePermissions(parent_rel, ATT_TABLE); /* Permanent rels cannot inherit from temporary ones */ - if (RelationUsesTempNamespace(parent_rel) - && !RelationUsesTempNamespace(child_rel)) + if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP && + child_rel->rd_rel->relpersistence != RELPERSISTENCE_TEMP) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot inherit from temporary relation \"%s\"", RelationGetRelationName(parent_rel)))); + /* If parent rel is temp, it must belong to this session */ + if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP && + !parent_rel->rd_islocaltemp) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot inherit from temporary relation of another session"))); + + /* Ditto for the child */ + if (child_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP && + !child_rel->rd_islocaltemp) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot inherit to temporary relation of another session"))); + /* * Check for duplicates in the list of parents, and determine the highest * inhseqno already present; we'll use the next one for the new parent. |