PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
reindexdb.c File Reference
#include "postgres_fe.h"
#include <limits.h>
#include <stdlib.h>
#include "catalog/pg_class_d.h"
#include "common.h"
#include "common/logging.h"
#include "fe_utils/cancel.h"
#include "fe_utils/option_utils.h"
#include "fe_utils/parallel_slot.h"
#include "fe_utils/query_utils.h"
#include "fe_utils/simple_list.h"
#include "fe_utils/string_utils.h"
Include dependency graph for reindexdb.c:

Go to the source code of this file.

Typedefs

typedef enum ReindexType ReindexType
 

Enumerations

enum  ReindexType {
  REINDEX_DATABASE , REINDEX_INDEX , REINDEX_SCHEMA , REINDEX_SYSTEM ,
  REINDEX_TABLE
}
 

Functions

static SimpleStringListget_parallel_tables_list (PGconn *conn, ReindexType type, SimpleStringList *user_list, bool echo)
 
static void get_parallel_tabidx_list (PGconn *conn, SimpleStringList *index_list, SimpleOidList **table_list, bool echo)
 
static void reindex_one_database (ConnParams *cparams, ReindexType type, SimpleStringList *user_list, const char *progname, bool echo, bool verbose, bool concurrently, int concurrentCons, const char *tablespace)
 
static void reindex_all_databases (ConnParams *cparams, const char *progname, bool echo, bool quiet, bool verbose, bool concurrently, int concurrentCons, const char *tablespace, bool syscatalog, SimpleStringList *schemas, SimpleStringList *tables, SimpleStringList *indexes)
 
static void gen_reindex_command (PGconn *conn, ReindexType type, const char *name, bool echo, bool verbose, bool concurrently, const char *tablespace, PQExpBufferData *sql)
 
static void run_reindex_command (PGconn *conn, ReindexType type, const char *name, bool echo, PQExpBufferData *sql)
 
static void help (const char *progname)
 
int main (int argc, char *argv[])
 

Typedef Documentation

◆ ReindexType

typedef enum ReindexType ReindexType

Enumeration Type Documentation

◆ ReindexType

Enumerator
REINDEX_DATABASE 
REINDEX_INDEX 
REINDEX_SCHEMA 
REINDEX_SYSTEM 
REINDEX_TABLE 

Definition at line 27 of file reindexdb.c.

