]> granicus.if.org Git - postgresql/commitdiff
REINDEX SCHEMA
authorSimon Riggs <simon@2ndQuadrant.com>
Mon, 8 Dec 2014 15:28:00 +0000 (00:28 +0900)
committerSimon Riggs <simon@2ndQuadrant.com>
Mon, 8 Dec 2014 15:28:00 +0000 (00:28 +0900)
Add new SCHEMA option to REINDEX and reindexdb.

Sawada Masahiko

Reviewed by Michael Paquier and Fabrízio de Royes Mello

12 files changed:
doc/src/sgml/ref/reindex.sgml
doc/src/sgml/ref/reindexdb.sgml
src/backend/commands/indexcmds.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/bin/psql/tab-complete.c
src/bin/scripts/reindexdb.c
src/bin/scripts/t/090_reindexdb.pl
src/include/commands/defrem.h
src/include/nodes/parsenodes.h
src/test/regress/expected/create_index.out
src/test/regress/sql/create_index.sql

index cabae191bc7779adf56a6fa7500aea19456a5645..0a4c7d45cbf8cd397cad38b8d5d7800cac59f776 100644 (file)
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
+REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -100,6 +100,19 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">nam
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>SCHEMA</literal></term>
+    <listitem>
+     <para>
+      Recreate all indexes of the specified schema.  If a table of this
+      schema has a secondary <quote>TOAST</> table, that is reindexed as
+      well. Indexes on shared system catalogs are also processed.
+      This form of <command>REINDEX</command> cannot be executed inside a
+      transaction block.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>DATABASE</literal></term>
     <listitem>
index 486f5c9367a92d5d7e37c7e13b6ba3b756e89210..b5b449c256fac56aa91fc49506cf9dbddd5c5b11 100644 (file)
@@ -24,6 +24,16 @@ PostgreSQL documentation
    <command>reindexdb</command>
    <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
 
+   <arg choice="plain" rep="repeat">
+    <arg choice="opt">
+     <group choice="plain">
+      <arg choice="plain"><option>--schema</option></arg>
+      <arg choice="plain"><option>-S</option></arg>
+     </group>
+     <replaceable>table</replaceable>
+    </arg>
+   </arg>
+
    <arg choice="plain" rep="repeat">
     <arg choice="opt">
      <group choice="plain">
@@ -161,6 +171,18 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>-S <replaceable class="parameter">schema</replaceable></></term>
+      <term><option>--schema=<replaceable class="parameter">schema</replaceable></></term>
+      <listitem>
+       <para>
+        Reindex <replaceable class="parameter">schema</replaceable> only.
+        Multiple schemas can be reindexed by writing multiple
+        <option>-S</> switches.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-t <replaceable class="parameter">table</replaceable></></term>
       <term><option>--table=<replaceable class="parameter">table</replaceable></></term>
