PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
reindexdb.c File Reference
#include "postgres_fe.h"
#include <limits.h>
#include "catalog/pg_class_d.h"
#include "common.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, bool syscatalog, SimpleStringList *schemas, SimpleStringList *tables, SimpleStringList *indexes)
 
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 26 of file reindexdb.c.

27{
ReindexType
Definition: reindexdb.c:27
@ REINDEX_SYSTEM
Definition: reindexdb.c:31
@ REINDEX_DATABASE
Definition: reindexdb.c:28
@ REINDEX_INDEX
Definition: reindexdb.c:29
@ REINDEX_SCHEMA
Definition: reindexdb.c:30
@ REINDEX_TABLE
Definition: reindexdb.c:32

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 622 of file reindexdb.c.

624{
625 PQExpBufferData catalog_query;
627 PGresult *res;
628 SimpleStringList *tables;
629 int ntups,
630 i;
631
632 initPQExpBuffer(&catalog_query);
633
634 /*
635 * The queries here are using a safe search_path, so there's no need to
636 * fully qualify everything.
637 */
638 switch (type)
639 {
640 case REINDEX_DATABASE:
641 Assert(user_list == NULL);
642 appendPQExpBufferStr(&catalog_query,
643 "SELECT c.relname, ns.nspname\n"
644 " FROM pg_catalog.pg_class c\n"
645 " JOIN pg_catalog.pg_namespace ns"
646 " ON c.relnamespace = ns.oid\n"
647 " WHERE ns.nspname != 'pg_catalog'\n"
648 " AND c.relkind IN ("
649 CppAsString2(RELKIND_RELATION) ", "
650 CppAsString2(RELKIND_MATVIEW) ")\n"
651 " AND c.relpersistence != "
652 CppAsString2(RELPERSISTENCE_TEMP) "\n"
653 " ORDER BY c.relpages DESC;");
654 break;
655
656 case REINDEX_SCHEMA:
657 {
659 bool nsp_listed = false;
660
661 Assert(user_list != NULL);
662
663 /*
664 * All the tables from all the listed schemas are grabbed at
665 * once.
666 */
667 appendPQExpBufferStr(&catalog_query,
668 "SELECT c.relname, ns.nspname\n"
669 " FROM pg_catalog.pg_class c\n"
670 " JOIN pg_catalog.pg_namespace ns"
671 " ON c.relnamespace = ns.oid\n"
672 " WHERE c.relkind IN ("
673 CppAsString2(RELKIND_RELATION) ", "
674 CppAsString2(RELKIND_MATVIEW) ")\n"
675 " AND c.relpersistence != "
676 CppAsString2(RELPERSISTENCE_TEMP) "\n"
677 " AND ns.nspname IN (");
678
679 for (cell = user_list->head; cell; cell = cell->next)
680 {
681 const char *nspname = cell->val;
682
683 if (nsp_listed)
684 appendPQExpBufferStr(&catalog_query, ", ");
685 else
686 nsp_listed = true;
687
688 appendStringLiteralConn(&catalog_query, nspname, conn);
689 }
690
691 appendPQExpBufferStr(&catalog_query, ")\n"
692 " ORDER BY c.relpages DESC;");
693 }
694 break;
695
696 case REINDEX_INDEX:
697 {
699
700 Assert(user_list != NULL);
701
702 /*
703 * Straight-forward index-level REINDEX is not supported with
704 * multiple jobs as we cannot control the concurrent
705 * processing of multiple indexes depending on the same
706 * relation. But we can extract the appropriate table name
707 * for the index and put REINDEX INDEX commands into different
708 * jobs, according to the parent tables.
709 *
710 * We will order the results to group the same tables
711 * together. We fetch index names as well to build a new list
712 * of them with matching order.
713 */
714 appendPQExpBufferStr(&catalog_query,
715 "SELECT t.relname, n.nspname, i.relname\n"
716 "FROM pg_catalog.pg_index x\n"
717 "JOIN pg_catalog.pg_class t ON t.oid = x.indrelid\n"
718 "JOIN pg_catalog.pg_class i ON i.oid = x.indexrelid\n"
719 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.relnamespace\n"
720 "WHERE x.indexrelid OPERATOR(pg_catalog.=) ANY(ARRAY['");
721
722 for (cell = user_list->head; cell; cell = cell->next)
723 {
724 if (cell != user_list->head)
725 appendPQExpBufferStr(&catalog_query, "', '");
726
727 appendQualifiedRelation(&catalog_query, cell->val, conn, echo);
728 }
729
730 /*
731 * Order tables by the size of its greatest index. Within the
732 * table, order indexes by their sizes.
733 */
734 appendPQExpBufferStr(&catalog_query,
735 "']::pg_catalog.regclass[])\n"
736 "ORDER BY max(i.relpages) OVER \n"
737 " (PARTITION BY n.nspname, t.relname),\n"
738 " n.nspname, t.relname, i.relpages;\n");
739
740 /*
741 * We're going to re-order the user_list to match the order of
742 * tables. So, empty the user_list to fill it from the query
743 * result.
744 */
746 user_list->head = user_list->tail = NULL;
747 }
748 break;
749
750 case REINDEX_SYSTEM:
751 case REINDEX_TABLE:
752 Assert(false);
753 break;
754 }
755
756 res = executeQuery(conn, catalog_query.data, echo);
757 termPQExpBuffer(&catalog_query);
758
759 /*
760 * If no rows are returned, there are no matching tables, so we are done.
761 */
762 ntups = PQntuples(res);
763 if (ntups == 0)
764 {
765 PQclear(res);
766 PQfinish(conn);
767 return NULL;
768 }
769
770 tables = pg_malloc0(sizeof(SimpleStringList));
771
772 /* Build qualified identifiers for each table */
774 for (i = 0; i < ntups; i++)
775 {
778 PQgetvalue(res, i, 0)));
779
780 simple_string_list_append(tables, buf.data);
782
783 if (type == REINDEX_INDEX)
784 {
785 /*
786 * For index-level REINDEX, rebuild the list of indexes to match
787 * the order of tables list.
788 */
791 PQgetvalue(res, i, 2)));
792
793 simple_string_list_append(user_list, buf.data);
795 }
796 }
798 PQclear(res);
799
800 return tables;
801}
void appendQualifiedRelation(PQExpBuffer buf, const char *spec, PGconn *conn, bool echo)
Definition: common.c:68
#define Assert(condition)
Definition: c.h:812
#define CppAsString2(x)
Definition: c.h:346
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4880
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
int i
Definition: isn.c:72
static PGresult * executeQuery(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1883
static char * buf
Definition: pg_test_fsync.c:72
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
void simple_string_list_append(SimpleStringList *list, const char *val)
Definition: simple_list.c:63
void simple_string_list_destroy(SimpleStringList *list)
Definition: simple_list.c:125
PGconn * conn
Definition: streamutil.c:53
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
char val[FLEXIBLE_ARRAY_MEMBER]
Definition: simple_list.h:37
struct SimpleStringListCell * next
Definition: simple_list.h:34
SimpleStringListCell * head
Definition: simple_list.h:42
SimpleStringListCell * tail
Definition: simple_list.h:43
const char * type

References appendPQExpBufferStr(), appendQualifiedRelation(), appendStringLiteralConn(), Assert, buf, conn, 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, res, resetPQExpBuffer(), simple_string_list_append(), simple_string_list_destroy(), SimpleStringList::tail, termPQExpBuffer(), type, and SimpleStringListCell::val.

Referenced by reindex_one_database().

◆ help()

static void help ( const char *  progname)
static

Definition at line 868 of file reindexdb.c.

869{
870 printf(_("%s reindexes a PostgreSQL database.\n\n"), progname);
871 printf(_("Usage:\n"));
872 printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
873 printf(_("\nOptions:\n"));
874 printf(_(" -a, --all reindex all databases\n"));
875 printf(_(" --concurrently reindex concurrently\n"));
876 printf(_(" -d, --dbname=DBNAME database to reindex\n"));
877 printf(_(" -e, --echo show the commands being sent to the server\n"));
878 printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
879 printf(_(" -j, --jobs=NUM use this many concurrent connections to reindex\n"));
880 printf(_(" -q, --quiet don't write any messages\n"));
881 printf(_(" -s, --system reindex system catalogs only\n"));
882 printf(_(" -S, --schema=SCHEMA reindex specific schema(s) only\n"));
883 printf(_(" -t, --table=TABLE reindex specific table(s) only\n"));
884 printf(_(" --tablespace=TABLESPACE tablespace where indexes are rebuilt\n"));
885 printf(_(" -v, --verbose write a lot of output\n"));
886 printf(_(" -V, --version output version information, then exit\n"));
887 printf(_(" -?, --help show this help, then exit\n"));
888 printf(_("\nConnection options:\n"));
889 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
890 printf(_(" -p, --port=PORT database server port\n"));
891 printf(_(" -U, --username=USERNAME user name to connect as\n"));
892 printf(_(" -w, --no-password never prompt for password\n"));
893 printf(_(" -W, --password force password prompt\n"));
894 printf(_(" --maintenance-db=DBNAME alternate maintenance database\n"));
895 printf(_("\nRead the description of the SQL command REINDEX for details.\n"));
896 printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
897 printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
898}
#define _(x)
Definition: elog.c:90
const char * progname
Definition: main.c:44
#define printf(...)
Definition: port.h:244

References _, printf, and progname.

Referenced by main().

◆ main()

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

Definition at line 60 of file reindexdb.c.

61{
62 static struct option long_options[] = {
63 {"host", required_argument, NULL, 'h'},
64 {"port", required_argument, NULL, 'p'},
65 {"username", required_argument, NULL, 'U'},
66 {"no-password", no_argument, NULL, 'w'},
67 {"password", no_argument, NULL, 'W'},
68 {"echo", no_argument, NULL, 'e'},
69 {"quiet", no_argument, NULL, 'q'},
70 {"schema", required_argument, NULL, 'S'},
71 {"dbname", required_argument, NULL, 'd'},
72 {"all", no_argument, NULL, 'a'},
73 {"system", no_argument, NULL, 's'},
74 {"table", required_argument, NULL, 't'},
75 {"index", required_argument, NULL, 'i'},
76 {"jobs", required_argument, NULL, 'j'},
77 {"verbose", no_argument, NULL, 'v'},
78 {"concurrently", no_argument, NULL, 1},
79 {"maintenance-db", required_argument, NULL, 2},
80 {"tablespace", required_argument, NULL, 3},
81 {NULL, 0, NULL, 0}
82 };
83
84 const char *progname;
85 int optindex;
86 int c;
87
88 const char *dbname = NULL;
89 const char *maintenance_db = NULL;
90 const char *host = NULL;
91 const char *port = NULL;
92 const char *username = NULL;
93 const char *tablespace = NULL;
94 enum trivalue prompt_password = TRI_DEFAULT;
95 ConnParams cparams;
96 bool syscatalog = false;
97 bool alldb = false;
98 bool echo = false;
99 bool quiet = false;
100 bool verbose = false;
101 bool concurrently = false;
102 SimpleStringList indexes = {NULL, NULL};
103 SimpleStringList tables = {NULL, NULL};
104 SimpleStringList schemas = {NULL, NULL};
105 int concurrentCons = 1;
106
107 pg_logging_init(argv[0]);
108 progname = get_progname(argv[0]);
109 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
110
111 handle_help_version_opts(argc, argv, "reindexdb", help);
112
113 /* process command-line options */
114 while ((c = getopt_long(argc, argv, "ad:eh:i:j:qp:sS:t:U:vwW", long_options, &optindex)) != -1)
115 {
116 switch (c)
117 {
118 case 'a':
119 alldb = true;
120 break;
121 case 'd':
123 break;
124 case 'e':
125 echo = true;
126 break;
127 case 'h':
128 host = pg_strdup(optarg);
129 break;
130 case 'i':
132 break;
133 case 'j':
134 if (!option_parse_int(optarg, "-j/--jobs", 1, INT_MAX,
135 &concurrentCons))
136 exit(1);
137 break;
138 case 'q':
139 quiet = true;
140 break;
141 case 'p':
143 break;
144 case 's':
145 syscatalog = true;
146 break;
147 case 'S':
149 break;
150 case 't':
152 break;
153 case 'U':
155 break;
156 case 'v':
157 verbose = true;
158 break;
159 case 'w':
160 prompt_password = TRI_NO;
161 break;
162 case 'W':
163 prompt_password = TRI_YES;
164 break;
165 case 1:
166 concurrently = true;
167 break;
168 case 2:
169 maintenance_db = pg_strdup(optarg);
170 break;
171 case 3:
173 break;
174 default:
175 /* getopt_long already emitted a complaint */
176 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
177 exit(1);
178 }
179 }
180
181 /*
182 * Non-option argument specifies database name as long as it wasn't
183 * already specified with -d / --dbname
184 */
185 if (optind < argc && dbname == NULL)
186 {
187 dbname = argv[optind];
188 optind++;
189 }
190
191 if (optind < argc)
192 {
193 pg_log_error("too many command-line arguments (first is \"%s\")",
194 argv[optind]);
195 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
196 exit(1);
197 }
198
199 /* fill cparams except for dbname, which is set below */
200 cparams.pghost = host;
201 cparams.pgport = port;
202 cparams.pguser = username;
203 cparams.prompt_password = prompt_password;
204 cparams.override_dbname = NULL;
205
207
208 if (concurrentCons > 1 && syscatalog)
209 pg_fatal("cannot use multiple jobs to reindex system catalogs");
210
211 if (alldb)
212 {
213 if (dbname)
214 pg_fatal("cannot reindex all databases and a specific one at the same time");
215
216 cparams.dbname = maintenance_db;
217
218 reindex_all_databases(&cparams, progname, echo, quiet, verbose,
219 concurrently, concurrentCons, tablespace,
220 syscatalog, &schemas, &tables, &indexes);
221 }
222 else
223 {
224 if (dbname == NULL)
225 {
226 if (getenv("PGDATABASE"))
227 dbname = getenv("PGDATABASE");
228 else if (getenv("PGUSER"))
229 dbname = getenv("PGUSER");
230 else
232 }
233
234 cparams.dbname = dbname;
235
236 if (syscatalog)
237 reindex_one_database(&cparams, REINDEX_SYSTEM, NULL,
238 progname, echo, verbose,
239 concurrently, 1, tablespace);
240
241 if (schemas.head != NULL)
242 reindex_one_database(&cparams, REINDEX_SCHEMA, &schemas,
243 progname, echo, verbose,
244 concurrently, concurrentCons, tablespace);
245
246 if (indexes.head != NULL)
247 reindex_one_database(&cparams, REINDEX_INDEX, &indexes,
248 progname, echo, verbose,
249 concurrently, concurrentCons, tablespace);
250
251 if (tables.head != NULL)
252 reindex_one_database(&cparams, REINDEX_TABLE, &tables,
253 progname, echo, verbose,
254 concurrently, concurrentCons, tablespace);
255
256 /*
257 * reindex database only if neither index nor table nor schema nor
258 * system catalogs is specified
259 */
260 if (!syscatalog && indexes.head == NULL &&
261 tables.head == NULL && schemas.head == NULL)
263 progname, echo, verbose,
264 concurrently, concurrentCons, tablespace);
265 }
266
267 exit(0);
268}
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1168
void setup_cancel_handler(void(*query_cancel_callback)(void))
Definition: cancel.c:183
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:429
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:60
#define no_argument
Definition: getopt_long.h:24
#define required_argument
Definition: getopt_long.h:25
int verbose
static char * username
Definition: initdb.c:153
exit(1)
void pg_logging_init(const char *argv0)
Definition: logging.c:83
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_error_hint(...)
Definition: logging.h:112
bool option_parse_int(const char *optarg, const char *optname, int min_range, int max_range, int *result)
Definition: option_utils.c:50
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
Definition: option_utils.c:24
#define pg_fatal(...)
PGDLLIMPORT int optind
Definition: getopt.c:51
PGDLLIMPORT char * optarg
Definition: getopt.c:53
static int port
Definition: pg_regress.c:115
static char * tablespace
Definition: pgbench.c:216
const char * get_progname(const char *argv0)
Definition: path.c:575
char * c
static void reindex_all_databases(ConnParams *cparams, const char *progname, bool echo, bool quiet, bool verbose, bool concurrently, int concurrentCons, const char *tablespace, bool syscatalog, SimpleStringList *schemas, SimpleStringList *tables, SimpleStringList *indexes)
Definition: reindexdb.c:804
static void help(const char *progname)
Definition: reindexdb.c:868
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:271
char * dbname
Definition: streamutil.c:50
const char * pguser
Definition: connect_utils.h:31
char * override_dbname
Definition: pg_backup.h:92
char * pgport
Definition: pg_backup.h:86
char * pghost
Definition: pg_backup.h:87
char * dbname
Definition: pg_backup.h:85
enum trivalue prompt_password
Definition: connect_utils.h:32
const char * get_user_name_or_exit(const char *progname)
Definition: username.c:74
trivalue
Definition: vacuumlo.c:35
@ TRI_YES
Definition: vacuumlo.c:38
@ TRI_DEFAULT
Definition: vacuumlo.c:36
@ TRI_NO
Definition: vacuumlo.c:37