28{
ReindexType
Definition: reindexdb.c:28
@ REINDEX_SYSTEM
Definition: reindexdb.c:32
@ REINDEX_DATABASE
Definition: reindexdb.c:29
@ REINDEX_INDEX
Definition: reindexdb.c:30
@ REINDEX_SCHEMA
Definition: reindexdb.c:31
@ REINDEX_TABLE
Definition: reindexdb.c:33

Function Documentation

◆ gen_reindex_command()

static void gen_reindex_command ( PGconn conn,
ReindexType  type,
const char *  name,
bool  echo,
bool  verbose,
bool  concurrently,
const char *  tablespace,
PQExpBufferData sql 
)
static

Definition at line 499 of file reindexdb.c.

502{
503 const char *paren = "(";
504 const char *comma = ", ";
505 const char *sep = paren;
506
507 Assert(name);
508
509 /* build the REINDEX query */
510 appendPQExpBufferStr(sql, "REINDEX ");
511
512 if (verbose)
513 {
514 appendPQExpBuffer(sql, "%sVERBOSE", sep);
515 sep = comma;
516 }
517
518 if (tablespace)
519 {
520 appendPQExpBuffer(sql, "%sTABLESPACE %s", sep,
522 sep = comma;
523 }
524
525 if (sep != paren)
526 appendPQExpBufferStr(sql, ") ");
527
528 /* object type */
529 switch (type)
530 {
531 case REINDEX_DATABASE:
532 appendPQExpBufferStr(sql, "DATABASE ");
533 break;
534 case REINDEX_INDEX:
535 appendPQExpBufferStr(sql, "INDEX ");
536 break;
537 case REINDEX_SCHEMA:
538 appendPQExpBufferStr(sql, "SCHEMA ");
539 break;
540 case REINDEX_SYSTEM:
541 appendPQExpBufferStr(sql, "SYSTEM ");
542 break;
543 case REINDEX_TABLE:
544 appendPQExpBufferStr(sql, "TABLE ");
545 break;
546 }
547
548 /*
549 * Parenthesized grammar is only supported for CONCURRENTLY since
550 * PostgreSQL 14. Since 12, CONCURRENTLY can be specified after the
551 * object type.
552 */
553 if (concurrently)
554 appendPQExpBufferStr(sql, "CONCURRENTLY ");
555
556 /* object name */
557 switch (type)
558 {
559 case REINDEX_DATABASE:
560 case REINDEX_SYSTEM:
563 break;
564 case REINDEX_INDEX:
565 case REINDEX_TABLE:
566 appendQualifiedRelation(sql, name, conn, echo);
567 break;
568 case REINDEX_SCHEMA:
570 break;
571 }
572
573 /* finish the query */
574 appendPQExpBufferChar(sql, ';');
575}
void appendQualifiedRelation(PQExpBuffer buf, const char *spec, PGconn *conn, bool echo)
Definition: common.c:68
int PQclientEncoding(const PGconn *conn)
Definition: fe-connect.c:7709
Assert(PointerIsAligned(start, uint64))
#define comma
Definition: indent_codes.h:48
int verbose
static char * tablespace
Definition: pgbench.c:217
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
PGconn * conn
Definition: streamutil.c:52
const char * fmtIdEnc(const char *rawid, int encoding)
Definition: string_utils.c:101
const char * type
const char * name

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), appendQualifiedRelation(), Assert(), comma, conn, fmtIdEnc(), name, PQclientEncoding(), REINDEX_DATABASE, REINDEX_INDEX, REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, tablespace, type, and verbose.

Referenced by reindex_one_database().

◆ get_parallel_tabidx_list()

static void get_parallel_tabidx_list ( PGconn conn,
SimpleStringList index_list,
SimpleOidList **  table_list,
bool  echo 
)
static

Definition at line 744 of file reindexdb.c.

748{
749 PQExpBufferData catalog_query;
750 PGresult *res;
752 int ntups;
753
754 Assert(index_list != NULL);
755
756 initPQExpBuffer(&catalog_query);
757
758 /*
759 * The queries here are using a safe search_path, so there's no need to
760 * fully qualify everything.
761 */
762
763 /*
764 * We cannot use REINDEX in parallel in a straightforward way, because
765 * we'd be unable to control concurrent processing of multiple indexes on
766 * the same table. But we can extract the table OID together with each
767 * index, so that we can send all the REINDEX INDEX commands for the same
768 * table together on one parallel job.
769 */
770 appendPQExpBufferStr(&catalog_query,
771 "SELECT x.indrelid, n.nspname, i.relname\n"
772 "FROM pg_catalog.pg_index x\n"
773 "JOIN pg_catalog.pg_class i ON i.oid = x.indexrelid\n"
774 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = i.relnamespace\n"
775 "WHERE x.indexrelid = ANY(ARRAY['");
776
777 for (cell = index_list->head; cell; cell = cell->next)
778 {
779 if (cell != index_list->head)
780 appendPQExpBufferStr(&catalog_query, "', '");
781
782 appendQualifiedRelation(&catalog_query, cell->val, conn, echo);
783 }
784
785 /*
786 * We want all indexes of the same table together. Order tables by the
787 * size of its greatest index. Within each table, order indexes by size.
788 */
789 appendPQExpBufferStr(&catalog_query,
790 "']::pg_catalog.regclass[])\n"
791 "ORDER BY max(i.relpages) OVER \n"
792 " (PARTITION BY x.indrelid),\n"
793 " x.indrelid, i.relpages;\n");
794
795 /* Empty the original index_list to fill it from the query result. */
796 simple_string_list_destroy(index_list);
797 index_list->head = index_list->tail = NULL;
798
799 res = executeQuery(conn, catalog_query.data, echo);
800 termPQExpBuffer(&catalog_query);
801
802 /*
803 * If no rows are returned, there are no matching tables, so we are done.
804 */
805 ntups = PQntuples(res);
806 if (ntups == 0)
807 {
808 PQclear(res);
809 return;
810 }
811
812 *table_list = pg_malloc0(sizeof(SimpleOidList));
813
814 /*
815 * Build two lists, one with table OIDs and the other with fully-qualified
816 * index names.
817 */
818 for (int i = 0; i < ntups; i++)
819 {
820 simple_oid_list_append(*table_list, atooid(PQgetvalue(res, i, 0)));
821 simple_string_list_append(index_list,
823 PQgetvalue(res, i, 2),
825 }
826
827 PQclear(res);
828}
PGresult * executeQuery(PGconn *conn, const char *query)
Definition: connectdb.c:277
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
void PQclear(PGresult *res)
Definition: fe-exec.c:721
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
int i
Definition: isn.c:77
#define atooid(x)
Definition: postgres_ext.h:41
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
void simple_string_list_append(SimpleStringList *list, const char *val)
Definition: simple_list.c:63
void simple_string_list_destroy(SimpleStringList *list)
Definition: simple_list.c:125
void simple_oid_list_append(SimpleOidList *list, Oid val)
Definition: simple_list.c:26
const char * fmtQualifiedIdEnc(const char *schema, const char *id, int encoding)
Definition: string_utils.c:263
char val[FLEXIBLE_ARRAY_MEMBER]
Definition: simple_list.h:37
struct SimpleStringListCell * next
Definition: simple_list.h:34
SimpleStringListCell * head
Definition: simple_list.h:42
SimpleStringListCell * tail
Definition: simple_list.h:43

References appendPQExpBufferStr(), appendQualifiedRelation(), Assert(), atooid, conn, PQExpBufferData::data, executeQuery(), fmtQualifiedIdEnc(), SimpleStringList::head, i, initPQExpBuffer(), SimpleStringListCell::next, pg_malloc0(), PQclear(), PQclientEncoding(), PQgetvalue(), PQntuples(), simple_oid_list_append(), simple_string_list_append(), simple_string_list_destroy(), SimpleStringList::tail, termPQExpBuffer(), and SimpleStringListCell::val.

Referenced by reindex_one_database().

◆ get_parallel_tables_list()

static SimpleStringList * get_parallel_tables_list ( PGconn conn,
ReindexType  type,
SimpleStringList user_list,
bool  echo 
)
static

Definition at line 629 of file reindexdb.c.

631{
632 PQExpBufferData catalog_query;
633 PGresult *res;
634 SimpleStringList *tables;
635 int ntups;
636
637 initPQExpBuffer(&catalog_query);
638
639 /*
640 * The queries here are using a safe search_path, so there's no need to
641 * fully qualify everything.
642 */
643 switch (type)
644 {
645 case REINDEX_DATABASE:
646 Assert(user_list == NULL);
647 appendPQExpBufferStr(&catalog_query,
648 "SELECT c.relname, ns.nspname\n"
649 " FROM pg_catalog.pg_class c\n"
650 " JOIN pg_catalog.pg_namespace ns"
651 " ON c.relnamespace = ns.oid\n"
652 " WHERE ns.nspname != 'pg_catalog'\n"
653 " AND c.relkind IN ("
654 CppAsString2(RELKIND_RELATION) ", "
655 CppAsString2(RELKIND_MATVIEW) ")\n"
656 " AND c.relpersistence != "
657 CppAsString2(RELPERSISTENCE_TEMP) "\n"
658 " ORDER BY c.relpages DESC;");
659 break;
660
661 case REINDEX_SCHEMA:
662 {
664
665 Assert(user_list != NULL);
666
667 /*
668 * All the tables from all the listed schemas are grabbed at
669 * once.
670 */
671 appendPQExpBufferStr(&catalog_query,
672 "SELECT c.relname, ns.nspname\n"
673 " FROM pg_catalog.pg_class c\n"
674 " JOIN pg_catalog.pg_namespace ns"
675 " ON c.relnamespace = ns.oid\n"
676 " WHERE c.relkind IN ("
677 CppAsString2(RELKIND_RELATION) ", "
678 CppAsString2(RELKIND_MATVIEW) ")\n"
679 " AND c.relpersistence != "
680 CppAsString2(RELPERSISTENCE_TEMP) "\n"
681 " AND ns.nspname IN (");
682
683 for (cell = user_list->head; cell; cell = cell->next)
684 {
685 if (cell != user_list->head)
686 appendPQExpBufferChar(&catalog_query, ',');
687
688 appendStringLiteralConn(&catalog_query, cell->val, conn);
689 }
690
691 appendPQExpBufferStr(&catalog_query, ")\n"
692 " ORDER BY c.relpages DESC;");
693 }
694 break;
695
696 case REINDEX_INDEX:
697 case REINDEX_SYSTEM:
698 case REINDEX_TABLE:
699 Assert(false);
700 break;
701 }
702
703 res = executeQuery(conn, catalog_query.data, echo);
704 termPQExpBuffer(&catalog_query);
705
706 /*
707 * If no rows are returned, there are no matching tables, so we are done.
708 */
709 ntups = PQntuples(res);
710 if (ntups == 0)
711 {
712 PQclear(res);
713 return NULL;
714 }
715
716 tables = pg_malloc0(sizeof(SimpleStringList));
717
718 /* Build qualified identifiers for each table */
719 for (int i = 0; i < ntups; i++)
720 {
723 PQgetvalue(res, i, 0),
725 }
726 PQclear(res);
727
728 return tables;
729}
#define CppAsString2(x)
Definition: c.h:363
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
Definition: string_utils.c:446

References appendPQExpBufferChar(), appendPQExpBufferStr(), appendStringLiteralConn(), Assert(), conn, CppAsString2, PQExpBufferData::data, executeQuery(), fmtQualifiedIdEnc(), SimpleStringList::head, i, initPQExpBuffer(), SimpleStringListCell::next, pg_malloc0(), PQclear(), PQclientEncoding(), PQgetvalue(), PQntuples(), REINDEX_DATABASE, REINDEX_INDEX, REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, simple_string_list_append(), termPQExpBuffer(), type, and SimpleStringListCell::val.

Referenced by reindex_one_database().

◆ help()

static void help ( const char *  progname)
static

Definition at line 895 of file reindexdb.c.

896{
897 printf(_("%s reindexes a PostgreSQL database.\n\n"), progname);
898 printf(_("Usage:\n"));
899 printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
900 printf(_("\nOptions:\n"));
901 printf(_(" -a, --all reindex all databases\n"));
902 printf(_(" --concurrently reindex concurrently\n"));
903 printf(_(" -d, --dbname=DBNAME database to reindex\n"));
904 printf(_(" -e, --echo show the commands being sent to the server\n"));
905 printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
906 printf(_(" -j, --jobs=NUM use this many concurrent connections to reindex\n"));
907 printf(_(" -q, --quiet don't write any messages\n"));
908 printf(_(" -s, --system reindex system catalogs only\n"));
909 printf(_(" -S, --schema=SCHEMA reindex specific schema(s) only\n"));
910 printf(_(" -t, --table=TABLE reindex specific table(s) only\n"));
911 printf(_(" --tablespace=TABLESPACE tablespace where indexes are rebuilt\n"));
912 printf(_(" -v, --verbose write a lot of output\n"));
913 printf(_(" -V, --version output version information, then exit\n"));
914 printf(_(" -?, --help show this help, then exit\n"));
915 printf(_("\nConnection options:\n"));
916 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
917 printf(_(" -p, --port=PORT database server port\n"));
918 printf(_(" -U, --username=USERNAME user name to connect as\n"));
919 printf(_(" -w, --no-password never prompt for password\n"));
920 printf(_(" -W, --password force password prompt\n"));
921 printf(_(" --maintenance-db=DBNAME alternate maintenance database\n"));
922 printf(_("\nRead the description of the SQL command REINDEX for details.\n"));
923 printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
924 printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
925}
#define _(x)
Definition: elog.c:91
const char * progname
Definition: main.c:44
#define printf(...)
Definition: port.h:245

References _, printf, and progname.

Referenced by main().

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 68 of file reindexdb.c.

69{
70 static struct option long_options[] = {
71 {"host", required_argument, NULL, 'h'},
72 {"port", required_argument, NULL, 'p'},
73 {"username", required_argument, NULL, 'U'},
74 {"no-password", no_argument, NULL, 'w'},
75 {"password", no_argument, NULL, 'W'},
76 {"echo", no_argument, NULL, 'e'},
77 {"quiet", no_argument, NULL, 'q'},
78 {"schema", required_argument, NULL, 'S'},
79 {"dbname", required_argument, NULL, 'd'},
80 {"all", no_argument, NULL, 'a'},
81 {"system", no_argument, NULL, 's'},
82 {"table", required_argument, NULL, 't'},
83 {"index", required_argument, NULL, 'i'},
84 {"jobs", required_argument, NULL, 'j'},
85 {"verbose", no_argument, NULL, 'v'},
86 {"concurrently", no_argument, NULL, 1},
87 {"maintenance-db", required_argument, NULL, 2},
88 {"tablespace", required_argument, NULL, 3},
89 {NULL, 0, NULL, 0}
90 };
91
92 const char *progname;
93 int optindex;
94 int c;
95
96 const char *dbname = NULL;
97 const char *maintenance_db = NULL;
98 const char *host = NULL;
99 const char *port = NULL;
100 const char *username = NULL;
101 const char *tablespace = NULL;
102 enum trivalue prompt_password = TRI_DEFAULT;
103 ConnParams cparams;
104 bool syscatalog = false;
105 bool alldb = false;
106 bool echo = false;
107 bool quiet = false;
108 bool verbose = false;
109 bool concurrently = false;
110 SimpleStringList indexes = {NULL, NULL};
111 SimpleStringList tables = {NULL, NULL};
112 SimpleStringList schemas = {NULL, NULL};
113 int concurrentCons = 1;
114
115 pg_logging_init(argv[0]);
116 progname = get_progname(argv[0]);
117 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
118
119 handle_help_version_opts(argc, argv, "reindexdb", help);
120
121 /* process command-line options */
122 while ((c = getopt_long(argc, argv, "ad:eh:i:j:qp:sS:t:U:vwW", long_options, &optindex)) != -1)
123 {
124 switch (c)
125 {
126 case 'a':
127 alldb = true;
128 break;
129 case 'd':
131 break;
132 case 'e':
133 echo = true;
134 break;
135 case 'h':
136 host = pg_strdup(optarg);
137 break;
138 case 'i':
140 break;
141 case 'j':
142 if (!option_parse_int(optarg, "-j/--jobs", 1, INT_MAX,
143 &concurrentCons))
144 exit(1);
145 break;
146 case 'q':
147 quiet = true;
148 break;
149 case 'p':
151 break;
152 case 's':
153 syscatalog = true;
154 break;
155 case 'S':
157 break;
158 case 't':
160 break;
161 case 'U':
163 break;
164 case 'v':
165 verbose = true;
166 break;
167 case 'w':
168 prompt_password = TRI_NO;
169 break;
170 case 'W':
171 prompt_password = TRI_YES;
172 break;
173 case 1:
174 concurrently = true;
175 break;
176 case 2:
177 maintenance_db = pg_strdup(optarg);
178 break;
179 case 3:
181 break;
182 default:
183 /* getopt_long already emitted a complaint */
184 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
185 exit(1);
186 }
187 }
188
189 /*
190 * Non-option argument specifies database name as long as it wasn't
191 * already specified with -d / --dbname
192 */
193 if (optind < argc && dbname == NULL)
194 {
195 dbname = argv[optind];
196 optind++;
197 }
198
199 if (optind < argc)
200 {
201 pg_log_error("too many command-line arguments (first is \"%s\")",
202 argv[optind]);
203 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
204 exit(1);
205 }
206
207 /* fill cparams except for dbname, which is set below */
208 cparams.pghost = host;
209 cparams.pgport = port;
210 cparams.pguser = username;
211 cparams.prompt_password = prompt_password;
212 cparams.override_dbname = NULL;
213
215
216 if (concurrentCons > 1 && syscatalog)
217 pg_fatal("cannot use multiple jobs to reindex system catalogs");
218
219 if (alldb)
220 {
221 if (dbname)
222 pg_fatal("cannot reindex all databases and a specific one at the same time");
223
224 cparams.dbname = maintenance_db;
225
226 reindex_all_databases(&cparams, progname, echo, quiet, verbose,
227 concurrently, concurrentCons, tablespace,
228 syscatalog, &schemas, &tables, &indexes);
229 }
230 else
231 {
232 if (dbname == NULL)
233 {
234 if (getenv("PGDATABASE"))
235 dbname = getenv("PGDATABASE");
236 else if (getenv("PGUSER"))
237 dbname = getenv("PGUSER");
238 else
240 }
241
242 cparams.dbname = dbname;
243
244 if (syscatalog)
245 reindex_one_database(&cparams, REINDEX_SYSTEM, NULL,
246 progname, echo, verbose,
247 concurrently, 1, tablespace);
248
249 if (schemas.head != NULL)
250 reindex_one_database(&cparams, REINDEX_SCHEMA, &schemas,
251 progname, echo, verbose,
252 concurrently, concurrentCons, tablespace);
253
254 if (indexes.head != NULL)
255 reindex_one_database(&cparams, REINDEX_INDEX, &indexes,
256 progname, echo, verbose,
257 concurrently, concurrentCons, tablespace);
258
259 if (tables.head != NULL)
260 reindex_one_database(&cparams, REINDEX_TABLE, &tables,
261 progname, echo, verbose,
262 concurrently, concurrentCons, tablespace);
263
264 /*
265 * reindex database only if neither index nor table nor schema nor
266 * system catalogs is specified
267 */
268 if (!syscatalog && indexes.head == NULL &&
269 tables.head == NULL && schemas.head == NULL)
271 progname, echo, verbose,
272 concurrently, concurrentCons, tablespace);
273 }
274
275 exit(0);
276}
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1185
void setup_cancel_handler(void(*query_cancel_callback)(void))
Definition: cancel.c:183
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:429
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:60
#define no_argument
Definition: getopt_long.h:25
#define required_argument
Definition: getopt_long.h:26
static char * username
Definition: initdb.c:153
void pg_logging_init(const char *argv0)
Definition: logging.c:83
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_error_hint(...)
Definition: logging.h:112
bool option_parse_int(const char *optarg, const char *optname, int min_range, int max_range, int *result)
Definition: option_utils.c:50
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
Definition: option_utils.c:24
#define pg_fatal(...)
PGDLLIMPORT int optind
Definition: getopt.c:51
PGDLLIMPORT char * optarg
Definition: getopt.c:53
static int port
Definition: pg_regress.c:115
const char * get_progname(const char *argv0)
Definition: path.c:652
char * c
static void reindex_all_databases(ConnParams *cparams, const char *progname, bool echo, bool quiet, bool verbose, bool concurrently, int concurrentCons, const char *tablespace, bool syscatalog, SimpleStringList *schemas, SimpleStringList *tables, SimpleStringList *indexes)
Definition: reindexdb.c:831
static void help(const char *progname)
Definition: reindexdb.c:895
static void reindex_one_database(ConnParams *cparams, ReindexType type, SimpleStringList *user_list, const char *progname, bool echo, bool verbose, bool concurrently, int concurrentCons, const char *tablespace)
Definition: reindexdb.c:279
char * dbname
Definition: streamutil.c:49
const char * pguser
Definition: connect_utils.h:31
char * override_dbname
Definition: pg_backup.h:93
char * pgport
Definition: pg_backup.h:87
char * pghost
Definition: pg_backup.h:88
char * dbname
Definition: pg_backup.h:86
enum trivalue prompt_password
Definition: connect_utils.h:32
const char * get_user_name_or_exit(const char *progname)
Definition: username.c:74
trivalue
Definition: vacuumlo.c:35
@ TRI_YES
Definition: vacuumlo.c:38
@ TRI_DEFAULT
Definition: vacuumlo.c:36
@ TRI_NO
Definition: vacuumlo.c:37

References dbname, _connParams::dbname, get_progname(), get_user_name_or_exit(), getopt_long(), handle_help_version_opts(), SimpleStringList::head, help(), no_argument, optarg, optind, option_parse_int(), _connParams::override_dbname, pg_fatal, pg_log_error, pg_log_error_hint, pg_logging_init(), pg_strdup(), PG_TEXTDOMAIN, _connParams::pghost, _connParams::pgport, _connParams::pguser, port, progname, _connParams::prompt_password, reindex_all_databases(), REINDEX_DATABASE, REINDEX_INDEX, reindex_one_database(), REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, required_argument, set_pglocale_pgservice(), setup_cancel_handler(), simple_string_list_append(), tablespace, TRI_DEFAULT, TRI_NO, TRI_YES, username, and verbose.

◆ reindex_all_databases()

static void reindex_all_databases ( ConnParams cparams,
const char *  progname,
bool  echo,
bool  quiet,
bool  verbose,
bool  concurrently,
int  concurrentCons,
const char *  tablespace,
bool  syscatalog,
SimpleStringList schemas,
SimpleStringList tables,
SimpleStringList indexes 
)
static

Definition at line 831 of file reindexdb.c.

837{
838 PGconn *conn;
839 PGresult *result;
840 int i;
841
842 conn = connectMaintenanceDatabase(cparams, progname, echo);
843 result = executeQuery(conn,
844 "SELECT datname FROM pg_database WHERE datallowconn AND datconnlimit <> -2 ORDER BY 1;",
845 echo);
846 PQfinish(conn);
847
848 for (i = 0; i < PQntuples(result); i++)
849 {
850 char *dbname = PQgetvalue(result, i, 0);
851
852 if (!quiet)
853 {
854 printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
855 fflush(stdout);
856 }
857
858 cparams->override_dbname = dbname;
859
860 if (syscatalog)
862 progname, echo, verbose,
863 concurrently, 1, tablespace);
864
865 if (schemas->head != NULL)
866 reindex_one_database(cparams, REINDEX_SCHEMA, schemas,
867 progname, echo, verbose,
868 concurrently, concurrentCons, tablespace);
869
870 if (indexes->head != NULL)
871 reindex_one_database(cparams, REINDEX_INDEX, indexes,
872 progname, echo, verbose,
873 concurrently, 1, tablespace);
874
875 if (tables->head != NULL)
876 reindex_one_database(cparams, REINDEX_TABLE, tables,
877 progname, echo, verbose,
878 concurrently, concurrentCons, tablespace);
879
880 /*
881 * reindex database only if neither index nor table nor schema nor
882 * system catalogs is specified
883 */
884 if (!syscatalog && indexes->head == NULL &&
885 tables->head == NULL && schemas->head == NULL)
887 progname, echo, verbose,
888 concurrently, concurrentCons, tablespace);
889 }
890
891 PQclear(result);
892}
PGconn * connectMaintenanceDatabase(ConnParams *cparams, const char *progname, bool echo)
void PQfinish(PGconn *conn)
Definition: fe-connect.c:5290

