Reimplement temp tables using schemas. The temp table map is history;
temp table entries in pg_class have the names the user would expect.
This commit is contained in:
parent
5f4745adf4
commit
3114102521
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.118 2002/03/15 19:20:29 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.119 2002/03/31 06:26:29 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Transaction aborts can now occur two ways:
|
||||
@ -178,10 +178,9 @@
|
||||
#include "utils/portal.h"
|
||||
#include "utils/catcache.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
#include "pgstat.h"
|
||||
|
||||
|
||||
extern bool SharedBufferChanged;
|
||||
|
||||
static void AbortTransaction(void);
|
||||
@ -999,7 +998,6 @@ CommitTransaction(void)
|
||||
*/
|
||||
|
||||
RelationPurgeLocalRelation(true);
|
||||
AtEOXact_temp_relations(true);
|
||||
smgrDoPendingDeletes(true);
|
||||
|
||||
AtEOXact_SPI();
|
||||
@ -1102,7 +1100,6 @@ AbortTransaction(void)
|
||||
}
|
||||
|
||||
RelationPurgeLocalRelation(false);
|
||||
AtEOXact_temp_relations(false);
|
||||
smgrDoPendingDeletes(false);
|
||||
|
||||
AtEOXact_SPI();
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlogutils.c,v 1.22 2002/03/02 21:39:20 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlogutils.c,v 1.23 2002/03/31 06:26:29 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -335,7 +335,7 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
|
||||
{
|
||||
res = _xl_new_reldesc();
|
||||
|
||||
sprintf(RelationGetPhysicalRelationName(&(res->reldata)), "%u", rnode.relNode);
|
||||
sprintf(RelationGetRelationName(&(res->reldata)), "%u", rnode.relNode);
|
||||
|
||||
/* unexisting DB id */
|
||||
res->reldata.rd_lockInfo.lockRelId.dbId = RecoveryDb;
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.41 2002/03/26 19:15:16 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.42 2002/03/31 06:26:29 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -184,7 +184,7 @@ Boot_CreateStmt:
|
||||
reldesc = heap_create(LexIDStr($4),
|
||||
PG_CATALOG_NAMESPACE,
|
||||
tupdesc,
|
||||
false, true, true);
|
||||
true, true);
|
||||
reldesc->rd_rel->relhasoids = ! ($3);
|
||||
elog(DEBUG3, "bootstrap relation created");
|
||||
}
|
||||
@ -199,7 +199,6 @@ Boot_CreateStmt:
|
||||
tupdesc,
|
||||
RELKIND_RELATION,
|
||||
! ($3),
|
||||
false,
|
||||
true);
|
||||
elog(DEBUG3, "relation created with oid %u", id);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.60 2002/03/29 19:05:59 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.61 2002/03/31 06:26:29 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* See acl.h.
|
||||
@ -40,7 +40,6 @@
|
||||
#include "parser/parse_type.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
static void ExecuteGrantStmt_Table(GrantStmt *stmt);
|
||||
@ -811,7 +810,6 @@ pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode)
|
||||
relname = NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname);
|
||||
if ((mode & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
|
||||
!allowSystemTableMods && IsSystemRelationName(relname) &&
|
||||
!is_temp_relname(relname) &&
|
||||
!usecatupd)
|
||||
{
|
||||
#ifdef ACLDEBUG
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.193 2002/03/29 19:05:59 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.194 2002/03/31 06:26:29 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -61,14 +61,12 @@
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
static void AddNewRelationTuple(Relation pg_class_desc,
|
||||
Relation new_rel_desc,
|
||||
Oid new_rel_oid, Oid new_type_oid,
|
||||
char relkind, bool relhasoids,
|
||||
char *temp_relname);
|
||||
char relkind, bool relhasoids);
|
||||
static void DeleteAttributeTuples(Relation rel);
|
||||
static void DeleteRelationTuple(Relation rel);
|
||||
static void DeleteTypeTuple(Relation rel);
|
||||
@ -205,34 +203,29 @@ SystemAttributeByName(const char *attname, bool relhasoids)
|
||||
*
|
||||
* Remove the system relation specific code to elsewhere eventually.
|
||||
*
|
||||
* NOTE: if istemp is TRUE then heap_create will overwrite relname with
|
||||
* the unique "real" name chosen for the temp relation.
|
||||
*
|
||||
* If storage_create is TRUE then heap_storage_create is called here,
|
||||
* else caller must call heap_storage_create later.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
Relation
|
||||
heap_create(char *relname,
|
||||
heap_create(const char *relname,
|
||||
Oid relnamespace,
|
||||
TupleDesc tupDesc,
|
||||
bool istemp,
|
||||
bool storage_create,
|
||||
bool allow_system_table_mods)
|
||||
{
|
||||
static unsigned int uniqueId = 0;
|
||||
|
||||
Oid relid;
|
||||
Oid dbid = MyDatabaseId;
|
||||
RelFileNode rnode;
|
||||
bool nailme = false;
|
||||
RelFileNode rnode;
|
||||
Relation rel;
|
||||
|
||||
/*
|
||||
* sanity checks
|
||||
*/
|
||||
if (relname && !allow_system_table_mods &&
|
||||
IsSystemRelationName(relname) && IsNormalProcessingMode())
|
||||
if (!allow_system_table_mods &&
|
||||
IsSystemRelationName(relname) &&
|
||||
IsNormalProcessingMode())
|
||||
elog(ERROR, "invalid relation name \"%s\"; "
|
||||
"the 'pg_' name prefix is reserved for system catalogs",
|
||||
relname);
|
||||
@ -291,16 +284,6 @@ heap_create(char *relname,
|
||||
else
|
||||
relid = newoid();
|
||||
|
||||
if (istemp)
|
||||
{
|
||||
/*
|
||||
* replace relname of caller with a unique name for a temp
|
||||
* relation
|
||||
*/
|
||||
snprintf(relname, NAMEDATALEN, "%s_%d_%u",
|
||||
PG_TEMP_REL_PREFIX, (int) MyProcPid, uniqueId++);
|
||||
}
|
||||
|
||||
/*
|
||||
* For now, the physical identifier of the relation is the same as the
|
||||
* logical identifier.
|
||||
@ -528,8 +511,7 @@ AddNewRelationTuple(Relation pg_class_desc,
|
||||
Oid new_rel_oid,
|
||||
Oid new_type_oid,
|
||||
char relkind,
|
||||
bool relhasoids,
|
||||
char *temp_relname)
|
||||
bool relhasoids)
|
||||
{
|
||||
Form_pg_class new_rel_reltup;
|
||||
HeapTuple tup;
|
||||
@ -599,9 +581,6 @@ AddNewRelationTuple(Relation pg_class_desc,
|
||||
*/
|
||||
heap_insert(pg_class_desc, tup);
|
||||
|
||||
if (temp_relname)
|
||||
create_temp_relation(temp_relname, tup);
|
||||
|
||||
if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
/*
|
||||
@ -669,19 +648,17 @@ AddNewRelationType(const char *typeName,
|
||||
* --------------------------------
|
||||
*/
|
||||
Oid
|
||||
heap_create_with_catalog(char *relname,
|
||||
heap_create_with_catalog(const char *relname,
|
||||
Oid relnamespace,
|
||||
TupleDesc tupdesc,
|
||||
char relkind,
|
||||
bool relhasoids,
|
||||
bool istemp,
|
||||
bool allow_system_table_mods)
|
||||
{
|
||||
Relation pg_class_desc;
|
||||
Relation new_rel_desc;
|
||||
Oid new_rel_oid;
|
||||
Oid new_type_oid;
|
||||
char *temp_relname = NULL;
|
||||
|
||||
/*
|
||||
* sanity checks
|
||||
@ -693,32 +670,17 @@ heap_create_with_catalog(char *relname,
|
||||
|
||||
CheckAttributeNames(tupdesc, relhasoids);
|
||||
|
||||
/* temp tables can mask non-temp tables */
|
||||
if ((!istemp && get_relname_relid(relname, relnamespace)) ||
|
||||
(istemp && is_temp_rel_name(relname)))
|
||||
if (get_relname_relid(relname, relnamespace))
|
||||
elog(ERROR, "Relation '%s' already exists", relname);
|
||||
|
||||
if (istemp)
|
||||
{
|
||||
/* save user relation name because heap_create changes it */
|
||||
temp_relname = pstrdup(relname); /* save original value */
|
||||
relname = palloc(NAMEDATALEN);
|
||||
strcpy(relname, temp_relname); /* heap_create will change this */
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell heap_create not to create a physical file; we'll do that below
|
||||
* after all our catalog updates are done. (This isn't really
|
||||
* necessary anymore, but we may as well avoid the cycles of creating
|
||||
* and deleting the file in case we fail.)
|
||||
*
|
||||
* Note: The call to heap_create() changes relname for temp tables; it
|
||||
* becomes the true physical relname. The call to
|
||||
* heap_storage_create() does all the "real" work of creating the disk
|
||||
* file for the relation.
|
||||
*/
|
||||
new_rel_desc = heap_create(relname, relnamespace, tupdesc,
|
||||
istemp, false, allow_system_table_mods);
|
||||
false, allow_system_table_mods);
|
||||
|
||||
/* Fetch the relation OID assigned by heap_create */
|
||||
new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
|
||||
@ -740,8 +702,7 @@ heap_create_with_catalog(char *relname,
|
||||
new_rel_oid,
|
||||
new_type_oid,
|
||||
relkind,
|
||||
relhasoids,
|
||||
temp_relname);
|
||||
relhasoids);
|
||||
|
||||
/*
|
||||
* since defining a relation also defines a complex type, we add a new
|
||||
@ -780,12 +741,6 @@ heap_create_with_catalog(char *relname,
|
||||
heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
|
||||
heap_close(pg_class_desc, RowExclusiveLock);
|
||||
|
||||
if (istemp)
|
||||
{
|
||||
pfree(relname);
|
||||
pfree(temp_relname);
|
||||
}
|
||||
|
||||
return new_rel_oid;
|
||||
}
|
||||
|
||||
@ -1226,26 +1181,19 @@ heap_drop_with_catalog(Oid rid,
|
||||
{
|
||||
Relation rel;
|
||||
Oid toasttableOid;
|
||||
bool has_toasttable;
|
||||
bool istemp;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Open and lock the relation.
|
||||
*/
|
||||
rel = heap_open(rid, AccessExclusiveLock);
|
||||
has_toasttable = rel->rd_rel->reltoastrelid != InvalidOid;
|
||||
toasttableOid = rel->rd_rel->reltoastrelid;
|
||||
istemp = is_temp_rel_name(RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* prevent deletion of system relations
|
||||
*/
|
||||
/* allow temp of pg_class? Guess so. */
|
||||
if (!istemp &&
|
||||
!allow_system_table_mods &&
|
||||
IsSystemRelationName(RelationGetRelationName(rel)) &&
|
||||
!is_temp_relname(RelationGetRelationName(rel)))
|
||||
if (!allow_system_table_mods &&
|
||||
IsSystemRelationName(RelationGetRelationName(rel)))
|
||||
elog(ERROR, "System relation \"%s\" may not be dropped",
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
@ -1319,11 +1267,8 @@ heap_drop_with_catalog(Oid rid,
|
||||
*/
|
||||
RelationForgetRelation(rid);
|
||||
|
||||
/* and from the temp-table map */
|
||||
if (istemp)
|
||||
remove_temp_rel_by_relid(rid);
|
||||
|
||||
if (has_toasttable)
|
||||
/* If it has a toast table, recurse to get rid of that too */
|
||||
if (OidIsValid(toasttableOid))
|
||||
heap_drop_with_catalog(toasttableOid, true);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.174 2002/03/26 19:15:28 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.175 2002/03/31 06:26:29 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -33,6 +33,7 @@
|
||||
#include "catalog/index.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_index.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_type.h"
|
||||
@ -51,7 +52,6 @@
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -69,7 +69,7 @@ static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
|
||||
int numatts, AttrNumber *attNums,
|
||||
Oid *classObjectId);
|
||||
static void ConstructIndexReldesc(Relation indexRelation, Oid amoid);
|
||||
static void UpdateRelationRelation(Relation indexRelation, char *temp_relname);
|
||||
static void UpdateRelationRelation(Relation indexRelation);
|
||||
static void InitializeAttributeOids(Relation indexRelation,
|
||||
int numatts, Oid indexoid);
|
||||
static void AppendAttributeTuples(Relation indexRelation, int numatts);
|
||||
@ -320,7 +320,8 @@ ConstructIndexReldesc(Relation indexRelation, Oid amoid)
|
||||
indexRelation->rd_rel->relowner = GetUserId();
|
||||
indexRelation->rd_rel->relam = amoid;
|
||||
indexRelation->rd_rel->relisshared =
|
||||
IsSharedSystemRelationName(RelationGetPhysicalRelationName(indexRelation));
|
||||
(RelationGetNamespace(indexRelation) == PG_CATALOG_NAMESPACE) &&
|
||||
IsSharedSystemRelationName(RelationGetRelationName(indexRelation));
|
||||
indexRelation->rd_rel->relkind = RELKIND_INDEX;
|
||||
indexRelation->rd_rel->relhasoids = false;
|
||||
}
|
||||
@ -330,7 +331,7 @@ ConstructIndexReldesc(Relation indexRelation, Oid amoid)
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
UpdateRelationRelation(Relation indexRelation, char *temp_relname)
|
||||
UpdateRelationRelation(Relation indexRelation)
|
||||
{
|
||||
Relation pg_class;
|
||||
HeapTuple tuple;
|
||||
@ -350,16 +351,12 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
|
||||
tuple->t_data->t_oid = RelationGetRelid(indexRelation);
|
||||
heap_insert(pg_class, tuple);
|
||||
|
||||
if (temp_relname)
|
||||
create_temp_relation(temp_relname, tuple);
|
||||
|
||||
/*
|
||||
* During normal processing, we need to make sure that the system
|
||||
* catalog indices are correct. Bootstrap (initdb) time doesn't
|
||||
* require this, because we make sure that the indices are correct
|
||||
* just before exiting.
|
||||
*/
|
||||
|
||||
if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
||||
@ -555,11 +552,10 @@ UpdateIndexRelation(Oid indexoid,
|
||||
*/
|
||||
Oid
|
||||
index_create(Oid heapRelationId,
|
||||
char *indexRelationName,
|
||||
const char *indexRelationName,
|
||||
IndexInfo *indexInfo,
|
||||
Oid accessMethodObjectId,
|
||||
Oid *classObjectId,
|
||||
bool istemp,
|
||||
bool primary,
|
||||
bool allow_system_table_mods)
|
||||
{
|
||||
@ -568,7 +564,6 @@ index_create(Oid heapRelationId,
|
||||
TupleDesc indexTupDesc;
|
||||
Oid namespaceId;
|
||||
Oid indexoid;
|
||||
char *temp_relname = NULL;
|
||||
|
||||
SetReindexProcessing(false);
|
||||
|
||||
@ -591,8 +586,7 @@ index_create(Oid heapRelationId,
|
||||
IsNormalProcessingMode())
|
||||
elog(ERROR, "User-defined indexes on system catalogs are not supported");
|
||||
|
||||
if ((!istemp && get_relname_relid(indexRelationName, namespaceId)) ||
|
||||
(istemp && is_temp_rel_name(indexRelationName)))
|
||||
if (get_relname_relid(indexRelationName, namespaceId))
|
||||
elog(ERROR, "index named \"%s\" already exists",
|
||||
indexRelationName);
|
||||
|
||||
@ -608,22 +602,14 @@ index_create(Oid heapRelationId,
|
||||
indexInfo->ii_KeyAttrNumbers,
|
||||
classObjectId);
|
||||
|
||||
if (istemp)
|
||||
{
|
||||
/* save user relation name because heap_create changes it */
|
||||
temp_relname = pstrdup(indexRelationName); /* save original */
|
||||
indexRelationName = palloc(NAMEDATALEN);
|
||||
strcpy(indexRelationName, temp_relname); /* heap_create will
|
||||
* change this */
|
||||
}
|
||||
|
||||
/*
|
||||
* create the index relation
|
||||
* create the index relation (but don't create storage yet)
|
||||
*/
|
||||
indexRelation = heap_create(indexRelationName,
|
||||
namespaceId,
|
||||
indexTupDesc,
|
||||
istemp, false, allow_system_table_mods);
|
||||
false,
|
||||
allow_system_table_mods);
|
||||
indexoid = RelationGetRelid(indexRelation);
|
||||
|
||||
/*
|
||||
@ -645,7 +631,7 @@ index_create(Oid heapRelationId,
|
||||
* (append RELATION tuple)
|
||||
* ----------------
|
||||
*/
|
||||
UpdateRelationRelation(indexRelation, temp_relname);
|
||||
UpdateRelationRelation(indexRelation);
|
||||
|
||||
/*
|
||||
* We create the disk file for this relation here
|
||||
@ -835,9 +821,6 @@ index_drop(Oid indexId)
|
||||
heap_close(userHeapRelation, NoLock);
|
||||
|
||||
RelationForgetRelation(indexId);
|
||||
|
||||
/* if it's a temp index, clear the temp mapping table entry */
|
||||
remove_temp_rel_by_relid(indexId);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
|
@ -13,20 +13,86 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.3 2002/03/30 01:02:41 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.4 2002/03/31 06:26:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "access/xact.h"
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/heap.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_inherits.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_shadow.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "storage/backendid.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
/*
|
||||
* The namespace search path is a possibly-empty list of namespace OIDs.
|
||||
* In addition to the explicit list, the TEMP table namespace is always
|
||||
* implicitly searched first (if it's been initialized). Also, the system
|
||||
* catalog namespace is always searched. If the system namespace is
|
||||
* explicitly present in the path then it will be searched in the specified
|
||||
* order; otherwise it will be searched after TEMP tables and *before* the
|
||||
* explicit list. (It might seem that the system namespace should be
|
||||
* implicitly last, but this behavior appears to be required by SQL99.
|
||||
* Also, this provides a way to search the system namespace first without
|
||||
* thereby making it the default creation target namespace.)
|
||||
*
|
||||
* The default creation target namespace is kept equal to the first element
|
||||
* of the explicit list, or is the system namespace if the list is empty.
|
||||
*
|
||||
* In bootstrap mode or a standalone backend, the default search path is
|
||||
* empty, so that the system namespace is the only one searched or inserted
|
||||
* into. In multiuser mode, the default search path contains the PG_PUBLIC
|
||||
* namespace, preceded by the user's own namespace if one exists.
|
||||
*/
|
||||
|
||||
static List *namespaceSearchPath = NIL;
|
||||
|
||||
/* this flag must be updated correctly when namespaceSearchPath is changed */
|
||||
static bool pathContainsSystemNamespace = false;
|
||||
|
||||
/* default place to create stuff */
|
||||
static Oid defaultCreationNamespace = PG_CATALOG_NAMESPACE;
|
||||
|
||||
/*
|
||||
* myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
|
||||
* in a particular backend session (this happens when a CREATE TEMP TABLE
|
||||
* command is first executed). Thereafter it's the OID of the temp namespace.
|
||||
*/
|
||||
static Oid myTempNamespace = InvalidOid;
|
||||
|
||||
|
||||
/*
|
||||
* Deletion ordering constraint item.
|
||||
*/
|
||||
typedef struct DelConstraint
|
||||
{
|
||||
Oid referencer; /* table to delete first */
|
||||
Oid referencee; /* table to delete second */
|
||||
int pred; /* workspace for TopoSortRels */
|
||||
struct DelConstraint *link; /* workspace for TopoSortRels */
|
||||
} DelConstraint;
|
||||
|
||||
|
||||
/* Local functions */
|
||||
static Oid GetTempTableNamespace(void);
|
||||
static void RemoveTempRelations(Oid tempNamespaceId);
|
||||
static List *FindTempRelations(Oid tempNamespaceId);
|
||||
static List *FindDeletionConstraints(List *relOids);
|
||||
static List *TopoSortRels(List *relOids, List *constraintList);
|
||||
static void RemoveTempRelationsCallback(void);
|
||||
|
||||
|
||||
/*
|
||||
* RangeVarGetRelid
|
||||
* Given a RangeVar describing an existing relation,
|
||||
@ -52,6 +118,7 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
|
||||
|
||||
if (relation->schemaname)
|
||||
{
|
||||
/* use exact schema given */
|
||||
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
||||
CStringGetDatum(relation->schemaname),
|
||||
0, 0, 0);
|
||||
@ -62,6 +129,7 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* search the namespace path */
|
||||
relId = RelnameGetRelid(relation->relname);
|
||||
}
|
||||
|
||||
@ -100,8 +168,20 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
|
||||
elog(ERROR, "Cross-database references are not implemented");
|
||||
}
|
||||
|
||||
if (newRelation->istemp)
|
||||
{
|
||||
/* TEMP tables are created in our backend-local temp namespace */
|
||||
if (newRelation->schemaname)
|
||||
elog(ERROR, "TEMP tables may not specify a namespace");
|
||||
/* Initialize temp namespace if first time through */
|
||||
if (!OidIsValid(myTempNamespace))
|
||||
myTempNamespace = GetTempTableNamespace();
|
||||
return myTempNamespace;
|
||||
}
|
||||
|
||||
if (newRelation->schemaname)
|
||||
{
|
||||
/* use exact schema given */
|
||||
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
||||
CStringGetDatum(newRelation->schemaname),
|
||||
0, 0, 0);
|
||||
@ -111,8 +191,8 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX Wrong! Need to get a default schema from somewhere */
|
||||
namespaceId = PG_CATALOG_NAMESPACE;
|
||||
/* use the default creation namespace */
|
||||
namespaceId = defaultCreationNamespace;
|
||||
}
|
||||
|
||||
return namespaceId;
|
||||
@ -126,23 +206,91 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
|
||||
Oid
|
||||
RelnameGetRelid(const char *relname)
|
||||
{
|
||||
/* XXX Wrong! must search search path */
|
||||
return get_relname_relid(relname, PG_CATALOG_NAMESPACE);
|
||||
Oid relid;
|
||||
List *lptr;
|
||||
|
||||
/*
|
||||
* If a TEMP-table namespace has been set up, it is implicitly first
|
||||
* in the search path.
|
||||
*/
|
||||
if (OidIsValid(myTempNamespace))
|
||||
{
|
||||
relid = get_relname_relid(relname, myTempNamespace);
|
||||
if (OidIsValid(relid))
|
||||
return relid;
|
||||
}
|
||||
|
||||
/*
|
||||
* If system namespace is not in path, implicitly search it before path
|
||||
*/
|
||||
if (!pathContainsSystemNamespace)
|
||||
{
|
||||
relid = get_relname_relid(relname, PG_CATALOG_NAMESPACE);
|
||||
if (OidIsValid(relid))
|
||||
return relid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Else search the path
|
||||
*/
|
||||
foreach(lptr, namespaceSearchPath)
|
||||
{
|
||||
Oid namespaceId = (Oid) lfirsti(lptr);
|
||||
|
||||
relid = get_relname_relid(relname, namespaceId);
|
||||
if (OidIsValid(relid))
|
||||
return relid;
|
||||
}
|
||||
|
||||
/* Not found in path */
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* TypenameGetTypid
|
||||
* Try to resolve an unqualified datatype name.
|
||||
* Returns OID if type found in search path, else InvalidOid.
|
||||
*
|
||||
* This is essentially the same as RelnameGetRelid, but we never search
|
||||
* the TEMP table namespace --- there is no reason to refer to the types
|
||||
* of temp tables, AFAICS.
|
||||
*/
|
||||
Oid
|
||||
TypenameGetTypid(const char *typname)
|
||||
{
|
||||
/* XXX wrong, should use namespace search */
|
||||
return GetSysCacheOid(TYPENAMENSP,
|
||||
PointerGetDatum(typname),
|
||||
ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
|
||||
0, 0);
|
||||
Oid typid;
|
||||
List *lptr;
|
||||
|
||||
/*
|
||||
* If system namespace is not in path, implicitly search it before path
|
||||
*/
|
||||
if (!pathContainsSystemNamespace)
|
||||
{
|
||||
typid = GetSysCacheOid(TYPENAMENSP,
|
||||
PointerGetDatum(typname),
|
||||
ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
|
||||
0, 0);
|
||||
if (OidIsValid(typid))
|
||||
return typid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Else search the path
|
||||
*/
|
||||
foreach(lptr, namespaceSearchPath)
|
||||
{
|
||||
Oid namespaceId = (Oid) lfirsti(lptr);
|
||||
|
||||
typid = GetSysCacheOid(TYPENAMENSP,
|
||||
PointerGetDatum(typname),
|
||||
ObjectIdGetDatum(namespaceId),
|
||||
0, 0);
|
||||
if (OidIsValid(typid))
|
||||
return typid;
|
||||
}
|
||||
|
||||
/* Not found in path */
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -150,6 +298,9 @@ TypenameGetTypid(const char *typname)
|
||||
* Given a possibly-qualified name for an object (in List-of-Values
|
||||
* format), determine what namespace the object should be created in.
|
||||
* Also extract and return the object name (last component of list).
|
||||
*
|
||||
* This is *not* used for tables. Hence, the TEMP table namespace is
|
||||
* never selected as the creation target.
|
||||
*/
|
||||
Oid
|
||||
QualifiedNameGetCreationNamespace(List *names, char **objname_p)
|
||||
@ -186,6 +337,7 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
|
||||
|
||||
if (schemaname)
|
||||
{
|
||||
/* use exact schema given */
|
||||
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
||||
CStringGetDatum(schemaname),
|
||||
0, 0, 0);
|
||||
@ -195,8 +347,8 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX Wrong! Need to get a default schema from somewhere */
|
||||
namespaceId = PG_CATALOG_NAMESPACE;
|
||||
/* use the default creation namespace */
|
||||
namespaceId = defaultCreationNamespace;
|
||||
}
|
||||
|
||||
*objname_p = objname;
|
||||
@ -233,3 +385,320 @@ makeRangeVarFromNameList(List *names)
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
/*
|
||||
* isTempNamespace - is the given namespace my temporary-table namespace?
|
||||
*/
|
||||
bool
|
||||
isTempNamespace(Oid namespaceId)
|
||||
{
|
||||
if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* GetTempTableNamespace
|
||||
* Initialize temp table namespace on first use in a particular backend
|
||||
*/
|
||||
static Oid
|
||||
GetTempTableNamespace(void)
|
||||
{
|
||||
char namespaceName[NAMEDATALEN];
|
||||
Oid namespaceId;
|
||||
|
||||
snprintf(namespaceName, NAMEDATALEN, "pg_temp_%d", MyBackendId);
|
||||
|
||||
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
||||
CStringGetDatum(namespaceName),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(namespaceId))
|
||||
{
|
||||
/*
|
||||
* First use of this temp namespace in this database; create it.
|
||||
* The temp namespaces are always owned by the superuser.
|
||||
*/
|
||||
namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID);
|
||||
/* Advance command counter to make namespace visible */
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If the namespace already exists, clean it out (in case the
|
||||
* former owner crashed without doing so).
|
||||
*/
|
||||
RemoveTempRelations(namespaceId);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register exit callback to clean out temp tables at backend shutdown.
|
||||
*/
|
||||
on_shmem_exit(RemoveTempRelationsCallback, 0);
|
||||
|
||||
return namespaceId;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all relations in the specified temp namespace.
|
||||
*
|
||||
* This is called at backend shutdown (if we made any temp relations).
|
||||
* It is also called when we begin using a pre-existing temp namespace,
|
||||
* in order to clean out any relations that might have been created by
|
||||
* a crashed backend.
|
||||
*/
|
||||
static void
|
||||
RemoveTempRelations(Oid tempNamespaceId)
|
||||
{
|
||||
List *tempRelList;
|
||||
List *constraintList;
|
||||
List *lptr;
|
||||
|
||||
/* Get a list of relations to delete */
|
||||
tempRelList = FindTempRelations(tempNamespaceId);
|
||||
|
||||
if (tempRelList == NIL)
|
||||
return; /* nothing to do */
|
||||
|
||||
/* If more than one, sort them to respect any deletion-order constraints */
|
||||
if (length(tempRelList) > 1)
|
||||
{
|
||||
constraintList = FindDeletionConstraints(tempRelList);
|
||||
if (constraintList != NIL)
|
||||
tempRelList = TopoSortRels(tempRelList, constraintList);
|
||||
}
|
||||
|
||||
/* Scan the list and delete all entries */
|
||||
foreach(lptr, tempRelList)
|
||||
{
|
||||
Oid reloid = (Oid) lfirsti(lptr);
|
||||
|
||||
heap_drop_with_catalog(reloid, true);
|
||||
/*
|
||||
* Advance cmd counter to make catalog changes visible, in case
|
||||
* a later entry depends on this one.
|
||||
*/
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find all relations in the specified temp namespace.
|
||||
*
|
||||
* Returns a list of relation OIDs.
|
||||
*/
|
||||
static List *
|
||||
FindTempRelations(Oid tempNamespaceId)
|
||||
{
|
||||
List *tempRelList = NIL;
|
||||
Relation pgclass;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
ScanKeyData key;
|
||||
|
||||
/*
|
||||
* Scan pg_class to find all the relations in the target namespace.
|
||||
* Ignore indexes, though, on the assumption that they'll go away
|
||||
* when their tables are deleted.
|
||||
*/
|
||||
ScanKeyEntryInitialize(&key, 0x0,
|
||||
Anum_pg_class_relnamespace,
|
||||
F_OIDEQ,
|
||||
ObjectIdGetDatum(tempNamespaceId));
|
||||
|
||||
pgclass = heap_openr(RelationRelationName, AccessShareLock);
|
||||
scan = heap_beginscan(pgclass, false, SnapshotNow, 1, &key);
|
||||
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||
{
|
||||
switch (((Form_pg_class) GETSTRUCT(tuple))->relkind)
|
||||
{
|
||||
case RELKIND_RELATION:
|
||||
case RELKIND_SEQUENCE:
|
||||
case RELKIND_VIEW:
|
||||
tempRelList = lconsi(tuple->t_data->t_oid, tempRelList);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
heap_endscan(scan);
|
||||
heap_close(pgclass, AccessShareLock);
|
||||
|
||||
return tempRelList;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find deletion-order constraints involving the given relation OIDs.
|
||||
*
|
||||
* Returns a list of DelConstraint objects.
|
||||
*/
|
||||
static List *
|
||||
FindDeletionConstraints(List *relOids)
|
||||
{
|
||||
List *constraintList = NIL;
|
||||
Relation inheritsrel;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
|
||||
/*
|
||||
* Scan pg_inherits to find parents and children that are in the list.
|
||||
*/
|
||||
inheritsrel = heap_openr(InheritsRelationName, AccessShareLock);
|
||||
scan = heap_beginscan(inheritsrel, 0, SnapshotNow, 0, NULL);
|
||||
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||
{
|
||||
Oid inhrelid = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
|
||||
Oid inhparent = ((Form_pg_inherits) GETSTRUCT(tuple))->inhparent;
|
||||
|
||||
if (intMember(inhrelid, relOids) && intMember(inhparent, relOids))
|
||||
{
|
||||
DelConstraint *item;
|
||||
|
||||
item = (DelConstraint *) palloc(sizeof(DelConstraint));
|
||||
item->referencer = inhrelid;
|
||||
item->referencee = inhparent;
|
||||
constraintList = lcons(item, constraintList);
|
||||
}
|
||||
}
|
||||
|
||||
heap_endscan(scan);
|
||||
heap_close(inheritsrel, AccessShareLock);
|
||||
|
||||
return constraintList;
|
||||
}
|
||||
|
||||
/*
|
||||
* TopoSortRels -- topological sort of a list of rels to delete
|
||||
*
|
||||
* This is a lot simpler and slower than, for example, the topological sort
|
||||
* algorithm shown in Knuth's Volume 1. However, we are not likely to be
|
||||
* working with more than a few constraints, so the apparent slowness of the
|
||||
* algorithm won't really matter.
|
||||
*/
|
||||
static List *
|
||||
TopoSortRels(List *relOids, List *constraintList)
|
||||
{
|
||||
int queue_size = length(relOids);
|
||||
Oid *rels;
|
||||
int *beforeConstraints;
|
||||
DelConstraint **afterConstraints;
|
||||
List *resultList = NIL;
|
||||
List *lptr;
|
||||
int i,
|
||||
j,
|
||||
k,
|
||||
last;
|
||||
|
||||
/* Allocate workspace */
|
||||
rels = (Oid *) palloc(queue_size * sizeof(Oid));
|
||||
beforeConstraints = (int *) palloc(queue_size * sizeof(int));
|
||||
afterConstraints = (DelConstraint **)
|
||||
palloc(queue_size * sizeof(DelConstraint*));
|
||||
|
||||
/* Build an array of the target relation OIDs */
|
||||
i = 0;
|
||||
foreach(lptr, relOids)
|
||||
{
|
||||
rels[i++] = (Oid) lfirsti(lptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the constraints, and for each rel in the array, generate a
|
||||
* count of the number of constraints that say it must be before
|
||||
* something else, plus a list of the constraints that say it must be
|
||||
* after something else. The count for the j'th rel is stored in
|
||||
* beforeConstraints[j], and the head of its list in
|
||||
* afterConstraints[j]. Each constraint stores its list link in
|
||||
* its link field (note any constraint will be in just one list).
|
||||
* The array index for the before-rel of each constraint is
|
||||
* remembered in the constraint's pred field.
|
||||
*/
|
||||
MemSet(beforeConstraints, 0, queue_size * sizeof(int));
|
||||
MemSet(afterConstraints, 0, queue_size * sizeof(DelConstraint*));
|
||||
foreach(lptr, constraintList)
|
||||
{
|
||||
DelConstraint *constraint = (DelConstraint *) lfirst(lptr);
|
||||
Oid rel;
|
||||
|
||||
/* Find the referencer rel in the array */
|
||||
rel = constraint->referencer;
|
||||
for (j = queue_size; --j >= 0;)
|
||||
{
|
||||
if (rels[j] == rel)
|
||||
break;
|
||||
}
|
||||
Assert(j >= 0); /* should have found a match */
|
||||
/* Find the referencee rel in the array */
|
||||
rel = constraint->referencee;
|
||||
for (k = queue_size; --k >= 0;)
|
||||
{
|
||||
if (rels[k] == rel)
|
||||
break;
|
||||
}
|
||||
Assert(k >= 0); /* should have found a match */
|
||||
beforeConstraints[j]++; /* referencer must come before */
|
||||
/* add this constraint to list of after-constraints for referencee */
|
||||
constraint->pred = j;
|
||||
constraint->link = afterConstraints[k];
|
||||
afterConstraints[k] = constraint;
|
||||
}
|
||||
/*--------------------
|
||||
* Now scan the rels array backwards. At each step, output the
|
||||
* last rel that has no remaining before-constraints, and decrease
|
||||
* the beforeConstraints count of each of the rels it was constrained
|
||||
* against. (This is the right order since we are building the result
|
||||
* list back-to-front.)
|
||||
* i = counter for number of rels left to output
|
||||
* j = search index for rels[]
|
||||
* dc = temp for scanning constraint list for rel j
|
||||
* last = last valid index in rels (avoid redundant searches)
|
||||
*--------------------
|
||||
*/
|
||||
last = queue_size - 1;
|
||||
for (i = queue_size; --i >= 0;)
|
||||
{
|
||||
DelConstraint *dc;
|
||||
|
||||
/* Find next candidate to output */
|
||||
while (rels[last] == InvalidOid)
|
||||
last--;
|
||||
for (j = last; j >= 0; j--)
|
||||
{
|
||||
if (rels[j] != InvalidOid && beforeConstraints[j] == 0)
|
||||
break;
|
||||
}
|
||||
/* If no available candidate, topological sort fails */
|
||||
if (j < 0)
|
||||
elog(ERROR, "TopoSortRels: failed to find a workable deletion ordering");
|
||||
/* Output candidate, and mark it done by zeroing rels[] entry */
|
||||
resultList = lconsi(rels[j], resultList);
|
||||
rels[j] = InvalidOid;
|
||||
/* Update beforeConstraints counts of its predecessors */
|
||||
for (dc = afterConstraints[j]; dc; dc = dc->link)
|
||||
beforeConstraints[dc->pred]--;
|
||||
}
|
||||
|
||||
/* Done */
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback to remove temp relations at backend exit.
|
||||
*/
|
||||
static void
|
||||
RemoveTempRelationsCallback(void)
|
||||
{
|
||||
if (OidIsValid(myTempNamespace)) /* should always be true */
|
||||
{
|
||||
/* Need to ensure we have a usable transaction. */
|
||||
AbortOutOfAnyTransaction();
|
||||
StartTransactionCommand();
|
||||
|
||||
RemoveTempRelations(myTempNamespace);
|
||||
|
||||
CommitTransactionCommand();
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_namespace.c,v 1.1 2002/03/22 21:34:44 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_namespace.c,v 1.2 2002/03/31 06:26:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -18,7 +18,6 @@
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
@ -28,7 +27,7 @@
|
||||
* ---------------
|
||||
*/
|
||||
Oid
|
||||
NamespaceCreate(const char *nspName)
|
||||
NamespaceCreate(const char *nspName, int32 ownerSysId)
|
||||
{
|
||||
Relation nspdesc;
|
||||
HeapTuple tup;
|
||||
@ -57,7 +56,7 @@ NamespaceCreate(const char *nspName)
|
||||
}
|
||||
namestrcpy(&nname, nspName);
|
||||
values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
|
||||
values[Anum_pg_namespace_nspowner - 1] = Int32GetDatum(GetUserId());
|
||||
values[Anum_pg_namespace_nspowner - 1] = Int32GetDatum(ownerSysId);
|
||||
nulls[Anum_pg_namespace_nspacl - 1] = 'n';
|
||||
|
||||
nspdesc = heap_openr(NamespaceRelationName, RowExclusiveLock);
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.75 2002/03/29 22:10:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.76 2002/03/31 06:26:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -35,12 +35,10 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
static Oid copy_heap(Oid OIDOldHeap, char *NewName, bool istemp);
|
||||
static void copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName,
|
||||
bool istemp);
|
||||
static Oid copy_heap(Oid OIDOldHeap, char *NewName);
|
||||
static void copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName);
|
||||
static void rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex);
|
||||
|
||||
/*
|
||||
@ -63,7 +61,6 @@ cluster(RangeVar *oldrelation, char *oldindexname)
|
||||
OIDNewHeap;
|
||||
Relation OldHeap,
|
||||
OldIndex;
|
||||
bool istemp;
|
||||
char NewHeapName[NAMEDATALEN];
|
||||
char NewIndexName[NAMEDATALEN];
|
||||
RangeVar *NewHeap;
|
||||
@ -76,8 +73,6 @@ cluster(RangeVar *oldrelation, char *oldindexname)
|
||||
OldHeap = heap_openrv(oldrelation, AccessExclusiveLock);
|
||||
OIDOldHeap = RelationGetRelid(OldHeap);
|
||||
|
||||
istemp = is_temp_rel_name(oldrelation->relname);
|
||||
|
||||
/*
|
||||
* The index is expected to be in the same namespace as the relation.
|
||||
*/
|
||||
@ -105,7 +100,7 @@ cluster(RangeVar *oldrelation, char *oldindexname)
|
||||
*/
|
||||
snprintf(NewHeapName, NAMEDATALEN, "temp_%u", OIDOldHeap);
|
||||
|
||||
OIDNewHeap = copy_heap(OIDOldHeap, NewHeapName, istemp);
|
||||
OIDNewHeap = copy_heap(OIDOldHeap, NewHeapName);
|
||||
|
||||
/* We do not need CommandCounterIncrement() because copy_heap did it. */
|
||||
|
||||
@ -120,7 +115,7 @@ cluster(RangeVar *oldrelation, char *oldindexname)
|
||||
/* Create new index over the tuples of the new heap. */
|
||||
snprintf(NewIndexName, NAMEDATALEN, "temp_%u", OIDOldIndex);
|
||||
|
||||
copy_index(OIDOldIndex, OIDNewHeap, NewIndexName, istemp);
|
||||
copy_index(OIDOldIndex, OIDNewHeap, NewIndexName);
|
||||
|
||||
CommandCounterIncrement();
|
||||
|
||||
@ -145,7 +140,7 @@ cluster(RangeVar *oldrelation, char *oldindexname)
|
||||
}
|
||||
|
||||
static Oid
|
||||
copy_heap(Oid OIDOldHeap, char *NewName, bool istemp)
|
||||
copy_heap(Oid OIDOldHeap, char *NewName)
|
||||
{
|
||||
TupleDesc OldHeapDesc,
|
||||
tupdesc;
|
||||
@ -166,7 +161,6 @@ copy_heap(Oid OIDOldHeap, char *NewName, bool istemp)
|
||||
tupdesc,
|
||||
OldHeap->rd_rel->relkind,
|
||||
OldHeap->rd_rel->relhasoids,
|
||||
istemp,
|
||||
allowSystemTableMods);
|
||||
|
||||
/*
|
||||
@ -188,7 +182,7 @@ copy_heap(Oid OIDOldHeap, char *NewName, bool istemp)
|
||||
}
|
||||
|
||||
static void
|
||||
copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName, bool istemp)
|
||||
copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName)
|
||||
{
|
||||
Relation OldIndex,
|
||||
NewHeap;
|
||||
@ -209,7 +203,6 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName, bool istemp)
|
||||
indexInfo,
|
||||
OldIndex->rd_rel->relam,
|
||||
OldIndex->rd_index->indclass,
|
||||
istemp,
|
||||
OldIndex->rd_index->indisprimary,
|
||||
allowSystemTableMods);
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.168 2002/03/30 01:02:41 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.169 2002/03/31 06:26:30 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The PerformAddAttribute() code, like most of the relation
|
||||
@ -55,7 +55,7 @@
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
static void drop_default(Oid relid, int16 attnum);
|
||||
static bool needs_toast_table(Relation rel);
|
||||
@ -1344,20 +1344,27 @@ AlterTableAddConstraint(Oid myrelid,
|
||||
List *list;
|
||||
int count;
|
||||
|
||||
if (is_temp_rel_name(fkconstraint->pktable->relname) &&
|
||||
!is_temp_rel_name(RelationGetRelationName(rel)))
|
||||
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
|
||||
|
||||
/*
|
||||
* Grab an exclusive lock on the pk table, so that
|
||||
* someone doesn't delete rows out from under us.
|
||||
*
|
||||
* XXX wouldn't a lesser lock be sufficient?
|
||||
*/
|
||||
|
||||
pkrel = heap_openrv(fkconstraint->pktable,
|
||||
AccessExclusiveLock);
|
||||
|
||||
/*
|
||||
* Validity checks
|
||||
*/
|
||||
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
|
||||
elog(ERROR, "referenced table \"%s\" not a relation",
|
||||
fkconstraint->pktable->relname);
|
||||
|
||||
if (isTempNamespace(RelationGetNamespace(pkrel)) &&
|
||||
!isTempNamespace(RelationGetNamespace(rel)))
|
||||
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
|
||||
|
||||
/* Don't need pkrel open anymore, but hold lock */
|
||||
heap_close(pkrel, NoLock);
|
||||
|
||||
/*
|
||||
@ -1763,8 +1770,9 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
||||
toast_relid = heap_create_with_catalog(toast_relname,
|
||||
PG_TOAST_NAMESPACE,
|
||||
tupdesc,
|
||||
RELKIND_TOASTVALUE, false,
|
||||
false, true);
|
||||
RELKIND_TOASTVALUE,
|
||||
false,
|
||||
true);
|
||||
|
||||
/* make the toast relation visible, else index creation will fail */
|
||||
CommandCounterIncrement();
|
||||
@ -1794,7 +1802,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
||||
|
||||
toast_idxid = index_create(toast_relid, toast_idxname, indexInfo,
|
||||
BTREE_AM_OID, classObjectId,
|
||||
false, true, true);
|
||||
true, true);
|
||||
|
||||
/*
|
||||
* Update toast rel's pg_class entry to show that it has an index. The
|
||||
@ -1971,7 +1979,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
|
||||
}
|
||||
|
||||
/* Create the schema's namespace */
|
||||
NamespaceCreate(schemaName);
|
||||
NamespaceCreate(schemaName, owner_userid);
|
||||
|
||||
/* Let commands in the schema-element-list know about the schema */
|
||||
CommandCounterIncrement();
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.94 2002/03/29 22:10:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.95 2002/03/31 06:26:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,7 +30,7 @@
|
||||
#include "parser/parse_type.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
/* ----------------
|
||||
* local stuff
|
||||
@ -157,11 +157,11 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
}
|
||||
}
|
||||
|
||||
relationId = heap_create_with_catalog(relname, namespaceId,
|
||||
relationId = heap_create_with_catalog(relname,
|
||||
namespaceId,
|
||||
descriptor,
|
||||
relkind,
|
||||
stmt->hasoids || parentHasOids,
|
||||
stmt->relation->istemp,
|
||||
allowSystemTableMods);
|
||||
|
||||
StoreCatalogInheritance(relationId, inheritOids);
|
||||
@ -447,7 +447,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table",
|
||||
parent->relname);
|
||||
/* Permanent rels cannot inherit from temporary ones */
|
||||
if (!istemp && is_temp_rel_name(parent->relname))
|
||||
if (!istemp && isTempNamespace(RelationGetNamespace(relation)))
|
||||
elog(ERROR, "CREATE TABLE: cannot inherit from temp relation \"%s\"",
|
||||
parent->relname);
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.65 2002/03/26 19:15:41 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.66 2002/03/31 06:26:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -33,7 +33,6 @@
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args != NIL)
|
||||
@ -74,7 +73,6 @@ DefineIndex(RangeVar *heapRelation,
|
||||
Oid *classObjectId;
|
||||
Oid accessMethodId;
|
||||
Oid relationId;
|
||||
bool istemp = is_temp_rel_name(heapRelation->relname);
|
||||
Relation rel;
|
||||
HeapTuple tuple;
|
||||
Form_pg_am accessMethodForm;
|
||||
@ -191,7 +189,7 @@ DefineIndex(RangeVar *heapRelation,
|
||||
|
||||
index_create(relationId, indexRelationName,
|
||||
indexInfo, accessMethodId, classObjectId,
|
||||
istemp, primary, allowSystemTableMods);
|
||||
primary, allowSystemTableMods);
|
||||
|
||||
/*
|
||||
* We update the relation's pg_class tuple even if it already has
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.66 2002/03/29 19:06:07 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.67 2002/03/31 06:26:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -39,7 +39,6 @@
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
#define RI_TRIGGER_PK 1 /* is a trigger on the PK relation */
|
||||
@ -270,13 +269,6 @@ renamerel(const RangeVar *relation, const char *newrelname)
|
||||
elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
|
||||
newrelname);
|
||||
|
||||
/*
|
||||
* Check for renaming a temp table, which only requires altering the
|
||||
* temp-table mapping, not the underlying table.
|
||||
*/
|
||||
if (rename_temp_relation(relation->relname, newrelname))
|
||||
return; /* all done... */
|
||||
|
||||
/*
|
||||
* Grab an exclusive lock on the target table or index, which we will
|
||||
* NOT release until end of transaction.
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.109 2002/03/29 22:10:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.110 2002/03/31 06:26:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -471,7 +471,7 @@ RelationRemoveTriggers(Relation rel)
|
||||
Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tup);
|
||||
|
||||
elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"",
|
||||
get_temp_rel_by_physicalname(get_rel_name(pg_trigger->tgrelid)));
|
||||
get_rel_name(pg_trigger->tgrelid));
|
||||
|
||||
DropTrigger(pg_trigger->tgrelid, NameStr(pg_trigger->tgname));
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.219 2002/03/21 23:27:22 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.220 2002/03/31 06:26:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -42,8 +42,6 @@
|
||||
#include "utils/inval.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
#include "pgstat.h"
|
||||
|
||||
|
||||
@ -351,16 +349,9 @@ getrels(Name VacRelP, const char *stmttype)
|
||||
* we could use the cache here, but it is clearer to use scankeys
|
||||
* for both vacuum cases, bjm 2000/01/19
|
||||
*/
|
||||
char *nontemp_relname;
|
||||
|
||||
/* We must re-map temp table names bjm 2000-04-06 */
|
||||
nontemp_relname = get_temp_rel_by_username(NameStr(*VacRelP));
|
||||
if (nontemp_relname == NULL)
|
||||
nontemp_relname = NameStr(*VacRelP);
|
||||
|
||||
ScanKeyEntryInitialize(&key, 0x0, Anum_pg_class_relname,
|
||||
F_NAMEEQ,
|
||||
PointerGetDatum(nontemp_relname));
|
||||
PointerGetDatum(NameStr(*VacRelP)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -27,7 +27,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.155 2002/03/26 19:15:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.156 2002/03/31 06:26:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -724,8 +724,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
|
||||
heap_create_with_catalog(intoName,
|
||||
namespaceId,
|
||||
tupdesc,
|
||||
RELKIND_RELATION, true,
|
||||
parseTree->into->istemp,
|
||||
RELKIND_RELATION,
|
||||
true,
|
||||
allowSystemTableMods);
|
||||
|
||||
FreeTupleDesc(tupdesc);
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.224 2002/03/29 19:06:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.225 2002/03/31 06:26:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -37,8 +37,6 @@
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
#include "mb/pg_wchar.h"
|
||||
#endif
|
||||
@ -2553,7 +2551,6 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
cxt.stmtType = "ALTER TABLE";
|
||||
cxt.relation = stmt->relation;
|
||||
cxt.inhRelations = NIL;
|
||||
cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
|
||||
cxt.relOid = RangeVarGetRelid(stmt->relation, false);
|
||||
cxt.hasoids = SearchSysCacheExists(ATTNUM,
|
||||
ObjectIdGetDatum(cxt.relOid),
|
||||
@ -2583,7 +2580,6 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
|
||||
cxt.stmtType = "ALTER TABLE";
|
||||
cxt.relation = stmt->relation;
|
||||
cxt.inhRelations = NIL;
|
||||
cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
|
||||
cxt.relOid = RangeVarGetRelid(stmt->relation, false);
|
||||
cxt.hasoids = SearchSysCacheExists(ATTNUM,
|
||||
ObjectIdGetDatum(cxt.relOid),
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.142 2002/03/29 22:10:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.143 2002/03/31 06:26:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -49,7 +49,6 @@
|
||||
#include "utils/acl.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
#include "access/xlog.h"
|
||||
|
||||
/*
|
||||
@ -128,8 +127,7 @@ CheckDropPermissions(RangeVar *rel, char rightkind)
|
||||
elog(ERROR, "you do not own %s \"%s\"",
|
||||
rentry->name, rel->relname);
|
||||
|
||||
if (!allowSystemTableMods && IsSystemRelationName(rel->relname) &&
|
||||
!is_temp_relname(rel->relname))
|
||||
if (!allowSystemTableMods && IsSystemRelationName(rel->relname))
|
||||
elog(ERROR, "%s \"%s\" is a system %s",
|
||||
rentry->name, rel->relname, rentry->name);
|
||||
|
||||
|
4
src/backend/utils/cache/Makefile
vendored
4
src/backend/utils/cache/Makefile
vendored
@ -4,7 +4,7 @@
|
||||
# Makefile for utils/cache
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.15 2001/10/06 23:21:44 tgl Exp $
|
||||
# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.16 2002/03/31 06:26:31 tgl Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -13,7 +13,7 @@ top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o \
|
||||
fcache.o temprel.o
|
||||
fcache.o
|
||||
|
||||
all: SUBSYS.o
|
||||
|
||||
|
16
src/backend/utils/cache/relcache.c
vendored
16
src/backend/utils/cache/relcache.c
vendored
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.158 2002/03/26 19:16:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.159 2002/03/31 06:26:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -60,7 +60,6 @@
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -186,7 +185,7 @@ do { \
|
||||
nodentry->reldesc = RELATION; \
|
||||
if (RelationGetNamespace(RELATION) == PG_CATALOG_NAMESPACE) \
|
||||
{ \
|
||||
char *relname = RelationGetPhysicalRelationName(RELATION); \
|
||||
char *relname = RelationGetRelationName(RELATION); \
|
||||
RelNameCacheEnt *namehentry; \
|
||||
namehentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \
|
||||
relname, \
|
||||
@ -247,7 +246,7 @@ do { \
|
||||
elog(WARNING, "trying to delete a reldesc that does not exist."); \
|
||||
if (RelationGetNamespace(RELATION) == PG_CATALOG_NAMESPACE) \
|
||||
{ \
|
||||
char *relname = RelationGetPhysicalRelationName(RELATION); \
|
||||
char *relname = RelationGetRelationName(RELATION); \
|
||||
RelNameCacheEnt *namehentry; \
|
||||
namehentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \
|
||||
relname, \
|
||||
@ -1571,18 +1570,9 @@ RelationIdGetRelation(Oid relationId)
|
||||
Relation
|
||||
RelationSysNameGetRelation(const char *relationName)
|
||||
{
|
||||
char *temprelname;
|
||||
Relation rd;
|
||||
RelationBuildDescInfo buildinfo;
|
||||
|
||||
/*
|
||||
* if caller is looking for a temp relation, substitute its real name;
|
||||
* we only index temp rels by their real names.
|
||||
*/
|
||||
temprelname = get_temp_rel_by_username(relationName);
|
||||
if (temprelname != NULL)
|
||||
relationName = temprelname;
|
||||
|
||||
/*
|
||||
* first try and get a reldesc from the cache
|
||||
*/
|
||||
|
27
src/backend/utils/cache/syscache.c
vendored
27
src/backend/utils/cache/syscache.c
vendored
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.71 2002/03/29 19:06:15 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.72 2002/03/31 06:26:32 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* These routines allow the parser/planner/executor to perform
|
||||
@ -42,7 +42,6 @@
|
||||
#include "catalog/pg_type.h"
|
||||
#include "utils/catcache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
#include "miscadmin.h"
|
||||
|
||||
|
||||
@ -500,29 +499,9 @@ SearchSysCache(int cacheId,
|
||||
Datum key3,
|
||||
Datum key4)
|
||||
{
|
||||
if (cacheId < 0 || cacheId >= SysCacheSize)
|
||||
{
|
||||
if (cacheId < 0 || cacheId >= SysCacheSize ||
|
||||
! PointerIsValid(SysCache[cacheId]))
|
||||
elog(ERROR, "SearchSysCache: Bad cache id %d", cacheId);
|
||||
return (HeapTuple) NULL;
|
||||
}
|
||||
|
||||
Assert(PointerIsValid(SysCache[cacheId]));
|
||||
|
||||
/*
|
||||
* If someone tries to look up a relname, translate temp relation
|
||||
* names to real names. Less obviously, apply the same translation to
|
||||
* type names, so that the type tuple of a temp table will be found
|
||||
* when sought. This is a kluge ... temp table substitution should be
|
||||
* happening at a higher level ...
|
||||
*/
|
||||
if (cacheId == RELNAMENSP || cacheId == TYPENAMENSP)
|
||||
{
|
||||
char *nontemp_relname;
|
||||
|
||||
nontemp_relname = get_temp_rel_by_username(DatumGetCString(key1));
|
||||
if (nontemp_relname != NULL)
|
||||
key1 = CStringGetDatum(nontemp_relname);
|
||||
}
|
||||
|
||||
return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
|
||||
}
|
||||
|
335
src/backend/utils/cache/temprel.c
vendored
335
src/backend/utils/cache/temprel.c
vendored
@ -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);
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.100 2002/03/06 06:10:25 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.101 2002/03/31 06:26:32 tgl Exp $
|
||||
*
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
@ -39,7 +39,6 @@
|
||||
#include "utils/portal.h"
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
|
||||
|
||||
static void ReverifyMyDatabase(const char *name);
|
||||
@ -386,20 +385,13 @@ InitPostgres(const char *dbname, const char *username)
|
||||
RelationCacheInitializePhase3();
|
||||
|
||||
/*
|
||||
* Set up process-exit callbacks to remove temp relations and then do
|
||||
* pre-shutdown cleanup. This should be last because we want
|
||||
* shmem_exit to call these routines before the exit callbacks that
|
||||
* are registered by buffer manager, lock manager, etc. We need to
|
||||
* run this code before we close down database access!
|
||||
* Set up process-exit callback to do pre-shutdown cleanup. This should
|
||||
* be last because we want shmem_exit to call this routine before the exit
|
||||
* callbacks that are registered by buffer manager, lock manager, etc.
|
||||
* We need to run this code before we close down database access!
|
||||
*/
|
||||
on_shmem_exit(ShutdownPostgres, 0);
|
||||
|
||||
/*
|
||||
* because callbacks are called in reverse order, this gets done
|
||||
* first:
|
||||
*/
|
||||
on_shmem_exit(remove_all_temp_relations, 0);
|
||||
|
||||
/* close the transaction we started above */
|
||||
if (!bootstrap)
|
||||
CommitTransactionCommand();
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: heap.h,v 1.48 2002/03/29 19:06:17 tgl Exp $
|
||||
* $Id: heap.h,v 1.49 2002/03/31 06:26:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -27,16 +27,19 @@ typedef struct RawColumnDefault
|
||||
* tree) */
|
||||
} RawColumnDefault;
|
||||
|
||||
extern Relation heap_create(char *relname, Oid relnamespace,
|
||||
extern Relation heap_create(const char *relname,
|
||||
Oid relnamespace,
|
||||
TupleDesc tupDesc,
|
||||
bool istemp, bool storage_create,
|
||||
bool storage_create,
|
||||
bool allow_system_table_mods);
|
||||
|
||||
extern void heap_storage_create(Relation rel);
|
||||
|
||||
extern Oid heap_create_with_catalog(char *relname, Oid relnamespace,
|
||||
extern Oid heap_create_with_catalog(const char *relname,
|
||||
Oid relnamespace,
|
||||
TupleDesc tupdesc,
|
||||
char relkind, bool relhasoids, bool istemp,
|
||||
char relkind,
|
||||
bool relhasoids,
|
||||
bool allow_system_table_mods);
|
||||
|
||||
extern void heap_drop_with_catalog(Oid rid, bool allow_system_table_mods);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: index.h,v 1.46 2002/03/26 19:16:25 tgl Exp $
|
||||
* $Id: index.h,v 1.47 2002/03/31 06:26:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,11 +30,10 @@ typedef void (*IndexBuildCallback) (Relation index,
|
||||
|
||||
|
||||
extern Oid index_create(Oid heapRelationId,
|
||||
char *indexRelationName,
|
||||
const char *indexRelationName,
|
||||
IndexInfo *indexInfo,
|
||||
Oid accessMethodObjectId,
|
||||
Oid *classObjectId,
|
||||
bool istemp,
|
||||
bool primary,
|
||||
bool allow_system_table_mods);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: namespace.h,v 1.3 2002/03/30 01:02:42 tgl Exp $
|
||||
* $Id: namespace.h,v 1.4 2002/03/31 06:26:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,4 +29,6 @@ extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
|
||||
|
||||
extern RangeVar *makeRangeVarFromNameList(List *names);
|
||||
|
||||
extern bool isTempNamespace(Oid namespaceId);
|
||||
|
||||
#endif /* NAMESPACE_H */
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pg_namespace.h,v 1.2 2002/03/30 01:02:42 tgl Exp $
|
||||
* $Id: pg_namespace.h,v 1.3 2002/03/31 06:26:32 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -69,7 +69,7 @@ typedef FormData_pg_namespace *Form_pg_namespace;
|
||||
DATA(insert OID = 11 ( "pg_catalog" PGUID "{=r}" ));
|
||||
DESCR("System catalog namespace");
|
||||
#define PG_CATALOG_NAMESPACE 11
|
||||
DATA(insert OID = 99 ( "pg_toast" PGUID "{=r}" ));
|
||||
DATA(insert OID = 99 ( "pg_toast" PGUID "{=}" ));
|
||||
DESCR("Reserved namespace for TOAST tables");
|
||||
#define PG_TOAST_NAMESPACE 99
|
||||
DATA(insert OID = 2071 ( "pg_public" PGUID "{=rw}" ));
|
||||
@ -80,6 +80,6 @@ DESCR("Standard public namespace");
|
||||
/*
|
||||
* prototypes for functions in pg_namespace.c
|
||||
*/
|
||||
extern Oid NamespaceCreate(const char *nspName);
|
||||
extern Oid NamespaceCreate(const char *nspName, int32 ownerSysId);
|
||||
|
||||
#endif /* PG_NAMESPACE_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: rel.h,v 1.57 2002/03/26 19:16:58 tgl Exp $
|
||||
* $Id: rel.h,v 1.58 2002/03/31 06:26:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -238,49 +238,15 @@ typedef Relation *RelationPtr;
|
||||
*/
|
||||
#define RelationGetIndexStrategy(relation) ((relation)->rd_istrat)
|
||||
|
||||
/*
|
||||
* Handle temp relations
|
||||
*/
|
||||
#define PG_TEMP_REL_PREFIX "pg_temp"
|
||||
#define PG_TEMP_REL_PREFIX_LEN 7
|
||||
|
||||
#define is_temp_relname(relname) \
|
||||
(strncmp(relname, PG_TEMP_REL_PREFIX, PG_TEMP_REL_PREFIX_LEN) == 0)
|
||||
|
||||
/*
|
||||
* RelationGetPhysicalRelationName
|
||||
*
|
||||
* Returns the rel's physical name, ie, the name appearing in pg_class.
|
||||
*
|
||||
* While this name is unique across all rels in the database, it is not
|
||||
* necessarily useful for accessing the rel, since a temp table of the
|
||||
* same name might mask the rel. It is useful mainly for determining if
|
||||
* the rel is a shared system rel or not.
|
||||
*
|
||||
* The macro is rather unfortunately named, since the pg_class name no longer
|
||||
* has anything to do with the file name used for physical storage of the rel.
|
||||
*/
|
||||
#define RelationGetPhysicalRelationName(relation) \
|
||||
(NameStr((relation)->rd_rel->relname))
|
||||
|
||||
/*
|
||||
* RelationGetRelationName
|
||||
*
|
||||
* Returns the relation's logical name (as seen by the user).
|
||||
* Returns the rel's name.
|
||||
*
|
||||
* If the rel is a temp rel, the temp name will be returned. Therefore,
|
||||
* this name is not unique. But it is the name to use in heap_openr(),
|
||||
* for example.
|
||||
* Note that the name is only unique within the containing namespace.
|
||||
*/
|
||||
#define RelationGetRelationName(relation) \
|
||||
(\
|
||||
is_temp_relname(RelationGetPhysicalRelationName(relation)) \
|
||||
? \
|
||||
get_temp_rel_by_physicalname( \
|
||||
RelationGetPhysicalRelationName(relation)) \
|
||||
: \
|
||||
RelationGetPhysicalRelationName(relation) \
|
||||
)
|
||||
(NameStr((relation)->rd_rel->relname))
|
||||
|
||||
/*
|
||||
* RelationGetNamespace
|
||||
@ -290,7 +256,4 @@ typedef Relation *RelationPtr;
|
||||
#define RelationGetNamespace(relation) \
|
||||
((relation)->rd_rel->relnamespace)
|
||||
|
||||
/* added to prevent circular dependency. bjm 1999/11/15 */
|
||||
extern char *get_temp_rel_by_physicalname(const char *relname);
|
||||
|
||||
#endif /* REL_H */
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* temprel.h
|
||||
* Temporary relation functions
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: temprel.h,v 1.20 2001/11/05 17:46:36 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef TEMPREL_H
|
||||
#define TEMPREL_H
|
||||
|
||||
#include "access/htup.h"
|
||||
|
||||
extern void create_temp_relation(const char *relname,
|
||||
HeapTuple pg_class_tuple);
|
||||
extern void remove_temp_rel_by_relid(Oid relid);
|
||||
extern bool rename_temp_relation(const char *oldname,
|
||||
const char *newname);
|
||||
|
||||
extern void remove_all_temp_relations(void);
|
||||
extern void AtEOXact_temp_relations(bool isCommit);
|
||||
|
||||
extern char *get_temp_rel_by_username(const char *user_relname);
|
||||
extern char *get_temp_rel_by_physicalname(const char *relname);
|
||||
|
||||
#define is_temp_rel_name(relname) (get_temp_rel_by_username(relname) != NULL)
|
||||
|
||||
#endif /* TEMPREL_H */
|
Loading…
Reference in New Issue
Block a user