References dbname, _connParams::dbname, exit(), 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_fatal, pg_log_error, pg_log_error_hint, 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.

◆ 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,
bool  syscatalog,
SimpleStringList schemas,
SimpleStringList tables,
SimpleStringList indexes 
)
static

Definition at line 804 of file reindexdb.c.

810{
811 PGconn *conn;
812 PGresult *result;
813 int i;
814
815 conn = connectMaintenanceDatabase(cparams, progname, echo);
816 result = executeQuery(conn,
817 "SELECT datname FROM pg_database WHERE datallowconn AND datconnlimit <> -2 ORDER BY 1;",
818 echo);
819 PQfinish(conn);
820
821 for (i = 0; i < PQntuples(result); i++)
822 {
823 char *dbname = PQgetvalue(result, i, 0);
824
825 if (!quiet)
826 {
827 printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
828 fflush(stdout);
829 }
830
831 cparams->override_dbname = dbname;
832
833 if (syscatalog)
835 progname, echo, verbose,
836 concurrently, 1, tablespace);
837
838 if (schemas->head != NULL)
839 reindex_one_database(cparams, REINDEX_SCHEMA, schemas,
840 progname, echo, verbose,
841 concurrently, concurrentCons, tablespace);
842
843 if (indexes->head != NULL)
844 reindex_one_database(cparams, REINDEX_INDEX, indexes,
845 progname, echo, verbose,
846 concurrently, 1, tablespace);
847
848 if (tables->head != NULL)
849 reindex_one_database(cparams, REINDEX_TABLE, tables,
850 progname, echo, verbose,
851 concurrently, concurrentCons, tablespace);
852
853 /*
854 * reindex database only if neither index nor table nor schema nor
855 * system catalogs is specified
856 */
857 if (!syscatalog && indexes->head == NULL &&
858 tables->head == NULL && schemas->head == NULL)
860 progname, echo, verbose,
861 concurrently, concurrentCons, tablespace);
862 }
863
864 PQclear(result);
865}
PGconn * connectMaintenanceDatabase(ConnParams *cparams, const char *progname, bool echo)
static void const char fflush(stdout)

