Implement reindex command
This commit is contained in:
parent
e3befe4a66
commit
e3a97b370c
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.40 2000/01/26 05:55:57 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.41 2000/02/18 09:29:16 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -477,8 +477,9 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
|
||||||
{
|
{
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
HeapScanDesc scan = NULL;
|
HeapScanDesc scan = NULL;
|
||||||
|
bool cachesearch = (!IsBootstrapProcessingMode()) && IsCacheInitialized();
|
||||||
|
|
||||||
if (!IsBootstrapProcessingMode())
|
if (cachesearch)
|
||||||
{
|
{
|
||||||
tuple = SearchSysCacheTuple(OPEROID,
|
tuple = SearchSysCacheTuple(OPEROID,
|
||||||
ObjectIdGetDatum(operatorObjectId),
|
ObjectIdGetDatum(operatorObjectId),
|
||||||
|
@ -501,7 +502,7 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
|
||||||
|
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
{
|
{
|
||||||
if (IsBootstrapProcessingMode())
|
if (!cachesearch)
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
elog(ERROR, "OperatorObjectIdFillScanKeyEntry: unknown operator %u",
|
elog(ERROR, "OperatorObjectIdFillScanKeyEntry: unknown operator %u",
|
||||||
operatorObjectId);
|
operatorObjectId);
|
||||||
|
@ -512,7 +513,7 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
|
||||||
fmgr_info(entry->sk_procedure, &entry->sk_func);
|
fmgr_info(entry->sk_procedure, &entry->sk_func);
|
||||||
entry->sk_nargs = entry->sk_func.fn_nargs;
|
entry->sk_nargs = entry->sk_func.fn_nargs;
|
||||||
|
|
||||||
if (IsBootstrapProcessingMode())
|
if (!cachesearch)
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
|
|
||||||
if (!RegProcedureIsValid(entry->sk_procedure))
|
if (!RegProcedureIsValid(entry->sk_procedure))
|
||||||
|
@ -546,8 +547,9 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
|
||||||
AttrNumber attributeNumber;
|
AttrNumber attributeNumber;
|
||||||
int attributeIndex;
|
int attributeIndex;
|
||||||
Oid operatorClassObjectId[INDEX_MAX_KEYS];
|
Oid operatorClassObjectId[INDEX_MAX_KEYS];
|
||||||
|
bool cachesearch = (!IsBootstrapProcessingMode()) && IsCacheInitialized();
|
||||||
|
|
||||||
if (!IsBootstrapProcessingMode())
|
if (cachesearch)
|
||||||
{
|
{
|
||||||
tuple = SearchSysCacheTuple(INDEXRELID,
|
tuple = SearchSysCacheTuple(INDEXRELID,
|
||||||
ObjectIdGetDatum(indexObjectId),
|
ObjectIdGetDatum(indexObjectId),
|
||||||
|
@ -589,7 +591,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
|
||||||
operatorClassObjectId[attributeIndex] = iform->indclass[attributeIndex];
|
operatorClassObjectId[attributeIndex] = iform->indclass[attributeIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsBootstrapProcessingMode())
|
if (!cachesearch)
|
||||||
{
|
{
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
heap_close(relation, AccessShareLock);
|
heap_close(relation, AccessShareLock);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.52 2000/01/26 05:55:58 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.53 2000/02/18 09:29:54 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -310,16 +310,22 @@ btbuild(Relation heap,
|
||||||
{
|
{
|
||||||
Oid hrelid = RelationGetRelid(heap);
|
Oid hrelid = RelationGetRelid(heap);
|
||||||
Oid irelid = RelationGetRelid(index);
|
Oid irelid = RelationGetRelid(index);
|
||||||
|
bool inplace = IsReindexProcessing();
|
||||||
|
|
||||||
heap_close(heap, NoLock);
|
heap_close(heap, NoLock);
|
||||||
index_close(index);
|
index_close(index);
|
||||||
|
/*
|
||||||
UpdateStats(hrelid, nhtups, true);
|
UpdateStats(hrelid, nhtups, true);
|
||||||
UpdateStats(irelid, nitups, false);
|
UpdateStats(irelid, nitups, false);
|
||||||
|
*/
|
||||||
|
UpdateStats(hrelid, nhtups, inplace);
|
||||||
|
UpdateStats(irelid, nitups, inplace);
|
||||||
if (oldPred != NULL)
|
if (oldPred != NULL)
|
||||||
{
|
{
|
||||||
if (nitups == nhtups)
|
if (nitups == nhtups)
|
||||||
pred = NULL;
|
pred = NULL;
|
||||||
UpdateIndexPredicate(irelid, oldPred, pred);
|
if (!inplace)
|
||||||
|
UpdateIndexPredicate(irelid, oldPred, pred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.60 2000/01/29 16:58:29 petere Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.61 2000/02/18 09:30:20 inoue Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Transaction aborts can now occur two ways:
|
* Transaction aborts can now occur two ways:
|
||||||
|
@ -147,6 +147,7 @@
|
||||||
|
|
||||||
#include "access/nbtree.h"
|
#include "access/nbtree.h"
|
||||||
#include "catalog/heap.h"
|
#include "catalog/heap.h"
|
||||||
|
#include "catalog/index.h"
|
||||||
#include "commands/async.h"
|
#include "commands/async.h"
|
||||||
#include "commands/sequence.h"
|
#include "commands/sequence.h"
|
||||||
#include "commands/vacuum.h"
|
#include "commands/vacuum.h"
|
||||||
|
@ -850,6 +851,7 @@ StartTransaction()
|
||||||
*/
|
*/
|
||||||
s->state = TRANS_START;
|
s->state = TRANS_START;
|
||||||
|
|
||||||
|
SetReindexProcessing(false);
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* generate a new transaction id
|
* generate a new transaction id
|
||||||
* ----------------
|
* ----------------
|
||||||
|
@ -1046,8 +1048,8 @@ AbortTransaction()
|
||||||
AtAbort_Notify();
|
AtAbort_Notify();
|
||||||
CloseSequences();
|
CloseSequences();
|
||||||
AtEOXact_portals();
|
AtEOXact_portals();
|
||||||
if (VacuumRunning)
|
if (CommonSpecialPortalIsOpen())
|
||||||
vc_abort();
|
CommonSpecialPortalClose();
|
||||||
RecordTransactionAbort();
|
RecordTransactionAbort();
|
||||||
RelationPurgeLocalRelation(false);
|
RelationPurgeLocalRelation(false);
|
||||||
DropNoNameRels();
|
DropNoNameRels();
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.79 2000/01/26 05:56:07 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.80 2000/02/18 09:28:39 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -292,6 +292,7 @@ BootstrapMain(int argc, char *argv[])
|
||||||
dbName = argv[optind];
|
dbName = argv[optind];
|
||||||
|
|
||||||
SetProcessingMode(BootstrapProcessing);
|
SetProcessingMode(BootstrapProcessing);
|
||||||
|
IgnoreSystemIndexes(true);
|
||||||
|
|
||||||
if (!DataDir)
|
if (!DataDir)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.121 2000/02/15 03:36:34 thomas Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.122 2000/02/18 09:28:40 inoue Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
|
@ -713,7 +713,7 @@ AddNewRelationTuple(Relation pg_class_desc,
|
||||||
if (temp_relname)
|
if (temp_relname)
|
||||||
create_temp_relation(temp_relname, tup);
|
create_temp_relation(temp_relname, tup);
|
||||||
|
|
||||||
if (!IsBootstrapProcessingMode())
|
if (!IsIgnoringSystemIndexes())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* First, open the catalog indices and insert index tuples for the
|
* First, open the catalog indices and insert index tuples for the
|
||||||
|
@ -1263,8 +1263,7 @@ heap_truncate(char *relname)
|
||||||
rel->rd_nblocks = 0;
|
rel->rd_nblocks = 0;
|
||||||
|
|
||||||
/* If this relation has indexes, truncate the indexes too */
|
/* If this relation has indexes, truncate the indexes too */
|
||||||
if (rel->rd_rel->relhasindex)
|
RelationTruncateIndexes(rel);
|
||||||
RelationTruncateIndexes(rel);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Close the relation, but keep exclusive lock on it until commit.
|
* Close the relation, but keep exclusive lock on it until commit.
|
||||||
|
@ -1491,8 +1490,8 @@ heap_drop_with_catalog(const char *relname)
|
||||||
* remove indexes if necessary
|
* remove indexes if necessary
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
if (rel->rd_rel->relhasindex)
|
/* should ignore relhasindex */
|
||||||
RelationRemoveIndexes(rel);
|
RelationRemoveIndexes(rel);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* remove rules if necessary
|
* remove rules if necessary
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.104 2000/01/26 05:56:10 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.105 2000/02/18 09:28:41 inoue Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
|
@ -44,6 +44,7 @@
|
||||||
#include "utils/relcache.h"
|
#include "utils/relcache.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "utils/temprel.h"
|
#include "utils/temprel.h"
|
||||||
|
#include "utils/inval.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* macros used in guessing how many tuples are on a page.
|
* macros used in guessing how many tuples are on a page.
|
||||||
|
@ -75,6 +76,17 @@ static void DefaultBuild(Relation heapRelation, Relation indexRelation,
|
||||||
Datum *parameter, FuncIndexInfoPtr funcInfo, PredInfo *predInfo);
|
Datum *parameter, FuncIndexInfoPtr funcInfo, PredInfo *predInfo);
|
||||||
static Oid IndexGetRelation(Oid indexId);
|
static Oid IndexGetRelation(Oid indexId);
|
||||||
|
|
||||||
|
static bool reindexing = false;
|
||||||
|
extern bool SetReindexProcessing(bool reindexmode)
|
||||||
|
{
|
||||||
|
bool old = reindexing;
|
||||||
|
reindexing = reindexmode;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
extern bool IsReindexProcessing(void)
|
||||||
|
{
|
||||||
|
return reindexing;
|
||||||
|
}
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* sysatts is a structure containing attribute tuple forms
|
* sysatts is a structure containing attribute tuple forms
|
||||||
* for system attributes (numbered -1, -2, ...). This really
|
* for system attributes (numbered -1, -2, ...). This really
|
||||||
|
@ -484,7 +496,7 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
|
||||||
* just before exiting.
|
* just before exiting.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!IsBootstrapProcessingMode())
|
if (!IsIgnoringSystemIndexes())
|
||||||
{
|
{
|
||||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
||||||
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, tuple);
|
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, tuple);
|
||||||
|
@ -569,7 +581,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
|
||||||
(char *) (indexRelation->rd_att->attrs[0]));
|
(char *) (indexRelation->rd_att->attrs[0]));
|
||||||
|
|
||||||
hasind = false;
|
hasind = false;
|
||||||
if (!IsBootstrapProcessingMode() && pg_attribute->rd_rel->relhasindex)
|
if (!IsIgnoringSystemIndexes() && pg_attribute->rd_rel->relhasindex)
|
||||||
{
|
{
|
||||||
hasind = true;
|
hasind = true;
|
||||||
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
|
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
|
||||||
|
@ -758,7 +770,7 @@ UpdateIndexRelation(Oid indexoid,
|
||||||
* insert the index tuple into the pg_index
|
* insert the index tuple into the pg_index
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
if (!IsBootstrapProcessingMode())
|
if (!IsIgnoringSystemIndexes())
|
||||||
{
|
{
|
||||||
CatalogOpenIndices(Num_pg_index_indices, Name_pg_index_indices, idescs);
|
CatalogOpenIndices(Num_pg_index_indices, Name_pg_index_indices, idescs);
|
||||||
CatalogIndexInsert(idescs, Num_pg_index_indices, pg_index, tuple);
|
CatalogIndexInsert(idescs, Num_pg_index_indices, pg_index, tuple);
|
||||||
|
@ -956,6 +968,7 @@ index_create(char *heapRelationName,
|
||||||
* check parameters
|
* check parameters
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
SetReindexProcessing(false);
|
||||||
if (numatts < 1)
|
if (numatts < 1)
|
||||||
elog(ERROR, "must index at least one attribute");
|
elog(ERROR, "must index at least one attribute");
|
||||||
|
|
||||||
|
@ -1271,12 +1284,217 @@ FormIndexDatum(int numberOfAttributes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* --------------------------------------------
|
||||||
|
* Lock class info for update
|
||||||
|
* --------------------------------------------
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
bool LockClassinfoForUpdate(Oid relid, HeapTuple rtup, Buffer *buffer, bool confirmCommitted)
|
||||||
|
{
|
||||||
|
HeapTuple classTuple;
|
||||||
|
Form_pg_class pgcform;
|
||||||
|
bool test;
|
||||||
|
Relation relationRelation;
|
||||||
|
|
||||||
|
classTuple = SearchSysCacheTuple(RELOID, PointerGetDatum(relid),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(classTuple))
|
||||||
|
return false;
|
||||||
|
rtup->t_self = classTuple->t_self;
|
||||||
|
pgcform = (Form_pg_class) GETSTRUCT(classTuple);
|
||||||
|
relationRelation = heap_openr(RelationRelationName, RowShareLock);
|
||||||
|
test = heap_mark4update(relationRelation, rtup, buffer);
|
||||||
|
switch (test)
|
||||||
|
{
|
||||||
|
case HeapTupleSelfUpdated:
|
||||||
|
case HeapTupleMayBeUpdated:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
elog(ERROR, "LockStatsForUpdate couldn't lock relid %u", relid);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RelationInvalidateHeapTuple(relationRelation, rtup);
|
||||||
|
if (confirmCommitted)
|
||||||
|
{
|
||||||
|
HeapTupleHeader th = rtup->t_data;
|
||||||
|
if (!(th->t_infomask & HEAP_XMIN_COMMITTED))
|
||||||
|
elog(ERROR, "The tuple isn't committed");
|
||||||
|
if (th->t_infomask & HEAP_XMAX_COMMITTED)
|
||||||
|
if (!(th->t_infomask & HEAP_MARKED_FOR_UPDATE))
|
||||||
|
elog(ERROR, "The tuple is already deleted");
|
||||||
|
}
|
||||||
|
heap_close(relationRelation, NoLock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------
|
||||||
|
* Indexes of the relation active ?
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
bool IndexesAreActive(Oid relid, bool confirmCommitted)
|
||||||
|
{
|
||||||
|
HeapTupleData tuple;
|
||||||
|
Relation indexRelation;
|
||||||
|
Buffer buffer;
|
||||||
|
HeapScanDesc scan;
|
||||||
|
ScanKeyData entry;
|
||||||
|
bool isactive;
|
||||||
|
|
||||||
|
if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted))
|
||||||
|
elog(ERROR, "IndexesAreActive couldn't lock %u", relid);
|
||||||
|
if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION)
|
||||||
|
elog(ERROR, "relation %u isn't an relation", relid);
|
||||||
|
isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex;
|
||||||
|
ReleaseBuffer(buffer);
|
||||||
|
if (isactive)
|
||||||
|
return isactive;
|
||||||
|
indexRelation = heap_openr(IndexRelationName, AccessShareLock);
|
||||||
|
ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid,
|
||||||
|
F_OIDEQ, ObjectIdGetDatum(relid));
|
||||||
|
scan = heap_beginscan(indexRelation, false, SnapshotNow,
|
||||||
|
1, &entry);
|
||||||
|
if (!heap_getnext(scan, 0))
|
||||||
|
isactive = true;
|
||||||
|
heap_endscan(scan);
|
||||||
|
heap_close(indexRelation, NoLock);
|
||||||
|
return isactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* set relhasindex of pg_class in place
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
setRelhasindexInplace(Oid relid, bool hasindex, bool immediate)
|
||||||
|
{
|
||||||
|
Relation whichRel;
|
||||||
|
Relation pg_class;
|
||||||
|
HeapTuple tuple;
|
||||||
|
Form_pg_class rd_rel;
|
||||||
|
HeapScanDesc pg_class_scan = NULL;
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* This routine handles updates for only the heap relation
|
||||||
|
* hasindex. In order to guarantee that we're able to *see* the index
|
||||||
|
* relation tuple, we bump the command counter id here.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
CommandCounterIncrement();
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* CommandCounterIncrement() flushes invalid cache entries, including
|
||||||
|
* those for the heap and index relations for which we're updating
|
||||||
|
* statistics. Now that the cache is flushed, it's safe to open the
|
||||||
|
* relation again. We need the relation open in order to figure out
|
||||||
|
* how many blocks it contains.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
whichRel = heap_open(relid, ShareLock);
|
||||||
|
|
||||||
|
if (!RelationIsValid(whichRel))
|
||||||
|
elog(ERROR, "setRelhasindexInplace: cannot open relation id %u", relid);
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* Find the RELATION relation tuple for the given relation.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||||
|
if (!RelationIsValid(pg_class))
|
||||||
|
elog(ERROR, "setRelhasindexInplace: could not open RELATION relation");
|
||||||
|
|
||||||
|
if (!IsIgnoringSystemIndexes())
|
||||||
|
{
|
||||||
|
tuple = SearchSysCacheTupleCopy(RELOID,
|
||||||
|
ObjectIdGetDatum(relid), 0, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScanKeyData key[1];
|
||||||
|
|
||||||
|
ScanKeyEntryInitialize(&key[0], 0,
|
||||||
|
ObjectIdAttributeNumber,
|
||||||
|
F_OIDEQ,
|
||||||
|
ObjectIdGetDatum(relid));
|
||||||
|
|
||||||
|
pg_class_scan = heap_beginscan(pg_class, 0, SnapshotNow, 1, key);
|
||||||
|
tuple = heap_getnext(pg_class_scan, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HeapTupleIsValid(tuple))
|
||||||
|
{
|
||||||
|
if (pg_class_scan)
|
||||||
|
heap_endscan(pg_class_scan);
|
||||||
|
heap_close(pg_class, RowExclusiveLock);
|
||||||
|
elog(ERROR, "setRelhasindexInplace: cannot scan RELATION relation");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Confirm that target tuple is locked by this transaction
|
||||||
|
* in case of immedaite updation.
|
||||||
|
*/
|
||||||
|
if (immediate)
|
||||||
|
{
|
||||||
|
HeapTupleHeader th = tuple->t_data;
|
||||||
|
if (!(th->t_infomask & HEAP_XMIN_COMMITTED))
|
||||||
|
elog(ERROR, "Immediate hasindex updation can be done only for committed tuples %x", th->t_infomask);
|
||||||
|
if (th->t_infomask & HEAP_XMAX_INVALID)
|
||||||
|
elog(ERROR, "Immediate hasindex updation can be done only for locked tuples %x", th->t_infomask);
|
||||||
|
if (th->t_infomask & HEAP_XMAX_COMMITTED)
|
||||||
|
elog(ERROR, "Immediate hasindex updation can be done only for locked tuples %x", th->t_infomask);
|
||||||
|
if (!(th->t_infomask & HEAP_MARKED_FOR_UPDATE))
|
||||||
|
elog(ERROR, "Immediate hasindex updation can be done only for locked tuples %x", th->t_infomask);
|
||||||
|
if (!(TransactionIdIsCurrentTransactionId(th->t_xmax)))
|
||||||
|
elog(ERROR, "The updating tuple is already locked by another backend");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We shouldn't have to do this, but we do... Modify the reldesc in
|
||||||
|
* place with the new values so that the cache contains the latest
|
||||||
|
* copy.
|
||||||
|
*/
|
||||||
|
whichRel->rd_rel->relhasindex = hasindex;
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* Update hasindex in pg_class.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
if (pg_class_scan)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!IsBootstrapProcessingMode())
|
||||||
|
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
|
||||||
|
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
|
||||||
|
rd_rel->relhasindex = hasindex;
|
||||||
|
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HeapTupleData htup;
|
||||||
|
Buffer buffer;
|
||||||
|
|
||||||
|
htup.t_self = tuple->t_self;
|
||||||
|
heap_fetch(pg_class, SnapshotNow, &htup, &buffer);
|
||||||
|
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
|
||||||
|
rd_rel = (Form_pg_class) GETSTRUCT(&htup);
|
||||||
|
rd_rel->relhasindex = hasindex;
|
||||||
|
WriteBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pg_class_scan)
|
||||||
|
heap_freetuple(tuple);
|
||||||
|
else
|
||||||
|
heap_endscan(pg_class_scan);
|
||||||
|
|
||||||
|
heap_close(pg_class, NoLock);
|
||||||
|
heap_close(whichRel, NoLock);
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* UpdateStats
|
* UpdateStats
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
UpdateStats(Oid relid, long reltuples, bool hasindex)
|
UpdateStats(Oid relid, long reltuples, bool inplace)
|
||||||
{
|
{
|
||||||
Relation whichRel;
|
Relation whichRel;
|
||||||
Relation pg_class;
|
Relation pg_class;
|
||||||
|
@ -1289,7 +1507,8 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||||
Datum values[Natts_pg_class];
|
Datum values[Natts_pg_class];
|
||||||
char nulls[Natts_pg_class];
|
char nulls[Natts_pg_class];
|
||||||
char replace[Natts_pg_class];
|
char replace[Natts_pg_class];
|
||||||
HeapScanDesc pg_class_scan = NULL;
|
HeapScanDesc pg_class_scan = NULL;
|
||||||
|
bool in_place_upd;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* This routine handles updates for both the heap and index relation
|
* This routine handles updates for both the heap and index relation
|
||||||
|
@ -1327,7 +1546,8 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||||
if (!RelationIsValid(pg_class))
|
if (!RelationIsValid(pg_class))
|
||||||
elog(ERROR, "UpdateStats: could not open RELATION relation");
|
elog(ERROR, "UpdateStats: could not open RELATION relation");
|
||||||
|
|
||||||
if (!IsBootstrapProcessingMode())
|
in_place_upd = (inplace || IsBootstrapProcessingMode());
|
||||||
|
if (!in_place_upd)
|
||||||
{
|
{
|
||||||
tuple = SearchSysCacheTupleCopy(RELOID,
|
tuple = SearchSysCacheTupleCopy(RELOID,
|
||||||
ObjectIdGetDatum(relid),
|
ObjectIdGetDatum(relid),
|
||||||
|
@ -1348,7 +1568,7 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||||
|
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
{
|
{
|
||||||
if (IsBootstrapProcessingMode())
|
if (pg_class_scan)
|
||||||
heap_endscan(pg_class_scan);
|
heap_endscan(pg_class_scan);
|
||||||
heap_close(pg_class, RowExclusiveLock);
|
heap_close(pg_class, RowExclusiveLock);
|
||||||
elog(ERROR, "UpdateStats: cannot scan RELATION relation");
|
elog(ERROR, "UpdateStats: cannot scan RELATION relation");
|
||||||
|
@ -1389,7 +1609,6 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||||
* place with the new values so that the cache contains the latest
|
* place with the new values so that the cache contains the latest
|
||||||
* copy.
|
* copy.
|
||||||
*/
|
*/
|
||||||
whichRel->rd_rel->relhasindex = hasindex;
|
|
||||||
whichRel->rd_rel->relpages = relpages;
|
whichRel->rd_rel->relpages = relpages;
|
||||||
whichRel->rd_rel->reltuples = reltuples;
|
whichRel->rd_rel->reltuples = reltuples;
|
||||||
|
|
||||||
|
@ -1397,17 +1616,18 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||||
* Update statistics in pg_class.
|
* Update statistics in pg_class.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
if (IsBootstrapProcessingMode())
|
if (in_place_upd)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At bootstrap time, we don't need to worry about concurrency or
|
* At bootstrap time, we don't need to worry about concurrency or
|
||||||
* visibility of changes, so we cheat.
|
* visibility of changes, so we cheat.
|
||||||
*/
|
*/
|
||||||
|
if (!IsBootstrapProcessingMode())
|
||||||
|
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
|
||||||
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
|
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
|
||||||
rd_rel->relpages = relpages;
|
rd_rel->relpages = relpages;
|
||||||
rd_rel->reltuples = reltuples;
|
rd_rel->reltuples = reltuples;
|
||||||
rd_rel->relhasindex = hasindex;
|
|
||||||
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
|
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1425,18 +1645,18 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||||
values[Anum_pg_class_relpages - 1] = (Datum) relpages;
|
values[Anum_pg_class_relpages - 1] = (Datum) relpages;
|
||||||
replace[Anum_pg_class_reltuples - 1] = 'r';
|
replace[Anum_pg_class_reltuples - 1] = 'r';
|
||||||
values[Anum_pg_class_reltuples - 1] = (Datum) reltuples;
|
values[Anum_pg_class_reltuples - 1] = (Datum) reltuples;
|
||||||
replace[Anum_pg_class_relhasindex - 1] = 'r';
|
|
||||||
values[Anum_pg_class_relhasindex - 1] = CharGetDatum(hasindex);
|
|
||||||
|
|
||||||
newtup = heap_modifytuple(tuple, pg_class, values, nulls, replace);
|
newtup = heap_modifytuple(tuple, pg_class, values, nulls, replace);
|
||||||
heap_update(pg_class, &tuple->t_self, newtup, NULL);
|
heap_update(pg_class, &tuple->t_self, newtup, NULL);
|
||||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
if (!IsIgnoringSystemIndexes())
|
||||||
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
|
{
|
||||||
CatalogCloseIndices(Num_pg_class_indices, idescs);
|
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
||||||
|
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
|
||||||
|
CatalogCloseIndices(Num_pg_class_indices, idescs);
|
||||||
|
}
|
||||||
heap_freetuple(newtup);
|
heap_freetuple(newtup);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsBootstrapProcessingMode())
|
if (!pg_class_scan)
|
||||||
heap_freetuple(tuple);
|
heap_freetuple(tuple);
|
||||||
else
|
else
|
||||||
heap_endscan(pg_class_scan);
|
heap_endscan(pg_class_scan);
|
||||||
|
@ -1668,16 +1888,18 @@ DefaultBuild(Relation heapRelation,
|
||||||
{
|
{
|
||||||
Oid hrelid = RelationGetRelid(heapRelation);
|
Oid hrelid = RelationGetRelid(heapRelation);
|
||||||
Oid irelid = RelationGetRelid(indexRelation);
|
Oid irelid = RelationGetRelid(indexRelation);
|
||||||
|
bool inplace = IsReindexProcessing();
|
||||||
|
|
||||||
heap_close(heapRelation, NoLock);
|
heap_close(heapRelation, NoLock);
|
||||||
index_close(indexRelation);
|
index_close(indexRelation);
|
||||||
UpdateStats(hrelid, reltuples, true);
|
UpdateStats(hrelid, reltuples, inplace);
|
||||||
UpdateStats(irelid, indtuples, false);
|
UpdateStats(irelid, indtuples, inplace);
|
||||||
if (oldPred != NULL)
|
if (oldPred != NULL)
|
||||||
{
|
{
|
||||||
if (indtuples == reltuples)
|
if (indtuples == reltuples)
|
||||||
predicate = NULL;
|
predicate = NULL;
|
||||||
UpdateIndexPredicate(irelid, oldPred, predicate);
|
if (!inplace)
|
||||||
|
UpdateIndexPredicate(irelid, oldPred, predicate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1826,3 +2048,226 @@ IndexIsUniqueNoCache(Oid indexId)
|
||||||
heap_close(pg_index, AccessShareLock);
|
heap_close(pg_index, AccessShareLock);
|
||||||
return isunique;
|
return isunique;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------
|
||||||
|
* activate_index -- activate/deactivate the specified index.
|
||||||
|
* Note that currelntly PostgreSQL doesn't hold the
|
||||||
|
* status per index
|
||||||
|
* ---------------------------------
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
activate_index(Oid indexId, bool activate)
|
||||||
|
{
|
||||||
|
if (!activate) /* Currently does nothing */
|
||||||
|
return true;
|
||||||
|
return reindex_index(indexId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------
|
||||||
|
* reindex_index - This routine is used to recreate an index
|
||||||
|
* --------------------------------
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
reindex_index(Oid indexId, bool force)
|
||||||
|
{
|
||||||
|
Relation iRel, indexRelation, heapRelation;
|
||||||
|
ScanKeyData entry;
|
||||||
|
HeapScanDesc scan;
|
||||||
|
HeapTuple indexTuple, procTuple, classTuple;
|
||||||
|
Form_pg_index index;
|
||||||
|
Oid heapId, procId, accessMethodId;
|
||||||
|
Node *oldPred = NULL;
|
||||||
|
PredInfo *predInfo;
|
||||||
|
List *cnfPred = NULL;
|
||||||
|
AttrNumber *attributeNumberA;
|
||||||
|
FuncIndexInfo fInfo, *funcInfo = NULL;
|
||||||
|
int i, numberOfAttributes;
|
||||||
|
char *predString;
|
||||||
|
bool old;
|
||||||
|
|
||||||
|
old = SetReindexProcessing(true);
|
||||||
|
/* Scan pg_index to find indexes on heapRelation */
|
||||||
|
indexRelation = heap_openr(IndexRelationName, AccessShareLock);
|
||||||
|
ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indexrelid, F_OIDEQ,
|
||||||
|
ObjectIdGetDatum(indexId));
|
||||||
|
scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry);
|
||||||
|
indexTuple = heap_getnext(scan, 0);
|
||||||
|
if (!HeapTupleIsValid(indexTuple))
|
||||||
|
elog(ERROR, "reindex_index index %d tuple is invalid", indexId);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the index, fetch index attributes so we can apply index_build
|
||||||
|
*/
|
||||||
|
index = (Form_pg_index) GETSTRUCT(indexTuple);
|
||||||
|
heapId = index->indrelid;
|
||||||
|
procId = index->indproc;
|
||||||
|
|
||||||
|
for (i = 0; i < INDEX_MAX_KEYS; i++)
|
||||||
|
{
|
||||||
|
if (index->indkey[i] == InvalidAttrNumber)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numberOfAttributes = i;
|
||||||
|
|
||||||
|
/* If a valid where predicate, compute predicate Node */
|
||||||
|
if (VARSIZE(&index->indpred) != 0)
|
||||||
|
{
|
||||||
|
predString = fmgr(F_TEXTOUT, &index->indpred);
|
||||||
|
oldPred = stringToNode(predString);
|
||||||
|
pfree(predString);
|
||||||
|
}
|
||||||
|
predInfo = (PredInfo *) palloc(sizeof(PredInfo));
|
||||||
|
predInfo->pred = (Node *) cnfPred;
|
||||||
|
predInfo->oldPred = oldPred;
|
||||||
|
|
||||||
|
/* Assign Index keys to attributes array */
|
||||||
|
attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * sizeof(AttrNumber));
|
||||||
|
for (i = 0; i < numberOfAttributes; i++)
|
||||||
|
attributeNumberA[i] = index->indkey[i];
|
||||||
|
|
||||||
|
/* If this is a procedural index, initialize our FuncIndexInfo */
|
||||||
|
if (procId != InvalidOid)
|
||||||
|
{
|
||||||
|
funcInfo = &fInfo;
|
||||||
|
FIsetnArgs(funcInfo, numberOfAttributes);
|
||||||
|
procTuple = SearchSysCacheTuple(PROCOID, ObjectIdGetDatum(procId),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(procTuple))
|
||||||
|
elog(ERROR, "RelationTruncateIndexes: index procedure not found");
|
||||||
|
namecpy(&(funcInfo->funcName),
|
||||||
|
&(((Form_pg_proc) GETSTRUCT(procTuple))->proname));
|
||||||
|
FIsetProcOid(funcInfo, procTuple->t_data->t_oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch the classTuple associated with this index */
|
||||||
|
classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId), 0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(classTuple))
|
||||||
|
elog(ERROR, "RelationTruncateIndexes: index access method not found");
|
||||||
|
accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;
|
||||||
|
|
||||||
|
/* Open our index relation */
|
||||||
|
iRel = index_open(indexId);
|
||||||
|
if (iRel == NULL)
|
||||||
|
elog(ERROR, "reindex_index: can't open index relation");
|
||||||
|
heapRelation = heap_open(heapId, ExclusiveLock);
|
||||||
|
if (heapRelation == NULL)
|
||||||
|
elog(ERROR, "reindex_index: can't open heap relation");
|
||||||
|
|
||||||
|
/* Obtain exclusive lock on it, just to be sure */
|
||||||
|
LockRelation(iRel, AccessExclusiveLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release any buffers associated with this index. If they're dirty,
|
||||||
|
* they're just dropped without bothering to flush to disk.
|
||||||
|
*/
|
||||||
|
ReleaseRelationBuffers(iRel);
|
||||||
|
if (FlushRelationBuffers(iRel, (BlockNumber) 0, false) < 0)
|
||||||
|
elog(ERROR, "reindex_index: unable to flush index from buffer pool");
|
||||||
|
|
||||||
|
/* Now truncate the actual data and set blocks to zero */
|
||||||
|
smgrtruncate(DEFAULT_SMGR, iRel, 0);
|
||||||
|
iRel->rd_nblocks = 0;
|
||||||
|
|
||||||
|
/* Initialize the index and rebuild */
|
||||||
|
InitIndexStrategy(numberOfAttributes, iRel, accessMethodId);
|
||||||
|
index_build(heapRelation, iRel, numberOfAttributes,
|
||||||
|
attributeNumberA, 0, NULL, funcInfo, predInfo);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* index_build will close both the heap and index relations
|
||||||
|
* (but not give up the locks we hold on them). That's fine
|
||||||
|
* for the index, but we need to open the heap again. We need
|
||||||
|
* no new lock, since this backend still has the exclusive lock
|
||||||
|
* grabbed by heap_truncate.
|
||||||
|
*/
|
||||||
|
iRel = index_open(indexId);
|
||||||
|
Assert(iRel != NULL);
|
||||||
|
|
||||||
|
/* Complete the scan and close pg_index */
|
||||||
|
heap_endscan(scan);
|
||||||
|
heap_close(indexRelation, AccessShareLock);
|
||||||
|
SetReindexProcessing(old);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------
|
||||||
|
* activate_indexes_of_a_table
|
||||||
|
* activate/deactivate indexes of the specified table.
|
||||||
|
* ----------------------------
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
activate_indexes_of_a_table(Oid relid, bool activate)
|
||||||
|
{
|
||||||
|
if (IndexesAreActive(relid, true))
|
||||||
|
{
|
||||||
|
if (!activate)
|
||||||
|
setRelhasindexInplace(relid, false, true);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (activate)
|
||||||
|
reindex_relation(relid, false);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/* --------------------------------
|
||||||
|
* reindex_relation - This routine is used to recreate indexes
|
||||||
|
* of a relation.
|
||||||
|
* --------------------------------
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
reindex_relation(Oid relid, bool force)
|
||||||
|
{
|
||||||
|
Relation indexRelation;
|
||||||
|
ScanKeyData entry;
|
||||||
|
HeapScanDesc scan;
|
||||||
|
HeapTuple indexTuple;
|
||||||
|
bool old, reindexed;
|
||||||
|
|
||||||
|
old = SetReindexProcessing(true);
|
||||||
|
if (IndexesAreActive(relid, true))
|
||||||
|
{
|
||||||
|
if (!force)
|
||||||
|
{
|
||||||
|
SetReindexProcessing(old);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
activate_indexes_of_a_table(relid, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
indexRelation = heap_openr(IndexRelationName, AccessShareLock);
|
||||||
|
ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid,
|
||||||
|
F_OIDEQ, ObjectIdGetDatum(relid));
|
||||||
|
scan = heap_beginscan(indexRelation, false, SnapshotNow,
|
||||||
|
1, &entry);
|
||||||
|
reindexed = false;
|
||||||
|
while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
|
||||||
|
{
|
||||||
|
Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple);
|
||||||
|
if (activate_index(index->indexrelid, true))
|
||||||
|
reindexed = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reindexed = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
heap_endscan(scan);
|
||||||
|
heap_close(indexRelation, AccessShareLock);
|
||||||
|
if (reindexed)
|
||||||
|
{
|
||||||
|
setRelhasindexInplace(relid, true, false);
|
||||||
|
}
|
||||||
|
SetReindexProcessing(old);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.58 2000/01/26 05:56:10 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.59 2000/02/18 09:28:41 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -92,6 +92,8 @@ CatalogOpenIndices(int nIndices, char **names, Relation *idescs)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (IsIgnoringSystemIndexes())
|
||||||
|
return;
|
||||||
for (i = 0; i < nIndices; i++)
|
for (i = 0; i < nIndices; i++)
|
||||||
idescs[i] = index_openr(names[i]);
|
idescs[i] = index_openr(names[i]);
|
||||||
}
|
}
|
||||||
|
@ -104,6 +106,8 @@ CatalogCloseIndices(int nIndices, Relation *idescs)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (IsIgnoringSystemIndexes())
|
||||||
|
return;
|
||||||
for (i = 0; i < nIndices; i++)
|
for (i = 0; i < nIndices; i++)
|
||||||
index_close(idescs[i]);
|
index_close(idescs[i]);
|
||||||
}
|
}
|
||||||
|
@ -131,6 +135,8 @@ CatalogIndexInsert(Relation *idescs,
|
||||||
*finfoP;
|
*finfoP;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (IsIgnoringSystemIndexes())
|
||||||
|
return;
|
||||||
heapDescriptor = RelationGetDescr(heapRelation);
|
heapDescriptor = RelationGetDescr(heapRelation);
|
||||||
|
|
||||||
for (i = 0; i < nIndices; i++)
|
for (i = 0; i < nIndices; i++)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.20 2000/01/26 05:56:13 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.21 2000/02/18 09:29:37 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -17,12 +17,15 @@
|
||||||
|
|
||||||
#include "access/genam.h"
|
#include "access/genam.h"
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
|
#include "catalog/catname.h"
|
||||||
#include "catalog/heap.h"
|
#include "catalog/heap.h"
|
||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "catalog/pg_index.h"
|
#include "catalog/pg_index.h"
|
||||||
#include "catalog/pg_opclass.h"
|
#include "catalog/pg_opclass.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
|
#include "catalog/pg_database.h"
|
||||||
|
#include "catalog/pg_shadow.h"
|
||||||
#include "commands/defrem.h"
|
#include "commands/defrem.h"
|
||||||
#include "optimizer/clauses.h"
|
#include "optimizer/clauses.h"
|
||||||
#include "optimizer/planmain.h"
|
#include "optimizer/planmain.h"
|
||||||
|
@ -30,6 +33,9 @@
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
#include "miscadmin.h" /* ReindexDatabase() */
|
||||||
|
#include "utils/portal.h" /* ReindexDatabase() */
|
||||||
|
#include "catalog/catalog.h" /* ReindexDatabase() */
|
||||||
|
|
||||||
#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args!=NULL)
|
#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args!=NULL)
|
||||||
|
|
||||||
|
@ -149,6 +155,8 @@ DefineIndex(char *heapRelationName,
|
||||||
CheckPredicate(cnfPred, rangetable, relationId);
|
CheckPredicate(cnfPred, rangetable, relationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false))
|
||||||
|
elog(ERROR, "existent indexes are inactive. REINDEX first");
|
||||||
if (IsFuncIndex(attributeList))
|
if (IsFuncIndex(attributeList))
|
||||||
{
|
{
|
||||||
IndexElem *funcIndex = lfirst(attributeList);
|
IndexElem *funcIndex = lfirst(attributeList);
|
||||||
|
@ -195,6 +203,7 @@ DefineIndex(char *heapRelationName,
|
||||||
classObjectId, parameterCount, parameterA, (Node *) cnfPred,
|
classObjectId, parameterCount, parameterA, (Node *) cnfPred,
|
||||||
lossy, unique, primary);
|
lossy, unique, primary);
|
||||||
}
|
}
|
||||||
|
setRelhasindexInplace(relationId, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -570,3 +579,163 @@ RemoveIndex(char *name)
|
||||||
|
|
||||||
index_drop(tuple->t_data->t_oid);
|
index_drop(tuple->t_data->t_oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reindex
|
||||||
|
* Recreate an index.
|
||||||
|
*
|
||||||
|
* Exceptions:
|
||||||
|
* "ERROR" if index nonexistent.
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ReindexIndex(const char *name, bool force /* currently unused */)
|
||||||
|
{
|
||||||
|
HeapTuple tuple;
|
||||||
|
|
||||||
|
tuple = SearchSysCacheTuple(RELNAME,
|
||||||
|
PointerGetDatum(name),
|
||||||
|
0, 0, 0);
|
||||||
|
|
||||||
|
if (!HeapTupleIsValid(tuple))
|
||||||
|
elog(ERROR, "index \"%s\" nonexistent", name);
|
||||||
|
|
||||||
|
if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX)
|
||||||
|
{
|
||||||
|
elog(ERROR, "relation \"%s\" is of type \"%c\"",
|
||||||
|
name,
|
||||||
|
((Form_pg_class) GETSTRUCT(tuple))->relkind);
|
||||||
|
}
|
||||||
|
|
||||||
|
reindex_index(tuple->t_data->t_oid, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ReindexTable
|
||||||
|
* Recreate indexes of a table.
|
||||||
|
*
|
||||||
|
* Exceptions:
|
||||||
|
* "ERROR" if table nonexistent.
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ReindexTable(const char *name, bool force)
|
||||||
|
{
|
||||||
|
HeapTuple tuple;
|
||||||
|
|
||||||
|
tuple = SearchSysCacheTuple(RELNAME,
|
||||||
|
PointerGetDatum(name),
|
||||||
|
0, 0, 0);
|
||||||
|
|
||||||
|
if (!HeapTupleIsValid(tuple))
|
||||||
|
elog(ERROR, "table \"%s\" nonexistent", name);
|
||||||
|
|
||||||
|
if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_RELATION)
|
||||||
|
{
|
||||||
|
elog(ERROR, "relation \"%s\" is of type \"%c\"",
|
||||||
|
name,
|
||||||
|
((Form_pg_class) GETSTRUCT(tuple))->relkind);
|
||||||
|
}
|
||||||
|
|
||||||
|
reindex_relation(tuple->t_data->t_oid, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ReindexDatabase
|
||||||
|
* Recreate indexes of a database.
|
||||||
|
*
|
||||||
|
* Exceptions:
|
||||||
|
* "ERROR" if table nonexistent.
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
extern Oid MyDatabaseId;
|
||||||
|
void
|
||||||
|
ReindexDatabase(const char *dbname, bool force, bool all)
|
||||||
|
{
|
||||||
|
Relation relation, relationRelation;
|
||||||
|
HeapTuple usertuple, dbtuple, tuple;
|
||||||
|
HeapScanDesc scan;
|
||||||
|
int4 user_id, db_owner;
|
||||||
|
bool superuser;
|
||||||
|
Oid db_id;
|
||||||
|
char *username;
|
||||||
|
ScanKeyData scankey;
|
||||||
|
PortalVariableMemory pmem;
|
||||||
|
MemoryContext old;
|
||||||
|
int relcnt, relalc, i, oncealc = 200;
|
||||||
|
Oid *relids = (Oid *) NULL;
|
||||||
|
|
||||||
|
AssertArg(dbname);
|
||||||
|
|
||||||
|
username = GetPgUserName();
|
||||||
|
usertuple = SearchSysCacheTuple(SHADOWNAME, PointerGetDatum(username),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(usertuple))
|
||||||
|
elog(ERROR, "Current user '%s' is invalid.", username);
|
||||||
|
user_id = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesysid;
|
||||||
|
superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper;
|
||||||
|
|
||||||
|
relation = heap_openr(DatabaseRelationName, AccessShareLock);
|
||||||
|
ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname,
|
||||||
|
F_NAMEEQ, NameGetDatum(dbname));
|
||||||
|
scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scankey);
|
||||||
|
dbtuple = heap_getnext(scan, 0);
|
||||||
|
if (!HeapTupleIsValid(dbtuple))
|
||||||
|
elog(ERROR, "Database '%s' doesn't exist", dbname);
|
||||||
|
db_id = dbtuple->t_data->t_oid;
|
||||||
|
db_owner = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
|
||||||
|
heap_endscan(scan);
|
||||||
|
if (user_id != db_owner && !superuser)
|
||||||
|
elog(ERROR, "REINDEX DATABASE: Permission denied.");
|
||||||
|
|
||||||
|
if (db_id != MyDatabaseId)
|
||||||
|
elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
|
||||||
|
|
||||||
|
heap_close(relation, NoLock);
|
||||||
|
/** reindex_database(db_id, force, !all); **/
|
||||||
|
|
||||||
|
CommonSpecialPortalOpen();
|
||||||
|
pmem = CommonSpecialPortalGetMemory();
|
||||||
|
relationRelation = heap_openr(RelationRelationName, AccessShareLock);
|
||||||
|
scan = heap_beginscan(relationRelation, false, SnapshotNow, 0, NULL);
|
||||||
|
relcnt = relalc = 0;
|
||||||
|
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||||
|
{
|
||||||
|
if (!all)
|
||||||
|
{
|
||||||
|
if (!IsSystemRelationName(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname)))
|
||||||
|
continue;
|
||||||
|
if (((Form_pg_class) GETSTRUCT(tuple))->relhasrules)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (((Form_pg_class) GETSTRUCT(tuple))->relkind == RELKIND_RELATION)
|
||||||
|
{
|
||||||
|
old = MemoryContextSwitchTo((MemoryContext) pmem);
|
||||||
|
if (relcnt == 0)
|
||||||
|
{
|
||||||
|
relalc = oncealc;
|
||||||
|
relids = palloc(sizeof(Oid) * relalc);
|
||||||
|
}
|
||||||
|
else if (relcnt >= relalc)
|
||||||
|
{
|
||||||
|
relalc *= 2;
|
||||||
|
relids = repalloc(relids, sizeof(Oid) * relalc);
|
||||||
|
}
|
||||||
|
MemoryContextSwitchTo(old);
|
||||||
|
relids[relcnt] = tuple->t_data->t_oid;
|
||||||
|
relcnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
heap_endscan(scan);
|
||||||
|
heap_close(relationRelation, AccessShareLock);
|
||||||
|
|
||||||
|
CommitTransactionCommand();
|
||||||
|
for (i = 0; i < relcnt; i++)
|
||||||
|
{
|
||||||
|
StartTransactionCommand();
|
||||||
|
reindex_relation(relids[i], force);
|
||||||
|
CommitTransactionCommand();
|
||||||
|
}
|
||||||
|
CommonSpecialPortalClose();
|
||||||
|
StartTransactionCommand();
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.60 2000/02/13 13:21:10 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.61 2000/02/18 09:29:37 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -433,15 +433,18 @@ RelationBuildTriggers(Relation relation)
|
||||||
Trigger *build;
|
Trigger *build;
|
||||||
Relation tgrel;
|
Relation tgrel;
|
||||||
Form_pg_trigger pg_trigger;
|
Form_pg_trigger pg_trigger;
|
||||||
Relation irel;
|
Relation irel = (Relation) NULL;
|
||||||
ScanKeyData skey;
|
ScanKeyData skey;
|
||||||
HeapTupleData tuple;
|
HeapTupleData tuple;
|
||||||
IndexScanDesc sd;
|
IndexScanDesc sd = (IndexScanDesc) NULL;
|
||||||
|
HeapScanDesc tgscan = (HeapScanDesc) NULL;
|
||||||
|
HeapTuple htup;
|
||||||
RetrieveIndexResult indexRes;
|
RetrieveIndexResult indexRes;
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
struct varlena *val;
|
struct varlena *val;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
int found;
|
int found;
|
||||||
|
bool hasindex;
|
||||||
|
|
||||||
MemSet(trigdesc, 0, sizeof(TriggerDesc));
|
MemSet(trigdesc, 0, sizeof(TriggerDesc));
|
||||||
|
|
||||||
|
@ -452,25 +455,41 @@ RelationBuildTriggers(Relation relation)
|
||||||
ObjectIdGetDatum(RelationGetRelid(relation)));
|
ObjectIdGetDatum(RelationGetRelid(relation)));
|
||||||
|
|
||||||
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
|
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
|
||||||
irel = index_openr(TriggerRelidIndex);
|
hasindex = (tgrel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
|
||||||
sd = index_beginscan(irel, false, 1, &skey);
|
if (hasindex)
|
||||||
|
{
|
||||||
|
irel = index_openr(TriggerRelidIndex);
|
||||||
|
sd = index_beginscan(irel, false, 1, &skey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &skey);
|
||||||
|
|
||||||
for (found = 0;;)
|
for (found = 0;;)
|
||||||
{
|
{
|
||||||
indexRes = index_getnext(sd, ForwardScanDirection);
|
if (hasindex)
|
||||||
if (!indexRes)
|
{
|
||||||
break;
|
indexRes = index_getnext(sd, ForwardScanDirection);
|
||||||
|
if (!indexRes)
|
||||||
|
break;
|
||||||
|
|
||||||
tuple.t_self = indexRes->heap_iptr;
|
tuple.t_self = indexRes->heap_iptr;
|
||||||
heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
|
heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
|
||||||
pfree(indexRes);
|
pfree(indexRes);
|
||||||
if (!tuple.t_data)
|
if (!tuple.t_data)
|
||||||
continue;
|
continue;
|
||||||
|
htup = &tuple;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
htup = heap_getnext(tgscan, 0);
|
||||||
|
if (!HeapTupleIsValid(htup))
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (found == ntrigs)
|
if (found == ntrigs)
|
||||||
elog(ERROR, "RelationBuildTriggers: unexpected record found for rel %s",
|
elog(ERROR, "RelationBuildTriggers: unexpected record found for rel %s",
|
||||||
RelationGetRelationName(relation));
|
RelationGetRelationName(relation));
|
||||||
|
|
||||||
pg_trigger = (Form_pg_trigger) GETSTRUCT(&tuple);
|
pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
|
||||||
|
|
||||||
if (triggers == NULL)
|
if (triggers == NULL)
|
||||||
triggers = (Trigger *) palloc(sizeof(Trigger));
|
triggers = (Trigger *) palloc(sizeof(Trigger));
|
||||||
|
@ -478,7 +497,7 @@ RelationBuildTriggers(Relation relation)
|
||||||
triggers = (Trigger *) repalloc(triggers, (found + 1) * sizeof(Trigger));
|
triggers = (Trigger *) repalloc(triggers, (found + 1) * sizeof(Trigger));
|
||||||
build = &(triggers[found]);
|
build = &(triggers[found]);
|
||||||
|
|
||||||
build->tgoid = tuple.t_data->t_oid;
|
build->tgoid = htup->t_data->t_oid;
|
||||||
build->tgname = nameout(&pg_trigger->tgname);
|
build->tgname = nameout(&pg_trigger->tgname);
|
||||||
build->tgfoid = pg_trigger->tgfoid;
|
build->tgfoid = pg_trigger->tgfoid;
|
||||||
build->tgfunc.fn_addr = NULL;
|
build->tgfunc.fn_addr = NULL;
|
||||||
|
@ -489,7 +508,7 @@ RelationBuildTriggers(Relation relation)
|
||||||
build->tginitdeferred = pg_trigger->tginitdeferred;
|
build->tginitdeferred = pg_trigger->tginitdeferred;
|
||||||
build->tgnargs = pg_trigger->tgnargs;
|
build->tgnargs = pg_trigger->tgnargs;
|
||||||
memcpy(build->tgattr, &(pg_trigger->tgattr), FUNC_MAX_ARGS * sizeof(int16));
|
memcpy(build->tgattr, &(pg_trigger->tgattr), FUNC_MAX_ARGS * sizeof(int16));
|
||||||
val = (struct varlena *) fastgetattr(&tuple,
|
val = (struct varlena *) fastgetattr(htup,
|
||||||
Anum_pg_trigger_tgargs,
|
Anum_pg_trigger_tgargs,
|
||||||
tgrel->rd_att, &isnull);
|
tgrel->rd_att, &isnull);
|
||||||
if (isnull)
|
if (isnull)
|
||||||
|
@ -500,7 +519,7 @@ RelationBuildTriggers(Relation relation)
|
||||||
char *p;
|
char *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
val = (struct varlena *) fastgetattr(&tuple,
|
val = (struct varlena *) fastgetattr(htup,
|
||||||
Anum_pg_trigger_tgargs,
|
Anum_pg_trigger_tgargs,
|
||||||
tgrel->rd_att, &isnull);
|
tgrel->rd_att, &isnull);
|
||||||
if (isnull)
|
if (isnull)
|
||||||
|
@ -518,7 +537,8 @@ RelationBuildTriggers(Relation relation)
|
||||||
build->tgargs = NULL;
|
build->tgargs = NULL;
|
||||||
|
|
||||||
found++;
|
found++;
|
||||||
ReleaseBuffer(buffer);
|
if (hasindex)
|
||||||
|
ReleaseBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found < ntrigs)
|
if (found < ntrigs)
|
||||||
|
@ -526,8 +546,13 @@ RelationBuildTriggers(Relation relation)
|
||||||
ntrigs - found,
|
ntrigs - found,
|
||||||
RelationGetRelationName(relation));
|
RelationGetRelationName(relation));
|
||||||
|
|
||||||
index_endscan(sd);
|
if (hasindex)
|
||||||
index_close(irel);
|
{
|
||||||
|
index_endscan(sd);
|
||||||
|
index_close(irel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
heap_endscan(tgscan);
|
||||||
heap_close(tgrel, AccessShareLock);
|
heap_close(tgrel, AccessShareLock);
|
||||||
|
|
||||||
/* Build trigdesc */
|
/* Build trigdesc */
|
||||||
|
@ -1460,7 +1485,7 @@ void
|
||||||
DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||||
{
|
{
|
||||||
Relation tgrel;
|
Relation tgrel;
|
||||||
Relation irel;
|
Relation irel = (Relation) NULL;
|
||||||
List *l;
|
List *l;
|
||||||
List *ls;
|
List *ls;
|
||||||
List *lnext;
|
List *lnext;
|
||||||
|
@ -1468,6 +1493,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||||
MemoryContext oldcxt;
|
MemoryContext oldcxt;
|
||||||
bool found;
|
bool found;
|
||||||
DeferredTriggerStatus state;
|
DeferredTriggerStatus state;
|
||||||
|
bool hasindex;
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Handle SET CONSTRAINTS ALL ...
|
* Handle SET CONSTRAINTS ALL ...
|
||||||
|
@ -1548,13 +1574,17 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
|
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
|
||||||
irel = index_openr(TriggerConstrNameIndex);
|
hasindex = (tgrel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
|
||||||
|
if (hasindex)
|
||||||
|
irel = index_openr(TriggerConstrNameIndex);
|
||||||
|
|
||||||
foreach (l, stmt->constraints)
|
foreach (l, stmt->constraints)
|
||||||
{
|
{
|
||||||
ScanKeyData skey;
|
ScanKeyData skey;
|
||||||
HeapTupleData tuple;
|
HeapTupleData tuple;
|
||||||
IndexScanDesc sd;
|
IndexScanDesc sd = (IndexScanDesc) NULL;
|
||||||
|
HeapScanDesc tgscan = (HeapScanDesc) NULL;
|
||||||
|
HeapTuple htup;
|
||||||
RetrieveIndexResult indexRes;
|
RetrieveIndexResult indexRes;
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
Form_pg_trigger pg_trigger;
|
Form_pg_trigger pg_trigger;
|
||||||
|
@ -1577,7 +1607,10 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||||
(RegProcedure) F_NAMEEQ,
|
(RegProcedure) F_NAMEEQ,
|
||||||
PointerGetDatum((char *)lfirst(l)));
|
PointerGetDatum((char *)lfirst(l)));
|
||||||
|
|
||||||
sd = index_beginscan(irel, false, 1, &skey);
|
if (hasindex)
|
||||||
|
sd = index_beginscan(irel, false, 1, &skey);
|
||||||
|
else
|
||||||
|
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &skey);
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* ... and search for the constraint trigger row
|
* ... and search for the constraint trigger row
|
||||||
|
@ -1586,33 +1619,43 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||||
found = false;
|
found = false;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
indexRes = index_getnext(sd, ForwardScanDirection);
|
if (hasindex)
|
||||||
if (!indexRes)
|
|
||||||
break;
|
|
||||||
|
|
||||||
tuple.t_self = indexRes->heap_iptr;
|
|
||||||
heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
|
|
||||||
pfree(indexRes);
|
|
||||||
if (!tuple.t_data)
|
|
||||||
{
|
{
|
||||||
ReleaseBuffer(buffer);
|
indexRes = index_getnext(sd, ForwardScanDirection);
|
||||||
continue;
|
if (!indexRes)
|
||||||
|
break;
|
||||||
|
|
||||||
|
tuple.t_self = indexRes->heap_iptr;
|
||||||
|
heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
|
||||||
|
pfree(indexRes);
|
||||||
|
if (!tuple.t_data)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
htup = &tuple;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
htup = heap_getnext(tgscan, 0);
|
||||||
|
if (!HeapTupleIsValid(htup))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* If we found some, check that they fit the deferrability
|
* If we found some, check that they fit the deferrability
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
pg_trigger = (Form_pg_trigger) GETSTRUCT(&tuple);
|
pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
|
||||||
if (stmt->deferred & !pg_trigger->tgdeferrable)
|
if (stmt->deferred & !pg_trigger->tgdeferrable)
|
||||||
elog(ERROR, "Constraint '%s' is not deferrable",
|
elog(ERROR, "Constraint '%s' is not deferrable",
|
||||||
(char *)lfirst(l));
|
(char *)lfirst(l));
|
||||||
|
|
||||||
constr_oid = tuple.t_data->t_oid;
|
constr_oid = htup->t_data->t_oid;
|
||||||
loid = lappend(loid, (Node *)constr_oid);
|
loid = lappend(loid, (Node *)constr_oid);
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
ReleaseBuffer(buffer);
|
if (hasindex)
|
||||||
|
ReleaseBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
|
@ -1622,9 +1665,13 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
|
||||||
if (!found)
|
if (!found)
|
||||||
elog(ERROR, "Constraint '%s' does not exist", (char *)lfirst(l));
|
elog(ERROR, "Constraint '%s' does not exist", (char *)lfirst(l));
|
||||||
|
|
||||||
index_endscan(sd);
|
if (hasindex)
|
||||||
|
index_endscan(sd);
|
||||||
|
else
|
||||||
|
heap_endscan(tgscan);
|
||||||
}
|
}
|
||||||
index_close(irel);
|
if (hasindex)
|
||||||
|
index_close(irel);
|
||||||
heap_close(tgrel, AccessShareLock);
|
heap_close(tgrel, AccessShareLock);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.138 2000/01/26 05:56:13 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.139 2000/02/18 09:29:37 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bool VacuumRunning = false;
|
bool CommonSpecialPortalInUse = false;
|
||||||
|
|
||||||
static Portal vc_portal;
|
static Portal vc_portal;
|
||||||
|
|
||||||
|
@ -99,6 +99,53 @@ static bool vc_enough_space(VPageDescr vpd, Size len);
|
||||||
static char *vc_show_rusage(struct rusage * ru0);
|
static char *vc_show_rusage(struct rusage * ru0);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routines handle a special cross-transaction portal.
|
||||||
|
* However it is automatically closed in case of abort.
|
||||||
|
*/
|
||||||
|
void CommonSpecialPortalOpen(void)
|
||||||
|
{
|
||||||
|
char *pname;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a portal for safe memory across transactions. We need to
|
||||||
|
* palloc the name space for it because our hash function expects the
|
||||||
|
* name to be on a longword boundary. CreatePortal copies the name to
|
||||||
|
* safe storage for us.
|
||||||
|
*/
|
||||||
|
pname = pstrdup(VACPNAME);
|
||||||
|
vc_portal = CreatePortal(pname);
|
||||||
|
pfree(pname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set flag to indicate that vc_portal must be removed after an error.
|
||||||
|
* This global variable is checked in the transaction manager on xact
|
||||||
|
* abort, and the routine CommonSpecialPortalClose() is called if
|
||||||
|
* necessary.
|
||||||
|
*/
|
||||||
|
CommonSpecialPortalInUse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonSpecialPortalClose(void)
|
||||||
|
{
|
||||||
|
/* Clear flag first, to avoid recursion if PortalDrop elog's */
|
||||||
|
CommonSpecialPortalInUse = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release our portal for cross-transaction memory.
|
||||||
|
*/
|
||||||
|
PortalDrop(&vc_portal);
|
||||||
|
}
|
||||||
|
|
||||||
|
PortalVariableMemory CommonSpecialPortalGetMemory(void)
|
||||||
|
{
|
||||||
|
return PortalGetVariableMemory(vc_portal);
|
||||||
|
}
|
||||||
|
bool CommonSpecialPortalIsOpen(void)
|
||||||
|
{
|
||||||
|
return CommonSpecialPortalInUse;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vacuum(char *vacrel, bool verbose, bool analyze, List *va_spec)
|
vacuum(char *vacrel, bool verbose, bool analyze, List *va_spec)
|
||||||
{
|
{
|
||||||
|
@ -136,7 +183,7 @@ vacuum(char *vacrel, bool verbose, bool analyze, List *va_spec)
|
||||||
strcpy(NameStr(VacRel), vacrel);
|
strcpy(NameStr(VacRel), vacrel);
|
||||||
|
|
||||||
/* must also copy the column list, if any, to safe storage */
|
/* must also copy the column list, if any, to safe storage */
|
||||||
pmem = PortalGetVariableMemory(vc_portal);
|
pmem = CommonSpecialPortalGetMemory();
|
||||||
old = MemoryContextSwitchTo((MemoryContext) pmem);
|
old = MemoryContextSwitchTo((MemoryContext) pmem);
|
||||||
foreach(le, va_spec)
|
foreach(le, va_spec)
|
||||||
{
|
{
|
||||||
|
@ -179,24 +226,7 @@ vacuum(char *vacrel, bool verbose, bool analyze, List *va_spec)
|
||||||
static void
|
static void
|
||||||
vc_init()
|
vc_init()
|
||||||
{
|
{
|
||||||
char *pname;
|
CommonSpecialPortalOpen();
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a portal for safe memory across transactions. We need to
|
|
||||||
* palloc the name space for it because our hash function expects the
|
|
||||||
* name to be on a longword boundary. CreatePortal copies the name to
|
|
||||||
* safe storage for us.
|
|
||||||
*/
|
|
||||||
pname = pstrdup(VACPNAME);
|
|
||||||
vc_portal = CreatePortal(pname);
|
|
||||||
pfree(pname);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set flag to indicate that vc_portal must be removed after an error.
|
|
||||||
* This global variable is checked in the transaction manager on xact
|
|
||||||
* abort, and the routine vc_abort() is called if necessary.
|
|
||||||
*/
|
|
||||||
VacuumRunning = true;
|
|
||||||
|
|
||||||
/* matches the StartTransaction in PostgresMain() */
|
/* matches the StartTransaction in PostgresMain() */
|
||||||
CommitTransactionCommand();
|
CommitTransactionCommand();
|
||||||
|
@ -219,30 +249,12 @@ vc_shutdown()
|
||||||
*/
|
*/
|
||||||
unlink(RELCACHE_INIT_FILENAME);
|
unlink(RELCACHE_INIT_FILENAME);
|
||||||
|
|
||||||
/*
|
CommonSpecialPortalClose();
|
||||||
* Release our portal for cross-transaction memory.
|
|
||||||
*/
|
|
||||||
PortalDrop(&vc_portal);
|
|
||||||
|
|
||||||
/* okay, we're done */
|
|
||||||
VacuumRunning = false;
|
|
||||||
|
|
||||||
/* matches the CommitTransaction in PostgresMain() */
|
/* matches the CommitTransaction in PostgresMain() */
|
||||||
StartTransactionCommand();
|
StartTransactionCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
vc_abort()
|
|
||||||
{
|
|
||||||
/* Clear flag first, to avoid recursion if PortalDrop elog's */
|
|
||||||
VacuumRunning = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release our portal for cross-transaction memory.
|
|
||||||
*/
|
|
||||||
PortalDrop(&vc_portal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* vc_vacuum() -- vacuum the database.
|
* vc_vacuum() -- vacuum the database.
|
||||||
*
|
*
|
||||||
|
@ -302,7 +314,7 @@ vc_getrels(NameData *VacRelP)
|
||||||
F_CHAREQ, CharGetDatum('r'));
|
F_CHAREQ, CharGetDatum('r'));
|
||||||
}
|
}
|
||||||
|
|
||||||
portalmem = PortalGetVariableMemory(vc_portal);
|
portalmem = CommonSpecialPortalGetMemory();
|
||||||
vrl = cur = (VRelList) NULL;
|
vrl = cur = (VRelList) NULL;
|
||||||
|
|
||||||
rel = heap_openr(RelationRelationName, AccessShareLock);
|
rel = heap_openr(RelationRelationName, AccessShareLock);
|
||||||
|
@ -379,6 +391,7 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
|
||||||
int32 nindices,
|
int32 nindices,
|
||||||
i;
|
i;
|
||||||
VRelStats *vacrelstats;
|
VRelStats *vacrelstats;
|
||||||
|
bool reindex = false;
|
||||||
|
|
||||||
StartTransactionCommand();
|
StartTransactionCommand();
|
||||||
|
|
||||||
|
@ -552,17 +565,31 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
|
||||||
GetXmaxRecent(&XmaxRecent);
|
GetXmaxRecent(&XmaxRecent);
|
||||||
|
|
||||||
/* scan it */
|
/* scan it */
|
||||||
|
reindex = false;
|
||||||
vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;
|
vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;
|
||||||
vc_scanheap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
|
vc_scanheap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
|
||||||
|
if (IsIgnoringSystemIndexes() && IsSystemRelationName(RelationGetRelationName(onerel)))
|
||||||
|
reindex = true;
|
||||||
|
|
||||||
/* Now open indices */
|
/* Now open indices */
|
||||||
|
nindices = 0;
|
||||||
Irel = (Relation *) NULL;
|
Irel = (Relation *) NULL;
|
||||||
vc_getindices(vacrelstats->relid, &nindices, &Irel);
|
vc_getindices(vacrelstats->relid, &nindices, &Irel);
|
||||||
|
if (!Irel)
|
||||||
|
reindex = false;
|
||||||
|
else if (!RelationGetForm(onerel)->relhasindex)
|
||||||
|
reindex = true;
|
||||||
if (nindices > 0)
|
if (nindices > 0)
|
||||||
vacrelstats->hasindex = true;
|
vacrelstats->hasindex = true;
|
||||||
else
|
else
|
||||||
vacrelstats->hasindex = false;
|
vacrelstats->hasindex = false;
|
||||||
|
if (reindex)
|
||||||
|
{
|
||||||
|
for (i = 0; i < nindices; i++)
|
||||||
|
index_close(Irel[i]);
|
||||||
|
Irel = (Relation *) NULL;
|
||||||
|
activate_indexes_of_a_table(relid, false);
|
||||||
|
}
|
||||||
|
|
||||||
/* Clean/scan index relation(s) */
|
/* Clean/scan index relation(s) */
|
||||||
if (Irel != (Relation *) NULL)
|
if (Irel != (Relation *) NULL)
|
||||||
|
@ -590,6 +617,8 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
|
||||||
* vacuum_pages list */
|
* vacuum_pages list */
|
||||||
vc_vacheap(vacrelstats, onerel, &vacuum_pages);
|
vc_vacheap(vacrelstats, onerel, &vacuum_pages);
|
||||||
}
|
}
|
||||||
|
if (reindex)
|
||||||
|
activate_indexes_of_a_table(relid, true);
|
||||||
|
|
||||||
/* ok - free vacuum_pages list of reaped pages */
|
/* ok - free vacuum_pages list of reaped pages */
|
||||||
if (vacuum_pages.vpl_num_pages > 0)
|
if (vacuum_pages.vpl_num_pages > 0)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.53 2000/01/26 05:56:22 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.54 2000/02/18 09:29:57 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -48,8 +48,10 @@
|
||||||
#include "catalog/catname.h"
|
#include "catalog/catname.h"
|
||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "catalog/pg_index.h"
|
#include "catalog/pg_index.h"
|
||||||
|
#include "catalog/catalog.h"
|
||||||
#include "executor/execdebug.h"
|
#include "executor/execdebug.h"
|
||||||
#include "executor/executor.h"
|
#include "executor/executor.h"
|
||||||
|
#include "miscadmin.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);
|
||||||
|
@ -770,6 +772,12 @@ ExecOpenIndices(Oid resultRelationOid,
|
||||||
PredInfo *predicate;
|
PredInfo *predicate;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
resultRelationInfo->ri_NumIndices = 0;
|
||||||
|
if (!RelationGetForm(resultRelationInfo->ri_RelationDesc)->relhasindex)
|
||||||
|
return;
|
||||||
|
if (IsIgnoringSystemIndexes() &&
|
||||||
|
IsSystemRelationName(RelationGetRelationName(resultRelationInfo->ri_RelationDesc)))
|
||||||
|
return;
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* open pg_index
|
* open pg_index
|
||||||
* ----------------
|
* ----------------
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.46 2000/02/05 23:19:44 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.47 2000/02/18 09:29:57 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -1048,6 +1048,10 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||||
¤tRelation, /* return: rel desc */
|
¤tRelation, /* return: rel desc */
|
||||||
(Pointer *) ¤tScanDesc); /* return: scan desc */
|
(Pointer *) ¤tScanDesc); /* return: scan desc */
|
||||||
|
|
||||||
|
if (!RelationGetForm(currentRelation)->relhasindex)
|
||||||
|
{
|
||||||
|
elog(ERROR, "indexes of the relation %u was inactivated", reloid);
|
||||||
|
}
|
||||||
scanstate->css_currentRelation = currentRelation;
|
scanstate->css_currentRelation = currentRelation;
|
||||||
scanstate->css_currentScanDesc = currentScanDesc;
|
scanstate->css_currentScanDesc = currentScanDesc;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.48 2000/02/17 03:39:40 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.49 2000/02/18 09:30:09 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -29,6 +29,8 @@
|
||||||
#include "optimizer/plancat.h"
|
#include "optimizer/plancat.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
#include "catalog/catalog.h"
|
||||||
|
#include "miscadmin.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -55,7 +57,10 @@ relation_info(Query *root, Index relid,
|
||||||
relationObjectId);
|
relationObjectId);
|
||||||
relation = (Form_pg_class) GETSTRUCT(relationTuple);
|
relation = (Form_pg_class) GETSTRUCT(relationTuple);
|
||||||
|
|
||||||
*hasindex = (relation->relhasindex) ? true : false;
|
if (IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(relation->relname)))
|
||||||
|
*hasindex = false;
|
||||||
|
else
|
||||||
|
*hasindex = (relation->relhasindex) ? true : false;
|
||||||
*pages = relation->relpages;
|
*pages = relation->relpages;
|
||||||
*tuples = relation->reltuples;
|
*tuples = relation->reltuples;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.143 2000/02/16 17:24:36 thomas Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.144 2000/02/18 09:29:40 inoue Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
|
@ -124,7 +124,7 @@ static Node *doNegate(Node *n);
|
||||||
ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
|
ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
|
||||||
CreatePLangStmt, DropPLangStmt,
|
CreatePLangStmt, DropPLangStmt,
|
||||||
IndexStmt, ListenStmt, UnlistenStmt, LockStmt, OptimizableStmt,
|
IndexStmt, ListenStmt, UnlistenStmt, LockStmt, OptimizableStmt,
|
||||||
ProcedureStmt, RemoveAggrStmt, RemoveOperStmt,
|
ProcedureStmt, ReindexStmt, RemoveAggrStmt, RemoveOperStmt,
|
||||||
RemoveFuncStmt, RemoveStmt,
|
RemoveFuncStmt, RemoveStmt,
|
||||||
RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
|
RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
|
||||||
CreatedbStmt, DropdbStmt, VacuumStmt, CursorStmt, SubSelect,
|
CreatedbStmt, DropdbStmt, VacuumStmt, CursorStmt, SubSelect,
|
||||||
|
@ -141,7 +141,7 @@ static Node *doNegate(Node *n);
|
||||||
%type <ival> createdb_opt_encoding
|
%type <ival> createdb_opt_encoding
|
||||||
|
|
||||||
%type <ival> opt_lock, lock_type
|
%type <ival> opt_lock, lock_type
|
||||||
%type <boolean> opt_lmode
|
%type <boolean> opt_lmode, opt_force
|
||||||
|
|
||||||
%type <ival> user_createdb_clause, user_createuser_clause
|
%type <ival> user_createdb_clause, user_createuser_clause
|
||||||
%type <str> user_passwd_clause
|
%type <str> user_passwd_clause
|
||||||
|
@ -211,7 +211,7 @@ static Node *doNegate(Node *n);
|
||||||
opt_with_copy, index_opt_unique, opt_verbose, opt_analyze
|
opt_with_copy, index_opt_unique, opt_verbose, opt_analyze
|
||||||
%type <boolean> opt_cursor
|
%type <boolean> opt_cursor
|
||||||
|
|
||||||
%type <ival> copy_dirn, def_type, direction, remove_type,
|
%type <ival> copy_dirn, def_type, direction, reindex_type, remove_type,
|
||||||
opt_column, event, comment_type, comment_cl,
|
opt_column, event, comment_type, comment_cl,
|
||||||
comment_ag, comment_fn, comment_op, comment_tg
|
comment_ag, comment_fn, comment_op, comment_tg
|
||||||
|
|
||||||
|
@ -339,13 +339,13 @@ static Node *doNegate(Node *n);
|
||||||
CACHE, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
|
CACHE, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
|
||||||
DATABASE, DELIMITERS, DO,
|
DATABASE, DELIMITERS, DO,
|
||||||
EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
|
EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
|
||||||
FORWARD, FUNCTION, HANDLER,
|
FORCE, FORWARD, FUNCTION, HANDLER,
|
||||||
INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
|
INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
|
||||||
LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
|
LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
|
||||||
MAXVALUE, MINVALUE, MODE, MOVE,
|
MAXVALUE, MINVALUE, MODE, MOVE,
|
||||||
NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
|
NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
|
||||||
OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL,
|
OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL,
|
||||||
RENAME, RESET, RETURNS, ROW, RULE,
|
REINDEX, RENAME, RESET, RETURNS, ROW, RULE,
|
||||||
SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, SYSID,
|
SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, SYSID,
|
||||||
TRUNCATE, TRUSTED,
|
TRUNCATE, TRUSTED,
|
||||||
UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
|
UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
|
||||||
|
@ -440,6 +440,7 @@ stmt : AlterTableStmt
|
||||||
| UnlistenStmt
|
| UnlistenStmt
|
||||||
| LockStmt
|
| LockStmt
|
||||||
| ProcedureStmt
|
| ProcedureStmt
|
||||||
|
| ReindexStmt
|
||||||
| RemoveAggrStmt
|
| RemoveAggrStmt
|
||||||
| RemoveOperStmt
|
| RemoveOperStmt
|
||||||
| RemoveFuncStmt
|
| RemoveFuncStmt
|
||||||
|
@ -2445,6 +2446,35 @@ oper_argtypes: name
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* QUERY:
|
||||||
|
*
|
||||||
|
* REINDEX type <typename> [FORCE] [ALL]
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
ReindexStmt: REINDEX reindex_type name opt_force
|
||||||
|
{
|
||||||
|
ReindexStmt *n = makeNode(ReindexStmt);
|
||||||
|
if (IsTransactionBlock())
|
||||||
|
elog(ERROR,"REINDEX command could only be used outside begin/end transaction blocks");
|
||||||
|
n->reindexType = $2;
|
||||||
|
n->name = $3;
|
||||||
|
n->force = $4;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
reindex_type: INDEX { $$ = INDEX; }
|
||||||
|
| TABLE { $$ = TABLE; }
|
||||||
|
| DATABASE { $$ = DATABASE; }
|
||||||
|
;
|
||||||
|
opt_force: FORCE { $$ = TRUE; }
|
||||||
|
| /* EMPTY */ { $$ = FALSE; }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* QUERY:
|
* QUERY:
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.66 2000/02/15 03:26:38 thomas Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.67 2000/02/18 09:29:40 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -107,6 +107,7 @@ static ScanKeyword ScanKeywords[] = {
|
||||||
{"fetch", FETCH},
|
{"fetch", FETCH},
|
||||||
{"float", FLOAT},
|
{"float", FLOAT},
|
||||||
{"for", FOR},
|
{"for", FOR},
|
||||||
|
{"force", FORCE},
|
||||||
{"foreign", FOREIGN},
|
{"foreign", FOREIGN},
|
||||||
{"forward", FORWARD},
|
{"forward", FORWARD},
|
||||||
{"from", FROM},
|
{"from", FROM},
|
||||||
|
@ -196,6 +197,7 @@ static ScanKeyword ScanKeywords[] = {
|
||||||
{"public", PUBLIC},
|
{"public", PUBLIC},
|
||||||
{"read", READ},
|
{"read", READ},
|
||||||
{"references", REFERENCES},
|
{"references", REFERENCES},
|
||||||
|
{"reindex", REINDEX},
|
||||||
{"relative", RELATIVE},
|
{"relative", RELATIVE},
|
||||||
{"rename", RENAME},
|
{"rename", RENAME},
|
||||||
{"reset", RESET},
|
{"reset", RESET},
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.135 2000/01/26 05:56:48 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.136 2000/02/18 09:28:44 inoue Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
*
|
*
|
||||||
|
@ -430,6 +430,7 @@ PostmasterMain(int argc, char *argv[])
|
||||||
DataDir = getenv("PGDATA"); /* default value */
|
DataDir = getenv("PGDATA"); /* default value */
|
||||||
|
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
|
IgnoreSystemIndexes(false);
|
||||||
while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:d:ilm:MN:no:p:Ss")) != EOF)
|
while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:d:ilm:MN:no:p:Ss")) != EOF)
|
||||||
{
|
{
|
||||||
switch (opt)
|
switch (opt)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.141 2000/01/26 05:57:07 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.142 2000/02/18 09:29:27 inoue Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* this is the "main" module of the postgres backend and
|
* this is the "main" module of the postgres backend and
|
||||||
|
@ -963,7 +963,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||||
optind = 1; /* reset after postmaster's usage */
|
optind = 1; /* reset after postmaster's usage */
|
||||||
|
|
||||||
while ((flag = getopt(argc, argv,
|
while ((flag = getopt(argc, argv,
|
||||||
"A:B:CD:d:EeFf:iK:LNOo:p:QS:sT:t:v:W:x:"))
|
"A:B:CD:d:EeFf:iK:LNOPo:p:QS:sT:t:v:W:x:"))
|
||||||
!= EOF)
|
!= EOF)
|
||||||
switch (flag)
|
switch (flag)
|
||||||
{
|
{
|
||||||
|
@ -1116,6 +1116,15 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||||
allowSystemTableMods = true;
|
allowSystemTableMods = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
/* --------------------
|
||||||
|
* ignore system indexes
|
||||||
|
* --------------------
|
||||||
|
*/
|
||||||
|
if (secure) /* XXX safe to allow from client??? */
|
||||||
|
IgnoreSystemIndexes(true);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* o - send output (stdout and stderr) to the given file
|
* o - send output (stdout and stderr) to the given file
|
||||||
|
@ -1516,7 +1525,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||||
if (!IsUnderPostmaster)
|
if (!IsUnderPostmaster)
|
||||||
{
|
{
|
||||||
puts("\nPOSTGRES backend interactive interface ");
|
puts("\nPOSTGRES backend interactive interface ");
|
||||||
puts("$Revision: 1.141 $ $Date: 2000/01/26 05:57:07 $\n");
|
puts("$Revision: 1.142 $ $Date: 2000/02/18 09:29:27 $\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.82 2000/01/29 16:58:38 petere Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.83 2000/02/18 09:29:31 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -846,6 +846,61 @@ ProcessUtility(Node *parsetree,
|
||||||
DropGroup((DropGroupStmt *) parsetree);
|
DropGroup((DropGroupStmt *) parsetree);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_ReindexStmt:
|
||||||
|
{
|
||||||
|
ReindexStmt *stmt = (ReindexStmt *) parsetree;
|
||||||
|
|
||||||
|
PS_SET_STATUS(commandTag = "REINDEX");
|
||||||
|
CHECK_IF_ABORTED();
|
||||||
|
|
||||||
|
switch (stmt->reindexType)
|
||||||
|
{
|
||||||
|
case INDEX:
|
||||||
|
relname = stmt->name;
|
||||||
|
if (IsSystemRelationName(relname))
|
||||||
|
{
|
||||||
|
if (!allowSystemTableMods && IsSystemRelationName(relname))
|
||||||
|
elog(ERROR, "class \"%s\" is a system catalog index",
|
||||||
|
relname);
|
||||||
|
if (!IsIgnoringSystemIndexes())
|
||||||
|
elog(ERROR, "class \"%s\" is a system catalog index",
|
||||||
|
relname);
|
||||||
|
}
|
||||||
|
#ifndef NO_SECURITY
|
||||||
|
if (!pg_ownercheck(userName, relname, RELNAME))
|
||||||
|
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
||||||
|
#endif
|
||||||
|
ReindexIndex(relname, stmt->force);
|
||||||
|
break;
|
||||||
|
case TABLE:
|
||||||
|
relname = stmt->name;
|
||||||
|
if (IsSystemRelationName(relname))
|
||||||
|
{
|
||||||
|
if (!allowSystemTableMods && IsSystemRelationName(relname))
|
||||||
|
elog(ERROR, "class \"%s\" is a system catalog index",
|
||||||
|
relname);
|
||||||
|
if (!IsIgnoringSystemIndexes())
|
||||||
|
elog(ERROR, "class \"%s\" is a system catalog index",
|
||||||
|
relname);
|
||||||
|
}
|
||||||
|
#ifndef NO_SECURITY
|
||||||
|
if (!pg_ownercheck(userName, relname, RELNAME))
|
||||||
|
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
||||||
|
#endif
|
||||||
|
ReindexTable(relname, stmt->force);
|
||||||
|
break;
|
||||||
|
case DATABASE:
|
||||||
|
relname = stmt->name;
|
||||||
|
if (!allowSystemTableMods)
|
||||||
|
elog(ERROR, "-O option is needed");
|
||||||
|
if (!IsIgnoringSystemIndexes())
|
||||||
|
elog(ERROR, "-P option is needed");
|
||||||
|
ReindexDatabase(relname, stmt->force, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
/*
|
/*
|
||||||
* ******************************** default ********************************
|
* ******************************** default ********************************
|
||||||
*
|
*
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.51 2000/01/26 05:57:14 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.52 2000/02/18 09:28:48 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -45,7 +45,7 @@ regprocin(char *pro_name_or_oid)
|
||||||
if (pro_name_or_oid[0] == '-' && pro_name_or_oid[1] == '\0')
|
if (pro_name_or_oid[0] == '-' && pro_name_or_oid[1] == '\0')
|
||||||
return InvalidOid;
|
return InvalidOid;
|
||||||
|
|
||||||
if (!IsBootstrapProcessingMode())
|
if (!IsIgnoringSystemIndexes())
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.60 2000/02/04 03:16:03 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.61 2000/02/18 09:28:53 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -233,7 +233,7 @@ CatalogCacheInitializeCache(struct catcache * cache,
|
||||||
*/
|
*/
|
||||||
if (cache->cc_indname != NULL && cache->indexId == InvalidOid)
|
if (cache->cc_indname != NULL && cache->indexId == InvalidOid)
|
||||||
{
|
{
|
||||||
if (RelationGetForm(relation)->relhasindex)
|
if (!IsIgnoringSystemIndexes() && RelationGetForm(relation)->relhasindex)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -817,14 +817,19 @@ SearchSelfReferences(struct catcache * cache)
|
||||||
|
|
||||||
if (!OidIsValid(indexSelfOid))
|
if (!OidIsValid(indexSelfOid))
|
||||||
{
|
{
|
||||||
|
ScanKeyData key;
|
||||||
|
HeapScanDesc sd;
|
||||||
/* Find oid of pg_index_indexrelid_index */
|
/* Find oid of pg_index_indexrelid_index */
|
||||||
rel = heap_openr(RelationRelationName, AccessShareLock);
|
rel = heap_openr(RelationRelationName, AccessShareLock);
|
||||||
ntp = ClassNameIndexScan(rel, IndexRelidIndex);
|
ScanKeyEntryInitialize(&key, 0, Anum_pg_class_relname,
|
||||||
|
F_NAMEEQ, PointerGetDatum(IndexRelidIndex));
|
||||||
|
sd = heap_beginscan(rel, false, SnapshotNow, 1, &key);
|
||||||
|
ntp = heap_getnext(sd, 0);
|
||||||
if (!HeapTupleIsValid(ntp))
|
if (!HeapTupleIsValid(ntp))
|
||||||
elog(ERROR, "SearchSelfReferences: %s not found in %s",
|
elog(ERROR, "SearchSelfReferences: %s not found in %s",
|
||||||
IndexRelidIndex, RelationRelationName);
|
IndexRelidIndex, RelationRelationName);
|
||||||
indexSelfOid = ntp->t_data->t_oid;
|
indexSelfOid = ntp->t_data->t_oid;
|
||||||
heap_freetuple(ntp);
|
heap_endscan(sd);
|
||||||
heap_close(rel, AccessShareLock);
|
heap_close(rel, AccessShareLock);
|
||||||
}
|
}
|
||||||
/* Looking for something other than pg_index_indexrelid_index? */
|
/* Looking for something other than pg_index_indexrelid_index? */
|
||||||
|
@ -1031,7 +1036,7 @@ SearchSysCache(struct catcache * cache,
|
||||||
CACHE1_elog(DEBUG, "SearchSysCache: performing scan");
|
CACHE1_elog(DEBUG, "SearchSysCache: performing scan");
|
||||||
|
|
||||||
if ((RelationGetForm(relation))->relhasindex
|
if ((RelationGetForm(relation))->relhasindex
|
||||||
&& !IsBootstrapProcessingMode())
|
&& !IsIgnoringSystemIndexes())
|
||||||
{
|
{
|
||||||
/* ----------
|
/* ----------
|
||||||
* Switch back to old memory context so memory not freed
|
* Switch back to old memory context so memory not freed
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.89 2000/01/31 04:35:52 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.90 2000/02/18 09:28:55 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -229,6 +229,7 @@ static void IndexedAccessMethodInitialize(Relation relation);
|
||||||
static void AttrDefaultFetch(Relation relation);
|
static void AttrDefaultFetch(Relation relation);
|
||||||
static void RelCheckFetch(Relation relation);
|
static void RelCheckFetch(Relation relation);
|
||||||
|
|
||||||
|
static bool criticalRelcacheBuild = false;
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* RelationIdGetRelation() and RelationNameGetRelation()
|
* RelationIdGetRelation() and RelationNameGetRelation()
|
||||||
* support functions
|
* support functions
|
||||||
|
@ -254,7 +255,7 @@ ScanPgRelation(RelationBuildDescInfo buildinfo)
|
||||||
* can, and do.
|
* can, and do.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (IsBootstrapProcessingMode())
|
if (IsIgnoringSystemIndexes() || !criticalRelcacheBuild)
|
||||||
return scan_pg_rel_seq(buildinfo);
|
return scan_pg_rel_seq(buildinfo);
|
||||||
else
|
else
|
||||||
return scan_pg_rel_ind(buildinfo);
|
return scan_pg_rel_ind(buildinfo);
|
||||||
|
@ -424,12 +425,50 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
|
||||||
* can, and do.
|
* can, and do.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (IsBootstrapProcessingMode())
|
if (IsIgnoringSystemIndexes() || !criticalRelcacheBuild)
|
||||||
build_tupdesc_seq(buildinfo, relation, natts);
|
build_tupdesc_seq(buildinfo, relation, natts);
|
||||||
else
|
else
|
||||||
build_tupdesc_ind(buildinfo, relation, natts);
|
build_tupdesc_ind(buildinfo, relation, natts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SetConstrOfRelation(Relation relation, TupleConstr *constr, int ndef, AttrDefault *attrdef)
|
||||||
|
{
|
||||||
|
if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
|
||||||
|
{
|
||||||
|
relation->rd_att->constr = constr;
|
||||||
|
|
||||||
|
if (ndef > 0) /* DEFAULTs */
|
||||||
|
{
|
||||||
|
if (ndef < relation->rd_rel->relnatts)
|
||||||
|
constr->defval = (AttrDefault *)
|
||||||
|
repalloc(attrdef, ndef * sizeof(AttrDefault));
|
||||||
|
else
|
||||||
|
constr->defval = attrdef;
|
||||||
|
constr->num_defval = ndef;
|
||||||
|
AttrDefaultFetch(relation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
constr->num_defval = 0;
|
||||||
|
|
||||||
|
if (relation->rd_rel->relchecks > 0) /* CHECKs */
|
||||||
|
{
|
||||||
|
constr->num_check = relation->rd_rel->relchecks;
|
||||||
|
constr->check = (ConstrCheck *) palloc(constr->num_check *
|
||||||
|
sizeof(ConstrCheck));
|
||||||
|
MemSet(constr->check, 0, constr->num_check * sizeof(ConstrCheck));
|
||||||
|
RelCheckFetch(relation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
constr->num_check = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pfree(constr);
|
||||||
|
relation->rd_att->constr = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
build_tupdesc_seq(RelationBuildDescInfo buildinfo,
|
build_tupdesc_seq(RelationBuildDescInfo buildinfo,
|
||||||
Relation relation,
|
Relation relation,
|
||||||
|
@ -441,7 +480,11 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
|
||||||
Form_pg_attribute attp;
|
Form_pg_attribute attp;
|
||||||
ScanKeyData key;
|
ScanKeyData key;
|
||||||
int need;
|
int need;
|
||||||
|
TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
|
||||||
|
AttrDefault *attrdef = NULL;
|
||||||
|
int ndef = 0;
|
||||||
|
|
||||||
|
constr->has_not_null = false;
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* form a scan key
|
* form a scan key
|
||||||
* ----------------
|
* ----------------
|
||||||
|
@ -478,6 +521,23 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
|
||||||
(char *) attp,
|
(char *) attp,
|
||||||
ATTRIBUTE_TUPLE_SIZE);
|
ATTRIBUTE_TUPLE_SIZE);
|
||||||
need--;
|
need--;
|
||||||
|
/* Update if this attribute have a constraint */
|
||||||
|
if (attp->attnotnull)
|
||||||
|
constr->has_not_null = true;
|
||||||
|
|
||||||
|
if (attp->atthasdef)
|
||||||
|
{
|
||||||
|
if (attrdef == NULL)
|
||||||
|
{
|
||||||
|
attrdef = (AttrDefault *) palloc(relation->rd_rel->relnatts *
|
||||||
|
sizeof(AttrDefault));
|
||||||
|
MemSet(attrdef, 0,
|
||||||
|
relation->rd_rel->relnatts * sizeof(AttrDefault));
|
||||||
|
}
|
||||||
|
attrdef[ndef].adnum = attp->attnum;
|
||||||
|
attrdef[ndef].adbin = NULL;
|
||||||
|
ndef++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0);
|
pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0);
|
||||||
}
|
}
|
||||||
|
@ -492,6 +552,8 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
|
||||||
*/
|
*/
|
||||||
heap_endscan(pg_attribute_scan);
|
heap_endscan(pg_attribute_scan);
|
||||||
heap_close(pg_attribute_desc, AccessShareLock);
|
heap_close(pg_attribute_desc, AccessShareLock);
|
||||||
|
|
||||||
|
SetConstrOfRelation(relation, constr, ndef, attrdef);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -549,39 +611,7 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
|
||||||
|
|
||||||
heap_close(attrel, AccessShareLock);
|
heap_close(attrel, AccessShareLock);
|
||||||
|
|
||||||
if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
|
SetConstrOfRelation(relation, constr, ndef, attrdef);
|
||||||
{
|
|
||||||
relation->rd_att->constr = constr;
|
|
||||||
|
|
||||||
if (ndef > 0) /* DEFAULTs */
|
|
||||||
{
|
|
||||||
if (ndef < relation->rd_rel->relnatts)
|
|
||||||
constr->defval = (AttrDefault *)
|
|
||||||
repalloc(attrdef, ndef * sizeof(AttrDefault));
|
|
||||||
else
|
|
||||||
constr->defval = attrdef;
|
|
||||||
constr->num_defval = ndef;
|
|
||||||
AttrDefaultFetch(relation);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
constr->num_defval = 0;
|
|
||||||
|
|
||||||
if (relation->rd_rel->relchecks > 0) /* CHECKs */
|
|
||||||
{
|
|
||||||
constr->num_check = relation->rd_rel->relchecks;
|
|
||||||
constr->check = (ConstrCheck *) palloc(constr->num_check *
|
|
||||||
sizeof(ConstrCheck));
|
|
||||||
MemSet(constr->check, 0, constr->num_check * sizeof(ConstrCheck));
|
|
||||||
RelCheckFetch(relation);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
constr->num_check = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pfree(constr);
|
|
||||||
relation->rd_att->constr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1806,16 +1836,19 @@ AttrDefaultFetch(Relation relation)
|
||||||
AttrDefault *attrdef = relation->rd_att->constr->defval;
|
AttrDefault *attrdef = relation->rd_att->constr->defval;
|
||||||
int ndef = relation->rd_att->constr->num_defval;
|
int ndef = relation->rd_att->constr->num_defval;
|
||||||
Relation adrel;
|
Relation adrel;
|
||||||
Relation irel;
|
Relation irel = (Relation) NULL;
|
||||||
ScanKeyData skey;
|
ScanKeyData skey;
|
||||||
HeapTupleData tuple;
|
HeapTupleData tuple;
|
||||||
|
HeapTuple htup;
|
||||||
Form_pg_attrdef adform;
|
Form_pg_attrdef adform;
|
||||||
IndexScanDesc sd;
|
IndexScanDesc sd = (IndexScanDesc) NULL;
|
||||||
|
HeapScanDesc adscan = (HeapScanDesc) NULL;
|
||||||
RetrieveIndexResult indexRes;
|
RetrieveIndexResult indexRes;
|
||||||
struct varlena *val;
|
struct varlena *val;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
int found;
|
int found;
|
||||||
int i;
|
int i;
|
||||||
|
bool hasindex;
|
||||||
|
|
||||||
ScanKeyEntryInitialize(&skey,
|
ScanKeyEntryInitialize(&skey,
|
||||||
(bits16) 0x0,
|
(bits16) 0x0,
|
||||||
|
@ -1824,8 +1857,14 @@ AttrDefaultFetch(Relation relation)
|
||||||
ObjectIdGetDatum(RelationGetRelid(relation)));
|
ObjectIdGetDatum(RelationGetRelid(relation)));
|
||||||
|
|
||||||
adrel = heap_openr(AttrDefaultRelationName, AccessShareLock);
|
adrel = heap_openr(AttrDefaultRelationName, AccessShareLock);
|
||||||
irel = index_openr(AttrDefaultIndex);
|
hasindex = (adrel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
|
||||||
sd = index_beginscan(irel, false, 1, &skey);
|
if (hasindex)
|
||||||
|
{
|
||||||
|
irel = index_openr(AttrDefaultIndex);
|
||||||
|
sd = index_beginscan(irel, false, 1, &skey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
adscan = heap_beginscan(adrel, false, SnapshotNow, 1, &skey);
|
||||||
tuple.t_datamcxt = NULL;
|
tuple.t_datamcxt = NULL;
|
||||||
tuple.t_data = NULL;
|
tuple.t_data = NULL;
|
||||||
|
|
||||||
|
@ -1833,17 +1872,27 @@ AttrDefaultFetch(Relation relation)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
|
|
||||||
indexRes = index_getnext(sd, ForwardScanDirection);
|
if (hasindex)
|
||||||
if (!indexRes)
|
{
|
||||||
break;
|
indexRes = index_getnext(sd, ForwardScanDirection);
|
||||||
|
if (!indexRes)
|
||||||
|
break;
|
||||||
|
|
||||||
tuple.t_self = indexRes->heap_iptr;
|
tuple.t_self = indexRes->heap_iptr;
|
||||||
heap_fetch(adrel, SnapshotNow, &tuple, &buffer);
|
heap_fetch(adrel, SnapshotNow, &tuple, &buffer);
|
||||||
pfree(indexRes);
|
pfree(indexRes);
|
||||||
if (tuple.t_data == NULL)
|
if (tuple.t_data == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
htup = &tuple;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
htup = heap_getnext(adscan, 0);
|
||||||
|
if (!HeapTupleIsValid(htup))
|
||||||
|
break;
|
||||||
|
}
|
||||||
found++;
|
found++;
|
||||||
adform = (Form_pg_attrdef) GETSTRUCT(&tuple);
|
adform = (Form_pg_attrdef) GETSTRUCT(htup);
|
||||||
for (i = 0; i < ndef; i++)
|
for (i = 0; i < ndef; i++)
|
||||||
{
|
{
|
||||||
if (adform->adnum != attrdef[i].adnum)
|
if (adform->adnum != attrdef[i].adnum)
|
||||||
|
@ -1853,7 +1902,7 @@ AttrDefaultFetch(Relation relation)
|
||||||
NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
|
NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
|
||||||
RelationGetRelationName(relation));
|
RelationGetRelationName(relation));
|
||||||
|
|
||||||
val = (struct varlena *) fastgetattr(&tuple,
|
val = (struct varlena *) fastgetattr(htup,
|
||||||
Anum_pg_attrdef_adbin,
|
Anum_pg_attrdef_adbin,
|
||||||
adrel->rd_att, &isnull);
|
adrel->rd_att, &isnull);
|
||||||
if (isnull)
|
if (isnull)
|
||||||
|
@ -1863,7 +1912,8 @@ AttrDefaultFetch(Relation relation)
|
||||||
attrdef[i].adbin = textout(val);
|
attrdef[i].adbin = textout(val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ReleaseBuffer(buffer);
|
if (hasindex)
|
||||||
|
ReleaseBuffer(buffer);
|
||||||
|
|
||||||
if (i >= ndef)
|
if (i >= ndef)
|
||||||
elog(NOTICE, "AttrDefaultFetch: unexpected record found for attr %d in rel %s",
|
elog(NOTICE, "AttrDefaultFetch: unexpected record found for attr %d in rel %s",
|
||||||
|
@ -1875,8 +1925,13 @@ AttrDefaultFetch(Relation relation)
|
||||||
elog(NOTICE, "AttrDefaultFetch: %d record not found for rel %s",
|
elog(NOTICE, "AttrDefaultFetch: %d record not found for rel %s",
|
||||||
ndef - found, RelationGetRelationName(relation));
|
ndef - found, RelationGetRelationName(relation));
|
||||||
|
|
||||||
index_endscan(sd);
|
if (hasindex)
|
||||||
index_close(irel);
|
{
|
||||||
|
index_endscan(sd);
|
||||||
|
index_close(irel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
heap_endscan(adscan);
|
||||||
heap_close(adrel, AccessShareLock);
|
heap_close(adrel, AccessShareLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1886,15 +1941,18 @@ RelCheckFetch(Relation relation)
|
||||||
ConstrCheck *check = relation->rd_att->constr->check;
|
ConstrCheck *check = relation->rd_att->constr->check;
|
||||||
int ncheck = relation->rd_att->constr->num_check;
|
int ncheck = relation->rd_att->constr->num_check;
|
||||||
Relation rcrel;
|
Relation rcrel;
|
||||||
Relation irel;
|
Relation irel = (Relation)NULL;
|
||||||
ScanKeyData skey;
|
ScanKeyData skey;
|
||||||
HeapTupleData tuple;
|
HeapTupleData tuple;
|
||||||
IndexScanDesc sd;
|
HeapTuple htup;
|
||||||
|
IndexScanDesc sd = (IndexScanDesc)NULL;
|
||||||
|
HeapScanDesc rcscan = (HeapScanDesc)NULL;
|
||||||
RetrieveIndexResult indexRes;
|
RetrieveIndexResult indexRes;
|
||||||
Name rcname;
|
Name rcname;
|
||||||
struct varlena *val;
|
struct varlena *val;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
int found;
|
int found;
|
||||||
|
bool hasindex;
|
||||||
|
|
||||||
ScanKeyEntryInitialize(&skey,
|
ScanKeyEntryInitialize(&skey,
|
||||||
(bits16) 0x0,
|
(bits16) 0x0,
|
||||||
|
@ -1903,8 +1961,14 @@ RelCheckFetch(Relation relation)
|
||||||
ObjectIdGetDatum(RelationGetRelid(relation)));
|
ObjectIdGetDatum(RelationGetRelid(relation)));
|
||||||
|
|
||||||
rcrel = heap_openr(RelCheckRelationName, AccessShareLock);
|
rcrel = heap_openr(RelCheckRelationName, AccessShareLock);
|
||||||
irel = index_openr(RelCheckIndex);
|
hasindex = (rcrel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
|
||||||
sd = index_beginscan(irel, false, 1, &skey);
|
if (hasindex)
|
||||||
|
{
|
||||||
|
irel = index_openr(RelCheckIndex);
|
||||||
|
sd = index_beginscan(irel, false, 1, &skey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rcscan = heap_beginscan(rcrel, false, SnapshotNow, 1, &skey);
|
||||||
tuple.t_datamcxt = NULL;
|
tuple.t_datamcxt = NULL;
|
||||||
tuple.t_data = NULL;
|
tuple.t_data = NULL;
|
||||||
|
|
||||||
|
@ -1912,27 +1976,37 @@ RelCheckFetch(Relation relation)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
|
|
||||||
indexRes = index_getnext(sd, ForwardScanDirection);
|
if (hasindex)
|
||||||
if (!indexRes)
|
{
|
||||||
break;
|
indexRes = index_getnext(sd, ForwardScanDirection);
|
||||||
|
if (!indexRes)
|
||||||
|
break;
|
||||||
|
|
||||||
tuple.t_self = indexRes->heap_iptr;
|
tuple.t_self = indexRes->heap_iptr;
|
||||||
heap_fetch(rcrel, SnapshotNow, &tuple, &buffer);
|
heap_fetch(rcrel, SnapshotNow, &tuple, &buffer);
|
||||||
pfree(indexRes);
|
pfree(indexRes);
|
||||||
if (tuple.t_data == NULL)
|
if (tuple.t_data == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
htup = &tuple;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
htup = heap_getnext(rcscan, 0);
|
||||||
|
if (!HeapTupleIsValid(htup))
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (found == ncheck)
|
if (found == ncheck)
|
||||||
elog(ERROR, "RelCheckFetch: unexpected record found for rel %s",
|
elog(ERROR, "RelCheckFetch: unexpected record found for rel %s",
|
||||||
RelationGetRelationName(relation));
|
RelationGetRelationName(relation));
|
||||||
|
|
||||||
rcname = (Name) fastgetattr(&tuple,
|
rcname = (Name) fastgetattr(htup,
|
||||||
Anum_pg_relcheck_rcname,
|
Anum_pg_relcheck_rcname,
|
||||||
rcrel->rd_att, &isnull);
|
rcrel->rd_att, &isnull);
|
||||||
if (isnull)
|
if (isnull)
|
||||||
elog(ERROR, "RelCheckFetch: rcname IS NULL for rel %s",
|
elog(ERROR, "RelCheckFetch: rcname IS NULL for rel %s",
|
||||||
RelationGetRelationName(relation));
|
RelationGetRelationName(relation));
|
||||||
check[found].ccname = pstrdup(NameStr(*rcname));
|
check[found].ccname = pstrdup(NameStr(*rcname));
|
||||||
val = (struct varlena *) fastgetattr(&tuple,
|
val = (struct varlena *) fastgetattr(htup,
|
||||||
Anum_pg_relcheck_rcbin,
|
Anum_pg_relcheck_rcbin,
|
||||||
rcrel->rd_att, &isnull);
|
rcrel->rd_att, &isnull);
|
||||||
if (isnull)
|
if (isnull)
|
||||||
|
@ -1940,15 +2014,21 @@ RelCheckFetch(Relation relation)
|
||||||
RelationGetRelationName(relation));
|
RelationGetRelationName(relation));
|
||||||
check[found].ccbin = textout(val);
|
check[found].ccbin = textout(val);
|
||||||
found++;
|
found++;
|
||||||
ReleaseBuffer(buffer);
|
if (hasindex)
|
||||||
|
ReleaseBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found < ncheck)
|
if (found < ncheck)
|
||||||
elog(ERROR, "RelCheckFetch: %d record not found for rel %s",
|
elog(ERROR, "RelCheckFetch: %d record not found for rel %s",
|
||||||
ncheck - found, RelationGetRelationName(relation));
|
ncheck - found, RelationGetRelationName(relation));
|
||||||
|
|
||||||
index_endscan(sd);
|
if (hasindex)
|
||||||
index_close(irel);
|
{
|
||||||
|
index_endscan(sd);
|
||||||
|
index_close(irel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
heap_endscan(rcscan);
|
||||||
heap_close(rcrel, AccessShareLock);
|
heap_close(rcrel, AccessShareLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2148,6 +2228,7 @@ init_irels(void)
|
||||||
|
|
||||||
RelationCacheInsert(ird);
|
RelationCacheInsert(ird);
|
||||||
}
|
}
|
||||||
|
criticalRelcacheBuild = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2162,7 +2243,6 @@ write_irels(void)
|
||||||
Form_pg_class relform;
|
Form_pg_class relform;
|
||||||
IndexStrategy strat;
|
IndexStrategy strat;
|
||||||
RegProcedure *support;
|
RegProcedure *support;
|
||||||
ProcessingMode oldmode;
|
|
||||||
int i;
|
int i;
|
||||||
int relno;
|
int relno;
|
||||||
RelationBuildDescInfo bi;
|
RelationBuildDescInfo bi;
|
||||||
|
@ -2186,8 +2266,13 @@ write_irels(void)
|
||||||
* descriptors, nail them into cache so we never lose them.
|
* descriptors, nail them into cache so we never lose them.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Removed the following ProcessingMode change -- inoue
|
||||||
|
* At this point
|
||||||
|
* 1) Catalog Cache isn't initialized
|
||||||
|
* 2) Relation Cache for the following critical indexes aren't built
|
||||||
oldmode = GetProcessingMode();
|
oldmode = GetProcessingMode();
|
||||||
SetProcessingMode(BootstrapProcessing);
|
SetProcessingMode(BootstrapProcessing);
|
||||||
|
*/
|
||||||
|
|
||||||
bi.infotype = INFO_RELNAME;
|
bi.infotype = INFO_RELNAME;
|
||||||
bi.i.info_name = AttributeRelidNumIndex;
|
bi.i.info_name = AttributeRelidNumIndex;
|
||||||
|
@ -2202,7 +2287,10 @@ write_irels(void)
|
||||||
irel[2] = RelationBuildDesc(bi, NULL);
|
irel[2] = RelationBuildDesc(bi, NULL);
|
||||||
irel[2]->rd_isnailed = true;
|
irel[2]->rd_isnailed = true;
|
||||||
|
|
||||||
|
criticalRelcacheBuild = true;
|
||||||
|
/* Removed the following ProcessingMode -- inoue
|
||||||
SetProcessingMode(oldmode);
|
SetProcessingMode(oldmode);
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write out the index reldescs to the special cache file.
|
* Write out the index reldescs to the special cache file.
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.48 2000/01/26 05:57:18 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.49 2000/02/18 09:28:56 inoue Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* These routines allow the parser/planner/executor to perform
|
* These routines allow the parser/planner/executor to perform
|
||||||
|
@ -39,6 +39,7 @@
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "utils/catcache.h"
|
#include "utils/catcache.h"
|
||||||
#include "utils/temprel.h"
|
#include "utils/temprel.h"
|
||||||
|
#include "miscadmin.h"
|
||||||
|
|
||||||
extern bool AMI_OVERRIDE; /* XXX style */
|
extern bool AMI_OVERRIDE; /* XXX style */
|
||||||
|
|
||||||
|
@ -395,6 +396,11 @@ static struct cachedesc cacheinfo[] = {
|
||||||
|
|
||||||
static struct catcache *SysCache[lengthof(cacheinfo)];
|
static struct catcache *SysCache[lengthof(cacheinfo)];
|
||||||
static int32 SysCacheSize = lengthof(cacheinfo);
|
static int32 SysCacheSize = lengthof(cacheinfo);
|
||||||
|
static bool CacheInitialized = false;
|
||||||
|
extern bool IsCacheInitialized(void)
|
||||||
|
{
|
||||||
|
return CacheInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -442,6 +448,7 @@ InitCatalogCache()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CacheInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.43 2000/01/26 05:57:26 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.44 2000/02/18 09:28:58 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -38,6 +38,33 @@ unsigned char RecodeBackTable[128];
|
||||||
|
|
||||||
ProcessingMode Mode = InitProcessing;
|
ProcessingMode Mode = InitProcessing;
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------
|
||||||
|
* ignoring system indexes support stuff
|
||||||
|
* ----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool isIgnoringSystemIndexes = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IsIgnoringSystemIndexes
|
||||||
|
* True if ignoring system indexes.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsIgnoringSystemIndexes()
|
||||||
|
{
|
||||||
|
return isIgnoringSystemIndexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IgnoreSystemIndexes
|
||||||
|
* Set true or false whether PostgreSQL ignores system indexes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
IgnoreSystemIndexes(bool mode)
|
||||||
|
{
|
||||||
|
isIgnoringSystemIndexes = mode;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* database path / name support stuff
|
* database path / name support stuff
|
||||||
|
|
|
@ -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: index.h,v 1.21 2000/01/26 05:57:56 momjian Exp $
|
* $Id: index.h,v 1.22 2000/02/18 09:29:19 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -47,7 +47,11 @@ extern void FormIndexDatum(int numberOfAttributes,
|
||||||
TupleDesc heapDescriptor, Datum *datum,
|
TupleDesc heapDescriptor, Datum *datum,
|
||||||
char *nullv, FuncIndexInfoPtr fInfo);
|
char *nullv, FuncIndexInfoPtr fInfo);
|
||||||
|
|
||||||
extern void UpdateStats(Oid relid, long reltuples, bool hasindex);
|
extern void UpdateStats(Oid relid, long reltuples, bool inplace);
|
||||||
|
extern bool IndexesAreActive(Oid relid, bool comfirmCommitted);
|
||||||
|
extern void setRelhasindexInplace(Oid relid, bool hasindex, bool immediate);
|
||||||
|
extern bool SetReindexProcessing(bool processing);
|
||||||
|
extern bool IsReindexProcessing(void);
|
||||||
|
|
||||||
extern void FillDummyExprContext(ExprContext *econtext, TupleTableSlot *slot,
|
extern void FillDummyExprContext(ExprContext *econtext, TupleTableSlot *slot,
|
||||||
TupleDesc tupdesc, Buffer buffer);
|
TupleDesc tupdesc, Buffer buffer);
|
||||||
|
@ -60,4 +64,8 @@ extern void index_build(Relation heapRelation, Relation indexRelation,
|
||||||
extern bool IndexIsUnique(Oid indexId);
|
extern bool IndexIsUnique(Oid indexId);
|
||||||
extern bool IndexIsUniqueNoCache(Oid indexId);
|
extern bool IndexIsUniqueNoCache(Oid indexId);
|
||||||
|
|
||||||
|
extern bool activate_index(Oid indexId, bool activate);
|
||||||
|
extern bool reindex_index(Oid indexId, bool force);
|
||||||
|
extern bool activate_indexes_of_a_table(Oid relid, bool activate);
|
||||||
|
extern bool reindex_relation(Oid relid, bool force);
|
||||||
#endif /* INDEX_H */
|
#endif /* INDEX_H */
|
||||||
|
|
|
@ -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: defrem.h,v 1.18 2000/01/26 05:58:00 momjian Exp $
|
* $Id: defrem.h,v 1.19 2000/02/18 09:29:49 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -33,6 +33,9 @@ extern void ExtendIndex(char *indexRelationName,
|
||||||
Expr *predicate,
|
Expr *predicate,
|
||||||
List *rangetable);
|
List *rangetable);
|
||||||
extern void RemoveIndex(char *name);
|
extern void RemoveIndex(char *name);
|
||||||
|
extern void ReindexIndex(const char *indexRelationName, bool force);
|
||||||
|
extern void ReindexTable(const char *relationName, bool force);
|
||||||
|
extern void ReindexDatabase(const char *databaseName, bool force, bool all);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prototypes in define.c
|
* prototypes in define.c
|
||||||
|
|
|
@ -12,7 +12,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: miscadmin.h,v 1.50 2000/01/26 05:57:46 momjian Exp $
|
* $Id: miscadmin.h,v 1.51 2000/02/18 09:29:06 inoue Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* some of the information in this file will be moved to
|
* some of the information in this file will be moved to
|
||||||
|
@ -211,6 +211,9 @@ extern ProcessingMode Mode;
|
||||||
|
|
||||||
#define GetProcessingMode() Mode
|
#define GetProcessingMode() Mode
|
||||||
|
|
||||||
|
extern void IgnoreSystemIndexes(bool mode);
|
||||||
|
extern bool IsIgnoringSystemIndexes(void);
|
||||||
|
extern bool IsCacheInitialized(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "postmaster.pid" is a file containing postmaster's pid, being
|
* "postmaster.pid" is a file containing postmaster's pid, being
|
||||||
|
|
|
@ -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: nodes.h,v 1.64 2000/02/15 20:49:24 tgl Exp $
|
* $Id: nodes.h,v 1.65 2000/02/18 09:29:43 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -146,7 +146,7 @@ typedef enum NodeTag
|
||||||
T_DeleteStmt,
|
T_DeleteStmt,
|
||||||
T_UpdateStmt,
|
T_UpdateStmt,
|
||||||
T_SelectStmt,
|
T_SelectStmt,
|
||||||
T_AlterTableStmt,
|
T_AlterTableStmt,
|
||||||
T_AggregateStmt,
|
T_AggregateStmt,
|
||||||
T_ChangeACLStmt,
|
T_ChangeACLStmt,
|
||||||
T_ClosePortalStmt,
|
T_ClosePortalStmt,
|
||||||
|
@ -191,9 +191,10 @@ typedef enum NodeTag
|
||||||
T_DropUserStmt,
|
T_DropUserStmt,
|
||||||
T_LockStmt,
|
T_LockStmt,
|
||||||
T_ConstraintsSetStmt,
|
T_ConstraintsSetStmt,
|
||||||
T_CreateGroupStmt,
|
T_CreateGroupStmt,
|
||||||
T_AlterGroupStmt,
|
T_AlterGroupStmt,
|
||||||
T_DropGroupStmt,
|
T_DropGroupStmt,
|
||||||
|
T_ReindexStmt,
|
||||||
|
|
||||||
T_A_Expr = 700,
|
T_A_Expr = 700,
|
||||||
T_Attr,
|
T_Attr,
|
||||||
|
|
|
@ -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: parsenodes.h,v 1.99 2000/02/15 20:49:24 tgl Exp $
|
* $Id: parsenodes.h,v 1.100 2000/02/18 09:29:44 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -722,6 +722,19 @@ typedef struct ConstraintsSetStmt
|
||||||
bool deferred;
|
bool deferred;
|
||||||
} ConstraintsSetStmt;
|
} ConstraintsSetStmt;
|
||||||
|
|
||||||
|
/* ----------------------
|
||||||
|
* REINDEX Statement
|
||||||
|
* ----------------------
|
||||||
|
*/
|
||||||
|
typedef struct ReindexStmt
|
||||||
|
{
|
||||||
|
NodeTag type;
|
||||||
|
int reindexType; /* INDEX|TABLE|DATABASE */
|
||||||
|
const char *name; /* name to reindex */
|
||||||
|
bool force;
|
||||||
|
bool all;
|
||||||
|
} ReindexStmt;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Optimizable Statements
|
* Optimizable Statements
|
||||||
|
|
|
@ -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: portal.h,v 1.21 2000/01/26 05:58:38 momjian Exp $
|
* $Id: portal.h,v 1.22 2000/02/18 09:30:16 inoue Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -80,6 +80,10 @@ extern void EndPortalAllocMode(void);
|
||||||
extern void PortalResetHeapMemory(Portal portal);
|
extern void PortalResetHeapMemory(Portal portal);
|
||||||
extern PortalVariableMemory PortalGetVariableMemory(Portal portal);
|
extern PortalVariableMemory PortalGetVariableMemory(Portal portal);
|
||||||
extern PortalHeapMemory PortalGetHeapMemory(Portal portal);
|
extern PortalHeapMemory PortalGetHeapMemory(Portal portal);
|
||||||
|
extern void CommonSpecialPortalOpen(void);
|
||||||
|
extern void CommonSpecialPortalClose(void);
|
||||||
|
extern PortalVariableMemory CommonSpecialPortalGetMemory(void);
|
||||||
|
extern bool CommonSpecialPortalIsOpen(void);
|
||||||
|
|
||||||
/* estimate of the maximum number of open portals a user would have,
|
/* estimate of the maximum number of open portals a user would have,
|
||||||
* used in initially sizing the PortalHashTable in EnablePortalManager()
|
* used in initially sizing the PortalHashTable in EnablePortalManager()
|
||||||
|
|
Loading…
Reference in New Issue