diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index cabae19..096960d 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
-REINDEX { INDEX | TABLE | DATABASE | SYSTEM } name [ FORCE ]
+REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } name [ FORCE ]
@@ -101,6 +101,19 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } nam
+ SCHEMA
+
+
+ Recreate all indexes of the specified schema. If the table has a
+ secondary TOAST> table, that is reindexed as well.
+ Indexes on shared system catalogs are also processed.
+ This form of REINDEX cannot be executed inside a
+ transaction block.
+
+
+
+
+
DATABASE
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 12b4ac7..9cf09a8 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1777,34 +1777,52 @@ ReindexTable(RangeVar *relation)
}
/*
- * ReindexDatabase
- * Recreate indexes of a database.
+ * ReindexDatabaseOrSchema
+ * Recreate indexes of a database or schema.
*
+ * kind means the type of object, database or schema.
* To reduce the probability of deadlocks, each table is reindexed in a
* separate transaction, so we can release the lock on it right away.
* That means this must not be called within a user transaction block!
*/
Oid
-ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
+ReindexDatabaseOrSchema(const char *objectName, bool do_system, bool do_user, ObjectType kind)
{
+ Oid objectOid;
Relation relationRelation;
HeapScanDesc scan;
+ ScanKeyData *key = NULL;
HeapTuple tuple;
MemoryContext private_context;
MemoryContext old;
List *relids = NIL;
ListCell *l;
+ bool do_database = (kind == OBJECT_DATABASE);
+ int nkeys;
- AssertArg(databaseName);
+ AssertArg(objectName);
+ Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
- if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0)
+ /* Get OID of object for result */
+ if (do_database)
+ objectOid = MyDatabaseId;
+ else
+ objectOid = get_namespace_oid(objectName, false);
+
+ if (!do_database)
+ {
+ do_system = IsSystemNamespace(objectOid);
+ do_user = !do_system;
+ }
+
+ if (do_database && strcmp(objectName, get_database_name(MyDatabaseId)) != 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("can only reindex the currently open database")));
- if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
+ if (do_database && !pg_database_ownercheck(MyDatabaseId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
- databaseName);
+ objectName);
/*
* Create a memory context that will survive forced transaction commits we
@@ -1813,7 +1831,8 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* abort cleanup logic.
*/
private_context = AllocSetContextCreate(PortalContext,
- "ReindexDatabase",
+ (do_database) ?
+ "ReindexDatabase" : "ReindexSchema",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
@@ -1831,6 +1850,23 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextSwitchTo(old);
}
+ /* For schema, we search target relations by relnamespce and relkind */
+ if (!do_database)
+ {
+ key = palloc(sizeof(ScanKeyData) * 2);
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectOid));
+ ScanKeyInit(&key[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ 'r');
+ nkeys = 2;
+ }
+ else
+ nkeys = 0;
+
/*
* Scan pg_class to build a list of the relations we need to reindex.
*
@@ -1838,7 +1874,7 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* rels will be processed indirectly by reindex_relation).
*/
relationRelation = heap_open(RelationRelationId, AccessShareLock);
- scan = heap_beginscan_catalog(relationRelation, 0, NULL);
+ scan = heap_beginscan_catalog(relationRelation, nkeys, key);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
@@ -1899,5 +1935,5 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextDelete(private_context);
- return MyDatabaseId;
+ return objectOid;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index bd180e7..7f35b34 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7207,6 +7207,14 @@ ReindexStmt:
n->do_user = false;
$$ = (Node *)n;
}
+ | REINDEX SCHEMA name opt_force
+ {
+ ReindexStmt *n = makeNode(ReindexStmt);
+ n->kind = OBJECT_SCHEMA;
+ n->name = $3;
+ n->relation = NULL;
+ $$ = (Node *)n;
+ }
| REINDEX DATABASE name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 58f78ce..153b312 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -756,6 +756,7 @@ standard_ProcessUtility(Node *parsetree,
case OBJECT_MATVIEW:
ReindexTable(stmt->relation);
break;
+ case OBJECT_SCHEMA:
case OBJECT_DATABASE:
/*
@@ -765,9 +766,10 @@ standard_ProcessUtility(Node *parsetree,
* intended effect!
*/
PreventTransactionChain(isTopLevel,
- "REINDEX DATABASE");
- ReindexDatabase(stmt->name,
- stmt->do_system, stmt->do_user);
+ (stmt->kind == OBJECT_SCHEMA) ?
+ "REINDEX SCHEMA" : "REINDEX DATABASE");
+ ReindexDatabaseOrSchema(stmt->name,
+ stmt->do_system, stmt->do_user, stmt->kind);
break;
default:
elog(ERROR, "unrecognized object type: %d",
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 8c85425..380c579 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3330,7 +3330,7 @@ psql_completion(const char *text, int start, int end)
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
static const char *const list_REINDEX[] =
- {"TABLE", "INDEX", "SYSTEM", "DATABASE", NULL};
+ {"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
COMPLETE_WITH_LIST(list_REINDEX);
}
@@ -3340,6 +3340,8 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
else if (pg_strcasecmp(prev_wd, "INDEX") == 0)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
+ else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0 )
+ COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
else if (pg_strcasecmp(prev_wd, "SYSTEM") == 0 ||
pg_strcasecmp(prev_wd, "DATABASE") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 0ebdbc1..330d05c 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -30,8 +30,8 @@ extern Oid DefineIndex(Oid relationId,
bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation);
extern Oid ReindexTable(RangeVar *relation);
-extern Oid ReindexDatabase(const char *databaseName,
- bool do_system, bool do_user);
+extern Oid ReindexDatabaseOrSchema(const char *databaseName,
+ bool do_system, bool do_user, ObjectType kind);
extern char *makeObjectName(const char *name1, const char *name2,
const char *label);
extern char *ChooseRelationName(const char *name1, const char *name2,
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 3ecb238..560a77b 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2831,3 +2831,22 @@ explain (costs off)
Index Cond: ((thousand = 1) AND (tenthous = 1001))
(2 rows)
+--
+-- Reindex All In Schema
+--
+REINDEX SCHEMA tobereindexed; -- fail because schema doesn't exists
+ERROR: schema "tobereindexed" does not exist
+CREATE SCHEMA tobereindexed;
+CREATE TABLE tobereindexed.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE tobereindexed.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON tobereindexed.table2(col2);
+REINDEX SCHEMA tobereindexed;
+NOTICE: table "tobereindexed.table1" was reindexed
+NOTICE: table "tobereindexed.table2" was reindexed
+BEGIN;
+REINDEX SCHEMA tobereindexed;
+ERROR: REINDEX SCHEMA cannot run inside a transaction block
+END;
+DROP TABLE tobereindexed.table2;
+DROP TABLE tobereindexed.table1;
+DROP SCHEMA tobereindexed;
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index e837676..299fd81 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -964,3 +964,19 @@ RESET enable_indexscan;
explain (costs off)
select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
+
+--
+-- Reindex All In Schema
+--
+REINDEX SCHEMA tobereindexed; -- fail because schema doesn't exists
+CREATE SCHEMA tobereindexed;
+CREATE TABLE tobereindexed.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE tobereindexed.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON tobereindexed.table2(col2);
+REINDEX SCHEMA tobereindexed;
+BEGIN;
+REINDEX SCHEMA tobereindexed;
+END;
+DROP TABLE tobereindexed.table2;
+DROP TABLE tobereindexed.table1;
+DROP SCHEMA tobereindexed;