References _, conn, connectMaintenanceDatabase(), dbname, executeQuery(), fflush(), SimpleStringList::head, i, _connParams::override_dbname, PQclear(), PQfinish(), PQgetvalue(), PQntuples(), printf, progname, REINDEX_DATABASE, REINDEX_INDEX, reindex_one_database(), REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, generate_unaccent_rules::stdout, tablespace, and verbose.

Referenced by main().

◆ 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 271 of file reindexdb.c.

276{
277 PGconn *conn;
279 SimpleStringListCell *indices_tables_cell = NULL;
280 bool parallel = concurrentCons > 1;
281 SimpleStringList *process_list = user_list;
282 SimpleStringList *indices_tables_list = NULL;
283 ReindexType process_type = type;
285 bool failed = false;
286 int items_count = 0;
287 char *prev_index_table_name = NULL;
288 ParallelSlot *free_slot = NULL;
289
290 conn = connectDatabase(cparams, progname, echo, false, true);
291
292 if (concurrently && PQserverVersion(conn) < 120000)
293 {
294 PQfinish(conn);
295 pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
296 "concurrently", "12");
297 }
298
299 if (tablespace && PQserverVersion(conn) < 140000)
300 {
301 PQfinish(conn);
302 pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
303 "tablespace", "14");
304 }
305
306 if (!parallel)
307 {
308 switch (process_type)
309 {
310 case REINDEX_DATABASE:
311 case REINDEX_SYSTEM:
312
313 /*
314 * Database and system reindexes only need to work on the
315 * database itself, so build a list with a single entry.
316 */
317 Assert(user_list == NULL);
318 process_list = pg_malloc0(sizeof(SimpleStringList));
319 simple_string_list_append(process_list, PQdb(conn));
320 break;
321
322 case REINDEX_INDEX:
323 case REINDEX_SCHEMA:
324 case REINDEX_TABLE:
325 Assert(user_list != NULL);
326 break;
327 }
328 }
329 else
330 {
331 switch (process_type)
332 {
333 case REINDEX_DATABASE:
334
335 /* Build a list of relations from the database */
336 process_list = get_parallel_object_list(conn, process_type,
337 user_list, echo);
338 process_type = REINDEX_TABLE;
339
340 /* Bail out if nothing to process */
341 if (process_list == NULL)
342 return;
343 break;
344
345 case REINDEX_SCHEMA:
346 Assert(user_list != NULL);
347
348 /* Build a list of relations from all the schemas */
349 process_list = get_parallel_object_list(conn, process_type,
350 user_list, echo);
351 process_type = REINDEX_TABLE;
352
353 /* Bail out if nothing to process */
354 if (process_list == NULL)
355 return;
356 break;
357
358 case REINDEX_INDEX:
359 Assert(user_list != NULL);
360
361 /*
362 * Build a list of relations from the indices. This will
363 * accordingly reorder the list of indices too.
364 */
365 indices_tables_list = get_parallel_object_list(conn, process_type,
366 user_list, echo);
367
368 /*
369 * Bail out if nothing to process. 'user_list' was modified
370 * in-place, so check if it has at least one cell.
371 */
372 if (user_list->head == NULL)
373 return;
374
375 /*
376 * Assuming 'user_list' is not empty, 'indices_tables_list'
377 * shouldn't be empty as well.
378 */
379 Assert(indices_tables_list != NULL);
380 indices_tables_cell = indices_tables_list->head;
381
382 break;
383
384 case REINDEX_SYSTEM:
385 /* not supported */
386 Assert(false);
387 break;
388
389 case REINDEX_TABLE:
390
391 /*
392 * Fall through. The list of items for tables is already
393 * created.
394 */
395 break;
396 }
397 }
398
399 /*
400 * Adjust the number of concurrent connections depending on the items in
401 * the list. We choose the minimum between the number of concurrent
402 * connections and the number of items in the list.
403 */
404 for (cell = process_list->head; cell; cell = cell->next)
405 {
406 items_count++;
407
408 /* no need to continue if there are more elements than jobs */
409 if (items_count >= concurrentCons)
410 break;
411 }
412 concurrentCons = Min(concurrentCons, items_count);
413 Assert(concurrentCons > 0);
414
415 Assert(process_list != NULL);
416
417 sa = ParallelSlotsSetup(concurrentCons, cparams, progname, echo, NULL);
419
420 cell = process_list->head;
421 do
422 {
423 const char *objname = cell->val;
424 bool need_new_slot = true;
425
426 if (CancelRequested)
427 {
428 failed = true;
429 goto finish;
430 }
431
432 /*
433 * For parallel index-level REINDEX, the indices of the same table are
434 * ordered together and they are to be processed by the same job. So,
435 * we don't switch the job as soon as the index belongs to the same
436 * table as the previous one.
437 */
438 if (parallel && process_type == REINDEX_INDEX)
439 {
440 if (prev_index_table_name != NULL &&
441 strcmp(prev_index_table_name, indices_tables_cell->val) == 0)
442 need_new_slot = false;
443 prev_index_table_name = indices_tables_cell->val;
444 indices_tables_cell = indices_tables_cell->next;
445 }
446
447 if (need_new_slot)
448 {
449 free_slot = ParallelSlotsGetIdle(sa, NULL);
450 if (!free_slot)
451 {
452 failed = true;
453 goto finish;
454 }
455
457 }
458
459 run_reindex_command(free_slot->connection, process_type, objname,
460 echo, verbose, concurrently, true, tablespace);
461
462 cell = cell->next;
463 } while (cell != NULL);
464
466 failed = true;
467
468finish:
469 if (process_list != user_list)
470 {
471 simple_string_list_destroy(process_list);
472 pg_free(process_list);
473 }
474
475 if (indices_tables_list)
476 {
477 simple_string_list_destroy(indices_tables_list);
478 pg_free(indices_tables_list);
479 }
480
482 pfree(sa);
483
484 if (failed)
485 exit(1);
486}
#define Min(x, y)
Definition: c.h:958
volatile sig_atomic_t CancelRequested
Definition: cancel.c:59
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:7199
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:7037
void pg_free(void *ptr)
Definition: fe_memutils.c:105
void pfree(void *pointer)
Definition: mcxt.c:1521
ParallelSlotArray * ParallelSlotsSetup(int numslots, ConnParams *cparams, const char *progname, bool echo, const char *initcmd)
bool ParallelSlotsWaitCompletion(ParallelSlotArray *sa)
bool TableCommandResultHandler(PGresult *res, PGconn *conn, void *context)
ParallelSlot * ParallelSlotsGetIdle(ParallelSlotArray *sa, const char *dbname)
void ParallelSlotsTerminate(ParallelSlotArray *sa)
void ParallelSlotsAdoptConn(ParallelSlotArray *sa, PGconn *conn)
static void ParallelSlotSetHandler(ParallelSlot *slot, ParallelSlotResultHandler handler, void *context)
Definition: parallel_slot.h:47
static PGconn * connectDatabase(const char *dbname, const char *connection_string, const char *pghost, const char *pgport, const char *pguser, trivalue prompt_password, bool fail_on_error)
Definition: pg_dumpall.c:1663
static SimpleStringList * get_parallel_object_list(PGconn *conn, ReindexType type, SimpleStringList *user_list, bool echo)
Definition: reindexdb.c:622
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:489
PGconn * connection
Definition: parallel_slot.h:23

