PostgreSQL Source Code  git master
reindexdb.c File Reference
#include "postgres_fe.h"
#include "catalog/pg_class_d.h"
#include "common.h"
#include "common/connect.h"
#include "common/logging.h"
#include "fe_utils/cancel.h"
#include "fe_utils/simple_list.h"
#include "fe_utils/string_utils.h"
#include "scripts_parallel.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_object_list (PGconn *conn, ReindexType type, SimpleStringList *user_list, bool echo)
 
static void reindex_one_database (const ConnParams *cparams, ReindexType type, SimpleStringList *user_list, const char *progname, bool echo, bool verbose, bool concurrently, int concurrentCons)
 
static void reindex_all_databases (ConnParams *cparams, const char *progname, bool echo, bool quiet, bool verbose, bool concurrently, int concurrentCons)
 
static void run_reindex_command (PGconn *conn, ReindexType type, const char *name, bool echo, bool verbose, bool concurrently, bool async)
 
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 23 of file reindexdb.c.

Function Documentation

◆ get_parallel_object_list()

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

Definition at line 603 of file reindexdb.c.

References appendPQExpBufferStr(), appendStringLiteralConn(), Assert, buf, CppAsString2, PQExpBufferData::data, executeQuery(), fmtQualifiedId(), SimpleStringList::head, i, initPQExpBuffer(), SimpleStringListCell::next, pg_malloc0(), PQclear(), PQfinish(), PQgetvalue(), PQntuples(), REINDEX_DATABASE, REINDEX_INDEX, REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, resetPQExpBuffer(), simple_string_list_append(), termPQExpBuffer(), and SimpleStringListCell::val.

Referenced by reindex_one_database().

