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/cancel.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 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 597 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().

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

References _, and printf.

Referenced by main().

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

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

713 {
714  PGconn *conn;
715  PGresult *result;
717  int i;
718 
719  conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
720  prompt_password, progname, echo);
721  result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", echo);
722  PQfinish(conn);
723 
724  initPQExpBuffer(&connstr);
725  for (i = 0; i < PQntuples(result); i++)
726  {
727  char *dbname = PQgetvalue(result, i, 0);
728 
729  if (!quiet)
730  {
731  printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
732  fflush(stdout);
733  }
734 
735  resetPQExpBuffer(&connstr);
736  appendPQExpBufferStr(&connstr, "dbname=");
737  appendConnStrVal(&connstr, dbname);
738 
739  reindex_one_database(connstr.data, REINDEX_DATABASE, NULL, host,
740  port, username, prompt_password,
741  progname, echo, verbose, concurrently,
742  concurrentCons);
743  }
744  termPQExpBuffer(&connstr);
745 
746  PQclear(result);
747 }
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:153
static PGresult * executeQuery(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1879
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:4182
#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:90
static int verbose
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:316
#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 316 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().

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

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