References _, conn, connectMaintenanceDatabase(), dbname, executeQuery(), SimpleStringList::head, i, _connParams::override_dbname, PQclear(), PQfinish(), PQgetvalue(), PQntuples(), printf, progname, REINDEX_DATABASE, REINDEX_INDEX, reindex_one_database(), REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, generate_unaccent_rules::stdout, tablespace, and verbose.

Referenced by main().

◆ reindex_one_database()

static void reindex_one_database ( ConnParams cparams,
ReindexType  type,
SimpleStringList user_list,
const char *  progname,
bool  echo,
bool  verbose,
bool  concurrently,
int  concurrentCons,
const char *  tablespace 
)
static

Definition at line 279 of file reindexdb.c.

284{
285 PGconn *conn;
287 SimpleOidListCell *indices_tables_cell = NULL;
288 bool parallel = concurrentCons > 1;
289 SimpleStringList *process_list = NULL;
290 SimpleOidList *tableoid_list = NULL;
291 ReindexType process_type = type;
293 bool failed = false;
294 int items_count = 0;
295 ParallelSlot *free_slot = NULL;
296
297 conn = connectDatabase(cparams, progname, echo, false, true);
298
299 if (concurrently && PQserverVersion(conn) < 120000)
300 {
301 PQfinish(conn);
302 pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
303 "concurrently", "12");
304 }
305
306 if (tablespace && PQserverVersion(conn) < 140000)
307 {
308 PQfinish(conn);
309 pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
310 "tablespace", "14");
311 }
312
313 if (!parallel)
314 {
315 switch (process_type)
316 {
317 case REINDEX_DATABASE:
318 case REINDEX_SYSTEM:
319
320 /*
321 * Database and system reindexes only need to work on the
322 * database itself, so build a list with a single entry.
323 */
324 Assert(user_list == NULL);
325 process_list = pg_malloc0(sizeof(SimpleStringList));
326 simple_string_list_append(process_list, PQdb(conn));
327 break;
328
329 case REINDEX_INDEX:
330 case REINDEX_SCHEMA:
331 case REINDEX_TABLE:
332 process_list = user_list;
333 Assert(user_list != NULL);
334 break;
335 }
336 }
337 else
338 {
339 switch (process_type)
340 {
341 case REINDEX_SCHEMA:
342 Assert(user_list != NULL);
343 /* fall through */
344
345 case REINDEX_DATABASE:
346
347 /* Build a list of relations from the database */
348 process_list = get_parallel_tables_list(conn, process_type,
349 user_list, echo);
350 process_type = REINDEX_TABLE;
351
352 /* Bail out if nothing to process */
353 if (process_list == NULL)
354 {
355 PQfinish(conn);
356 return;
357 }
358 break;
359
360 case REINDEX_INDEX:
361 Assert(user_list != NULL);
362
363 /*
364 * Generate a list of indexes and a matching list of table
365 * OIDs, based on the user-specified index names.
366 */
367 get_parallel_tabidx_list(conn, user_list, &tableoid_list,
368 echo);
369
370 /* Bail out if nothing to process */
371 if (tableoid_list == NULL)
372 {
373 PQfinish(conn);
374 return;
375 }
376
377 indices_tables_cell = tableoid_list->head;
378 process_list = user_list;
379 break;
380
381 case REINDEX_SYSTEM:
382 /* not supported */
383 process_list = NULL;
384 Assert(false);
385 break;
386
387 case REINDEX_TABLE:
388 process_list = user_list;
389 break;
390 }
391 }
392
393 /*
394 * Adjust the number of concurrent connections depending on the items in
395 * the list. We choose the minimum between the number of concurrent
396 * connections and the number of items in the list.
397 */
398 items_count = 0;
399 for (cell = process_list->head; cell; cell = cell->next)
400 {
401 items_count++;
402
403 /* no need to continue if there are more elements than jobs */
404 if (items_count >= concurrentCons)
405 break;
406 }
407 concurrentCons = Min(concurrentCons, items_count);
408 Assert(concurrentCons > 0);
409
410 Assert(process_list != NULL);
411
412 sa = ParallelSlotsSetup(concurrentCons, cparams, progname, echo, NULL);
414 conn = NULL;
415
416 cell = process_list->head;
417 do
418 {
419 PQExpBufferData sql;
420 const char *objname = cell->val;
421
422 if (CancelRequested)
423 {
424 failed = true;
425 goto finish;
426 }
427
428 free_slot = ParallelSlotsGetIdle(sa, NULL);
429 if (!free_slot)
430 {
431 failed = true;
432 goto finish;
433 }
434
436 initPQExpBuffer(&sql);
437 if (parallel && process_type == REINDEX_INDEX)
438 {
439 /*
440 * For parallel index-level REINDEX, the indices of the same table
441 * are ordered together and they are to be processed by the same
442 * job. So, we put all the relevant REINDEX commands into the
443 * same SQL query to be processed by this job at once.
444 */
445 gen_reindex_command(free_slot->connection, process_type, objname,
446 echo, verbose, concurrently, tablespace, &sql);
447 while (indices_tables_cell->next &&
448 indices_tables_cell->val == indices_tables_cell->next->val)
449 {
450 indices_tables_cell = indices_tables_cell->next;
451 cell = cell->next;
452 objname = cell->val;
453 appendPQExpBufferChar(&sql, '\n');
454 gen_reindex_command(free_slot->connection, process_type, objname,
455 echo, verbose, concurrently, tablespace, &sql);
456 }
457 indices_tables_cell = indices_tables_cell->next;
458 }
459 else
460 {
461 gen_reindex_command(free_slot->connection, process_type, objname,
462 echo, verbose, concurrently, tablespace, &sql);
463 }
464 run_reindex_command(free_slot->connection, process_type, objname,
465 echo, &sql);
466 termPQExpBuffer(&sql);
467
468 cell = cell->next;
469 } while (cell != NULL);
470
472 failed = true;
473
474finish:
475 if (process_list != user_list)
476 {
477 simple_string_list_destroy(process_list);
478 pg_free(process_list);
479 }
480
481 if (tableoid_list)
482 {
483 simple_oid_list_destroy(tableoid_list);
484 pg_free(tableoid_list);
485 }
486
488 pfree(sa);
489
490 if (failed)
491 exit(1);
492}
#define Min(x, y)
Definition: c.h:975
volatile sig_atomic_t CancelRequested
Definition: cancel.c:59
PGconn * connectDatabase(const ConnParams *cparams, const char *progname, bool echo, bool fail_ok, bool allow_password_reuse)
Definition: connect_utils.c:32
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:7609
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:7447
void pg_free(void *ptr)
Definition: fe_memutils.c:105
void pfree(void *pointer)
Definition: mcxt.c:2150
ParallelSlotArray * ParallelSlotsSetup(int numslots, ConnParams *cparams, const char *progname, bool echo, const char *initcmd)
bool ParallelSlotsWaitCompletion(ParallelSlotArray *sa)
bool TableCommandResultHandler(PGresult *res, PGconn *conn, void *context)
ParallelSlot * ParallelSlotsGetIdle(ParallelSlotArray *sa, const char *dbname)
void ParallelSlotsTerminate(ParallelSlotArray *sa)
void ParallelSlotsAdoptConn(ParallelSlotArray *sa, PGconn *conn)
static void ParallelSlotSetHandler(ParallelSlot *slot, ParallelSlotResultHandler handler, void *context)
Definition: parallel_slot.h:47
static void get_parallel_tabidx_list(PGconn *conn, SimpleStringList *index_list, SimpleOidList **table_list, bool echo)
Definition: reindexdb.c:744
static SimpleStringList * get_parallel_tables_list(PGconn *conn, ReindexType type, SimpleStringList *user_list, bool echo)
Definition: reindexdb.c:629
static void run_reindex_command(PGconn *conn, ReindexType type, const char *name, bool echo, PQExpBufferData *sql)
Definition: reindexdb.c:582
static void gen_reindex_command(PGconn *conn, ReindexType type, const char *name, bool echo, bool verbose, bool concurrently, const char *tablespace, PQExpBufferData *sql)
Definition: reindexdb.c:499
void simple_oid_list_destroy(SimpleOidList *list)
Definition: simple_list.c:106
PGconn * connection
Definition: parallel_slot.h:23
struct SimpleOidListCell * next
Definition: simple_list.h:22
SimpleOidListCell * head
Definition: simple_list.h:28

