PostgreSQL Source Code  git master
reindexdb.c File Reference
#include "postgres_fe.h"
#include <limits.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/option_utils.h"
#include "fe_utils/parallel_slot.h"
#include "fe_utils/query_utils.h"
#include "fe_utils/simple_list.h"
#include "fe_utils/string_utils.h"
Include dependency graph for reindexdb.c:

Go to the source code of this file.

Typedefs

typedef enum ReindexType ReindexType
 

Enumerations

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

Functions

static SimpleStringListget_parallel_object_list (PGconn *conn, ReindexType type, SimpleStringList *user_list, bool echo)
 
static void reindex_one_database (ConnParams *cparams, ReindexType type, SimpleStringList *user_list, const char *progname, bool echo, bool verbose, bool concurrently, int concurrentCons, const char *tablespace)
 
static void reindex_all_databases (ConnParams *cparams, const char *progname, bool echo, bool quiet, bool verbose, bool concurrently, int concurrentCons, const char *tablespace)
 
static void run_reindex_command (PGconn *conn, ReindexType type, const char *name, bool echo, bool verbose, bool concurrently, bool async, const char *tablespace)
 
static void help (const char *progname)
 
int main (int argc, char *argv[])
 

Typedef Documentation

◆ ReindexType

typedef enum ReindexType ReindexType

Enumeration Type Documentation

◆ ReindexType

Enumerator
REINDEX_DATABASE 
REINDEX_INDEX 
REINDEX_SCHEMA 
REINDEX_SYSTEM 
REINDEX_TABLE 

Definition at line 27 of file reindexdb.c.

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 643 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().

645 {
646  PQExpBufferData catalog_query;
648  PGresult *res;
649  SimpleStringList *tables;
650  int ntups,
651  i;
652 
653  initPQExpBuffer(&catalog_query);
654 
655  /*
656  * The queries here are using a safe search_path, so there's no need to
657  * fully qualify everything.
658  */
659  switch (type)
660  {
661  case REINDEX_DATABASE:
662  Assert(user_list == NULL);
663  appendPQExpBufferStr(&catalog_query,
664  "SELECT c.relname, ns.nspname\n"
665  " FROM pg_catalog.pg_class c\n"
666  " JOIN pg_catalog.pg_namespace ns"
667  " ON c.relnamespace = ns.oid\n"
668  " WHERE ns.nspname != 'pg_catalog'\n"
669  " AND c.relkind IN ("
670  CppAsString2(RELKIND_RELATION) ", "
671  CppAsString2(RELKIND_MATVIEW) ")\n"
672  " ORDER BY c.relpages DESC;");
673  break;
674 
675  case REINDEX_SCHEMA:
676  {
677  SimpleStringListCell *cell;
678  bool nsp_listed = false;
679 
680  Assert(user_list != NULL);
681 
682  /*
683  * All the tables from all the listed schemas are grabbed at
684  * once.
685  */
686  appendPQExpBufferStr(&catalog_query,
687  "SELECT c.relname, ns.nspname\n"
688  " FROM pg_catalog.pg_class c\n"
689  " JOIN pg_catalog.pg_namespace ns"
690  " ON c.relnamespace = ns.oid\n"
691  " WHERE c.relkind IN ("
692  CppAsString2(RELKIND_RELATION) ", "
693  CppAsString2(RELKIND_MATVIEW) ")\n"
694  " AND ns.nspname IN (");
695 
696  for (cell = user_list->head; cell; cell = cell->next)
697  {
698  const char *nspname = cell->val;
699 
700  if (nsp_listed)
701  appendPQExpBufferStr(&catalog_query, ", ");
702  else
703  nsp_listed = true;
704 
705  appendStringLiteralConn(&catalog_query, nspname, conn);
706  }
707 
708  appendPQExpBufferStr(&catalog_query, ")\n"
709  " ORDER BY c.relpages DESC;");
710  }
711  break;
712 
713  case REINDEX_SYSTEM:
714  case REINDEX_INDEX:
715  case REINDEX_TABLE:
716  Assert(false);
717  break;
718  }
719 
720  res = executeQuery(conn, catalog_query.data, echo);
721  termPQExpBuffer(&catalog_query);
722 
723  /*
724  * If no rows are returned, there are no matching tables, so we are done.
725  */
726  ntups = PQntuples(res);
727  if (ntups == 0)
728  {
729  PQclear(res);
730  PQfinish(conn);
731  return NULL;
732  }
733 
734  tables = pg_malloc0(sizeof(SimpleStringList));
735 
736  /* Build qualified identifiers for each table */
737  initPQExpBuffer(&buf);
738  for (i = 0; i < ntups; i++)
739  {
741  fmtQualifiedId(PQgetvalue(res, i, 1),
742  PQgetvalue(res, i, 0)));
743 
744  simple_string_list_append(tables, buf.data);
745  resetPQExpBuffer(&buf);
746  }
747  termPQExpBuffer(&buf);
748  PQclear(res);
749 
750  return tables;
751 }
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:3642
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:4231
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3248
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:289
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:804
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 788 of file reindexdb.c.