index 12b4ac7b3ce74d1647eb7b9ea76d4bf2df7e4a42..a3e8a151413acf66fba277f4854ce940ad3a3595 100644 (file)
@@ -1777,34 +1777,58 @@ ReindexTable(RangeVar *relation)
 }
 
 /*
- * ReindexDatabase
- *             Recreate indexes of a database.
+ * ReindexObject
+ *             Recreate indexes of object whose type is defined by objectKind.
  *
  * 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)
+ReindexObject(const char *objectName, ReindexObjectType objectKind)
 {
+       Oid                     objectOid;
        Relation        relationRelation;
        HeapScanDesc scan;
+       ScanKeyData     *scan_keys = NULL;
        HeapTuple       tuple;
        MemoryContext private_context;
        MemoryContext old;
        List       *relids = NIL;
        ListCell   *l;
+       int     num_keys;
 
-       AssertArg(databaseName);
+       AssertArg(objectName);
+       Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
+                  objectKind == REINDEX_OBJECT_SYSTEM ||
+                  objectKind == REINDEX_OBJECT_DATABASE);
 
-       if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0)
-               ereport(ERROR,
-                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("can only reindex the currently open database")));
+       /*
+        * Get OID of object to reindex, being the database currently being
+        * used by session for a database or for system catalogs, or the schema
+        * defined by caller. At the same time do permission checks that need
+        * different processing depending on the object type.
+        */
+       if (objectKind == REINDEX_OBJECT_SCHEMA)
+       {
+               objectOid = get_namespace_oid(objectName, false);
 
-       if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
-               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
-                                          databaseName);
+               if (!pg_namespace_ownercheck(objectOid, GetUserId()))
+                       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
+                                                  objectName);
+       }
+       else
+       {
+               objectOid = MyDatabaseId;
+
+               if (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()))
+                       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
+                                                  objectName);
+       }
 
        /*
         * Create a memory context that will survive forced transaction commits we
@@ -1813,24 +1837,50 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
         * abort cleanup logic.
         */
        private_context = AllocSetContextCreate(PortalContext,
-                                                                                       "ReindexDatabase",
+                                                                                       (objectKind == REINDEX_OBJECT_SCHEMA) ?
+                                                                                       "ReindexSchema" : "ReindexDatabase",
                                                                                        ALLOCSET_DEFAULT_MINSIZE,
                                                                                        ALLOCSET_DEFAULT_INITSIZE,
                                                                                        ALLOCSET_DEFAULT_MAXSIZE);
 
        /*
-        * We always want to reindex pg_class first.  This ensures that if there
-        * is any corruption in pg_class' indexes, they will be fixed before we
-        * process any other tables.  This is critical because reindexing itself
-        * will try to update pg_class.
+        * We always want to reindex pg_class first when reindexing system
+        * catalogs or a database.  This ensures that if there is any corruption
+        * in pg_class' indexes, they will be fixed before we process any other
+        * tables.  This is critical because reindexing itself will try to
+        * update pg_class.
         */
-       if (do_system)
+       if (objectKind == REINDEX_OBJECT_DATABASE ||
+               objectKind == REINDEX_OBJECT_SYSTEM ||
+               (objectKind == REINDEX_OBJECT_SCHEMA &&
+                IsSystemNamespace(objectOid)))
        {
                old = MemoryContextSwitchTo(private_context);
                relids = lappend_oid(relids, RelationRelationId);
                MemoryContextSwitchTo(old);
        }
 
+       /*
+        * Define the search keys to find the objects to reindex. For a schema,
+        * we search target relations using relnamespace and relkind, something
+        * not necessary for a database-wide operation.
+        */
+       if (objectKind == REINDEX_OBJECT_SCHEMA)
+       {
+               scan_keys = palloc(sizeof(ScanKeyData) * 2);
+               ScanKeyInit(&scan_keys[0],
+                                       Anum_pg_class_relnamespace,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(objectOid));
+               ScanKeyInit(&scan_keys[1],
+                                       Anum_pg_class_relkind,
+                                       BTEqualStrategyNumber, F_CHAREQ,
+                                       'r');
+               num_keys = 2;
+       }
+       else
+               num_keys = 0;
+
        /*
         * Scan pg_class to build a list of the relations we need to reindex.
         *
@@ -1838,7 +1888,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, num_keys, scan_keys);
        while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
        {
                Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
@@ -1854,19 +1904,17 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
                        continue;
 
                /* Check user/system classification, and optionally skip */
-               if (IsSystemClass(relid, classtuple))
-               {
-                       if (!do_system)
-                               continue;
-               }
-               else
-               {
-                       if (!do_user)
-                               continue;
-               }
+               if (!IsSystemClass(relid, classtuple) &&
+                       objectKind == REINDEX_OBJECT_SYSTEM)
+                       continue;
 
+               /*
+                * Already have it in the case of system catalogs being all
+                * reindexed, of a database or of a system catalog being reindexed
+                * as a schema.
+                */
                if (HeapTupleGetOid(tuple) == RelationRelationId)