References Assert, CancelRequested, conn, connectDatabase(), ParallelSlot::connection, exit(), get_parallel_object_list(), SimpleStringList::head, Min, SimpleStringListCell::next, ParallelSlotsAdoptConn(), ParallelSlotSetHandler(), ParallelSlotsGetIdle(), ParallelSlotsSetup(), ParallelSlotsTerminate(), ParallelSlotsWaitCompletion(), pfree(), pg_fatal, pg_free(), pg_malloc0(), PQdb(), PQfinish(), PQserverVersion(), progname, REINDEX_DATABASE, REINDEX_INDEX, REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, run_reindex_command(), simple_string_list_append(), simple_string_list_destroy(), TableCommandResultHandler(), tablespace, type, SimpleStringListCell::val, and verbose.

Referenced by main(), and reindex_all_databases().

◆ 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 489 of file reindexdb.c.

492{
493 const char *paren = "(";
494 const char *comma = ", ";
495 const char *sep = paren;
496 PQExpBufferData sql;
497 bool status;
498
499 Assert(name);
500
501 /* build the REINDEX query */
502 initPQExpBuffer(&sql);
503
504 appendPQExpBufferStr(&sql, "REINDEX ");
505
506 if (verbose)
507 {
508 appendPQExpBuffer(&sql, "%sVERBOSE", sep);
509 sep = comma;
510 }
511
512 if (tablespace)
513 {
514 appendPQExpBuffer(&sql, "%sTABLESPACE %s", sep, fmtId(tablespace));
515 sep = comma;
516 }
517
518 if (sep != paren)
519 appendPQExpBufferStr(&sql, ") ");
520
521 /* object type */
522 switch (type)
523 {
524 case REINDEX_DATABASE:
525 appendPQExpBufferStr(&sql, "DATABASE ");
526 break;
527 case REINDEX_INDEX:
528 appendPQExpBufferStr(&sql, "INDEX ");
529 break;
530 case REINDEX_SCHEMA:
531 appendPQExpBufferStr(&sql, "SCHEMA ");
532 break;
533 case REINDEX_SYSTEM:
534 appendPQExpBufferStr(&sql, "SYSTEM ");
535 break;
536 case REINDEX_TABLE:
537 appendPQExpBufferStr(&sql, "TABLE ");
538 break;
539 }
540
541 /*
542 * Parenthesized grammar is only supported for CONCURRENTLY since
543 * PostgreSQL 14. Since 12, CONCURRENTLY can be specified after the
544 * object type.
545 */
546 if (concurrently)
547 appendPQExpBufferStr(&sql, "CONCURRENTLY ");
548
549 /* object name */
550 switch (type)
551 {
552 case REINDEX_DATABASE:
553 case REINDEX_SYSTEM:
555 break;
556 case REINDEX_INDEX:
557 case REINDEX_TABLE:
558 appendQualifiedRelation(&sql, name, conn, echo);
559 break;
560 case REINDEX_SCHEMA:
562 break;
563 }
564
565 /* finish the query */
566 appendPQExpBufferChar(&sql, ';');
567
568 if (async)
569 {
570 if (echo)
571 printf("%s\n", sql.data);
572
573 status = PQsendQuery(conn, sql.data) == 1;
574 }
575 else
576 status = executeMaintenanceCommand(conn, sql.data, echo);
577
578 if (!status)
579 {
580 switch (type)
581 {
582 case REINDEX_DATABASE:
583 pg_log_error("reindexing of database \"%s\" failed: %s",
585 break;
586 case REINDEX_INDEX:
587 pg_log_error("reindexing of index \"%s\" in database \"%s\" failed: %s",
589 break;
590 case REINDEX_SCHEMA:
591 pg_log_error("reindexing of schema \"%s\" in database \"%s\" failed: %s",
593 break;
594 case REINDEX_SYSTEM:
595 pg_log_error("reindexing of system catalogs in database \"%s\" failed: %s",
597 break;
598 case REINDEX_TABLE:
599 pg_log_error("reindexing of table \"%s\" in database \"%s\" failed: %s",
601 break;
602 }
603 if (!async)
604 {
605 PQfinish(conn);
606 exit(1);
607 }
608 }
609
610 termPQExpBuffer(&sql);
611}
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7209
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1416
#define comma
Definition: indent_codes.h:48
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
bool executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
Definition: query_utils.c:74
const char * fmtId(const char *rawid)
Definition: string_utils.c:64
const char * name

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), appendQualifiedRelation(), Assert, comma, conn, PQExpBufferData::data, executeMaintenanceCommand(), exit(), fmtId(), initPQExpBuffer(), name, pg_log_error, PQdb(), PQerrorMessage(), PQfinish(), PQsendQuery(), printf, REINDEX_DATABASE, REINDEX_INDEX, REINDEX_SCHEMA, REINDEX_SYSTEM, REINDEX_TABLE, tablespace, termPQExpBuffer(), type, and verbose.

Referenced by reindex_one_database().