mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Fix performance problems with pg_index lookups (see, for example,
discussion of 5/19/00). pg_index is now searched for indexes of a relation using an indexscan. Moreover, this is done once and cached in the relcache entry for the relation, in the form of a list of OIDs for the indexes. This list is used by the parser and executor to drive lookups in the pg_index syscache when they want to know the properties of the indexes. Net result: index information will be fully cached for repetitive operations such as inserts.
This commit is contained in:
parent
9cf80f2f55
commit
d03a933ec5
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.116 2000/06/17 04:56:36 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.117 2000/06/17 21:48:39 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -1105,6 +1105,7 @@ index_create(char *heapRelationName,
|
|||||||
void
|
void
|
||||||
index_drop(Oid indexId)
|
index_drop(Oid indexId)
|
||||||
{
|
{
|
||||||
|
Oid heapId;
|
||||||
Relation userHeapRelation;
|
Relation userHeapRelation;
|
||||||
Relation userIndexRelation;
|
Relation userIndexRelation;
|
||||||
Relation indexRelation;
|
Relation indexRelation;
|
||||||
@ -1125,8 +1126,8 @@ index_drop(Oid indexId)
|
|||||||
* else other backends will still see this index in pg_index.
|
* else other backends will still see this index in pg_index.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
userHeapRelation = heap_open(IndexGetRelation(indexId),
|
heapId = IndexGetRelation(indexId);
|
||||||
AccessExclusiveLock);
|
userHeapRelation = heap_open(heapId, AccessExclusiveLock);
|
||||||
|
|
||||||
userIndexRelation = index_open(indexId);
|
userIndexRelation = index_open(indexId);
|
||||||
LockRelation(userIndexRelation, AccessExclusiveLock);
|
LockRelation(userIndexRelation, AccessExclusiveLock);
|
||||||
@ -1158,6 +1159,7 @@ index_drop(Oid indexId)
|
|||||||
*/
|
*/
|
||||||
relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
|
relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||||
|
|
||||||
|
/* Remove the pg_class tuple for the index itself */
|
||||||
tuple = SearchSysCacheTupleCopy(RELOID,
|
tuple = SearchSysCacheTupleCopy(RELOID,
|
||||||
ObjectIdGetDatum(indexId),
|
ObjectIdGetDatum(indexId),
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
@ -1166,6 +1168,23 @@ index_drop(Oid indexId)
|
|||||||
|
|
||||||
heap_delete(relationRelation, &tuple->t_self, NULL);
|
heap_delete(relationRelation, &tuple->t_self, NULL);
|
||||||
heap_freetuple(tuple);
|
heap_freetuple(tuple);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the pg_class tuple for the owning relation. We do not attempt
|
||||||
|
* to clear relhasindex, since we are too lazy to test whether any other
|
||||||
|
* indexes remain (the next VACUUM will fix it if necessary). But we
|
||||||
|
* must send out a shared-cache-inval notice on the owning relation
|
||||||
|
* to ensure other backends update their relcache lists of indexes.
|
||||||
|
*/
|
||||||
|
tuple = SearchSysCacheTupleCopy(RELOID,
|
||||||
|
ObjectIdGetDatum(heapId),
|
||||||
|
0, 0, 0);
|
||||||
|
|
||||||
|
Assert(HeapTupleIsValid(tuple));
|
||||||
|
|
||||||
|
ImmediateInvalidateSharedHeapTuple(relationRelation, tuple);
|
||||||
|
heap_freetuple(tuple);
|
||||||
|
|
||||||
heap_close(relationRelation, RowExclusiveLock);
|
heap_close(relationRelation, RowExclusiveLock);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -1447,9 +1466,6 @@ setRelhasindexInplace(Oid relid, bool hasindex, bool immediate)
|
|||||||
*/
|
*/
|
||||||
if (pg_class_scan)
|
if (pg_class_scan)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!IsBootstrapProcessingMode())
|
|
||||||
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
|
|
||||||
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
|
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
|
||||||
rd_rel->relhasindex = hasindex;
|
rd_rel->relhasindex = hasindex;
|
||||||
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
|
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
|
||||||
@ -1461,12 +1477,18 @@ setRelhasindexInplace(Oid relid, bool hasindex, bool immediate)
|
|||||||
|
|
||||||
htup.t_self = tuple->t_self;
|
htup.t_self = tuple->t_self;
|
||||||
heap_fetch(pg_class, SnapshotNow, &htup, &buffer);
|
heap_fetch(pg_class, SnapshotNow, &htup, &buffer);
|
||||||
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
|
|
||||||
rd_rel = (Form_pg_class) GETSTRUCT(&htup);
|
rd_rel = (Form_pg_class) GETSTRUCT(&htup);
|
||||||
rd_rel->relhasindex = hasindex;
|
rd_rel->relhasindex = hasindex;
|
||||||
WriteBuffer(buffer);
|
WriteBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send out a shared-cache-inval message so other backends notice the
|
||||||
|
* update and fix their syscaches/relcaches.
|
||||||
|
*/
|
||||||
|
if (!IsBootstrapProcessingMode())
|
||||||
|
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
|
||||||
|
|
||||||
if (!pg_class_scan)
|
if (!pg_class_scan)
|
||||||
heap_freetuple(tuple);
|
heap_freetuple(tuple);
|
||||||
else
|
else
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.114 2000/06/15 03:32:07 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.115 2000/06/17 21:48:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -32,6 +32,7 @@
|
|||||||
#include "tcop/tcopprot.h"
|
#include "tcop/tcopprot.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
#include "utils/relcache.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
@ -1081,78 +1082,43 @@ IsTypeByVal(Oid type)
|
|||||||
* Space for the array itself is palloc'ed.
|
* Space for the array itself is palloc'ed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct rel_list
|
|
||||||
{
|
|
||||||
Oid index_rel_oid;
|
|
||||||
struct rel_list *next;
|
|
||||||
} RelationList;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
GetIndexRelations(Oid main_relation_oid,
|
GetIndexRelations(Oid main_relation_oid,
|
||||||
int *n_indices,
|
int *n_indices,
|
||||||
Relation **index_rels)
|
Relation **index_rels)
|
||||||
{
|
{
|
||||||
RelationList *head,
|
Relation relation;
|
||||||
*scan;
|
List *indexoidlist,
|
||||||
Relation pg_index_rel;
|
*indexoidscan;
|
||||||
HeapScanDesc scandesc;
|
|
||||||
Oid index_relation_oid;
|
|
||||||
HeapTuple tuple;
|
|
||||||
TupleDesc tupDesc;
|
|
||||||
int i;
|
int i;
|
||||||
bool isnull;
|
|
||||||
|
|
||||||
pg_index_rel = heap_openr(IndexRelationName, AccessShareLock);
|
relation = heap_open(main_relation_oid, AccessShareLock);
|
||||||
scandesc = heap_beginscan(pg_index_rel, 0, SnapshotNow, 0, NULL);
|
indexoidlist = RelationGetIndexList(relation);
|
||||||
tupDesc = RelationGetDescr(pg_index_rel);
|
|
||||||
|
|
||||||
*n_indices = 0;
|
*n_indices = length(indexoidlist);
|
||||||
|
|
||||||
head = (RelationList *) palloc(sizeof(RelationList));
|
|
||||||
scan = head;
|
|
||||||
head->next = NULL;
|
|
||||||
|
|
||||||
while (HeapTupleIsValid(tuple = heap_getnext(scandesc, 0)))
|
|
||||||
{
|
|
||||||
|
|
||||||
index_relation_oid = (Oid) DatumGetInt32(heap_getattr(tuple, 2,
|
|
||||||
tupDesc, &isnull));
|
|
||||||
if (index_relation_oid == main_relation_oid)
|
|
||||||
{
|
|
||||||
scan->index_rel_oid = (Oid) DatumGetInt32(heap_getattr(tuple,
|
|
||||||
Anum_pg_index_indexrelid,
|
|
||||||
tupDesc, &isnull));
|
|
||||||
(*n_indices)++;
|
|
||||||
scan->next = (RelationList *) palloc(sizeof(RelationList));
|
|
||||||
scan = scan->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
heap_endscan(scandesc);
|
|
||||||
heap_close(pg_index_rel, AccessShareLock);
|
|
||||||
|
|
||||||
/* We cannot trust to relhasindex of the main_relation now, so... */
|
|
||||||
if (*n_indices == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (*n_indices > 0)
|
||||||
*index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
|
*index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
|
||||||
|
else
|
||||||
|
*index_rels = NULL;
|
||||||
|
|
||||||
for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
|
i = 0;
|
||||||
|
foreach(indexoidscan, indexoidlist)
|
||||||
{
|
{
|
||||||
(*index_rels)[i] = index_open(scan->index_rel_oid);
|
Oid indexoid = lfirsti(indexoidscan);
|
||||||
|
Relation index = index_open(indexoid);
|
||||||
|
|
||||||
/* see comments in ExecOpenIndices() in execUtils.c */
|
/* see comments in ExecOpenIndices() in execUtils.c */
|
||||||
if ((*index_rels)[i] != NULL &&
|
if (index != NULL &&
|
||||||
((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID &&
|
index->rd_rel->relam != BTREE_AM_OID &&
|
||||||
((*index_rels)[i])->rd_rel->relam != HASH_AM_OID)
|
index->rd_rel->relam != HASH_AM_OID)
|
||||||
LockRelation((*index_rels)[i], AccessExclusiveLock);
|
LockRelation(index, AccessExclusiveLock);
|
||||||
|
(*index_rels)[i] = index;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, scan = head; i < *n_indices + 1; i++)
|
freeList(indexoidlist);
|
||||||
{
|
heap_close(relation, AccessShareLock);
|
||||||
scan = head->next;
|
|
||||||
pfree(head);
|
|
||||||
head = scan;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.29 2000/06/15 03:32:07 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.30 2000/06/17 21:48:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -221,6 +221,13 @@ DefineIndex(char *heapRelationName,
|
|||||||
lossy, unique, primary);
|
lossy, unique, primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We update the relation's pg_class tuple even if it already has
|
||||||
|
* relhasindex = true. This is needed to cause a shared-cache-inval
|
||||||
|
* message to be sent for the pg_class tuple, which will cause other
|
||||||
|
* backends to flush their relcache entries and in particular their
|
||||||
|
* cached lists of the indexes for this relation.
|
||||||
|
*/
|
||||||
setRelhasindexInplace(relationId, true, false);
|
setRelhasindexInplace(relationId, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.159 2000/05/29 17:40:43 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.160 2000/06/17 21:48:43 tgl Exp $
|
||||||
*
|
*
|
||||||
|
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
@ -72,7 +72,7 @@ static void update_relstats(Oid relid, int num_pages, int num_tuples, bool hasin
|
|||||||
static VacPage tid_reaped(ItemPointer itemptr, VacPageList vacpagelist);
|
static VacPage tid_reaped(ItemPointer itemptr, VacPageList vacpagelist);
|
||||||
static void reap_page(VacPageList vacpagelist, VacPage vacpage);
|
static void reap_page(VacPageList vacpagelist, VacPage vacpage);
|
||||||
static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
|
static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
|
||||||
static void get_indices(Oid relid, int *nindices, Relation **Irel);
|
static void get_indices(Relation relation, int *nindices, Relation **Irel);
|
||||||
static void close_indices(int nindices, Relation *Irel);
|
static void close_indices(int nindices, Relation *Irel);
|
||||||
static void get_index_desc(Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc);
|
static void get_index_desc(Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc);
|
||||||
static void *vac_find_eq(void *bot, int nelem, int size, void *elm,
|
static void *vac_find_eq(void *bot, int nelem, int size, void *elm,
|
||||||
@ -416,7 +416,7 @@ vacuum_rel(Oid relid, bool analyze)
|
|||||||
/* Now open indices */
|
/* Now open indices */
|
||||||
nindices = 0;
|
nindices = 0;
|
||||||
Irel = (Relation *) NULL;
|
Irel = (Relation *) NULL;
|
||||||
get_indices(vacrelstats->relid, &nindices, &Irel);
|
get_indices(onerel, &nindices, &Irel);
|
||||||
if (!Irel)
|
if (!Irel)
|
||||||
reindex = false;
|
reindex = false;
|
||||||
else if (!RelationGetForm(onerel)->relhasindex)
|
else if (!RelationGetForm(onerel)->relhasindex)
|
||||||
@ -2331,80 +2331,33 @@ CommonSpecialPortalIsOpen(void)
|
|||||||
return CommonSpecialPortalInUse;
|
return CommonSpecialPortalInUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_indices(Oid relid, int *nindices, Relation **Irel)
|
get_indices(Relation relation, int *nindices, Relation **Irel)
|
||||||
{
|
{
|
||||||
Relation pgindex;
|
List *indexoidlist,
|
||||||
Relation irel;
|
*indexoidscan;
|
||||||
TupleDesc tupdesc;
|
int i;
|
||||||
HeapTuple tuple;
|
|
||||||
HeapScanDesc scan;
|
|
||||||
Datum d;
|
|
||||||
int i,
|
|
||||||
k;
|
|
||||||
bool n;
|
|
||||||
ScanKeyData key;
|
|
||||||
Oid *ioid;
|
|
||||||
|
|
||||||
*nindices = i = 0;
|
indexoidlist = RelationGetIndexList(relation);
|
||||||
|
|
||||||
ioid = (Oid *) palloc(10 * sizeof(Oid));
|
*nindices = length(indexoidlist);
|
||||||
|
|
||||||
/* prepare a heap scan on the pg_index relation */
|
if (*nindices > 0)
|
||||||
pgindex = heap_openr(IndexRelationName, AccessShareLock);
|
*Irel = (Relation *) palloc(*nindices * sizeof(Relation));
|
||||||
tupdesc = RelationGetDescr(pgindex);
|
else
|
||||||
|
*Irel = NULL;
|
||||||
|
|
||||||
ScanKeyEntryInitialize(&key, 0x0, Anum_pg_index_indrelid,
|
i = 0;
|
||||||
F_OIDEQ,
|
foreach(indexoidscan, indexoidlist)
|
||||||
ObjectIdGetDatum(relid));
|
|
||||||
|
|
||||||
scan = heap_beginscan(pgindex, false, SnapshotNow, 1, &key);
|
|
||||||
|
|
||||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
|
||||||
{
|
{
|
||||||
d = heap_getattr(tuple, Anum_pg_index_indexrelid,
|
Oid indexoid = lfirsti(indexoidscan);
|
||||||
tupdesc, &n);
|
|
||||||
|
(*Irel)[i] = index_open(indexoid);
|
||||||
i++;
|
i++;
|
||||||
if (i % 10 == 0)
|
|
||||||
ioid = (Oid *) repalloc(ioid, (i + 10) * sizeof(Oid));
|
|
||||||
ioid[i - 1] = DatumGetObjectId(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
heap_endscan(scan);
|
|
||||||
heap_close(pgindex, AccessShareLock);
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
{ /* No one index found */
|
|
||||||
pfree(ioid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Irel != (Relation **) NULL)
|
|
||||||
*Irel = (Relation *) palloc(i * sizeof(Relation));
|
|
||||||
|
|
||||||
for (k = 0; i > 0;)
|
|
||||||
{
|
|
||||||
irel = index_open(ioid[--i]);
|
|
||||||
if (irel != (Relation) NULL)
|
|
||||||
{
|
|
||||||
if (Irel != (Relation **) NULL)
|
|
||||||
(*Irel)[k] = irel;
|
|
||||||
else
|
|
||||||
index_close(irel);
|
|
||||||
k++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
elog(NOTICE, "CAN'T OPEN INDEX %u - SKIP IT", ioid[i]);
|
|
||||||
}
|
|
||||||
*nindices = k;
|
|
||||||
pfree(ioid);
|
|
||||||
|
|
||||||
if (Irel != (Relation **) NULL && *nindices == 0)
|
|
||||||
{
|
|
||||||
pfree(*Irel);
|
|
||||||
*Irel = (Relation *) NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
freeList(indexoidlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.117 2000/06/15 04:09:50 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.118 2000/06/17 21:48:47 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -735,7 +735,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
|
|||||||
*/
|
*/
|
||||||
if (resultRelationDesc->rd_rel->relhasindex &&
|
if (resultRelationDesc->rd_rel->relhasindex &&
|
||||||
operation != CMD_DELETE)
|
operation != CMD_DELETE)
|
||||||
ExecOpenIndices(resultRelationOid, resultRelationInfo);
|
ExecOpenIndices(resultRelationInfo);
|
||||||
|
|
||||||
estate->es_result_relation_info = resultRelationInfo;
|
estate->es_result_relation_info = resultRelationInfo;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.59 2000/06/15 04:09:52 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.60 2000/06/17 21:48:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -53,6 +53,8 @@
|
|||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
|
#include "utils/relcache.h"
|
||||||
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
static void ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP,
|
static void ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP,
|
||||||
AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP);
|
AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP);
|
||||||
@ -657,7 +659,7 @@ ExecGetIndexKeyInfo(Form_pg_index indexTuple,
|
|||||||
* check parameters
|
* check parameters
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
if (numAttsOutP == NULL && attsOutP == NULL)
|
if (numAttsOutP == NULL || attsOutP == NULL)
|
||||||
{
|
{
|
||||||
elog(DEBUG, "ExecGetIndexKeyInfo: %s",
|
elog(DEBUG, "ExecGetIndexKeyInfo: %s",
|
||||||
"invalid parameters: numAttsOutP and attsOutP must be non-NULL");
|
"invalid parameters: numAttsOutP and attsOutP must be non-NULL");
|
||||||
@ -724,115 +726,112 @@ ExecGetIndexKeyInfo(Form_pg_index indexTuple,
|
|||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* ExecOpenIndices
|
* ExecOpenIndices
|
||||||
*
|
*
|
||||||
* Here we scan the pg_index relation to find indices
|
* Find the indices associated with a result relation, open them,
|
||||||
* associated with a given heap relation oid. Since we
|
* and save information about them in the result RelationInfo.
|
||||||
* don't know in advance how many indices we have, we
|
|
||||||
* form lists containing the information we need from
|
|
||||||
* pg_index and then process these lists.
|
|
||||||
*
|
*
|
||||||
* Note: much of this code duplicates effort done by
|
* At entry, caller has already opened and locked
|
||||||
* the IndexCatalogInformation function in plancat.c
|
* resultRelationInfo->ri_RelationDesc.
|
||||||
* because IndexCatalogInformation is poorly written.
|
|
||||||
*
|
*
|
||||||
* It would be much better if the functionality provided
|
* This used to be horribly ugly code, and slow too because it
|
||||||
* by this function and IndexCatalogInformation was
|
* did a sequential scan of pg_index. Now we rely on the relcache
|
||||||
* in the form of a small set of orthogonal routines..
|
* to cache a list of the OIDs of the indices associated with any
|
||||||
* If you are trying to understand this, I suggest you
|
* specific relation, and we use the pg_index syscache to get the
|
||||||
* look at the code to IndexCatalogInformation and
|
* entries we need from pg_index.
|
||||||
* FormIndexTuple.. -cim 9/27/89
|
|
||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ExecOpenIndices(Oid resultRelationOid,
|
ExecOpenIndices(RelationInfo *resultRelationInfo)
|
||||||
RelationInfo *resultRelationInfo)
|
|
||||||
{
|
{
|
||||||
Relation indexRd;
|
Relation resultRelation = resultRelationInfo->ri_RelationDesc;
|
||||||
HeapScanDesc indexSd;
|
List *indexoidlist,
|
||||||
ScanKeyData key;
|
*indexoidscan;
|
||||||
HeapTuple tuple;
|
int len,
|
||||||
Form_pg_index indexStruct;
|
i;
|
||||||
Oid indexOid;
|
|
||||||
List *oidList;
|
|
||||||
List *nkeyList;
|
|
||||||
List *keyList;
|
|
||||||
List *fiList;
|
|
||||||
char *predString;
|
|
||||||
List *predList;
|
|
||||||
List *indexoid;
|
|
||||||
List *numkeys;
|
|
||||||
List *indexkeys;
|
|
||||||
List *indexfuncs;
|
|
||||||
List *indexpreds;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
RelationPtr relationDescs;
|
RelationPtr relationDescs;
|
||||||
IndexInfo **indexInfoArray;
|
IndexInfo **indexInfoArray;
|
||||||
FuncIndexInfoPtr fInfoP;
|
|
||||||
int numKeyAtts;
|
|
||||||
AttrNumber *indexKeyAtts;
|
|
||||||
PredInfo *predicate;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
resultRelationInfo->ri_NumIndices = 0;
|
resultRelationInfo->ri_NumIndices = 0;
|
||||||
if (!RelationGetForm(resultRelationInfo->ri_RelationDesc)->relhasindex)
|
|
||||||
|
/* checks for disabled indexes */
|
||||||
|
if (! RelationGetForm(resultRelation)->relhasindex)
|
||||||
return;
|
return;
|
||||||
if (IsIgnoringSystemIndexes() &&
|
if (IsIgnoringSystemIndexes() &&
|
||||||
IsSystemRelationName(RelationGetRelationName(resultRelationInfo->ri_RelationDesc)))
|
IsSystemRelationName(RelationGetRelationName(resultRelation)))
|
||||||
return;
|
return;
|
||||||
/* ----------------
|
|
||||||
* open pg_index
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
indexRd = heap_openr(IndexRelationName, AccessShareLock);
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* form a scan key
|
* Get cached list of index OIDs
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_index_indrelid,
|
indexoidlist = RelationGetIndexList(resultRelation);
|
||||||
F_OIDEQ,
|
len = length(indexoidlist);
|
||||||
ObjectIdGetDatum(resultRelationOid));
|
if (len == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* scan the index relation, looking for indices for our
|
* allocate space for result arrays
|
||||||
* result relation..
|
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
indexSd = heap_beginscan(indexRd, /* scan desc */
|
relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
|
||||||
false, /* scan backward flag */
|
indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
|
||||||
SnapshotNow, /* NOW snapshot */
|
|
||||||
1, /* number scan keys */
|
|
||||||
&key); /* scan keys */
|
|
||||||
|
|
||||||
oidList = NIL;
|
resultRelationInfo->ri_NumIndices = len;
|
||||||
nkeyList = NIL;
|
resultRelationInfo->ri_IndexRelationDescs = relationDescs;
|
||||||
keyList = NIL;
|
resultRelationInfo->ri_IndexRelationInfo = indexInfoArray;
|
||||||
fiList = NIL;
|
|
||||||
predList = NIL;
|
|
||||||
|
|
||||||
while (HeapTupleIsValid(tuple = heap_getnext(indexSd, 0)))
|
/* ----------------
|
||||||
|
* For each index, open the index relation and save pg_index info.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
i = 0;
|
||||||
|
foreach(indexoidscan, indexoidlist)
|
||||||
{
|
{
|
||||||
|
Oid indexOid = lfirsti(indexoidscan);
|
||||||
|
Relation indexDesc;
|
||||||
|
HeapTuple indexTuple;
|
||||||
|
Form_pg_index indexStruct;
|
||||||
|
int numKeyAtts;
|
||||||
|
AttrNumber *indexKeyAtts;
|
||||||
|
FuncIndexInfoPtr fInfoP;
|
||||||
|
PredInfo *predicate;
|
||||||
|
IndexInfo *ii;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* For each index relation we find, extract the information
|
* Open (and lock, if necessary) the index relation
|
||||||
* we need and store it in a list..
|
|
||||||
*
|
*
|
||||||
* first get the oid of the index relation from the tuple
|
* Hack for not btree and hash indices: they use relation
|
||||||
|
* level exclusive locking on update (i.e. - they are not
|
||||||
|
* ready for MVCC) and so we have to exclusively lock
|
||||||
|
* indices here to prevent deadlocks if we will scan them
|
||||||
|
* - index_beginscan places AccessShareLock, indices
|
||||||
|
* update methods don't use locks at all. We release this
|
||||||
|
* lock in ExecCloseIndices. Note, that hashes use page
|
||||||
|
* level locking - i.e. are not deadlock-free, - let's
|
||||||
|
* them be on their way -:)) vadim 03-12-1998
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
indexStruct = (Form_pg_index) GETSTRUCT(tuple);
|
indexDesc = index_open(indexOid);
|
||||||
indexOid = indexStruct->indexrelid;
|
|
||||||
|
if (indexDesc->rd_rel->relam != BTREE_AM_OID &&
|
||||||
|
indexDesc->rd_rel->relam != HASH_AM_OID)
|
||||||
|
LockRelation(indexDesc, AccessExclusiveLock);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* allocate space for functional index information.
|
* Get the pg_index tuple for the index
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
indexTuple = SearchSysCacheTupleCopy(INDEXRELID,
|
||||||
|
ObjectIdGetDatum(indexOid),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(indexTuple))
|
||||||
|
elog(ERROR, "ExecOpenIndices: index %u not found", indexOid);
|
||||||
|
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* extract the index key information from the tuple
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
fInfoP = (FuncIndexInfoPtr) palloc(sizeof(*fInfoP));
|
fInfoP = (FuncIndexInfoPtr) palloc(sizeof(*fInfoP));
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* next get the index key information from the tuple
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
ExecGetIndexKeyInfo(indexStruct,
|
ExecGetIndexKeyInfo(indexStruct,
|
||||||
&numKeyAtts,
|
&numKeyAtts,
|
||||||
&indexKeyAtts,
|
&indexKeyAtts,
|
||||||
@ -844,6 +843,8 @@ ExecOpenIndices(Oid resultRelationOid,
|
|||||||
*/
|
*/
|
||||||
if (VARSIZE(&indexStruct->indpred) != 0)
|
if (VARSIZE(&indexStruct->indpred) != 0)
|
||||||
{
|
{
|
||||||
|
char *predString;
|
||||||
|
|
||||||
predString = textout(&indexStruct->indpred);
|
predString = textout(&indexStruct->indpred);
|
||||||
predicate = (PredInfo *) stringToNode(predString);
|
predicate = (PredInfo *) stringToNode(predString);
|
||||||
pfree(predString);
|
pfree(predString);
|
||||||
@ -851,152 +852,21 @@ ExecOpenIndices(Oid resultRelationOid,
|
|||||||
else
|
else
|
||||||
predicate = NULL;
|
predicate = NULL;
|
||||||
|
|
||||||
/* ----------------
|
/* Save the index info */
|
||||||
* save the index information into lists
|
ii = makeNode(IndexInfo);
|
||||||
* ----------------
|
ii->ii_NumKeyAttributes = numKeyAtts;
|
||||||
*/
|
ii->ii_KeyAttributeNumbers = indexKeyAtts;
|
||||||
oidList = lconsi(indexOid, oidList);
|
ii->ii_FuncIndexInfo = fInfoP;
|
||||||
nkeyList = lconsi(numKeyAtts, nkeyList);
|
ii->ii_Predicate = (Node *) predicate;
|
||||||
keyList = lcons(indexKeyAtts, keyList);
|
|
||||||
fiList = lcons(fInfoP, fiList);
|
|
||||||
predList = lcons(predicate, predList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------
|
heap_freetuple(indexTuple);
|
||||||
* we have the info we need so close the pg_index relation..
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
heap_endscan(indexSd);
|
|
||||||
heap_close(indexRd, AccessShareLock);
|
|
||||||
|
|
||||||
/* ----------------
|
relationDescs[i] = indexDesc;
|
||||||
* Now that we've collected the index information into three
|
|
||||||
* lists, we open the index relations and store the descriptors
|
|
||||||
* and the key information into arrays.
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
len = length(oidList);
|
|
||||||
if (len > 0)
|
|
||||||
{
|
|
||||||
/* ----------------
|
|
||||||
* allocate space for relation descs
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext);
|
|
||||||
relationDescs = (RelationPtr)
|
|
||||||
palloc(len * sizeof(Relation));
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* initialize index info array
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext);
|
|
||||||
indexInfoArray = (IndexInfo **)
|
|
||||||
palloc(len * sizeof(IndexInfo *));
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
IndexInfo *ii = makeNode(IndexInfo);
|
|
||||||
|
|
||||||
ii->ii_NumKeyAttributes = 0;
|
|
||||||
ii->ii_KeyAttributeNumbers = (AttrNumber *) NULL;
|
|
||||||
ii->ii_FuncIndexInfo = (FuncIndexInfoPtr) NULL;
|
|
||||||
ii->ii_Predicate = NULL;
|
|
||||||
indexInfoArray[i] = ii;
|
indexInfoArray[i] = ii;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
freeList(indexoidlist);
|
||||||
* attempt to open each of the indices. If we succeed,
|
|
||||||
* then store the index relation descriptor into the
|
|
||||||
* relation descriptor array.
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
i = 0;
|
|
||||||
foreach(indexoid, oidList)
|
|
||||||
{
|
|
||||||
Relation indexDesc;
|
|
||||||
|
|
||||||
indexOid = lfirsti(indexoid);
|
|
||||||
indexDesc = index_open(indexOid);
|
|
||||||
if (indexDesc != NULL)
|
|
||||||
{
|
|
||||||
relationDescs[i++] = indexDesc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Hack for not btree and hash indices: they use relation
|
|
||||||
* level exclusive locking on update (i.e. - they are not
|
|
||||||
* ready for MVCC) and so we have to exclusively lock
|
|
||||||
* indices here to prevent deadlocks if we will scan them
|
|
||||||
* - index_beginscan places AccessShareLock, indices
|
|
||||||
* update methods don't use locks at all. We release this
|
|
||||||
* lock in ExecCloseIndices. Note, that hashes use page
|
|
||||||
* level locking - i.e. are not deadlock-free, - let's
|
|
||||||
* them be on their way -:)) vadim 03-12-1998
|
|
||||||
*/
|
|
||||||
if (indexDesc->rd_rel->relam != BTREE_AM_OID &&
|
|
||||||
indexDesc->rd_rel->relam != HASH_AM_OID)
|
|
||||||
LockRelation(indexDesc, AccessExclusiveLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* store the relation descriptor array and number of
|
|
||||||
* descs into the result relation info.
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
resultRelationInfo->ri_NumIndices = i;
|
|
||||||
resultRelationInfo->ri_IndexRelationDescs = relationDescs;
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* store the index key information collected in our
|
|
||||||
* lists into the index info array
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
i = 0;
|
|
||||||
foreach(numkeys, nkeyList)
|
|
||||||
{
|
|
||||||
numKeyAtts = lfirsti(numkeys);
|
|
||||||
indexInfoArray[i++]->ii_NumKeyAttributes = numKeyAtts;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
foreach(indexkeys, keyList)
|
|
||||||
{
|
|
||||||
indexKeyAtts = (AttrNumber *) lfirst(indexkeys);
|
|
||||||
indexInfoArray[i++]->ii_KeyAttributeNumbers = indexKeyAtts;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
foreach(indexfuncs, fiList)
|
|
||||||
{
|
|
||||||
FuncIndexInfoPtr fiP = (FuncIndexInfoPtr) lfirst(indexfuncs);
|
|
||||||
|
|
||||||
indexInfoArray[i++]->ii_FuncIndexInfo = fiP;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
foreach(indexpreds, predList)
|
|
||||||
indexInfoArray[i++]->ii_Predicate = lfirst(indexpreds);
|
|
||||||
/* ----------------
|
|
||||||
* store the index info array into relation info
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
resultRelationInfo->ri_IndexRelationInfo = indexInfoArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* All done, resultRelationInfo now contains complete information
|
|
||||||
* on the indices associated with the result relation.
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* should free oidList, nkeyList and keyList here */
|
|
||||||
/* OK - let's do it -jolly */
|
|
||||||
freeList(oidList);
|
|
||||||
freeList(nkeyList);
|
|
||||||
freeList(keyList);
|
|
||||||
freeList(fiList);
|
|
||||||
freeList(predList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
@ -1035,91 +905,6 @@ ExecCloseIndices(RelationInfo *resultRelationInfo)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
|
||||||
* ExecFormIndexTuple
|
|
||||||
*
|
|
||||||
* Most of this code is cannabilized from DefaultBuild().
|
|
||||||
* As said in the comments for ExecOpenIndices, most of
|
|
||||||
* this functionality should be rearranged into a proper
|
|
||||||
* set of routines..
|
|
||||||
* ----------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
#ifdef NOT_USED
|
|
||||||
IndexTuple
|
|
||||||
ExecFormIndexTuple(HeapTuple heapTuple,
|
|
||||||
Relation heapRelation,
|
|
||||||
Relation indexRelation,
|
|
||||||
IndexInfo *indexInfo)
|
|
||||||
{
|
|
||||||
IndexTuple indexTuple;
|
|
||||||
TupleDesc heapDescriptor;
|
|
||||||
TupleDesc indexDescriptor;
|
|
||||||
Datum *datum;
|
|
||||||
char *nulls;
|
|
||||||
|
|
||||||
int numberOfAttributes;
|
|
||||||
AttrNumber *keyAttributeNumbers;
|
|
||||||
FuncIndexInfoPtr fInfoP;
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* get information from index info structure
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
numberOfAttributes = indexInfo->ii_NumKeyAttributes;
|
|
||||||
keyAttributeNumbers = indexInfo->ii_KeyAttributeNumbers;
|
|
||||||
fInfoP = indexInfo->ii_FuncIndexInfo;
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* datum and null are arrays in which we collect the index attributes
|
|
||||||
* when forming a new index tuple.
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
CXT1_printf("ExecFormIndexTuple: context is %d\n", CurrentMemoryContext);
|
|
||||||
datum = (Datum *) palloc(numberOfAttributes * sizeof *datum);
|
|
||||||
nulls = (char *) palloc(numberOfAttributes * sizeof *nulls);
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* get the tuple descriptors from the relations so we know
|
|
||||||
* how to form the index tuples..
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
heapDescriptor = RelationGetDescr(heapRelation);
|
|
||||||
indexDescriptor = RelationGetDescr(indexRelation);
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* FormIndexDatum fills in its datum and null parameters
|
|
||||||
* with attribute information taken from the given heap tuple.
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
FormIndexDatum(numberOfAttributes, /* num attributes */
|
|
||||||
keyAttributeNumbers, /* array of att nums to extract */
|
|
||||||
heapTuple, /* tuple from base relation */
|
|
||||||
heapDescriptor, /* heap tuple's descriptor */
|
|
||||||
datum, /* return: array of attributes */
|
|
||||||
nulls, /* return: array of char's */
|
|
||||||
fInfoP); /* functional index information */
|
|
||||||
|
|
||||||
indexTuple = index_formtuple(indexDescriptor,
|
|
||||||
datum,
|
|
||||||
nulls);
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* free temporary arrays
|
|
||||||
*
|
|
||||||
* XXX should store these in the IndexInfo instead of allocating
|
|
||||||
* and freeing on every insertion, but efficency here is not
|
|
||||||
* that important and FormIndexTuple is wasteful anyways..
|
|
||||||
* -cim 9/27/89
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
pfree(nulls);
|
|
||||||
pfree(datum);
|
|
||||||
|
|
||||||
return indexTuple;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* ExecInsertIndexTuples
|
* ExecInsertIndexTuples
|
||||||
*
|
*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.33 2000/06/15 04:09:52 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.34 2000/06/17 21:48:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -285,7 +285,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
|
|||||||
* indices, but how to tell that here?
|
* indices, but how to tell that here?
|
||||||
*/
|
*/
|
||||||
if (rri->ri_RelationDesc->rd_rel->relhasindex)
|
if (rri->ri_RelationDesc->rd_rel->relhasindex)
|
||||||
ExecOpenIndices(reloid, rri);
|
ExecOpenIndices(rri);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -9,11 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
<<<<<<< plancat.c
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.57 2000/06/17 21:48:51 tgl Exp $
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.56 2000/06/15 03:32:16 momjian Exp $
|
|
||||||
=======
|
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.56 2000/06/15 03:32:16 momjian Exp $
|
|
||||||
>>>>>>> 1.53
|
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -32,6 +28,7 @@
|
|||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
|
#include "utils/relcache.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "catalog/catalog.h"
|
#include "catalog/catalog.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
@ -81,33 +78,40 @@ relation_info(Query *root, Index relid,
|
|||||||
List *
|
List *
|
||||||
find_secondary_indexes(Query *root, Index relid)
|
find_secondary_indexes(Query *root, Index relid)
|
||||||
{
|
{
|
||||||
List *indexes = NIL;
|
List *indexinfos = NIL;
|
||||||
|
List *indexoidlist,
|
||||||
|
*indexoidscan;
|
||||||
Oid indrelid = getrelid(relid, root->rtable);
|
Oid indrelid = getrelid(relid, root->rtable);
|
||||||
Relation relation;
|
Relation relation;
|
||||||
HeapScanDesc scan;
|
|
||||||
ScanKeyData indexKey;
|
|
||||||
HeapTuple indexTuple;
|
|
||||||
|
|
||||||
/* Scan pg_index for tuples describing indexes of this rel */
|
/*
|
||||||
relation = heap_openr(IndexRelationName, AccessShareLock);
|
* We used to scan pg_index directly, but now the relcache offers
|
||||||
|
* a cached list of OID indexes for each relation. So, get that list
|
||||||
|
* and then use the syscache to obtain pg_index entries.
|
||||||
|
*/
|
||||||
|
relation = heap_open(indrelid, AccessShareLock);
|
||||||
|
indexoidlist = RelationGetIndexList(relation);
|
||||||
|
|
||||||
ScanKeyEntryInitialize(&indexKey, 0,
|
foreach(indexoidscan, indexoidlist)
|
||||||
Anum_pg_index_indrelid,
|
|
||||||
F_OIDEQ,
|
|
||||||
ObjectIdGetDatum(indrelid));
|
|
||||||
|
|
||||||
scan = heap_beginscan(relation, 0, SnapshotNow,
|
|
||||||
1, &indexKey);
|
|
||||||
|
|
||||||
while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
|
|
||||||
{
|
{
|
||||||
Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple);
|
Oid indexoid = lfirsti(indexoidscan);
|
||||||
IndexOptInfo *info = makeNode(IndexOptInfo);
|
HeapTuple indexTuple;
|
||||||
|
Form_pg_index index;
|
||||||
|
IndexOptInfo *info;
|
||||||
int i;
|
int i;
|
||||||
Relation indexRelation;
|
Relation indexRelation;
|
||||||
Oid relam;
|
Oid relam;
|
||||||
uint16 amorderstrategy;
|
uint16 amorderstrategy;
|
||||||
|
|
||||||
|
indexTuple = SearchSysCacheTupleCopy(INDEXRELID,
|
||||||
|
ObjectIdGetDatum(indexoid),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(indexTuple))
|
||||||
|
elog(ERROR, "find_secondary_indexes: index %u not found",
|
||||||
|
indexoid);
|
||||||
|
index = (Form_pg_index) GETSTRUCT(indexTuple);
|
||||||
|
info = makeNode(IndexOptInfo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Need to make these arrays large enough to be sure there is a
|
* Need to make these arrays large enough to be sure there is a
|
||||||
* terminating 0 at the end of each one.
|
* terminating 0 at the end of each one.
|
||||||
@ -172,13 +176,17 @@ find_secondary_indexes(Query *root, Index relid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
indexes = lcons(info, indexes);
|
heap_freetuple(indexTuple);
|
||||||
|
|
||||||
|
indexinfos = lcons(info, indexinfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_endscan(scan);
|
freeList(indexoidlist);
|
||||||
|
|
||||||
|
/* XXX keep the lock here? */
|
||||||
heap_close(relation, AccessShareLock);
|
heap_close(relation, AccessShareLock);
|
||||||
|
|
||||||
return indexes;
|
return indexinfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: analyze.c,v 1.147 2000/06/12 19:40:40 momjian Exp $
|
* $Id: analyze.c,v 1.148 2000/06/17 21:48:40 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -27,6 +27,8 @@
|
|||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
|
#include "utils/relcache.h"
|
||||||
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
void CheckSelectForUpdate(Query *qry); /* no points for style... */
|
void CheckSelectForUpdate(Query *qry); /* no points for style... */
|
||||||
|
|
||||||
@ -2003,13 +2005,9 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint)
|
|||||||
{
|
{
|
||||||
Relation pkrel;
|
Relation pkrel;
|
||||||
Form_pg_attribute *pkrel_attrs;
|
Form_pg_attribute *pkrel_attrs;
|
||||||
Relation indexRd;
|
List *indexoidlist,
|
||||||
HeapScanDesc indexSd;
|
*indexoidscan;
|
||||||
ScanKeyData key;
|
|
||||||
HeapTuple indexTup;
|
|
||||||
Form_pg_index indexStruct = NULL;
|
Form_pg_index indexStruct = NULL;
|
||||||
Ident *pkattr;
|
|
||||||
int pkattno;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
@ -2023,37 +2021,37 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint)
|
|||||||
pkrel_attrs = pkrel->rd_att->attrs;
|
pkrel_attrs = pkrel->rd_att->attrs;
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Open pg_index and begin a scan for all indices defined on
|
* Get the list of index OIDs for the table from the relcache,
|
||||||
* the referenced table
|
* and look up each one in the pg_index syscache until we find one
|
||||||
|
* marked primary key (hopefully there isn't more than one such).
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
indexRd = heap_openr(IndexRelationName, AccessShareLock);
|
indexoidlist = RelationGetIndexList(pkrel);
|
||||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_index_indrelid,
|
|
||||||
F_OIDEQ,
|
|
||||||
ObjectIdGetDatum(pkrel->rd_id));
|
|
||||||
indexSd = heap_beginscan(indexRd, /* scan desc */
|
|
||||||
false, /* scan backward flag */
|
|
||||||
SnapshotNow, /* NOW snapshot */
|
|
||||||
1, /* number scan keys */
|
|
||||||
&key); /* scan keys */
|
|
||||||
|
|
||||||
/* ----------
|
foreach(indexoidscan, indexoidlist)
|
||||||
* Fetch the index with indisprimary == true
|
|
||||||
* ----------
|
|
||||||
*/
|
|
||||||
while (HeapTupleIsValid(indexTup = heap_getnext(indexSd, 0)))
|
|
||||||
{
|
{
|
||||||
indexStruct = (Form_pg_index) GETSTRUCT(indexTup);
|
Oid indexoid = lfirsti(indexoidscan);
|
||||||
|
HeapTuple indexTuple;
|
||||||
|
|
||||||
|
indexTuple = SearchSysCacheTuple(INDEXRELID,
|
||||||
|
ObjectIdGetDatum(indexoid),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(indexTuple))
|
||||||
|
elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found",
|
||||||
|
indexoid);
|
||||||
|
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
|
||||||
if (indexStruct->indisprimary)
|
if (indexStruct->indisprimary)
|
||||||
break;
|
break;
|
||||||
|
indexStruct = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
freeList(indexoidlist);
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Check that we found it
|
* Check that we found it
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
if (!HeapTupleIsValid(indexTup))
|
if (indexStruct == NULL)
|
||||||
elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
|
elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
|
||||||
fkconstraint->pktable_name);
|
fkconstraint->pktable_name);
|
||||||
|
|
||||||
@ -2064,8 +2062,9 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint)
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
|
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
|
||||||
{
|
{
|
||||||
pkattno = indexStruct->indkey[i];
|
int pkattno = indexStruct->indkey[i];
|
||||||
pkattr = (Ident *) makeNode(Ident);
|
Ident *pkattr = makeNode(Ident);
|
||||||
|
|
||||||
pkattr->name = nameout(&(pkrel_attrs[pkattno - 1]->attname));
|
pkattr->name = nameout(&(pkrel_attrs[pkattno - 1]->attname));
|
||||||
pkattr->indirection = NIL;
|
pkattr->indirection = NIL;
|
||||||
pkattr->isRel = false;
|
pkattr->isRel = false;
|
||||||
@ -2073,12 +2072,6 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint)
|
|||||||
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
|
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
|
||||||
* End index scan and close relations
|
|
||||||
* ----------
|
|
||||||
*/
|
|
||||||
heap_endscan(indexSd);
|
|
||||||
heap_close(indexRd, AccessShareLock);
|
|
||||||
heap_close(pkrel, AccessShareLock);
|
heap_close(pkrel, AccessShareLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
134
src/backend/utils/cache/relcache.c
vendored
134
src/backend/utils/cache/relcache.c
vendored
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.100 2000/06/17 04:56:32 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.101 2000/06/17 21:48:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -46,6 +46,7 @@
|
|||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "catalog/indexing.h"
|
#include "catalog/indexing.h"
|
||||||
#include "catalog/pg_attrdef.h"
|
#include "catalog/pg_attrdef.h"
|
||||||
|
#include "catalog/pg_index.h"
|
||||||
#include "catalog/pg_log.h"
|
#include "catalog/pg_log.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_relcheck.h"
|
#include "catalog/pg_relcheck.h"
|
||||||
@ -1063,16 +1064,14 @@ formrdesc(char *relationName,
|
|||||||
FormData_pg_attribute *att)
|
FormData_pg_attribute *att)
|
||||||
{
|
{
|
||||||
Relation relation;
|
Relation relation;
|
||||||
Size len;
|
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* allocate new relation desc
|
* allocate new relation desc
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
len = sizeof(RelationData);
|
relation = (Relation) palloc(sizeof(RelationData));
|
||||||
relation = (Relation) palloc(len);
|
MemSet((char *) relation, 0, sizeof(RelationData));
|
||||||
MemSet((char *) relation, 0, len);
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* don't open the unix file yet..
|
* don't open the unix file yet..
|
||||||
@ -1090,9 +1089,8 @@ formrdesc(char *relationName,
|
|||||||
* initialize relation tuple form
|
* initialize relation tuple form
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
relation->rd_rel = (Form_pg_class)
|
relation->rd_rel = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
|
||||||
palloc((Size) (sizeof(*relation->rd_rel)));
|
MemSet(relation->rd_rel, 0, CLASS_TUPLE_SIZE);
|
||||||
MemSet(relation->rd_rel, 0, sizeof(FormData_pg_class));
|
|
||||||
strcpy(RelationGetPhysicalRelationName(relation), relationName);
|
strcpy(RelationGetPhysicalRelationName(relation), relationName);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -1414,6 +1412,7 @@ RelationClearRelation(Relation relation, bool rebuildIt)
|
|||||||
pfree(relation->rd_istrat);
|
pfree(relation->rd_istrat);
|
||||||
if (relation->rd_support)
|
if (relation->rd_support)
|
||||||
pfree(relation->rd_support);
|
pfree(relation->rd_support);
|
||||||
|
freeList(relation->rd_indexlist);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're really done with the relcache entry, blow it away. But if
|
* If we're really done with the relcache entry, blow it away. But if
|
||||||
@ -2075,6 +2074,125 @@ RelCheckFetch(Relation relation)
|
|||||||
heap_close(rcrel, AccessShareLock);
|
heap_close(rcrel, AccessShareLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RelationGetIndexList -- get a list of OIDs of indexes on this relation
|
||||||
|
*
|
||||||
|
* The index list is created only if someone requests it. We scan pg_index
|
||||||
|
* to find relevant indexes, and add the list to the relcache entry so that
|
||||||
|
* we won't have to compute it again. Note that shared cache inval of a
|
||||||
|
* relcache entry will delete the old list and set rd_indexfound to false,
|
||||||
|
* so that we must recompute the index list on next request. This handles
|
||||||
|
* creation or deletion of an index.
|
||||||
|
*
|
||||||
|
* Since shared cache inval causes the relcache's copy of the list to go away,
|
||||||
|
* we return a copy of the list palloc'd in the caller's context. The caller
|
||||||
|
* may freeList() the returned list after scanning it. This is necessary
|
||||||
|
* since the caller will typically be doing syscache lookups on the relevant
|
||||||
|
* indexes, and syscache lookup could cause SI messages to be processed!
|
||||||
|
*/
|
||||||
|
List *
|
||||||
|
RelationGetIndexList(Relation relation)
|
||||||
|
{
|
||||||
|
Relation indrel;
|
||||||
|
Relation irel = (Relation) NULL;
|
||||||
|
ScanKeyData skey;
|
||||||
|
IndexScanDesc sd = (IndexScanDesc) NULL;
|
||||||
|
HeapScanDesc hscan = (HeapScanDesc) NULL;
|
||||||
|
bool hasindex;
|
||||||
|
List *result;
|
||||||
|
MemoryContext oldcxt;
|
||||||
|
|
||||||
|
/* Quick exit if we already computed the list. */
|
||||||
|
if (relation->rd_indexfound)
|
||||||
|
return listCopy(relation->rd_indexlist);
|
||||||
|
|
||||||
|
/* Prepare to scan pg_index for entries having indrelid = this rel. */
|
||||||
|
indrel = heap_openr(IndexRelationName, AccessShareLock);
|
||||||
|
hasindex = (indrel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
|
||||||
|
if (hasindex)
|
||||||
|
{
|
||||||
|
irel = index_openr(IndexIndrelidIndex);
|
||||||
|
ScanKeyEntryInitialize(&skey,
|
||||||
|
(bits16) 0x0,
|
||||||
|
(AttrNumber) 1,
|
||||||
|
(RegProcedure) F_OIDEQ,
|
||||||
|
ObjectIdGetDatum(RelationGetRelid(relation)));
|
||||||
|
sd = index_beginscan(irel, false, 1, &skey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScanKeyEntryInitialize(&skey,
|
||||||
|
(bits16) 0x0,
|
||||||
|
(AttrNumber) Anum_pg_index_indrelid,
|
||||||
|
(RegProcedure) F_OIDEQ,
|
||||||
|
ObjectIdGetDatum(RelationGetRelid(relation)));
|
||||||
|
hscan = heap_beginscan(indrel, false, SnapshotNow, 1, &skey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We build the list we intend to return (in the caller's context) while
|
||||||
|
* doing the scan. After successfully completing the scan, we copy that
|
||||||
|
* list into the relcache entry. This avoids cache-context memory leakage
|
||||||
|
* if we get some sort of error partway through.
|
||||||
|
*/
|
||||||
|
result = NIL;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
HeapTupleData tuple;
|
||||||
|
HeapTuple htup;
|
||||||
|
Buffer buffer;
|
||||||
|
Form_pg_index index;
|
||||||
|
|
||||||
|
if (hasindex)
|
||||||
|
{
|
||||||
|
RetrieveIndexResult indexRes;
|
||||||
|
|
||||||
|
indexRes = index_getnext(sd, ForwardScanDirection);
|
||||||
|
if (!indexRes)
|
||||||
|
break;
|
||||||
|
tuple.t_self = indexRes->heap_iptr;
|
||||||
|
tuple.t_datamcxt = NULL;
|
||||||
|
tuple.t_data = NULL;
|
||||||
|
heap_fetch(indrel, SnapshotNow, &tuple, &buffer);
|
||||||
|
pfree(indexRes);
|
||||||
|
if (tuple.t_data == NULL)
|
||||||
|
continue;
|
||||||
|
htup = &tuple;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
htup = heap_getnext(hscan, 0);
|
||||||
|
if (!HeapTupleIsValid(htup))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = (Form_pg_index) GETSTRUCT(htup);
|
||||||
|
|
||||||
|
result = lappendi(result, index->indexrelid);
|
||||||
|
|
||||||
|
if (hasindex)
|
||||||
|
ReleaseBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasindex)
|
||||||
|
{
|
||||||
|
index_endscan(sd);
|
||||||
|
index_close(irel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
heap_endscan(hscan);
|
||||||
|
heap_close(indrel, AccessShareLock);
|
||||||
|
|
||||||
|
/* Now we can save the completed list in the relcache entry. */
|
||||||
|
oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
|
||||||
|
relation->rd_indexlist = listCopy(result);
|
||||||
|
relation->rd_indexfound = true;
|
||||||
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* init_irels(), write_irels() -- handle special-case initialization of
|
* init_irels(), write_irels() -- handle special-case initialization of
|
||||||
* index relation descriptors.
|
* index relation descriptors.
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: executor.h,v 1.43 2000/05/29 01:59:11 tgl Exp $
|
* $Id: executor.h,v 1.44 2000/06/17 21:48:56 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -142,8 +142,7 @@ extern void ExecAssignScanTypeFromOuterPlan(Plan *node,
|
|||||||
CommonScanState *csstate);
|
CommonScanState *csstate);
|
||||||
extern Form_pg_attribute ExecGetTypeInfo(Relation relDesc);
|
extern Form_pg_attribute ExecGetTypeInfo(Relation relDesc);
|
||||||
|
|
||||||
extern void ExecOpenIndices(Oid resultRelationOid,
|
extern void ExecOpenIndices(RelationInfo *resultRelationInfo);
|
||||||
RelationInfo *resultRelationInfo);
|
|
||||||
extern void ExecCloseIndices(RelationInfo *resultRelationInfo);
|
extern void ExecCloseIndices(RelationInfo *resultRelationInfo);
|
||||||
extern void ExecInsertIndexTuples(TupleTableSlot *slot, ItemPointer tupleid,
|
extern void ExecInsertIndexTuples(TupleTableSlot *slot, ItemPointer tupleid,
|
||||||
EState *estate, bool is_update);
|
EState *estate, bool is_update);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: rel.h,v 1.36 2000/04/12 17:16:55 momjian Exp $
|
* $Id: rel.h,v 1.37 2000/06/17 21:49:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -92,14 +92,15 @@ typedef struct RelationData
|
|||||||
bool rd_isnailed; /* rel is nailed in cache */
|
bool rd_isnailed; /* rel is nailed in cache */
|
||||||
bool rd_isnoname; /* rel has no name */
|
bool rd_isnoname; /* rel has no name */
|
||||||
bool rd_unlinked; /* rel already unlinked or not created yet */
|
bool rd_unlinked; /* rel already unlinked or not created yet */
|
||||||
|
bool rd_indexfound; /* true if rd_indexlist is valid */
|
||||||
Form_pg_am rd_am; /* AM tuple */
|
Form_pg_am rd_am; /* AM tuple */
|
||||||
Form_pg_class rd_rel; /* RELATION tuple */
|
Form_pg_class rd_rel; /* RELATION tuple */
|
||||||
Oid rd_id; /* relation's object id */
|
Oid rd_id; /* relation's object id */
|
||||||
LockInfoData rd_lockInfo; /* lock manager's info for locking
|
List *rd_indexlist; /* list of OIDs of indexes on relation */
|
||||||
* relation */
|
LockInfoData rd_lockInfo; /* lock mgr's info for locking relation */
|
||||||
TupleDesc rd_att; /* tuple descriptor */
|
TupleDesc rd_att; /* tuple descriptor */
|
||||||
RuleLock *rd_rules; /* rewrite rules */
|
RuleLock *rd_rules; /* rewrite rules */
|
||||||
IndexStrategy rd_istrat;
|
IndexStrategy rd_istrat; /* info needed if rel is an index */
|
||||||
RegProcedure *rd_support;
|
RegProcedure *rd_support;
|
||||||
TriggerDesc *trigdesc; /* Trigger info, or NULL if rel has none */
|
TriggerDesc *trigdesc; /* Trigger info, or NULL if rel has none */
|
||||||
} RelationData;
|
} RelationData;
|
||||||
@ -138,13 +139,15 @@ typedef Relation *RelationPtr;
|
|||||||
* RelationSetReferenceCount
|
* RelationSetReferenceCount
|
||||||
* Sets relation reference count.
|
* Sets relation reference count.
|
||||||
*/
|
*/
|
||||||
#define RelationSetReferenceCount(relation,count) ((relation)->rd_refcnt = (count))
|
#define RelationSetReferenceCount(relation,count) \
|
||||||
|
((relation)->rd_refcnt = (count))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RelationIncrementReferenceCount
|
* RelationIncrementReferenceCount
|
||||||
* Increments relation reference count.
|
* Increments relation reference count.
|
||||||
*/
|
*/
|
||||||
#define RelationIncrementReferenceCount(relation) ((relation)->rd_refcnt += 1)
|
#define RelationIncrementReferenceCount(relation) \
|
||||||
|
((relation)->rd_refcnt += 1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RelationDecrementReferenceCount
|
* RelationDecrementReferenceCount
|
||||||
@ -199,7 +202,8 @@ typedef Relation *RelationPtr;
|
|||||||
*
|
*
|
||||||
* Returns a Relation Name
|
* Returns a Relation Name
|
||||||
*/
|
*/
|
||||||
#define RelationGetPhysicalRelationName(relation) (NameStr((relation)->rd_rel->relname))
|
#define RelationGetPhysicalRelationName(relation) \
|
||||||
|
(NameStr((relation)->rd_rel->relname))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RelationGetNumberOfAttributes
|
* RelationGetNumberOfAttributes
|
||||||
@ -224,7 +228,9 @@ typedef Relation *RelationPtr;
|
|||||||
*/
|
*/
|
||||||
#define RelationGetIndexStrategy(relation) ((relation)->rd_istrat)
|
#define RelationGetIndexStrategy(relation) ((relation)->rd_istrat)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Routines in utils/cache/rel.c
|
||||||
|
*/
|
||||||
extern void RelationSetIndexSupport(Relation relation,
|
extern void RelationSetIndexSupport(Relation relation,
|
||||||
IndexStrategy strategy,
|
IndexStrategy strategy,
|
||||||
RegProcedure *support);
|
RegProcedure *support);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: relcache.h,v 1.19 2000/01/31 04:35:57 tgl Exp $
|
* $Id: relcache.h,v 1.20 2000/06/17 21:49:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -19,13 +19,20 @@
|
|||||||
/*
|
/*
|
||||||
* relation lookup routines
|
* relation lookup routines
|
||||||
*/
|
*/
|
||||||
extern Relation RelationIdCacheGetRelation(Oid relationId);
|
|
||||||
extern Relation RelationIdGetRelation(Oid relationId);
|
extern Relation RelationIdGetRelation(Oid relationId);
|
||||||
extern Relation RelationNameGetRelation(const char *relationName);
|
extern Relation RelationNameGetRelation(const char *relationName);
|
||||||
|
|
||||||
|
/* finds an existing cache entry, but won't make a new one */
|
||||||
|
extern Relation RelationIdCacheGetRelation(Oid relationId);
|
||||||
|
|
||||||
extern void RelationClose(Relation relation);
|
extern void RelationClose(Relation relation);
|
||||||
extern void RelationForgetRelation(Oid rid);
|
extern void RelationForgetRelation(Oid rid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Routines to compute/retrieve additional cached information
|
||||||
|
*/
|
||||||
|
extern List *RelationGetIndexList(Relation relation);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines for flushing/rebuilding relcache entries in various scenarios
|
* Routines for flushing/rebuilding relcache entries in various scenarios
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user