-                       continue;                       /* got it already */
+                       continue;
 
                old = MemoryContextSwitchTo(private_context);
                relids = lappend_oid(relids, relid);
@@ -1898,6 +1946,8 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
        StartTransactionCommand();
 
        MemoryContextDelete(private_context);
+       if (scan_keys)
+               pfree(scan_keys);
 
-       return MyDatabaseId;
+       return objectOid;
 }
index 7e48958ae85cdd3d8dd0aacbe1b8ea523f2d1031..4b5009b636dd7a944ffe5480e4e73dc15e3f39eb 100644 (file)
@@ -404,7 +404,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <boolean> copy_from opt_program
 
 %type <ival>   opt_column event cursor_options opt_hold opt_set_data
-%type <objtype>        reindex_type drop_type comment_type security_label_type
+%type <objtype>        drop_type comment_type security_label_type
 
 %type <node>   fetch_args limit_clause select_limit_value
                                offset_clause select_offset_value
@@ -7198,41 +7198,48 @@ opt_if_exists: IF_P EXISTS                                              { $$ = TRUE; }
  *****************************************************************************/
 
 ReindexStmt:
-                       REINDEX reindex_type qualified_name opt_force
+                       REINDEX INDEX qualified_name opt_force
                                {
                                        ReindexStmt *n = makeNode(ReindexStmt);
-                                       n->kind = $2;
+                                       n->kind = REINDEX_OBJECT_INDEX;
                                        n->relation = $3;
                                        n->name = NULL;
                                        $$ = (Node *)n;
                                }
+                       | REINDEX TABLE qualified_name opt_force
+                               {
+                                       ReindexStmt *n = makeNode(ReindexStmt);
+                                       n->kind = REINDEX_OBJECT_TABLE;
+                                       n->relation = $3;
+                                       n->name = NULL;
+                                       $$ = (Node *)n;
+                               }
+                       | REINDEX SCHEMA name opt_force
+                               {
+                                       ReindexStmt *n = makeNode(ReindexStmt);
+                                       n->kind = REINDEX_OBJECT_SCHEMA;
+                                       n->name = $3;
+                                       n->relation = NULL;
+                                       $$ = (Node *)n;
+                               }
                        | REINDEX SYSTEM_P name opt_force
                                {
                                        ReindexStmt *n = makeNode(ReindexStmt);
-                                       n->kind = OBJECT_DATABASE;
+                                       n->kind = REINDEX_OBJECT_SYSTEM;
                                        n->name = $3;
                                        n->relation = NULL;
-                                       n->do_system = true;
-                                       n->do_user = false;
                                        $$ = (Node *)n;
                                }
                        | REINDEX DATABASE name opt_force
                                {
                                        ReindexStmt *n = makeNode(ReindexStmt);
-                                       n->kind = OBJECT_DATABASE;
+                                       n->kind = REINDEX_OBJECT_DATABASE;
                                        n->name = $3;
                                        n->relation = NULL;
-                                       n->do_system = true;
-                                       n->do_user = true;
                                        $$ = (Node *)n;
                                }
                ;
 
-reindex_type:
-                       INDEX                                                                   { $$ = OBJECT_INDEX; }
-                       | TABLE                                                                 { $$ = OBJECT_TABLE; }
-               ;
-
 opt_force:     FORCE                                                                   {  $$ = TRUE; }
                        | /* EMPTY */                                                   {  $$ = FALSE; }
                ;