References _, and printf.

Referenced by main().

789 {
790  printf(_("%s reindexes a PostgreSQL database.\n\n"), progname);
791  printf(_("Usage:\n"));
792  printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
793  printf(_("\nOptions:\n"));
794  printf(_(" -a, --all reindex all databases\n"));
795  printf(_(" --concurrently reindex concurrently\n"));
796  printf(_(" -d, --dbname=DBNAME database to reindex\n"));
797  printf(_(" -e, --echo show the commands being sent to the server\n"));
798  printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
799  printf(_(" -j, --jobs=NUM use this many concurrent connections to reindex\n"));
800  printf(_(" -q, --quiet don't write any messages\n"));
801  printf(_(" -s, --system reindex system catalogs\n"));
802  printf(_(" -S, --schema=SCHEMA reindex specific schema(s) only\n"));
803  printf(_(" -t, --table=TABLE reindex specific table(s) only\n"));
804  printf(_(" --tablespace=TABLESPACE tablespace where indexes are rebuilt\n"));
805  printf(_(" -v, --verbose write a lot of output\n"));
806  printf(_(" -V, --version output version information, then exit\n"));
807  printf(_(" -?, --help show this help, then exit\n"));
808  printf(_("\nConnection options:\n"));
809  printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
810  printf(_(" -p, --port=PORT database server port\n"));
811  printf(_(" -U, --username=USERNAME user name to connect as\n"));
812  printf(_(" -w, --no-password never prompt for password\n"));
813  printf(_(" -W, --password force password prompt\n"));
814  printf(_(" --maintenance-db=DBNAME alternate maintenance database\n"));
815  printf(_("\nRead the description of the SQL command REINDEX for details.\n"));
816  printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
817  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
818 }
const char * progname
Definition: main.c:46
#define printf(...)
Definition: port.h:222
#define _(x)
Definition: elog.c:89

◆ main()

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

Definition at line 58 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, option_parse_int(), _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(), tablespace, TRI_DEFAULT, TRI_NO, TRI_YES, username, and verbose.

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

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

