diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml index cabae191bc7779adf56a6fa7500aea19456a5645..0a4c7d45cbf8cd397cad38b8d5d7800cac59f776 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 ] @@ -100,6 +100,19 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } nam + + SCHEMA + + + Recreate all indexes of the specified schema. If a table of this + schema 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/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml index 486f5c9367a92d5d7e37c7e13b6ba3b756e89210..b5b449c256fac56aa91fc49506cf9dbddd5c5b11 100644 --- a/doc/src/sgml/ref/reindexdb.sgml +++ b/doc/src/sgml/ref/reindexdb.sgml @@ -24,6 +24,16 @@ PostgreSQL documentation reindexdb connection-option + + + + + + + table + + + @@ -161,6 +171,18 @@ PostgreSQL documentation + + + + + + Reindex schema only. + Multiple schemas can be reindexed by writing multiple + + + + diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 12b4ac7b3ce74d1647eb7b9ea76d4bf2df7e4a42..a3e8a151413acf66fba277f4854ce940ad3a3595 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -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; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 7e48958ae85cdd3d8dd0aacbe1b8ea523f2d1031..4b5009b636dd7a944ffe5480e4e73dc15e3f39eb 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -404,7 +404,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type copy_from opt_program %type opt_column event cursor_options opt_hold opt_set_data -%type reindex_type drop_type comment_type security_label_type +%type drop_type comment_type security_label_type %type 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; } ; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 58f78ce50d54aa627c803a496591c8a87ff7a8ed..aa8fe880d7ec3de34f19019c067283a94da8155b 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -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", diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 7a509c1e4528e58f35969614c5098f7d0140356e..82c926de6fbeb704b59ac1b1049beea55a6f8b78 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -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); diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c index 561bbcebd233016eb866930ae262ce92c61854e4..5c4a64e08a33e8ec831f4d487e577e72f8916b53 100644 --- a/src/bin/scripts/reindexdb.c +++ b/src/bin/scripts/reindexdb.c @@ -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")); diff --git a/src/bin/scripts/t/090_reindexdb.pl b/src/bin/scripts/t/090_reindexdb.pl index d5b42dee034fe3a7d61a8049a384ad2cfd7f3905..0cdf7be299c981bf44c0bbf25b18f63121c77683 100644 --- a/src/bin/scripts/t/090_reindexdb.pl +++ b/src/bin/scripts/t/090_reindexdb.pl @@ -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;/, diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 0ebdbc1c186f29a0fb29b4ebeaf3626ebe672956..f6210d36abbe75e08f2b8f70f6bab940534a32ba 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -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, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 255415d93a3f50773a5aa24071c255d7d5a51406..5eaa435127343ba79e13f7c4c41827886666be59 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -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 */ diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index 3ecb23823084cb92fca9760391035a68a9157792..ebac9395ef6d42edbcc87331d46afa17481102bf 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -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 diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql index e837676d28e28bff15fa163cdc19130480090e5c..1cd57dada783bd2a0dd751e6a0df76e8bd95f2fb 100644 --- a/src/test/regress/sql/create_index.sql +++ b/src/test/regress/sql/create_index.sql @@ -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;