index 58f78ce50d54aa627c803a496591c8a87ff7a8ed..aa8fe880d7ec3de34f19019c067283a94da8155b 100644 (file)
@@ -749,14 +749,15 @@ standard_ProcessUtility(Node *parsetree,
                                PreventCommandDuringRecovery("REINDEX");
                                switch (stmt->kind)
                                {
-                                       case OBJECT_INDEX:
+                                       case REINDEX_OBJECT_INDEX:
                                                ReindexIndex(stmt->relation);
                                                break;
-                                       case OBJECT_TABLE:
-                                       case OBJECT_MATVIEW:
+                                       case REINDEX_OBJECT_TABLE:
                                                ReindexTable(stmt->relation);
                                                break;
-                                       case OBJECT_DATABASE:
+                                       case REINDEX_OBJECT_SCHEMA:
+                                       case REINDEX_OBJECT_SYSTEM:
+                                       case REINDEX_OBJECT_DATABASE:
 
                                                /*
                                                 * This cannot run inside a user transaction block; if
@@ -765,9 +766,9 @@ standard_ProcessUtility(Node *parsetree,
                                                 * intended effect!
                                                 */
                                                PreventTransactionChain(isTopLevel,
-                                                                                               "REINDEX DATABASE");
-                                               ReindexDatabase(stmt->name,
-                                                                               stmt->do_system, stmt->do_user);
+                                                                                               (stmt->kind == REINDEX_OBJECT_SCHEMA) ?
+                                                                                               "REINDEX SCHEMA" : "REINDEX DATABASE");
+                                               ReindexObject(stmt->name, stmt->kind);
                                                break;
                                        default:
                                                elog(ERROR, "unrecognized object type: %d",
index 7a509c1e4528e58f35969614c5098f7d0140356e..82c926de6fbeb704b59ac1b1049beea55a6f8b78 100644 (file)
@@ -3331,7 +3331,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);
        }
@@ -3341,6 +3341,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);
index 561bbcebd233016eb866930ae262ce92c61854e4..5c4a64e08a33e8ec831f4d487e577e72f8916b53 100644 (file)
@@ -41,6 +41,7 @@ main(int argc, char *argv[])
                {"password", no_argument, NULL, 'W'},
                {"echo", no_argument, NULL, 'e'},
                {"quiet", no_argument, NULL, 'q'},
+               {"schema", required_argument, NULL, 'S'},
                {"dbname", required_argument, NULL, 'd'},
                {"all", no_argument, NULL, 'a'},
                {"system", no_argument, NULL, 's'},
@@ -66,6 +67,7 @@ main(int argc, char *argv[])
        bool            quiet = false;
        SimpleStringList indexes = {NULL, NULL};
        SimpleStringList tables = {NULL, NULL};
+       SimpleStringList schemas = {NULL, NULL};
 
        progname = get_progname(argv[0]);
        set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
@@ -73,7 +75,7 @@ main(int argc, char *argv[])
        handle_help_version_opts(argc, argv, "reindexdb", help);
 
        /* process command-line options */
-       while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:ast:i:", long_options, &optindex)) != -1)
+       while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:", long_options, &optindex)) != -1)
        {
                switch (c)
                {
@@ -98,6 +100,9 @@ main(int argc, char *argv[])
                        case 'q':
                                quiet = true;
                                break;
+                       case 'S':
+                               simple_string_list_append(&schemas, optarg);
+                               break;
                        case 'd':
                                dbname = pg_strdup(optarg);
                                break;
@@ -154,6 +159,11 @@ main(int argc, char *argv[])
                        fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
                        exit(1);
                }
+               if (schemas.head != NULL)
+               {
+                       fprintf(stderr, _("%s: cannot reindex specific schema(s) in all databases\n"), progname);
+                       exit(1);
+               }
                if (tables.head != NULL)
                {
                        fprintf(stderr, _("%s: cannot reindex specific table(s) in all databases\n"), progname);
@@ -170,6 +180,11 @@ main(int argc, char *argv[])
        }
        else if (syscatalog)
        {
+               if (schemas.head != NULL)
+               {
+                       fprintf(stderr, _("%s: cannot reindex specific schema(s) and system catalogs at the same time\n"), progname);
+                       exit(1);
+               }
                if (tables.head != NULL)
                {
                        fprintf(stderr, _("%s: cannot reindex specific table(s) and system catalogs at the same time\n"), progname);
@@ -206,6 +221,17 @@ main(int argc, char *argv[])
                                dbname = get_user_name_or_exit(progname);
                }
 
+               if (schemas.head != NULL)
+               {
+                       SimpleStringListCell *cell;
+
+                       for (cell = schemas.head; cell; cell = cell->next)
+                       {
+                               reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
+                                                                  username, prompt_password, progname, echo);
+                       }
+               }
+
                if (indexes.head != NULL)
                {
                        SimpleStringListCell *cell;
@@ -226,8 +252,8 @@ main(int argc, char *argv[])
                                                                  username, prompt_password, progname, echo);
                        }
                }