605 {
606  PQExpBufferData catalog_query;
608  PGresult *res;
609  SimpleStringList *tables;
610  int ntups,
611  i;
612 
613  initPQExpBuffer(&catalog_query);
614 
615  /*
616  * The queries here are using a safe search_path, so there's no need to
617  * fully qualify everything.
618  */
619  switch (type)
620  {
621  case REINDEX_DATABASE:
622  Assert(user_list == NULL);
623  appendPQExpBufferStr(&catalog_query,
624  "SELECT c.relname, ns.nspname\n"
625  " FROM pg_catalog.pg_class c\n"
626  " JOIN pg_catalog.pg_namespace ns"
627  " ON c.relnamespace = ns.oid\n"
628  " WHERE ns.nspname != 'pg_catalog'\n"
629  " AND c.relkind IN ("
630  CppAsString2(RELKIND_RELATION) ", "
631  CppAsString2(RELKIND_MATVIEW) ")\n"
632  " ORDER BY c.relpages DESC;");
633  break;
634 
635  case REINDEX_SCHEMA:
636  {
637  SimpleStringListCell *cell;
638  bool nsp_listed = false;
639 
640  Assert(user_list != NULL);
641 
642  /*
643  * All the tables from all the listed schemas are grabbed at
644  * once.
645  */
646  appendPQExpBufferStr(&catalog_query,
647  "SELECT c.relname, ns.nspname\n"
648  " FROM pg_catalog.pg_class c\n"
649  " JOIN pg_catalog.pg_namespace ns"
650  " ON c.relnamespace = ns.oid\n"
651  " WHERE c.relkind IN ("
652  CppAsString2(RELKIND_RELATION) ", "
653  CppAsString2(RELKIND_MATVIEW) ")\n"
654  " AND ns.nspname IN (");
655 
656  for (cell = user_list->head; cell; cell = cell->next)
657  {
658  const char *nspname = cell->val;
659 
660  if (nsp_listed)
661  appendPQExpBufferStr(&catalog_query, ", ");
662  else
663  nsp_listed = true;
664 
665  appendStringLiteralConn(&catalog_query, nspname, conn);
666  }
667 
668  appendPQExpBufferStr(&catalog_query, ")\n"
669  " ORDER BY c.relpages DESC;");
670  }
671  break;
672 
673  case REINDEX_SYSTEM:
674  case REINDEX_INDEX:
675  case REINDEX_TABLE:
676  Assert(false);
677  break;
678  }
679 
680  res = executeQuery(conn, catalog_query.data, echo);
681  termPQExpBuffer(&catalog_query);
682 
683  /*
684  * If no rows are returned, there are no matching tables, so we are done.
685  */
686  ntups = PQntuples(res);
687  if (ntups == 0)
688  {
689  PQclear(res);
690  PQfinish(conn);
691  return NULL;
692  }
693 
694  tables = pg_malloc0(sizeof(SimpleStringList));
695 
696  /* Build qualified identifiers for each table */
697  initPQExpBuffer(&buf);
698  for (i = 0; i < ntups; i++)
699  {
701  fmtQualifiedId(PQgetvalue(res, i, 1),
702  PQgetvalue(res, i, 0)));
703 
704  simple_string_list_append(tables, buf.data);
705  resetPQExpBuffer(&buf);
706  }
707  termPQExpBuffer(&buf);
708  PQclear(res);
709 
710  return tables;
711 }
static PGresult * executeQuery(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1875
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3163
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4174
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2769
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
static char * buf
Definition: pg_test_fsync.c:68
struct SimpleStringListCell * next
Definition: simple_list.h:34
#define CppAsString2(x)
Definition: c.h:223
void simple_string_list_append(SimpleStringList *list, const char *val)
Definition: simple_list.c:63
void PQclear(PGresult *res)
Definition: fe-exec.c:694
#define Assert(condition)
Definition: c.h:746
SimpleStringListCell * head
Definition: simple_list.h:42
const char * fmtQualifiedId(const char *schema, const char *id)
Definition: string_utils.c:145
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
Definition: string_utils.c:293
int i
char val[FLEXIBLE_ARRAY_MEMBER]
Definition: simple_list.h:37
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92

◆ help()

static void help ( const char *  progname)
static

Definition at line 747 of file reindexdb.c.

References _, and printf.

Referenced by main().

748 {
749  printf(_("%s reindexes a PostgreSQL database.\n\n"), progname);
750  printf(_("Usage:\n"));
751  printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
752  printf(_("\nOptions:\n"));
753  printf(_(" -a, --all reindex all databases\n"));
754  printf(_(" --concurrently reindex concurrently\n"));
755  printf(_(" -d, --dbname=DBNAME database to reindex\n"));
756  printf(_(" -e, --echo show the commands being sent to the server\n"));
757  printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
758  printf(_(" -j, --jobs=NUM use this many concurrent connections to reindex\n"));
759  printf(_(" -q, --quiet don't write any messages\n"));
760  printf(_(" -s, --system reindex system catalogs\n"));
761  printf(_(" -S, --schema=SCHEMA reindex specific schema(s) only\n"));
762  printf(_(" -t, --table=TABLE reindex specific table(s) only\n"));
763  printf(_(" -v, --verbose write a lot of output\n"));
764  printf(_(" -V, --version output version information, then exit\n"));
765  printf(_(" -?, --help show this help, then exit\n"));
766  printf(_("\nConnection options:\n"));
767  printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
768  printf(_(" -p, --port=PORT database server port\n"));
769  printf(_(" -U, --username=USERNAME user name to connect as\n"));
770  printf(_(" -w, --no-password never prompt for password\n"));
771  printf(_(" -W, --password force password prompt\n"));
772  printf(_(" --maintenance-db=DBNAME alternate maintenance database\n"));
773  printf(_("\nRead the description of the SQL command REINDEX for details.\n"));
774  printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
775  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
776 }
#define printf(...)
Definition: port.h:221
const char * progname
Definition: pg_standby.c:36
#define _(x)
Definition: elog.c:88

◆ main()

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

Definition at line 53 of file reindexdb.c.

References _, dbname, _connParams::dbname, fprintf, get_progname(), get_user_name_or_exit(), getopt_long(), handle_help_version_opts(), SimpleStringList::head, help(), no_argument, optarg, optind, _connParams::override_dbname, pg_log_error, 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(), TRI_DEFAULT, TRI_NO, TRI_YES, username, and verbose.

54 {
55  static struct option long_options[] = {
56  {"host", required_argument, NULL, 'h'},
57  {"port", required_argument, NULL, 'p'},
58  {"username", required_argument, NULL, 'U'},
59  {"no-password", no_argument, NULL, 'w'},
60  {"password", no_argument, NULL, 'W'},
61  {"echo", no_argument, NULL, 'e'},
62  {"quiet", no_argument, NULL, 'q'},
63  {"schema", required_argument, NULL, 'S'},
64  {"dbname", required_argument, NULL, 'd'},
65  {"all", no_argument, NULL, 'a'},
66  {"system", no_argument, NULL, 's'},
67  {"table", required_argument, NULL, 't'},
68  {"index", required_argument, NULL, 'i'},
69  {"jobs", required_argument, NULL, 'j'},
70  {"verbose", no_argument, NULL, 'v'},
71  {"concurrently", no_argument, NULL, 1},
72  {"maintenance-db", required_argument, NULL, 2},
73  {NULL, 0, NULL, 0}
74  };
75 
76  const char *progname;
77  int optindex;
78  int c;
79 
80  const char *dbname = NULL;
81  const char *maintenance_db = NULL;
82  const char *host = NULL;
83  const char *port = NULL;
84  const char *username = NULL;
85  enum trivalue prompt_password = TRI_DEFAULT;
86  ConnParams cparams;
87  bool syscatalog = false;
88  bool alldb = false;
89  bool echo = false;
90  bool quiet = false;
91  bool verbose = false;
92  bool concurrently = false;
93  SimpleStringList indexes = {NULL, NULL};
94  SimpleStringList tables = {NULL, NULL};
95  SimpleStringList schemas = {NULL, NULL};
96  int concurrentCons = 1;
97 
98  pg_logging_init(argv[0]);
99  progname = get_progname(argv[0]);
100  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
101 
102  handle_help_version_opts(argc, argv, "reindexdb", help);
103 
104  /* process command-line options */
105  while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:j:v", long_options, &optindex)) != -1)
106  {
107  switch (c)
108  {
109  case 'h':
110  host = pg_strdup(optarg);
111  break;
112  case 'p':
113  port = pg_strdup(optarg);
114  break;
115  case 'U':
116  username = pg_strdup(optarg);
117  break;
118  case 'w':
119  prompt_password = TRI_NO;
120  break;
121  case 'W':
122  prompt_password = TRI_YES;
123  break;
124  case 'e':
125  echo = true;
126  break;
127  case 'q':
128  quiet = true;
129  break;
130  case 'S':
132  break;
133  case 'd':
134  dbname = pg_strdup(optarg);
135  break;
136  case 'a':
137  alldb = true;
138  break;
139  case 's':
140  syscatalog = true;
141  break;
142  case 't':
144  break;
145  case 'i':
147  break;
148  case 'j':
149  concurrentCons = atoi(optarg);
150  if (concurrentCons <= 0)
151  {
152  pg_log_error("number of parallel jobs must be at least 1");
153  exit(1);
154  }
155  break;
156  case 'v':
157  verbose = true;
158  break;
159  case 1:
160  concurrently = true;
161  break;
162  case 2:
163  maintenance_db = pg_strdup(optarg);
164  break;
165  default:
166  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
167  exit(1);
168  }
169  }
170 
171  /*
172  * Non-option argument specifies database name as long as it wasn't
173  * already specified with -d / --dbname
174  */
175  if (optind < argc && dbname == NULL)
176  {
177  dbname = argv[optind];
178  optind++;
179  }
180 
181  if (optind < argc)
182  {
183  pg_log_error("too many command-line arguments (first is \"%s\")",
184  argv[optind]);
185  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
186  exit(1);
187  }
188 
189  /* fill cparams except for dbname, which is set below */
190  cparams.pghost = host;
191  cparams.pgport = port;
192  cparams.pguser = username;
193  cparams.prompt_password = prompt_password;
194  cparams.override_dbname = NULL;
195 
196  setup_cancel_handler(NULL);
197 
198  if (alldb)
199  {
200  if (dbname)
201  {
202  pg_log_error("cannot reindex all databases and a specific one at the same time");
203  exit(1);
204  }
205  if (syscatalog)
206  {
207  pg_log_error("cannot reindex all databases and system catalogs at the same time");
208  exit(1);
209  }
210  if (schemas.head != NULL)
211  {
212  pg_log_error("cannot reindex specific schema(s) in all databases");
213  exit(1);
214  }
215  if (tables.head != NULL)
216  {
217  pg_log_error("cannot reindex specific table(s) in all databases");
218  exit(1);
219  }
220  if (indexes.head != NULL)
221  {
222  pg_log_error("cannot reindex specific index(es) in all databases");
223  exit(1);
224  }
225 
226  cparams.dbname = maintenance_db;
227 
228  reindex_all_databases(&cparams, progname, echo, quiet, verbose,
229  concurrently, concurrentCons);
230  }
231  else if (syscatalog)
232  {
233  if (schemas.head != NULL)
234  {
235  pg_log_error("cannot reindex specific schema(s) and system catalogs at the same time");
236  exit(1);
237  }
238  if (tables.head != NULL)
239  {
240  pg_log_error("cannot reindex specific table(s) and system catalogs at the same time");
241  exit(1);
242  }
243  if (indexes.head != NULL)
244  {
245  pg_log_error("cannot reindex specific index(es) and system catalogs at the same time");
246  exit(1);
247  }
248 
249  if (concurrentCons > 1)
250  {
251  pg_log_error("cannot use multiple jobs to reindex system catalogs");
252  exit(1);
253  }
254 
255  if (dbname == NULL)
256  {
257  if (getenv("PGDATABASE"))
258  dbname = getenv("PGDATABASE");
259  else if (getenv("PGUSER"))
260  dbname = getenv("PGUSER");
261  else
262  dbname = get_user_name_or_exit(progname);
263  }
264 
265  cparams.dbname = dbname;
266 
267  reindex_one_database(&cparams, REINDEX_SYSTEM, NULL,
268  progname, echo, verbose,
269  concurrently, 1);
270  }
271  else
272  {
273  /*
274  * Index-level REINDEX is not supported with multiple jobs as we
275  * cannot control the concurrent processing of multiple indexes
276  * depending on the same relation.
277  */
278  if (concurrentCons > 1 && indexes.head != NULL)
279  {
280  pg_log_error("cannot use multiple jobs to reindex indexes");
281  exit(1);
282  }
283 
284  if (dbname == NULL)
285  {
286  if (getenv("PGDATABASE"))
287  dbname = getenv("PGDATABASE");
288  else if (getenv("PGUSER"))
289  dbname = getenv("PGUSER");
290  else
291  dbname = get_user_name_or_exit(progname);
292  }
293 
294  cparams.dbname = dbname;
295 
296  if (schemas.head != NULL)
297  reindex_one_database(&cparams, REINDEX_SCHEMA, &schemas,
298  progname, echo, verbose,
299  concurrently, concurrentCons);
300 
301  if (indexes.head != NULL)
302  reindex_one_database(&cparams, REINDEX_INDEX, &indexes,
303  progname, echo, verbose,
304  concurrently, 1);
305 
306  if (tables.head != NULL)
307  reindex_one_database(&cparams, REINDEX_TABLE, &tables,
308  progname, echo, verbose,
309  concurrently, concurrentCons);
310 
311  /*
312  * reindex database only if neither index nor table nor schema is
313  * specified
314  */
315  if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
316  reindex_one_database(&cparams, REINDEX_DATABASE, NULL,
317  progname, echo, verbose,
318  concurrently, concurrentCons);
319  }
320 
321  exit(0);
322 }
char * pgport
Definition: pg_backup.h:66
const char * get_progname(const char *argv0)
Definition: path.c:453
#define pg_log_error(...)
Definition: logging.h:80
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
void pg_logging_init(const char *argv0)
Definition: logging.c:81
static void setup_cancel_handler(void)
Definition: parallel.c:613
const char * progname
Definition: pg_standby.c:36
#define fprintf
Definition: port.h:219
static void help(const char *progname)
Definition: reindexdb.c:747
char * dbname
Definition: pg_backup.h:65
#define required_argument
Definition: getopt_long.h:25
int optind
Definition: getopt.c:50
static void reindex_all_databases(ConnParams *cparams, const char *progname, bool echo, bool quiet, bool verbose, bool concurrently, int concurrentCons)
Definition: reindexdb.c:714
static void reindex_one_database(const ConnParams *cparams, ReindexType type, SimpleStringList *user_list, const char *progname, bool echo, bool verbose, bool concurrently, int concurrentCons)
Definition: reindexdb.c:325
char * c
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
char * override_dbname
Definition: pg_backup.h:72
static int port
Definition: pg_regress.c:92
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
Definition: common.c:34
char * pghost
Definition: pg_backup.h:67
enum trivalue prompt_password
Definition: common.h:32
static int verbose
trivalue
Definition: vacuumlo.c:34
#define no_argument
Definition: getopt_long.h:24
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1157
void simple_string_list_append(SimpleStringList *list, const char *val)
Definition: simple_list.c:63
static char * username
Definition: initdb.c:134
SimpleStringListCell * head
Definition: simple_list.h:42
char * dbname
Definition: streamutil.c:51
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:434
char * optarg
Definition: getopt.c:52
#define _(x)
Definition: elog.c:88
const char * pguser
Definition: common.h:31
const char * get_user_name_or_exit(const char *progname)
Definition: username.c:74

◆ reindex_all_databases()

static void reindex_all_databases ( ConnParams cparams,
const char *  progname,
bool  echo,
bool  quiet,
bool  verbose,
bool  concurrently,
int  concurrentCons 
)
static

Definition at line 714 of file reindexdb.c.

References _, conn, connectMaintenanceDatabase(), dbname, executeQuery(), i, _connParams::override_dbname, PQclear(), PQfinish(), PQgetvalue(), PQntuples(), printf, REINDEX_DATABASE, reindex_one_database(), and generate_unaccent_rules::stdout.

Referenced by main().

717 {
718  PGconn *conn;
719  PGresult *result;
720  int i;
721 
722  conn = connectMaintenanceDatabase(cparams, progname, echo);
723  result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", echo);
724  PQfinish(conn);
725 
726  for (i = 0; i < PQntuples(result); i++)
727  {
728  char *dbname = PQgetvalue(result, i, 0);
729 
730  if (!quiet)
731  {
732  printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
733  fflush(stdout);
734  }
735 
736  cparams->override_dbname = dbname;
737 
738  reindex_one_database(cparams, REINDEX_DATABASE, NULL,
739  progname, echo, verbose, concurrently,
740  concurrentCons);
741  }
742 
743  PQclear(result);
744 }
static PGresult * executeQuery(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1875
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3163
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4174
#define printf(...)
Definition: port.h:221
const char * progname
Definition: pg_standby.c:36
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2769
PGconn * conn
Definition: streamutil.c:54
static void reindex_one_database(const ConnParams *cparams, ReindexType type, SimpleStringList *user_list, const char *progname, bool echo, bool verbose, bool concurrently, int concurrentCons)
Definition: reindexdb.c:325
PGconn * connectMaintenanceDatabase(ConnParams *cparams, const char *progname, bool echo)
Definition: common.c:173
char * override_dbname
Definition: pg_backup.h:72
static int verbose
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * dbname
Definition: streamutil.c:51
int i
#define _(x)
Definition: elog.c:88

◆ reindex_one_database()

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

Definition at line 325 of file reindexdb.c.

References Assert, CancelRequested, conn, connectDatabase(), ParallelSlot::connection, get_parallel_object_list(), SimpleStringList::head, Min, SimpleStringListCell::next, ParallelSlotsGetIdle(), ParallelSlotsSetup(), ParallelSlotsTerminate(), ParallelSlotsWaitCompletion(), pfree(), pg_free(), pg_log_error, pg_log_warning, pg_malloc0(), PQdb(), PQfinish(), PQserverVersion(), REINDEX_DATABASE, REINDEX_INDEX, REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, run_reindex_command(), simple_string_list_append(), simple_string_list_destroy(), generate_unaccent_rules::type, and SimpleStringListCell::val.

Referenced by main(), and reindex_all_databases().

329 {
330  PGconn *conn;
331  SimpleStringListCell *cell;
332  bool parallel = concurrentCons > 1;
333  SimpleStringList *process_list = user_list;
334  ReindexType process_type = type;
335  ParallelSlot *slots;
336  bool failed = false;
337  int items_count = 0;
338 
339  conn = connectDatabase(cparams, progname, echo, false, false);
340 
341  if (concurrently && PQserverVersion(conn) < 120000)
342  {
343  PQfinish(conn);
344  pg_log_error("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
345  "concurrently", "12");
346  exit(1);
347  }
348 
349  if (!parallel)
350  {
351  switch (process_type)
352  {
353  case REINDEX_DATABASE:
354  case REINDEX_SYSTEM:
355 
356  /*
357  * Database and system reindexes only need to work on the
358  * database itself, so build a list with a single entry.
359  */
360  Assert(user_list == NULL);
361  process_list = pg_malloc0(sizeof(SimpleStringList));
362  simple_string_list_append(process_list, PQdb(conn));
363  break;
364 
365  case REINDEX_INDEX:
366  case REINDEX_SCHEMA:
367  case REINDEX_TABLE:
368  Assert(user_list != NULL);
369  break;
370  }
371  }
372  else
373  {
374  switch (process_type)
375  {
376  case REINDEX_DATABASE:
377 
378  /*
379  * Database-wide parallel reindex requires special processing.
380  * If multiple jobs were asked, we have to reindex system
381  * catalogs first as they cannot be processed in parallel.
382  */
383  if (concurrently)
384  pg_log_warning("cannot reindex system catalogs concurrently, skipping all");
385  else
386  run_reindex_command(conn, REINDEX_SYSTEM, PQdb(conn), echo,
387  verbose, concurrently, false);
388 
389  /* Build a list of relations from the database */
390  process_list = get_parallel_object_list(conn, process_type,
391  user_list, echo);
392  process_type = REINDEX_TABLE;
393 
394  /* Bail out if nothing to process */
395  if (process_list == NULL)
396  return;
397  break;
398 
399  case REINDEX_SCHEMA:
400  Assert(user_list != NULL);
401 
402  /* Build a list of relations from all the schemas */
403  process_list = get_parallel_object_list(conn, process_type,
404  user_list, echo);
405  process_type = REINDEX_TABLE;
406 
407  /* Bail out if nothing to process */
408  if (process_list == NULL)
409  return;
410  break;
411 
412  case REINDEX_SYSTEM:
413  case REINDEX_INDEX:
414  /* not supported */
415  Assert(false);
416  break;
417 
418  case REINDEX_TABLE:
419 
420  /*
421  * Fall through. The list of items for tables is already
422  * created.
423  */
424  break;
425  }
426  }
427 
428  /*
429  * Adjust the number of concurrent connections depending on the items in
430  * the list. We choose the minimum between the number of concurrent
431  * connections and the number of items in the list.
432  */
433  for (cell = process_list->head; cell; cell = cell->next)
434  {
435  items_count++;
436 
437  /* no need to continue if there are more elements than jobs */
438  if (items_count >= concurrentCons)
439  break;
440  }
441  concurrentCons = Min(concurrentCons, items_count);
442  Assert(concurrentCons > 0);
443 
444  Assert(process_list != NULL);
445 
446  slots = ParallelSlotsSetup(cparams, progname, echo, conn, concurrentCons);
447 
448  cell = process_list->head;
449  do
450  {
451  const char *objname = cell->val;
452  ParallelSlot *free_slot = NULL;
453 
454  if (CancelRequested)
455  {
456  failed = true;
457  goto finish;
458  }
459 
460  free_slot = ParallelSlotsGetIdle(slots, concurrentCons);
461  if (!free_slot)
462  {
463  failed = true;
464  goto finish;
465  }
466 
467  run_reindex_command(free_slot->connection, process_type, objname,
468  echo, verbose, concurrently, true);
469 
470  cell = cell->next;
471  } while (cell != NULL);
472 
473  if (!ParallelSlotsWaitCompletion(slots, concurrentCons))
474  failed = true;
475 
476 finish:
477  if (process_list != user_list)
478  {
479  simple_string_list_destroy(process_list);
480  pg_free(process_list);
481  }
482 
483  ParallelSlotsTerminate(slots, concurrentCons);
484  pfree(slots);
485 
486  if (failed)
487  exit(1);
488 }
#define pg_log_error(...)
Definition: logging.h:80
#define Min(x, y)
Definition: c.h:928
void simple_string_list_destroy(SimpleStringList *list)
Definition: simple_list.c:125
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4174
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6659
const char * progname
Definition: pg_standby.c:36
void pfree(void *pointer)
Definition: mcxt.c:1057
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
PGconn * conn
Definition: streamutil.c:54
static void run_reindex_command(PGconn *conn, ReindexType type, const char *name, bool echo, bool verbose, bool concurrently, bool async)
Definition: reindexdb.c:491
bool ParallelSlotsWaitCompletion(ParallelSlot *slots, int numslots)
struct SimpleStringListCell * next
Definition: simple_list.h:34
PGconn * connection
void ParallelSlotsTerminate(ParallelSlot *slots, int numslots)
static int verbose
ParallelSlot * ParallelSlotsGetIdle(ParallelSlot *slots, int numslots)
ParallelSlot * ParallelSlotsSetup(const ConnParams *cparams, const char *progname, bool echo, PGconn *conn, int numslots)
void simple_string_list_append(SimpleStringList *list, const char *val)
Definition: simple_list.c:63
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:6519
#define Assert(condition)
Definition: c.h:746
static PGconn * connectDatabase(const char *dbname, const char *connstr, const char *pghost, const char *pgport, const char *pguser, trivalue prompt_password, bool fail_on_error)
Definition: pg_dumpall.c:1636
SimpleStringListCell * head
Definition: simple_list.h:42
void pg_free(void *ptr)
Definition: fe_memutils.c:105
volatile sig_atomic_t CancelRequested
Definition: cancel.c:52
char val[FLEXIBLE_ARRAY_MEMBER]
Definition: simple_list.h:37
static SimpleStringList * get_parallel_object_list(PGconn *conn, ReindexType type, SimpleStringList *user_list, bool echo)
Definition: reindexdb.c:603
#define pg_log_warning(...)
Definition: pgfnames.c:24
ReindexType
Definition: reindexdb.c:23

◆ run_reindex_command()

static void run_reindex_command ( PGconn conn,
ReindexType  type,
const char *  name,
bool  echo,
bool  verbose,
bool  concurrently,
bool  async 
)
static

Definition at line 491 of file reindexdb.c.

References appendPQExpBufferChar(), appendPQExpBufferStr(), appendQualifiedRelation(), Assert, PQExpBufferData::data, executeMaintenanceCommand(), fmtId(), initPQExpBuffer(), pg_log_error, PQdb(), PQerrorMessage(), PQfinish(), PQsendQuery(), printf, REINDEX_DATABASE, REINDEX_INDEX, REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, status(), and termPQExpBuffer().

Referenced by reindex_one_database().

493 {
494  PQExpBufferData sql;
495  bool status;
496 
497  Assert(name);
498 
499  /* build the REINDEX query */
500  initPQExpBuffer(&sql);
501 
502  appendPQExpBufferStr(&sql, "REINDEX ");
503 
504  if (verbose)
505  appendPQExpBufferStr(&sql, "(VERBOSE) ");
506 
507  /* object type */
508  switch (type)
509  {
510  case REINDEX_DATABASE:
511  appendPQExpBufferStr(&sql, "DATABASE ");
512  break;
513  case REINDEX_INDEX:
514  appendPQExpBufferStr(&sql, "INDEX ");
515  break;
516  case REINDEX_SCHEMA:
517  appendPQExpBufferStr(&sql, "SCHEMA ");
518  break;
519  case REINDEX_SYSTEM:
520  appendPQExpBufferStr(&sql, "SYSTEM ");
521  break;
522  case REINDEX_TABLE:
523  appendPQExpBufferStr(&sql, "TABLE ");
524  break;
525  }
526 
527  if (concurrently)
528  appendPQExpBufferStr(&sql, "CONCURRENTLY ");
529 
530  /* object name */
531  switch (type)
532  {
533  case REINDEX_DATABASE:
534  case REINDEX_SYSTEM:
536  break;
537  case REINDEX_INDEX:
538  case REINDEX_TABLE:
539  appendQualifiedRelation(&sql, name, conn, echo);
540  break;
541  case REINDEX_SCHEMA:
542  appendPQExpBufferStr(&sql, name);
543  break;
544  }
545 
546  /* finish the query */
547  appendPQExpBufferChar(&sql, ';');
548 
549  if (async)
550  {
551  if (echo)
552  printf("%s\n", sql.data);
553 
554  status = PQsendQuery(conn, sql.data) == 1;
555  }
556  else
557  status = executeMaintenanceCommand(conn, sql.data, echo);
558 
559  if (!status)
560  {
561  switch (type)
562  {
563  case REINDEX_DATABASE:
564  pg_log_error("reindexing of database \"%s\" failed: %s",
565  PQdb(conn), PQerrorMessage(conn));
566  break;
567  case REINDEX_INDEX:
568  pg_log_error("reindexing of index \"%s\" in database \"%s\" failed: %s",
569  name, PQdb(conn), PQerrorMessage(conn));
570  break;
571  case REINDEX_SCHEMA:
572  pg_log_error("reindexing of schema \"%s\" in database \"%s\" failed: %s",
573  name, PQdb(conn), PQerrorMessage(conn));
574  break;
575  case REINDEX_SYSTEM:
576  pg_log_error("reindexing of system catalogs in database \"%s\" failed: %s",
577  PQdb(conn), PQerrorMessage(conn));
578  break;
579  case REINDEX_TABLE:
580  pg_log_error("reindexing of table \"%s\" in database \"%s\" failed: %s",
581  name, PQdb(conn), PQerrorMessage(conn));
582  break;
583  }
584  if (!async)
585  {
586  PQfinish(conn);
587  exit(1);
588  }
589  }
590 
591  termPQExpBuffer(&sql);
592 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6669
const char * fmtId(const char *rawid)
Definition: string_utils.c:64
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:80
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4174
#define printf(...)
Definition: port.h:221
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1234
bool executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
Definition: common.c:273
static int verbose
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:6519
#define Assert(condition)
Definition: c.h:746
const char * name
Definition: encode.c:561
void appendQualifiedRelation(PQExpBuffer buf, const char *spec, PGconn *conn, bool echo)
Definition: common.c:386
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92