diff options
Diffstat (limited to 'src/backend/utils/cache/temprel.c')
-rw-r--r-- | src/backend/utils/cache/temprel.c | 335 |
1 files changed, 0 insertions, 335 deletions
diff --git a/src/backend/utils/cache/temprel.c b/src/backend/utils/cache/temprel.c deleted file mode 100644 index 7ab609eaf36..00000000000 --- a/src/backend/utils/cache/temprel.c +++ /dev/null @@ -1,335 +0,0 @@ -/*------------------------------------------------------------------------- - * - * temprel.c - * POSTGRES temporary relation handling - * - * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.36 2002/03/29 19:06:16 tgl Exp $ - * - *------------------------------------------------------------------------- - */ - -/* - * This implements temp tables by modifying the relname cache lookups - * of pg_class. - * - * When a temp table is created, normal entries are made for it in pg_class, - * pg_type, etc using a unique "physical" relation name. We also make an - * entry in the temp table list maintained by this module. Subsequently, - * relname lookups are filtered through the temp table list, and attempts - * to look up a temp table name are changed to look up the physical name. - * This allows temp table names to mask a regular table of the same name - * for the duration of the session. The temp table list is also used - * to drop the underlying physical relations at session shutdown. - */ - -#include "postgres.h" - -#include <sys/types.h> - -#include "catalog/heap.h" -#include "catalog/index.h" -#include "miscadmin.h" -#include "utils/temprel.h" - - -/* ---------------- - * global variables - * ---------------- - */ - -static List *temp_rels = NIL; - -typedef struct TempTable -{ - NameData user_relname; /* logical name of temp table */ - NameData relname; /* underlying unique name */ - Oid relid; /* needed properties of rel */ - char relkind; - - /* - * If this entry was created during this xact, it should be deleted at - * xact abort. Conversely, if this entry was deleted during this - * xact, it should be removed at xact commit. We leave deleted - * entries in the list until commit so that we can roll back if needed - * --- but we ignore them for purposes of lookup! - */ - bool created_in_cur_xact; - bool deleted_in_cur_xact; -} TempTable; - - -/* - * Create a temp-relation list entry given the logical temp table name - * and the already-created pg_class tuple for the underlying relation. - * - * NB: we assume a check has already been made for a duplicate logical name. - */ -void -create_temp_relation(const char *relname, HeapTuple pg_class_tuple) -{ - Form_pg_class pg_class_form = (Form_pg_class) GETSTRUCT(pg_class_tuple); - MemoryContext oldcxt; - TempTable *temp_rel; - - oldcxt = MemoryContextSwitchTo(CacheMemoryContext); - - temp_rel = (TempTable *) palloc(sizeof(TempTable)); - - StrNCpy(NameStr(temp_rel->user_relname), relname, - NAMEDATALEN); - StrNCpy(NameStr(temp_rel->relname), NameStr(pg_class_form->relname), - NAMEDATALEN); - temp_rel->relid = pg_class_tuple->t_data->t_oid; - temp_rel->relkind = pg_class_form->relkind; - temp_rel->created_in_cur_xact = true; - temp_rel->deleted_in_cur_xact = false; - - temp_rels = lcons(temp_rel, temp_rels); - - MemoryContextSwitchTo(oldcxt); -} - -/* - * Remove a temp relation map entry (part of DROP TABLE on a temp table). - * We don't actually remove the entry, just mark it dead. - * - * We don't have the relname for indexes, so we just pass the oid. - */ -void -remove_temp_rel_by_relid(Oid relid) -{ - List *l; - - foreach(l, temp_rels) - { - TempTable *temp_rel = (TempTable *) lfirst(l); - - if (temp_rel->relid == relid) - temp_rel->deleted_in_cur_xact = true; - - /* - * Keep scanning 'cause there could be multiple matches; see - * RENAME - */ - } -} - -/* - * To implement ALTER TABLE RENAME on a temp table, we shouldn't touch - * the underlying physical table at all, just change the map entry! - * - * This routine is invoked early in ALTER TABLE RENAME to check for - * the temp-table case. If oldname matches a temp table name, change - * the mapping to the new logical name and return TRUE (or elog if - * there is a conflict with another temp table name). If there is - * no match, return FALSE indicating that normal rename should proceed. - * - * We also reject an attempt to rename a normal table to a name in use - * as a temp table name. That would fail later on anyway when rename.c - * looks for a rename conflict, but we can give a more specific error - * message for the problem here. - * - * It might seem that we need to check for attempts to rename the physical - * file underlying a temp table, but that'll be rejected anyway because - * pg_tempXXX looks like a system table name. - */ -bool -rename_temp_relation(const char *oldname, - const char *newname) -{ - List *l; - - foreach(l, temp_rels) - { - TempTable *temp_rel = (TempTable *) lfirst(l); - MemoryContext oldcxt; - TempTable *new_temp_rel; - - if (temp_rel->deleted_in_cur_xact) - continue; /* ignore it if logically deleted */ - - if (strcmp(NameStr(temp_rel->user_relname), oldname) != 0) - continue; /* ignore non-matching entries */ - - /* We are renaming a temp table --- is it OK to do so? */ - if (is_temp_rel_name(newname)) - elog(ERROR, "Cannot rename temp table \"%s\": temp table \"%s\" already exists", - oldname, newname); - - /* - * Create a new mapping entry and mark the old one deleted in this - * xact. One of these entries will be deleted at xact end. - * - * NOTE: the new mapping entry is inserted into the list just after - * the old one. We could alternatively insert it before the old - * one, but that'd take more code. It does need to be in one spot - * or the other, to ensure that deletion of temp rels happens in - * the right order during remove_all_temp_relations(). - */ - oldcxt = MemoryContextSwitchTo(CacheMemoryContext); - - new_temp_rel = (TempTable *) palloc(sizeof(TempTable)); - memcpy(new_temp_rel, temp_rel, sizeof(TempTable)); - - StrNCpy(NameStr(new_temp_rel->user_relname), newname, NAMEDATALEN); - new_temp_rel->created_in_cur_xact = true; - - lnext(l) = lcons(new_temp_rel, lnext(l)); - - temp_rel->deleted_in_cur_xact = true; - - MemoryContextSwitchTo(oldcxt); - - return true; - } - - /* Old name does not match any temp table name, what about new? */ - if (is_temp_rel_name(newname)) - elog(ERROR, "Cannot rename \"%s\" to \"%s\": a temp table by that name already exists", - oldname, newname); - - return false; -} - - -/* - * Remove underlying relations for all temp rels at backend shutdown. - */ -void -remove_all_temp_relations(void) -{ - List *l; - - /* skip xact start overhead if nothing to do */ - if (temp_rels == NIL) - return; - - AbortOutOfAnyTransaction(); - StartTransactionCommand(); - - /* - * Scan the list and delete all entries not already deleted. We need - * not worry about list entries getting deleted from under us, because - * remove_temp_rel_by_relid() doesn't remove entries, only mark them - * dead. Note that entries will be deleted in reverse order of - * creation --- that's critical for cases involving inheritance. - */ - foreach(l, temp_rels) - { - TempTable *temp_rel = (TempTable *) lfirst(l); - - if (temp_rel->deleted_in_cur_xact) - continue; /* ignore it if deleted already */ - - if (temp_rel->relkind != RELKIND_INDEX) - heap_drop_with_catalog(temp_rel->relid, allowSystemTableMods); - else - index_drop(temp_rel->relid); - /* advance cmd counter to make catalog changes visible */ - CommandCounterIncrement(); - } - - CommitTransactionCommand(); -} - -/* - * Clean up temprel mapping entries during transaction commit or abort. - * - * During commit, remove entries that were deleted during this transaction; - * during abort, remove those created during this transaction. - * - * We do not need to worry about removing the underlying physical relation; - * that's someone else's job. - */ -void -AtEOXact_temp_relations(bool isCommit) -{ - List *l, - *prev; - - prev = NIL; - l = temp_rels; - while (l != NIL) - { - TempTable *temp_rel = (TempTable *) lfirst(l); - - if (isCommit ? temp_rel->deleted_in_cur_xact : - temp_rel->created_in_cur_xact) - { - /* This entry must be removed */ - if (prev != NIL) - { - lnext(prev) = lnext(l); - pfree(l); - l = lnext(prev); - } - else - { - temp_rels = lnext(l); - pfree(l); - l = temp_rels; - } - pfree(temp_rel); - } - else - { - /* This entry must be preserved */ - temp_rel->created_in_cur_xact = false; - temp_rel->deleted_in_cur_xact = false; - prev = l; - l = lnext(l); - } - } -} - - -/* - * Map user name to physical name --- returns NULL if no entry. - * - * This also supports testing whether a name is a temp table name; - * see is_temp_rel_name() macro. - */ -char * -get_temp_rel_by_username(const char *user_relname) -{ - List *l; - - foreach(l, temp_rels) - { - TempTable *temp_rel = (TempTable *) lfirst(l); - - if (temp_rel->deleted_in_cur_xact) - continue; /* ignore it if logically deleted */ - - if (strcmp(NameStr(temp_rel->user_relname), user_relname) == 0) - return NameStr(temp_rel->relname); - } - return NULL; -} - -/* - * Map physical name to user name --- returns pstrdup'd input if no match. - */ -char * -get_temp_rel_by_physicalname(const char *relname) -{ - List *l; - - foreach(l, temp_rels) - { - TempTable *temp_rel = (TempTable *) lfirst(l); - - if (temp_rel->deleted_in_cur_xact) - continue; /* ignore it if logically deleted */ - - if (strcmp(NameStr(temp_rel->relname), relname) == 0) - return NameStr(temp_rel->user_relname); - } - /* needed for bootstrapping temp tables */ - return pstrdup(relname); -} |