PageRenderTime 66ms CodeModel.GetById 48ms app.highlight 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/bin/scripts/reindexdb.c

https://gitlab.com/kush/jarulraj-postgresql-cpp
C | 415 lines | 350 code | 46 blank | 19 comment | 72 complexity | 5051b60914b43b8b928b81d9eafe0de1 MD5 | raw file
  1/*-------------------------------------------------------------------------
  2 *
  3 * reindexdb
  4 *
  5 * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
  6 *
  7 * src/bin/scripts/reindexdb.c
  8 *
  9 *-------------------------------------------------------------------------
 10 */
 11
 12#include "postgres_fe.h"
 13#include "common.h"
 14#include "dumputils.h"
 15
 16
 17static void reindex_one_database(const char *name, const char *dbname,
 18					 const char *type, const char *host,
 19					 const char *port, const char *username,
 20					 enum trivalue prompt_password, const char *progname,
 21					 bool echo, bool verbose);
 22static void reindex_all_databases(const char *maintenance_db,
 23					  const char *host, const char *port,
 24					  const char *username, enum trivalue prompt_password,
 25					  const char *progname, bool echo,
 26					  bool quiet, bool verbose);
 27static void reindex_system_catalogs(const char *dbname,
 28						const char *host, const char *port,
 29						const char *username, enum trivalue prompt_password,
 30						const char *progname, bool echo, bool verbose);
 31static void help(const char *progname);
 32
 33int
 34main(int argc, char *argv[])
 35{
 36	static struct option long_options[] = {
 37		{"host", required_argument, NULL, 'h'},
 38		{"port", required_argument, NULL, 'p'},
 39		{"username", required_argument, NULL, 'U'},
 40		{"no-password", no_argument, NULL, 'w'},
 41		{"password", no_argument, NULL, 'W'},
 42		{"echo", no_argument, NULL, 'e'},
 43		{"quiet", no_argument, NULL, 'q'},
 44		{"schema", required_argument, NULL, 'S'},
 45		{"dbname", required_argument, NULL, 'd'},
 46		{"all", no_argument, NULL, 'a'},
 47		{"system", no_argument, NULL, 's'},
 48		{"table", required_argument, NULL, 't'},
 49		{"index", required_argument, NULL, 'i'},
 50		{"verbose", no_argument, NULL, 'v'},
 51		{"maintenance-db", required_argument, NULL, 2},
 52		{NULL, 0, NULL, 0}
 53	};
 54
 55	const char *progname;
 56	int			optindex;
 57	int			c;
 58
 59	const char *dbname = NULL;
 60	const char *maintenance_db = NULL;
 61	const char *host = NULL;
 62	const char *port = NULL;
 63	const char *username = NULL;
 64	enum trivalue prompt_password = TRI_DEFAULT;
 65	bool		syscatalog = false;
 66	bool		alldb = false;
 67	bool		echo = false;
 68	bool		quiet = false;
 69	bool		verbose = false;
 70	SimpleStringList indexes = {NULL, NULL};
 71	SimpleStringList tables = {NULL, NULL};
 72	SimpleStringList schemas = {NULL, NULL};
 73
 74	progname = get_progname(argv[0]);
 75	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
 76
 77	handle_help_version_opts(argc, argv, "reindexdb", help);
 78
 79	/* process command-line options */
 80	while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:v", long_options, &optindex)) != -1)
 81	{
 82		switch (c)
 83		{
 84			case 'h':
 85				host = pg_strdup(optarg);
 86				break;
 87			case 'p':
 88				port = pg_strdup(optarg);
 89				break;
 90			case 'U':
 91				username = pg_strdup(optarg);
 92				break;
 93			case 'w':
 94				prompt_password = TRI_NO;
 95				break;
 96			case 'W':
 97				prompt_password = TRI_YES;
 98				break;
 99			case 'e':
100				echo = true;
101				break;
102			case 'q':
103				quiet = true;
104				break;
105			case 'S':
106				simple_string_list_append(&schemas, optarg);
107				break;
108			case 'd':
109				dbname = pg_strdup(optarg);
110				break;
111			case 'a':
112				alldb = true;
113				break;
114			case 's':
115				syscatalog = true;
116				break;
117			case 't':
118				simple_string_list_append(&tables, optarg);
119				break;
120			case 'i':
121				simple_string_list_append(&indexes, optarg);
122				break;
123			case 'v':
124				verbose = true;
125				break;
126			case 2:
127				maintenance_db = pg_strdup(optarg);
128				break;
129			default:
130				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
131				exit(1);
132		}
133	}
134
135	/*
136	 * Non-option argument specifies database name as long as it wasn't
137	 * already specified with -d / --dbname
138	 */
139	if (optind < argc && dbname == NULL)
140	{
141		dbname = argv[optind];
142		optind++;
143	}
144
145	if (optind < argc)
146	{
147		fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
148				progname, argv[optind]);
149		fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
150		exit(1);
151	}
152
153	setup_cancel_handler();
154
155	if (alldb)
156	{
157		if (dbname)
158		{
159			fprintf(stderr, _("%s: cannot reindex all databases and a specific one at the same time\n"), progname);
160			exit(1);
161		}
162		if (syscatalog)
163		{
164			fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
165			exit(1);
166		}
167		if (schemas.head != NULL)
168		{
169			fprintf(stderr, _("%s: cannot reindex specific schema(s) in all databases\n"), progname);
170			exit(1);
171		}
172		if (tables.head != NULL)
173		{
174			fprintf(stderr, _("%s: cannot reindex specific table(s) in all databases\n"), progname);
175			exit(1);
176		}
177		if (indexes.head != NULL)
178		{
179			fprintf(stderr, _("%s: cannot reindex specific index(es) in all databases\n"), progname);
180			exit(1);
181		}
182
183		reindex_all_databases(maintenance_db, host, port, username,
184							prompt_password, progname, echo, quiet, verbose);
185	}
186	else if (syscatalog)
187	{
188		if (schemas.head != NULL)
189		{
190			fprintf(stderr, _("%s: cannot reindex specific schema(s) and system catalogs at the same time\n"), progname);
191			exit(1);
192		}
193		if (tables.head != NULL)
194		{
195			fprintf(stderr, _("%s: cannot reindex specific table(s) and system catalogs at the same time\n"), progname);
196			exit(1);
197		}
198		if (indexes.head != NULL)
199		{
200			fprintf(stderr, _("%s: cannot reindex specific index(es) and system catalogs at the same time\n"), progname);
201			exit(1);
202		}
203
204		if (dbname == NULL)
205		{
206			if (getenv("PGDATABASE"))
207				dbname = getenv("PGDATABASE");
208			else if (getenv("PGUSER"))
209				dbname = getenv("PGUSER");
210			else
211				dbname = get_user_name_or_exit(progname);
212		}
213
214		reindex_system_catalogs(dbname, host, port, username, prompt_password,
215								progname, echo, verbose);
216	}
217	else
218	{
219		if (dbname == NULL)
220		{
221			if (getenv("PGDATABASE"))
222				dbname = getenv("PGDATABASE");
223			else if (getenv("PGUSER"))
224				dbname = getenv("PGUSER");
225			else
226				dbname = get_user_name_or_exit(progname);
227		}
228
229		if (schemas.head != NULL)
230		{
231			SimpleStringListCell *cell;
232
233			for (cell = schemas.head; cell; cell = cell->next)
234			{
235				reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
236						 username, prompt_password, progname, echo, verbose);
237			}
238		}
239
240		if (indexes.head != NULL)
241		{
242			SimpleStringListCell *cell;
243
244			for (cell = indexes.head; cell; cell = cell->next)
245			{
246				reindex_one_database(cell->val, dbname, "INDEX", host, port,
247						 username, prompt_password, progname, echo, verbose);
248			}
249		}
250		if (tables.head != NULL)
251		{
252			SimpleStringListCell *cell;
253
254			for (cell = tables.head; cell; cell = cell->next)
255			{
256				reindex_one_database(cell->val, dbname, "TABLE", host, port,
257						 username, prompt_password, progname, echo, verbose);
258			}
259		}
260
261		/*
262		 * reindex database only if neither index nor table nor schema is
263		 * specified
264		 */
265		if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
266			reindex_one_database(dbname, dbname, "DATABASE", host, port,
267						 username, prompt_password, progname, echo, verbose);
268	}
269
270	exit(0);
271}
272
273static void
274reindex_one_database(const char *name, const char *dbname, const char *type,
275					 const char *host, const char *port, const char *username,
276			  enum trivalue prompt_password, const char *progname, bool echo,
277					 bool verbose)
278{
279	PQExpBufferData sql;
280
281	PGconn	   *conn;
282
283	initPQExpBuffer(&sql);
284
285	appendPQExpBufferStr(&sql, "REINDEX");
286
287	if (verbose)
288		appendPQExpBufferStr(&sql, " (VERBOSE)");
289
290	if (strcmp(type, "TABLE") == 0)
291		appendPQExpBuffer(&sql, " TABLE %s", name);
292	else if (strcmp(type, "INDEX") == 0)
293		appendPQExpBuffer(&sql, " INDEX %s", name);
294	else if (strcmp(type, "SCHEMA") == 0)
295		appendPQExpBuffer(&sql, " SCHEMA %s", name);
296	else if (strcmp(type, "DATABASE") == 0)
297		appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
298	appendPQExpBufferChar(&sql, ';');
299
300	conn = connectDatabase(dbname, host, port, username, prompt_password,
301						   progname, false, false);
302
303	if (!executeMaintenanceCommand(conn, sql.data, echo))
304	{
305		if (strcmp(type, "TABLE") == 0)
306			fprintf(stderr, _("%s: reindexing of table \"%s\" in database \"%s\" failed: %s"),
307					progname, name, dbname, PQerrorMessage(conn));
308		if (strcmp(type, "INDEX") == 0)
309			fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
310					progname, name, dbname, PQerrorMessage(conn));
311		if (strcmp(type, "SCHEMA") == 0)
312			fprintf(stderr, _("%s: reindexing of schema \"%s\" in database \"%s\" failed: %s"),
313					progname, name, dbname, PQerrorMessage(conn));
314		else
315			fprintf(stderr, _("%s: reindexing of database \"%s\" failed: %s"),
316					progname, dbname, PQerrorMessage(conn));
317		PQfinish(conn);
318		exit(1);
319	}
320
321	PQfinish(conn);
322	termPQExpBuffer(&sql);
323}
324
325static void
326reindex_all_databases(const char *maintenance_db,
327					  const char *host, const char *port,
328					  const char *username, enum trivalue prompt_password,
329				   const char *progname, bool echo, bool quiet, bool verbose)
330{
331	PGconn	   *conn;
332	PGresult   *result;
333	int			i;
334
335	conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
336									  prompt_password, progname);
337	result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
338	PQfinish(conn);
339
340	for (i = 0; i < PQntuples(result); i++)
341	{
342		char	   *dbname = PQgetvalue(result, i, 0);
343
344		if (!quiet)
345		{
346			printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
347			fflush(stdout);
348		}
349
350		reindex_one_database(dbname, dbname, "DATABASE", host, port, username,
351							 prompt_password, progname, echo, verbose);
352	}
353
354	PQclear(result);
355}
356
357static void
358reindex_system_catalogs(const char *dbname, const char *host, const char *port,
359						const char *username, enum trivalue prompt_password,
360						const char *progname, bool echo, bool verbose)
361{
362	PQExpBufferData sql;
363
364	PGconn	   *conn;
365
366	initPQExpBuffer(&sql);
367
368	appendPQExpBuffer(&sql, "REINDEX");
369
370	if (verbose)
371		appendPQExpBuffer(&sql, " (VERBOSE)");
372
373	appendPQExpBuffer(&sql, " SYSTEM %s;", dbname);
374
375	conn = connectDatabase(dbname, host, port, username, prompt_password,
376						   progname, false, false);
377	if (!executeMaintenanceCommand(conn, sql.data, echo))
378	{
379		fprintf(stderr, _("%s: reindexing of system catalogs failed: %s"),
380				progname, PQerrorMessage(conn));
381		PQfinish(conn);
382		exit(1);
383	}
384	PQfinish(conn);
385	termPQExpBuffer(&sql);
386}
387
388static void
389help(const char *progname)
390{
391	printf(_("%s reindexes a PostgreSQL database.\n\n"), progname);
392	printf(_("Usage:\n"));
393	printf(_("  %s [OPTION]... [DBNAME]\n"), progname);
394	printf(_("\nOptions:\n"));
395	printf(_("  -a, --all                 reindex all databases\n"));
396	printf(_("  -d, --dbname=DBNAME       database to reindex\n"));
397	printf(_("  -e, --echo                show the commands being sent to the server\n"));
398	printf(_("  -i, --index=INDEX         recreate specific index(es) only\n"));
399	printf(_("  -q, --quiet               don't write any messages\n"));
400	printf(_("  -s, --system              reindex system catalogs\n"));
401	printf(_("  -S, --schema=SCHEMA       reindex specific schema(s) only\n"));
402	printf(_("  -t, --table=TABLE         reindex specific table(s) only\n"));
403	printf(_("  -v, --verbose             write a lot of output\n"));
404	printf(_("  -V, --version             output version information, then exit\n"));
405	printf(_("  -?, --help                show this help, then exit\n"));
406	printf(_("\nConnection options:\n"));
407	printf(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));
408	printf(_("  -p, --port=PORT           database server port\n"));
409	printf(_("  -U, --username=USERNAME   user name to connect as\n"));
410	printf(_("  -w, --no-password         never prompt for password\n"));
411	printf(_("  -W, --password            force password prompt\n"));
412	printf(_("  --maintenance-db=DBNAME   alternate maintenance database\n"));
413	printf(_("\nRead the description of the SQL command REINDEX for details.\n"));
414	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
415}