References appendPQExpBufferChar(), Assert(), CancelRequested, conn, connectDatabase(), ParallelSlot::connection, gen_reindex_command(), get_parallel_tabidx_list(), get_parallel_tables_list(), SimpleOidList::head, SimpleStringList::head, initPQExpBuffer(), Min, SimpleOidListCell::next, SimpleStringListCell::next, ParallelSlotsAdoptConn(), ParallelSlotSetHandler(), ParallelSlotsGetIdle(), ParallelSlotsSetup(), ParallelSlotsTerminate(), ParallelSlotsWaitCompletion(), pfree(), pg_fatal, pg_free(), pg_malloc0(), PQdb(), PQfinish(), PQserverVersion(), progname, REINDEX_DATABASE, REINDEX_INDEX, REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, run_reindex_command(), simple_oid_list_destroy(), simple_string_list_append(), simple_string_list_destroy(), TableCommandResultHandler(), tablespace, termPQExpBuffer(), type, SimpleOidListCell::val, SimpleStringListCell::val, and verbose.

Referenced by main(), and reindex_all_databases().

◆ run_reindex_command()

static void run_reindex_command ( PGconn conn,
ReindexType  type,
const char *  name,
bool  echo,
PQExpBufferData sql 
)
static

Definition at line 582 of file reindexdb.c.

584{
585 bool status;
586
587 if (echo)
588 printf("%s\n", sql->data);
589
590 status = PQsendQuery(conn, sql->data) == 1;
591
592 if (!status)
593 {
594 switch (type)
595 {
596 case REINDEX_DATABASE:
597 pg_log_error("reindexing of database \"%s\" failed: %s",
599 break;
600 case REINDEX_INDEX:
601 pg_log_error("reindexing of index \"%s\" in database \"%s\" failed: %s",
603 break;
604 case REINDEX_SCHEMA:
605 pg_log_error("reindexing of schema \"%s\" in database \"%s\" failed: %s",
607 break;
608 case REINDEX_SYSTEM:
609 pg_log_error("reindexing of system catalogs in database \"%s\" failed: %s",
611 break;
612 case REINDEX_TABLE:
613 pg_log_error("reindexing of table \"%s\" in database \"%s\" failed: %s",
615 break;
616 }
617 }
618}
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7619
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1416

References conn, PQExpBufferData::data, name, pg_log_error, PQdb(), PQerrorMessage(), PQsendQuery(), printf, REINDEX_DATABASE, REINDEX_INDEX, REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, and type.

Referenced by reindex_one_database().