PostgreSQL Source Code  git master
reindexdb.c File Reference
#include "postgres_fe.h"
#include "catalog/pg_class_d.h"
#include "common.h"
#include "common/logging.h"
#include "fe_utils/connect.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 char *dbname, ReindexType type, SimpleStringList *user_list, const char *host, const char *port, const char *username, enum trivalue prompt_password, const char *progname, bool echo, bool verbose, bool concurrently, int concurrentCons)
 
static void reindex_all_databases (const char *maintenance_db, const char *host, const char *port, const char *username, enum trivalue prompt_password, 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 22 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 596 of file reindexdb.c.

References appendPQExpBuffer(), 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().

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

References _, and printf.

Referenced by main().

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

◆ main()

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

Definition at line 55 of file reindexdb.c.

References _, dbname, fprintf, get_progname(), get_user_name_or_exit(), getopt_long(), handle_help_version_opts(), SimpleStringList::head, help(), no_argument, optarg, optind, pg_log_error, pg_logging_init(), pg_strdup(), PG_TEXTDOMAIN, port, progname, 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.

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

◆ reindex_all_databases()

static void reindex_all_databases ( const char *  maintenance_db,
const char *  host,
const char *  port,
const char *  username,
enum trivalue  prompt_password,
const char *  progname,
bool  echo,
bool  quiet,
bool  verbose,
bool  concurrently,
int  concurrentCons 
)
static

Definition at line 707 of file reindexdb.c.

References _, appendConnStrVal(), appendPQExpBufferStr(), conn, connectMaintenanceDatabase(), connstr, PQExpBufferData::data, dbname, executeQuery(), i, initPQExpBuffer(), PQclear(), PQfinish(), PQgetvalue(), PQntuples(), printf, REINDEX_DATABASE, reindex_one_database(), resetPQExpBuffer(), generate_unaccent_rules::stdout, and termPQExpBuffer().

Referenced by main().

712 {
713  PGconn *conn;
714  PGresult *result;
716  int i;
717 
718  conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
719  prompt_password, progname, echo);
720  result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", echo);
721  PQfinish(conn);
722 
723  initPQExpBuffer(&connstr);
724  for (i = 0; i < PQntuples(result); i++)
725  {
726  char *dbname = PQgetvalue(result, i, 0);
727 
728  if (!quiet)
729  {
730  printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
731  fflush(stdout);
732  }
733 
734  resetPQExpBuffer(&connstr);
735  appendPQExpBufferStr(&connstr, "dbname=");
736  appendConnStrVal(&connstr, dbname);
737 
738  reindex_one_database(connstr.data, REINDEX_DATABASE, NULL, host,
739  port, username, prompt_password,
740  progname, echo, verbose, concurrently,
741  concurrentCons);
742  }
743  termPQExpBuffer(&connstr);
744 
745  PQclear(result);
746 }
PGconn * connectMaintenanceDatabase(const char *maintenance_db, const char *pghost, const char *pgport, const char *pguser, enum trivalue prompt_password, const char *progname, bool echo)
Definition: common.c:160
static PGresult * executeQuery(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1878
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 appendConnStrVal(PQExpBuffer buf, const char *str)
Definition: string_utils.c:545
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4119
#define printf(...)
Definition: port.h:198
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 int port
Definition: pg_regress.c:91
static int verbose
Definition: pg_basebackup.c:90
static char * username
Definition: initdb.c:133
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * dbname
Definition: streamutil.c:50
int i
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
static void reindex_one_database(const char *dbname, ReindexType type, SimpleStringList *user_list, const char *host, const char *port, const char *username, enum trivalue prompt_password, const char *progname, bool echo, bool verbose, bool concurrently, int concurrentCons)
Definition: reindexdb.c:315
#define _(x)
Definition: elog.c:87
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
static char * connstr
Definition: pg_dumpall.c:61

◆ reindex_one_database()

static void reindex_one_database ( const char *  dbname,
ReindexType  type,
SimpleStringList user_list,
const char *  host,
const char *  port,
const char *  username,
enum trivalue  prompt_password,
const char *  progname,
bool  echo,
bool  verbose,
bool  concurrently,
int  concurrentCons 
)
static

Definition at line 315 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().

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

◆ 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 484 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().

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