mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Add code to handle [ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP }]
for temp tables. Gavin Sherry
This commit is contained in:
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.91 2002/11/02 21:20:40 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.92 2002/11/09 23:56:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -25,6 +25,7 @@
|
||||
#include "catalog/index.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "commands/cluster.h"
|
||||
#include "commands/tablecmds.h"
|
||||
#include "miscadmin.h"
|
||||
@ -203,6 +204,7 @@ make_new_heap(Oid OIDOldHeap, const char *NewName)
|
||||
tupdesc,
|
||||
OldHeap->rd_rel->relkind,
|
||||
OldHeap->rd_rel->relisshared,
|
||||
ATEOXACTNOOP,
|
||||
allowSystemTableMods);
|
||||
|
||||
/*
|
||||
|
@ -8,12 +8,13 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.51 2002/11/02 22:02:08 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.52 2002/11/09 23:56:39 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/xact.h"
|
||||
#include "access/genam.h"
|
||||
#include "access/tuptoaster.h"
|
||||
#include "catalog/catalog.h"
|
||||
@ -48,9 +49,10 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
static List *temprels = NIL;
|
||||
|
||||
static List *MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
List **supOids, List **supconstr, bool *supHasOids);
|
||||
@ -116,6 +118,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
int i;
|
||||
AttrNumber attnum;
|
||||
|
||||
|
||||
/*
|
||||
* Truncate relname to appropriate length (probably a waste of time,
|
||||
* as parser should have done this already).
|
||||
@ -222,6 +225,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
descriptor,
|
||||
relkind,
|
||||
false,
|
||||
stmt->ateoxact,
|
||||
allowSystemTableMods);
|
||||
|
||||
StoreCatalogInheritance(relationId, inheritOids);
|
||||
@ -3783,11 +3787,18 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
||||
* when its master is, so there's no need to handle the toast rel as
|
||||
* temp.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Pass ATEOXACTNOOP for ateoxact since we want heap_drop_with_catalog()
|
||||
* to remove TOAST tables for temp tables, not AtEOXact_temp_relations()
|
||||
*/
|
||||
|
||||
toast_relid = heap_create_with_catalog(toast_relname,
|
||||
PG_TOAST_NAMESPACE,
|
||||
tupdesc,
|
||||
RELKIND_TOASTVALUE,
|
||||
shared_relation,
|
||||
ATEOXACTNOOP,
|
||||
true);
|
||||
|
||||
/* make the toast relation visible, else index creation will fail */
|
||||
@ -3922,3 +3933,206 @@ needs_toast_table(Relation rel)
|
||||
MAXALIGN(data_length);
|
||||
return (tuple_length > TOAST_TUPLE_THRESHOLD);
|
||||
}
|
||||
|
||||
/*
|
||||
* To handle ON COMMIT { DROP | PRESERVE ROWS | DELETE ROWS }
|
||||
*/
|
||||
void
|
||||
AtEOXact_temp_relations(bool iscommit, int bstate)
|
||||
{
|
||||
List *l,
|
||||
*prev;
|
||||
MemoryContext oldctx;
|
||||
|
||||
if (temprels == NIL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* These loops are tricky because we are removing items from the List
|
||||
* while we are traversing it.
|
||||
*/
|
||||
|
||||
|
||||
/* Remove 'dead' entries on commit and clear 'dead' status on abort */
|
||||
l = temprels;
|
||||
prev = NIL;
|
||||
while (l != NIL)
|
||||
{
|
||||
TempTable *t = lfirst(l);
|
||||
|
||||
if (t->dead)
|
||||
{
|
||||
if (iscommit)
|
||||
{
|
||||
/* Remove from temprels, since the user has DROP'd */
|
||||
oldctx = MemoryContextSwitchTo(CacheMemoryContext);
|
||||
if (prev == NIL)
|
||||
{
|
||||
pfree(t);
|
||||
temprels = lnext(l);
|
||||
pfree(l);
|
||||
l = temprels;
|
||||
}
|
||||
else
|
||||
{
|
||||
pfree(t);
|
||||
lnext(prev) = lnext(l);
|
||||
pfree(l);
|
||||
l = lnext(prev);
|
||||
}
|
||||
MemoryContextSwitchTo(oldctx);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
/* user dropped but now we're aborted */
|
||||
t->dead = false;
|
||||
}
|
||||
prev = l;
|
||||
l = lnext(l);
|
||||
}
|
||||
|
||||
if ((iscommit && bstate != TBLOCK_END) ||
|
||||
(!iscommit && bstate != TBLOCK_ABORT))
|
||||
return;
|
||||
|
||||
/* Perform per-xact actions */
|
||||
l = temprels;
|
||||
prev = NIL;
|
||||
|
||||
if (iscommit)
|
||||
{
|
||||
while (l != NIL)
|
||||
{
|
||||
TempTable *t = lfirst(l);
|
||||
|
||||
if (t->ateoxact == ATEOXACTDROP)
|
||||
{
|
||||
ObjectAddress object;
|
||||
|
||||
object.classId = RelOid_pg_class;
|
||||
object.objectId = t->relid;
|
||||
object.objectSubId = 0;
|
||||
|
||||
performDeletion(&object, DROP_CASCADE);
|
||||
oldctx = MemoryContextSwitchTo(CacheMemoryContext);
|
||||
|
||||
if (prev == NIL)
|
||||
{
|
||||
pfree(t);
|
||||
temprels = lnext(l);
|
||||
pfree(l);
|
||||
l = temprels;
|
||||
}
|
||||
else
|
||||
{
|
||||
pfree(t);
|
||||
lnext(prev) = lnext(l);
|
||||
pfree(l);
|
||||
l = lnext(prev);
|
||||
}
|
||||
|
||||
MemoryContextSwitchTo(oldctx);
|
||||
CommandCounterIncrement();
|
||||
continue;
|
||||
}
|
||||
else if (t->ateoxact == ATEOXACTDELETE)
|
||||
{
|
||||
heap_truncate(t->relid);
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
prev = l;
|
||||
l = lnext(l);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Abort --- remove entries added by this xact */
|
||||
TransactionId curtid = GetCurrentTransactionId();
|
||||
|
||||
oldctx = MemoryContextSwitchTo(CacheMemoryContext);
|
||||
|
||||
while (l != NIL)
|
||||
{
|
||||
TempTable *t = lfirst(l);
|
||||
|
||||
if (t->tid == curtid)
|
||||
{
|
||||
if (prev == NIL)
|
||||
{
|
||||
pfree(t);
|
||||
temprels = lnext(l);
|
||||
pfree(l);
|
||||
l = temprels;
|
||||
}
|
||||
else
|
||||
{
|
||||
pfree(t);
|
||||
lnext(prev) = lnext(l);
|
||||
pfree(l);
|
||||
l = lnext(prev);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
prev = l;
|
||||
l = lnext(l);
|
||||
}
|
||||
MemoryContextSwitchTo(oldctx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a temp rel in temprels
|
||||
*/
|
||||
|
||||
void
|
||||
reg_temp_rel(TempTable * t)
|
||||
{
|
||||
temprels = lcons(t, temprels);
|
||||
}
|
||||
|
||||
/*
|
||||
* return the ON COMMIT/ateoxact value for a given temp rel
|
||||
*/
|
||||
|
||||
void
|
||||
free_temp_rels(void)
|
||||
{
|
||||
MemoryContext oldctx;
|
||||
|
||||
oldctx = MemoryContextSwitchTo(CacheMemoryContext);
|
||||
while (temprels != NIL)
|
||||
{
|
||||
List *l = temprels;
|
||||
|
||||
temprels = lnext(temprels);
|
||||
pfree(lfirst(l));
|
||||
pfree(l);
|
||||
}
|
||||
MemoryContextSwitchTo(oldctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove (actually just mark for deletion, in case we abort)
|
||||
* Relid from the temprels list
|
||||
*/
|
||||
|
||||
void
|
||||
rm_temp_rel(Oid relid)
|
||||
{
|
||||
List *l;
|
||||
|
||||
foreach(l, temprels)
|
||||
{
|
||||
TempTable *t = lfirst(l);
|
||||
|
||||
if (t->relid == relid)
|
||||
{
|
||||
t->dead = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we get here, we're in trouble */
|
||||
Assert(1==1);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user