-               /* reindex database only if neither index nor table is specified */
-               if (indexes.head == NULL && tables.head == NULL)
+               /* reindex database only if neither index nor table nor schema is specified */
+               if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
                        reindex_one_database(dbname, dbname, "DATABASE", host, port,
                                                                 username, prompt_password, progname, echo);
        }
@@ -251,6 +277,8 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
                appendPQExpBuffer(&sql, " TABLE %s", name);
        else if (strcmp(type, "INDEX") == 0)
                appendPQExpBuffer(&sql, " INDEX %s", name);
+       else if (strcmp(type, "SCHEMA") == 0)
+               appendPQExpBuffer(&sql, " SCHEMA %s", name);
        else if (strcmp(type, "DATABASE") == 0)
                appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
        appendPQExpBufferStr(&sql, ";");
@@ -266,6 +294,9 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
                if (strcmp(type, "INDEX") == 0)
                        fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
                                        progname, name, dbname, PQerrorMessage(conn));
+               if (strcmp(type, "SCHEMA") == 0)
+                       fprintf(stderr, _("%s: reindexing of schema \"%s\" in database \"%s\" failed: %s"),
+                                       progname, name, dbname, PQerrorMessage(conn));
                else
                        fprintf(stderr, _("%s: reindexing of database \"%s\" failed: %s"),
                                        progname, dbname, PQerrorMessage(conn));
@@ -348,6 +379,7 @@ help(const char *progname)
        printf(_("  -i, --index=INDEX         recreate specific index(es) only\n"));
        printf(_("  -q, --quiet               don't write any messages\n"));
        printf(_("  -s, --system              reindex system catalogs\n"));
+       printf(_("  -S, --schema=SCHEMA       recreate specific schema(s) only\n"));
        printf(_("  -t, --table=TABLE         reindex specific table(s) only\n"));
        printf(_("  -V, --version             output version information, then exit\n"));
        printf(_("  -?, --help                show this help, then exit\n"));
index d5b42dee034fe3a7d61a8049a384ad2cfd7f3905..0cdf7be299c981bf44c0bbf25b18f63121c77683 100644 (file)
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 use TestLib;
-use Test::More tests => 16;
+use Test::More tests => 17;
 
 program_help_ok('reindexdb');
 program_version_ok('reindexdb');
@@ -27,7 +27,10 @@ issues_sql_like(
        [ 'reindexdb', 'postgres', '-i', 'test1x' ],
        qr/statement: REINDEX INDEX test1x;/,
        'reindex specific index');