758 {
759  PGconn *conn;
760  PGresult *result;
761  int i;
762 
763  conn = connectMaintenanceDatabase(cparams, progname, echo);
764  result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", echo);
765  PQfinish(conn);
766 
767  for (i = 0; i < PQntuples(result); i++)
768  {
769  char *dbname = PQgetvalue(result, i, 0);
770 
771  if (!quiet)
772  {
773  printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
774  fflush(stdout);
775  }
776 
777  cparams->override_dbname = dbname;
778 
779  reindex_one_database(cparams, REINDEX_DATABASE, NULL,
780  progname, echo, verbose, concurrently,
781  concurrentCons, tablespace);
782  }
783 
784  PQclear(result);
785 }
static PGresult * executeQuery(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1879
const char * progname
Definition: main.c:46
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3642
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4231
#define printf(...)
Definition: port.h:222
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3248
PGconn * conn
Definition: streamutil.c:54
char * tablespace
Definition: pgbench.c:226
char * override_dbname
Definition: pg_backup.h:72
static int verbose
PGconn * connectMaintenanceDatabase(ConnParams *cparams, const char *progname, bool echo)
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * dbname
Definition: streamutil.c:51
static void reindex_one_database(ConnParams *cparams, ReindexType type, SimpleStringList *user_list, const char *progname, bool echo, bool verbose, bool concurrently, int concurrentCons, const char *tablespace)
Definition: reindexdb.c:332
int i
#define _(x)
Definition: elog.c:89

◆ reindex_one_database()

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

Definition at line 332 of file reindexdb.c.

References Assert, CancelRequested, conn, connectDatabase(), ParallelSlot::connection, get_parallel_object_list(), SimpleStringList::head, Min, SimpleStringListCell::next, ParallelSlotsAdoptConn(), ParallelSlotSetHandler(), 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(), TableCommandResultHandler(), generate_unaccent_rules::type, and SimpleStringListCell::val.

Referenced by main(), and reindex_all_databases().

337 {
338  PGconn *conn;
339  SimpleStringListCell *cell;
340  bool parallel = concurrentCons > 1;
341  SimpleStringList *process_list = user_list;
342  ReindexType process_type = type;
344  bool failed = false;
345  int items_count = 0;
346 
347  conn = connectDatabase(cparams, progname, echo, false, false);
348 
349  if (concurrently && PQserverVersion(conn) < 120000)
350  {
351  PQfinish(conn);
352  pg_log_error("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
353  "concurrently", "12");
354  exit(1);
355  }
356 
357  if (tablespace && PQserverVersion(conn) < 140000)
358  {
359  PQfinish(conn);
360  pg_log_error("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
361  "tablespace", "14");
362  exit(1);
363  }
364 
365  if (!parallel)
366  {
367  switch (process_type)
368  {
369  case REINDEX_DATABASE:
370  case REINDEX_SYSTEM:
371 
372  /*
373  * Database and system reindexes only need to work on the
374  * database itself, so build a list with a single entry.
375  */
376  Assert(user_list == NULL);
377  process_list = pg_malloc0(sizeof(SimpleStringList));
378  simple_string_list_append(process_list, PQdb(conn));
379  break;
380 
381  case REINDEX_INDEX:
382  case REINDEX_SCHEMA:
383  case REINDEX_TABLE:
384  Assert(user_list != NULL);
385  break;
386  }
387  }
388  else
389  {
390  switch (process_type)
391  {
392  case REINDEX_DATABASE:
393 
394  /*
395  * Database-wide parallel reindex requires special processing.
396  * If multiple jobs were asked, we have to reindex system
397  * catalogs first as they cannot be processed in parallel.
398  */
399  if (concurrently)
400  pg_log_warning("cannot reindex system catalogs concurrently, skipping all");
401  else
402  run_reindex_command(conn, REINDEX_SYSTEM, PQdb(conn), echo,
403  verbose, concurrently, false,
404  tablespace);
405 
406  /* Build a list of relations from the database */
407  process_list = get_parallel_object_list(conn, process_type,
408  user_list, echo);
409  process_type = REINDEX_TABLE;
410 
411  /* Bail out if nothing to process */
412  if (process_list == NULL)
413  return;
414  break;
415 
416  case REINDEX_SCHEMA:
417  Assert(user_list != NULL);
418 
419  /* Build a list of relations from all the schemas */
420  process_list = get_parallel_object_list(conn, process_type,
421  user_list, echo);
422  process_type = REINDEX_TABLE;
423 
424  /* Bail out if nothing to process */
425  if (process_list == NULL)
426  return;
427  break;
428 
429  case REINDEX_SYSTEM:
430  case REINDEX_INDEX:
431  /* not supported */
432  Assert(false);
433  break;
434 
435  case REINDEX_TABLE:
436 
437  /*
438  * Fall through. The list of items for tables is already
439  * created.
440  */
441  break;
442  }
443  }
444 
445  /*
446  * Adjust the number of concurrent connections depending on the items in
447  * the list. We choose the minimum between the number of concurrent
448  * connections and the number of items in the list.
449  */
450  for (cell = process_list->head; cell; cell = cell->next)
451  {
452  items_count++;
453 
454  /* no need to continue if there are more elements than jobs */
455  if (items_count >= concurrentCons)
456  break;
457  }
458  concurrentCons = Min(concurrentCons, items_count);
459  Assert(concurrentCons > 0);
460 
461  Assert(process_list != NULL);
462 
463  sa = ParallelSlotsSetup(concurrentCons, cparams, progname, echo, NULL);
464  ParallelSlotsAdoptConn(sa, conn);
465 
466  cell = process_list->head;
467  do
468  {
469  const char *objname = cell->val;
470  ParallelSlot *free_slot = NULL;
471 
472  if (CancelRequested)
473  {
474  failed = true;
475  goto finish;
476  }
477 
478  free_slot = ParallelSlotsGetIdle(sa, NULL);
479  if (!free_slot)
480  {
481  failed = true;
482  goto finish;
483  }
484 
486  run_reindex_command(free_slot->connection, process_type, objname,
487  echo, verbose, concurrently, true, tablespace);
488 
489  cell = cell->next;
490  } while (cell != NULL);
491 
493  failed = true;
494 
495 finish:
496  if (process_list != user_list)
497  {
498  simple_string_list_destroy(process_list);
499  pg_free(process_list);
500  }
501 
503  pfree(sa);
504 
505  if (failed)
506  exit(1);
507 }
const char * progname
Definition: main.c:46
static void run_reindex_command(PGconn *conn, ReindexType type, const char *name, bool echo, bool verbose, bool concurrently, bool async, const char *tablespace)
Definition: reindexdb.c:510
#define pg_log_error(...)
Definition: logging.h:80
#define Min(x, y)
Definition: c.h:986
void ParallelSlotsAdoptConn(ParallelSlotArray *sa, PGconn *conn)
void simple_string_list_destroy(SimpleStringList *list)
Definition: simple_list.c:125
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4231
static void ParallelSlotSetHandler(ParallelSlot *slot, ParallelSlotResultHandler handler, void *context)
Definition: parallel_slot.h:47
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6734
ParallelSlotArray * ParallelSlotsSetup(int numslots, ConnParams *cparams, const char *progname, bool echo, const char *initcmd)
ParallelSlot * ParallelSlotsGetIdle(ParallelSlotArray *sa, const char *dbname)
void pfree(void *pointer)
Definition: mcxt.c:1169
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
PGconn * conn
Definition: streamutil.c:54
char * tablespace
Definition: pgbench.c:226
struct SimpleStringListCell * next
Definition: simple_list.h:34
PGconn * connection
Definition: parallel_slot.h:23
static int verbose
void simple_string_list_append(SimpleStringList *list, const char *val)
Definition: simple_list.c:63
bool ParallelSlotsWaitCompletion(ParallelSlotArray *sa)
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:6590
#define Assert(condition)
Definition: c.h:804
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:1641
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
void ParallelSlotsTerminate(ParallelSlotArray *sa)
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:643
bool TableCommandResultHandler(PGresult *res, PGconn *conn, void *context)
#define pg_log_warning(...)
Definition: pgfnames.c:24
ReindexType
Definition: reindexdb.c:27

◆ run_reindex_command()

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

Definition at line 510 of file reindexdb.c.

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

513 {
514  const char *paren = "(";
515  const char *comma = ", ";
516  const char *sep = paren;
517  PQExpBufferData sql;
518  bool status;
519 
520  Assert(name);
521 
522  /* build the REINDEX query */
523  initPQExpBuffer(&sql);
524 
525  appendPQExpBufferStr(&sql, "REINDEX ");
526 
527  if (verbose)
528  {
529  appendPQExpBuffer(&sql, "%sVERBOSE", sep);
530  sep = comma;
531  }
532 
533  if (tablespace)
534  {
535  appendPQExpBuffer(&sql, "%sTABLESPACE %s", sep, fmtId(tablespace));
536  sep = comma;
537  }
538 
539  if (sep != paren)
540  appendPQExpBufferStr(&sql, ") ");
541 
542  /* object type */
543  switch (type)
544  {
545  case REINDEX_DATABASE:
546  appendPQExpBufferStr(&sql, "DATABASE ");
547  break;
548  case REINDEX_INDEX:
549  appendPQExpBufferStr(&sql, "INDEX ");
550  break;
551  case REINDEX_SCHEMA:
552  appendPQExpBufferStr(&sql, "SCHEMA ");
553  break;
554  case REINDEX_SYSTEM:
555  appendPQExpBufferStr(&sql, "SYSTEM ");
556  break;
557  case REINDEX_TABLE:
558  appendPQExpBufferStr(&sql, "TABLE ");
559  break;
560  }
561 
562  /*
563  * Parenthesized grammar is only supported for CONCURRENTLY since
564  * PostgreSQL 14. Since 12, CONCURRENTLY can be specified after the
565  * object type.
566  */
567  if (concurrently)
568  appendPQExpBufferStr(&sql, "CONCURRENTLY ");
569 
570  /* object name */
571  switch (type)
572  {
573  case REINDEX_DATABASE:
574  case REINDEX_SYSTEM:
576  break;
577  case REINDEX_INDEX:
578  case REINDEX_TABLE:
579  appendQualifiedRelation(&sql, name, conn, echo);
580  break;
581  case REINDEX_SCHEMA:
582  appendPQExpBufferStr(&sql, name);
583  break;
584  }
585 
586  /* finish the query */
587  appendPQExpBufferChar(&sql, ';');
588 
589  if (async)
590  {
591  if (echo)
592  printf("%s\n", sql.data);
593 
594  status = PQsendQuery(conn, sql.data) == 1;
595  }
596  else
597  status = executeMaintenanceCommand(conn, sql.data, echo);
598 
599  if (!status)
600  {
601  switch (type)
602  {
603  case REINDEX_DATABASE:
604  pg_log_error("reindexing of database \"%s\" failed: %s",
605  PQdb(conn), PQerrorMessage(conn));
606  break;
607  case REINDEX_INDEX:
608  pg_log_error("reindexing of index \"%s\" in database \"%s\" failed: %s",
609  name, PQdb(conn), PQerrorMessage(conn));
610  break;
611  case REINDEX_SCHEMA:
612  pg_log_error("reindexing of schema \"%s\" in database \"%s\" failed: %s",
613  name, PQdb(conn), PQerrorMessage(conn));
614  break;
615  case REINDEX_SYSTEM:
616  pg_log_error("reindexing of system catalogs in database \"%s\" failed: %s",
617  PQdb(conn), PQerrorMessage(conn));
618  break;
619  case REINDEX_TABLE:
620  pg_log_error("reindexing of table \"%s\" in database \"%s\" failed: %s",
621  name, PQdb(conn), PQerrorMessage(conn));
622  break;
623  }
624  if (!async)
625  {
626  PQfinish(conn);
627  exit(1);
628  }
629  }
630 
631  termPQExpBuffer(&sql);
632 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6744
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:4231
#define printf(...)
Definition: port.h:222
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1326
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
char * tablespace
Definition: pgbench.c:226
static int verbose
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:6590
#define Assert(condition)
Definition: c.h:804
const char * name
Definition: encode.c:561
void appendQualifiedRelation(PQExpBuffer buf, const char *spec, PGconn *conn, bool echo)
Definition: common.c:69
bool executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
Definition: query_utils.c:74
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