PostgreSQL Source Code  git master
reindexdb.c File Reference
#include "postgres_fe.h"
#include "catalog/pg_class_d.h"
#include "common.h"
#include "common/connect.h"
#include "common/logging.h"
#include "fe_utils/cancel.h"
#include "fe_utils/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 25 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 644 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().

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

References _, and printf.

Referenced by main().

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

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

759 {
760  PGconn *conn;
761  PGresult *result;
762  int i;
763 
764  conn = connectMaintenanceDatabase(cparams, progname, echo);
765  result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", echo);
766  PQfinish(conn);
767 
768  for (i = 0; i < PQntuples(result); i++)
769  {
770  char *dbname = PQgetvalue(result, i, 0);
771 
772  if (!quiet)
773  {
774  printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
775  fflush(stdout);
776  }
777 
778  cparams->override_dbname = dbname;
779 
780  reindex_one_database(cparams, REINDEX_DATABASE, NULL,
781  progname, echo, verbose, concurrently,
782  concurrentCons, tablespace);
783  }
784 
785  PQclear(result);
786 }
static PGresult * executeQuery(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1874
const char * progname
Definition: main.c:46
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3561
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4221
#define printf(...)
Definition: port.h:222
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3167
PGconn * conn
Definition: streamutil.c:54
char * tablespace
Definition: pgbench.c:224
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:680
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:333
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 333 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().

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

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

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