diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml index cabae19..d05e1ac 100644 --- a/doc/src/sgml/ref/reindex.sgml +++ b/doc/src/sgml/ref/reindex.sgml @@ -22,6 +22,7 @@ PostgreSQL documentation REINDEX { INDEX | TABLE | DATABASE | SYSTEM } name [ FORCE ] +REINDEX USER TABLES @@ -126,14 +127,26 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } nam + USER TABLES + + + Recreate all indexes on user tables within the current database. + Indexes on system catalogs are not processed. + This form of REINDEX cannot be executed inside a + transaction block. + + + + + name The name of the specific index, table, or database to be reindexed. Index and table names can be schema-qualified. - Presently, REINDEX DATABASE and REINDEX SYSTEM - can only reindex the current database, so their parameter must match - the current database's name. + Presently, REINDEX DATABASE, REINDEX SYSTEM, + and REINDEX USER TABLES can only reindex the current + database, so their parameter must match the current database's name. diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml index 486f5c9..f69d84b 100644 --- a/doc/src/sgml/ref/reindexdb.sgml +++ b/doc/src/sgml/ref/reindexdb.sgml @@ -65,6 +65,15 @@ PostgreSQL documentation dbname + + + reindexdb + connection-option + + + + + @@ -173,6 +182,16 @@ PostgreSQL documentation + + + + + + Reindex database's user tables. + + + + diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index fdfa6ca..23e13f0 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -1772,6 +1772,9 @@ ReindexTable(RangeVar *relation) * 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! + * + * databaseName can be NULL when do_user is set and do_system isn't; this + * is the REINDEX USER TABLES case. */ Oid ReindexDatabase(const char *databaseName, bool do_system, bool do_user) @@ -1784,9 +1787,10 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user) List *relids = NIL; ListCell *l; - AssertArg(databaseName); + AssertArg(databaseName || (do_user && !do_system)); - if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0) + if (databaseName && + strcmp(databaseName, get_database_name(MyDatabaseId)) != 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("can only reindex the currently open database"))); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 6f4d645..0baef83 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -7040,6 +7040,7 @@ opt_if_exists: IF_P EXISTS { $$ = TRUE; } * QUERY: * * REINDEX type [FORCE] + * REINDEX USER TABLES * * FORCE no longer does anything, but we accept it for backwards compatibility *****************************************************************************/ @@ -7073,6 +7074,16 @@ ReindexStmt: n->do_user = true; $$ = (Node *)n; } + | REINDEX USER TABLES + { + ReindexStmt *n = makeNode(ReindexStmt); + n->kind = OBJECT_DATABASE; + n->name = NULL; + n->relation = NULL; + n->do_system = false; + n->do_user = true; + $$ = (Node *)n; + } ; reindex_type: diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 76b2b04..490d200 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3148,7 +3148,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", "DATABASE", "USER TABLES", NULL}; COMPLETE_WITH_LIST(list_REINDEX); } @@ -3161,6 +3161,8 @@ psql_completion(const char *text, int start, int end) else if (pg_strcasecmp(prev_wd, "SYSTEM") == 0 || pg_strcasecmp(prev_wd, "DATABASE") == 0) COMPLETE_WITH_QUERY(Query_for_list_of_databases); + else if (pg_strcasecmp(prev_wd, "USER") == 0) + COMPLETE_WITH_CONST("TABLES"); } /* SECURITY LABEL */ diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c index 561bbce..8e1b52d 100644 --- a/src/bin/scripts/reindexdb.c +++ b/src/bin/scripts/reindexdb.c @@ -28,8 +28,14 @@ static void reindex_system_catalogs(const char *dbname, const char *host, const char *port, const char *username, enum trivalue prompt_password, const char *progname, bool echo); +static void reindex_user_tables(const char *dbname, + const char *host, const char *port, + const char *username, enum trivalue prompt_password, + const char *progname, bool echo); static void help(const char *progname); +#define exit_nicely(code) exit(code) + int main(int argc, char *argv[]) { @@ -46,6 +52,7 @@ main(int argc, char *argv[]) {"system", no_argument, NULL, 's'}, {"table", required_argument, NULL, 't'}, {"index", required_argument, NULL, 'i'}, + {"user-tables", no_argument, NULL, 'u'}, {"maintenance-db", required_argument, NULL, 2}, {NULL, 0, NULL, 0} }; @@ -61,6 +68,7 @@ main(int argc, char *argv[]) const char *username = NULL; enum trivalue prompt_password = TRI_DEFAULT; bool syscatalog = false; + bool usertables = false; bool alldb = false; bool echo = false; bool quiet = false; @@ -73,7 +81,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:wWeqd:ast:i:u", long_options, &optindex)) != -1) { switch (c) { @@ -113,6 +121,9 @@ main(int argc, char *argv[]) case 'i': simple_string_list_append(&indexes, optarg); break; + case 'u': + usertables = true; + break; case 2: maintenance_db = pg_strdup(optarg); break; @@ -194,6 +205,32 @@ main(int argc, char *argv[]) reindex_system_catalogs(dbname, host, port, username, prompt_password, progname, echo); } + else if (usertables) + { + if (tables.head != NULL) + { + fprintf(stderr, _("%s: cannot reindex specific table(s) and all user tables at the same time\n"), progname); + exit(1); + } + if (indexes.head != NULL) + { + fprintf(stderr, _("%s: cannot reindex specific index(es) and all user tables at the same time\n"), progname); + exit(1); + } + + if (dbname == NULL) + { + if (getenv("PGDATABASE")) + dbname = getenv("PGDATABASE"); + else if (getenv("PGUSER")) + dbname = getenv("PGUSER"); + else + dbname = get_user_name_or_exit(progname); + } + + reindex_user_tables(dbname, host, port, username, prompt_password, + progname, echo); + } else { if (dbname == NULL) @@ -336,6 +373,41 @@ reindex_system_catalogs(const char *dbname, const char *host, const char *port, } static void +reindex_user_tables(const char *dbname, const char *host, const char *port, + const char *username, enum trivalue prompt_password, + const char *progname, bool echo) +{ + PQExpBufferData sql; + + PGconn *conn; + + initPQExpBuffer(&sql); + + appendPQExpBuffer(&sql, "REINDEX USER TABLES;"); + + conn = connectDatabase(dbname, host, port, username, prompt_password, + progname, false); + + /* This feature is only available starting in 9.5 */ + if (PQserverVersion(conn) < 90500) + { + fprintf(stderr, _("%s: REINDEX USER TABLES is only available in server versions 9.5 and newer\n"), + progname); + exit_nicely(1); + } + + if (!executeMaintenanceCommand(conn, sql.data, echo)) + { + fprintf(stderr, _("%s: reindexing of user tables failed: %s"), + progname, PQerrorMessage(conn)); + PQfinish(conn); + exit(1); + } + PQfinish(conn); + termPQExpBuffer(&sql); +} + +static void help(const char *progname) { printf(_("%s reindexes a PostgreSQL database.\n\n"), progname); @@ -349,6 +421,7 @@ help(const char *progname) printf(_(" -q, --quiet don't write any messages\n")); printf(_(" -s, --system reindex system catalogs\n")); printf(_(" -t, --table=TABLE reindex specific table(s) only\n")); + printf(_(" -u, --user-tables reindex all user tables\n")); printf(_(" -V, --version output version information, then exit\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_("\nConnection options:\n")); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index d2c0b29..226fffd 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -2689,9 +2689,9 @@ typedef struct ConstraintsSetStmt typedef struct ReindexStmt { NodeTag type; - ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, etc. */ - RangeVar *relation; /* Table or index to reindex */ - const char *name; /* name of database to reindex */ + ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, OBJECT_DATABASE */ + RangeVar *relation; /* Table or index to reindex; NULL for all */ + const char *name; /* name of database to reindex, or NULL */ bool do_system; /* include system tables in database case */ bool do_user; /* include user tables in database case */ } ReindexStmt;