-
+issues_sql_like(
+       [ 'reindexdb', 'postgres', '-S', 'pg_catalog' ],
+       qr/statement: REINDEX SCHEMA pg_catalog;/,
+       'reindex specific schema');
 issues_sql_like(
        [ 'reindexdb', 'postgres', '-s' ],
        qr/statement: REINDEX SYSTEM postgres;/,
index 0ebdbc1c186f29a0fb29b4ebeaf3626ebe672956..f6210d36abbe75e08f2b8f70f6bab940534a32ba 100644 (file)
@@ -30,8 +30,7 @@ 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 ReindexObject(const char *databaseName, ReindexObjectType kind);
 extern char *makeObjectName(const char *name1, const char *name2,
                           const char *label);
 extern char *ChooseRelationName(const char *name1, const char *name2,
index 255415d93a3f50773a5aa24071c255d7d5a51406..5eaa435127343ba79e13f7c4c41827886666be59 100644 (file)
@@ -2721,10 +2721,19 @@ typedef struct ConstraintsSetStmt
  *             REINDEX Statement
  * ----------------------
  */
+typedef enum ReindexObjectType
+{
+       REINDEX_OBJECT_INDEX,   /* index */
+       REINDEX_OBJECT_TABLE,   /* table or materialized view */
+       REINDEX_OBJECT_SCHEMA,  /* schema */
+       REINDEX_OBJECT_SYSTEM,  /* system catalogs */
+       REINDEX_OBJECT_DATABASE /* database */
+} ReindexObjectType;
+
 typedef struct ReindexStmt
 {
        NodeTag         type;
-       ObjectType      kind;                   /* OBJECT_INDEX, OBJECT_TABLE, etc. */
+       ReindexObjectType       kind;   /* REINDEX_OBJECT_INDEX, REINDEX_OBJECT_TABLE, etc. */
        RangeVar   *relation;           /* Table or index to reindex */
        const char *name;                       /* name of database to reindex */
        bool            do_system;              /* include system tables in database case */
index 3ecb23823084cb92fca9760391035a68a9157792..ebac9395ef6d42edbcc87331d46afa17481102bf 100644 (file)
@@ -2831,3 +2831,34 @@ explain (costs off)
    Index Cond: ((thousand = 1) AND (tenthous = 1001))
 (2 rows)
 
+--
+-- REINDEX SCHEMA
+--
+REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
+ERROR:  schema "schema_to_reindex" does not exist
+CREATE SCHEMA schema_to_reindex;
+CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON schema_to_reindex.table2(col2);
+REINDEX SCHEMA schema_to_reindex;
+NOTICE:  table "schema_to_reindex.table1" was reindexed
+NOTICE:  table "schema_to_reindex.table2" was reindexed
+BEGIN;
+REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
+ERROR:  REINDEX SCHEMA cannot run inside a transaction block
+END;
+-- Failure for unauthorized user
+CREATE ROLE reindexuser login;
+SET SESSION ROLE user_reindex;
+ERROR:  role "user_reindex" does not exist
+REINDEX SCHEMA schema_to_reindex;
+NOTICE:  table "schema_to_reindex.table1" was reindexed
+NOTICE:  table "schema_to_reindex.table2" was reindexed
+-- Clean up
+RESET ROLE;
+DROP ROLE user_reindex;
+ERROR:  role "user_reindex" does not exist
+DROP SCHEMA schema_to_reindex CASCADE;
+NOTICE:  drop cascades to 2 other objects
+DETAIL:  drop cascades to table schema_to_reindex.table1
+drop cascades to table schema_to_reindex.table2
index e837676d28e28bff15fa163cdc19130480090e5c..1cd57dada783bd2a0dd751e6a0df76e8bd95f2fb 100644 (file)
@@ -964,3 +964,26 @@ RESET enable_indexscan;
 
 explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
+
+--
+-- REINDEX SCHEMA
+--
+REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
+CREATE SCHEMA schema_to_reindex;
+CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON schema_to_reindex.table2(col2);
+REINDEX SCHEMA schema_to_reindex;
+BEGIN;
+REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
+END;
+
+-- Failure for unauthorized user
+CREATE ROLE reindexuser login;
+SET SESSION ROLE user_reindex;
+REINDEX SCHEMA schema_to_reindex;
+
+-- Clean up
+RESET ROLE;
+DROP ROLE user_reindex;
+DROP SCHEMA schema_to_reindex CASCADE;