mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Implement reindex command
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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/heapam.h"
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/heap.h"
|
||||
#include "catalog/index.h"
|
||||
#include "catalog/pg_index.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "catalog/pg_database.h"
|
||||
#include "catalog/pg_shadow.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "optimizer/clauses.h"
|
||||
#include "optimizer/planmain.h"
|
||||
@ -30,6 +33,9 @@
|
||||
#include "parser/parsetree.h"
|
||||
#include "utils/builtins.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)
|
||||
|
||||
@ -149,6 +155,8 @@ DefineIndex(char *heapRelationName,
|
||||
CheckPredicate(cnfPred, rangetable, relationId);
|
||||
}
|
||||
|
||||
if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false))
|
||||
elog(ERROR, "existent indexes are inactive. REINDEX first");
|
||||
if (IsFuncIndex(attributeList))
|
||||
{
|
||||
IndexElem *funcIndex = lfirst(attributeList);
|
||||
@ -195,6 +203,7 @@ DefineIndex(char *heapRelationName,
|
||||
classObjectId, parameterCount, parameterA, (Node *) cnfPred,
|
||||
lossy, unique, primary);
|
||||
}
|
||||
setRelhasindexInplace(relationId, true, false);
|
||||
}
|
||||
|
||||
|
||||
@ -570,3 +579,163 @@ RemoveIndex(char *name)
|
||||
|
||||
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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user