PageRenderTime 63ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/bin/scripts/reindexdb.c

http://github.com/postgres/postgres
C | 779 lines | 615 code | 92 blank | 72 comment | 95 complexity | d38bf2df467a946161cda8a755dda00e MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*-------------------------------------------------------------------------
  2. *
  3. * reindexdb
  4. *
  5. * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
  6. *
  7. * src/bin/scripts/reindexdb.c
  8. *
  9. *-------------------------------------------------------------------------
  10. */
  11. #include "postgres_fe.h"
  12. #include "catalog/pg_class_d.h"
  13. #include "common.h"
  14. #include "common/logging.h"
  15. #include "fe_utils/cancel.h"
  16. #include "fe_utils/connect.h"
  17. #include "fe_utils/simple_list.h"
  18. #include "fe_utils/string_utils.h"
  19. #include "scripts_parallel.h"
  20. typedef enum ReindexType
  21. {
  22. REINDEX_DATABASE,
  23. REINDEX_INDEX,
  24. REINDEX_SCHEMA,
  25. REINDEX_SYSTEM,
  26. REINDEX_TABLE
  27. } ReindexType;
  28. static SimpleStringList *get_parallel_object_list(PGconn *conn,
  29. ReindexType type,
  30. SimpleStringList *user_list,
  31. bool echo);
  32. static void reindex_one_database(const char *dbname, ReindexType type,
  33. SimpleStringList *user_list, const char *host,
  34. const char *port, const char *username,
  35. enum trivalue prompt_password, const char *progname,
  36. bool echo, bool verbose, bool concurrently,
  37. int concurrentCons);
  38. static void reindex_all_databases(const char *maintenance_db,
  39. const char *host, const char *port,
  40. const char *username, enum trivalue prompt_password,
  41. const char *progname, bool echo,
  42. bool quiet, bool verbose, bool concurrently,
  43. int concurrentCons);
  44. static void run_reindex_command(PGconn *conn, ReindexType type,
  45. const char *name, bool echo, bool verbose,
  46. bool concurrently, bool async);
  47. static void help(const char *progname);
  48. int
  49. main(int argc, char *argv[])
  50. {
  51. static struct option long_options[] = {
  52. {"host", required_argument, NULL, 'h'},
  53. {"port", required_argument, NULL, 'p'},
  54. {"username", required_argument, NULL, 'U'},
  55. {"no-password", no_argument, NULL, 'w'},
  56. {"password", no_argument, NULL, 'W'},
  57. {"echo", no_argument, NULL, 'e'},
  58. {"quiet", no_argument, NULL, 'q'},
  59. {"schema", required_argument, NULL, 'S'},
  60. {"dbname", required_argument, NULL, 'd'},
  61. {"all", no_argument, NULL, 'a'},
  62. {"system", no_argument, NULL, 's'},
  63. {"table", required_argument, NULL, 't'},
  64. {"index", required_argument, NULL, 'i'},
  65. {"jobs", required_argument, NULL, 'j'},
  66. {"verbose", no_argument, NULL, 'v'},
  67. {"concurrently", no_argument, NULL, 1},
  68. {"maintenance-db", required_argument, NULL, 2},
  69. {NULL, 0, NULL, 0}
  70. };
  71. const char *progname;
  72. int optindex;
  73. int c;
  74. const char *dbname = NULL;
  75. const char *maintenance_db = NULL;
  76. const char *host = NULL;
  77. const char *port = NULL;
  78. const char *username = NULL;
  79. enum trivalue prompt_password = TRI_DEFAULT;
  80. bool syscatalog = false;
  81. bool alldb = false;
  82. bool echo = false;
  83. bool quiet = false;
  84. bool verbose = false;
  85. bool concurrently = false;
  86. SimpleStringList indexes = {NULL, NULL};
  87. SimpleStringList tables = {NULL, NULL};
  88. SimpleStringList schemas = {NULL, NULL};
  89. int concurrentCons = 1;
  90. pg_logging_init(argv[0]);
  91. progname = get_progname(argv[0]);
  92. set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  93. handle_help_version_opts(argc, argv, "reindexdb", help);
  94. /* process command-line options */
  95. while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:j:v", long_options, &optindex)) != -1)
  96. {
  97. switch (c)
  98. {
  99. case 'h':
  100. host = pg_strdup(optarg);
  101. break;
  102. case 'p':
  103. port = pg_strdup(optarg);
  104. break;
  105. case 'U':
  106. username = pg_strdup(optarg);
  107. break;
  108. case 'w':
  109. prompt_password = TRI_NO;
  110. break;
  111. case 'W':
  112. prompt_password = TRI_YES;
  113. break;
  114. case 'e':
  115. echo = true;
  116. break;
  117. case 'q':
  118. quiet = true;
  119. break;
  120. case 'S':
  121. simple_string_list_append(&schemas, optarg);
  122. break;
  123. case 'd':
  124. dbname = pg_strdup(optarg);
  125. break;
  126. case 'a':
  127. alldb = true;
  128. break;
  129. case 's':
  130. syscatalog = true;
  131. break;
  132. case 't':
  133. simple_string_list_append(&tables, optarg);
  134. break;
  135. case 'i':
  136. simple_string_list_append(&indexes, optarg);
  137. break;
  138. case 'j':
  139. concurrentCons = atoi(optarg);
  140. if (concurrentCons <= 0)
  141. {
  142. pg_log_error("number of parallel jobs must be at least 1");
  143. exit(1);
  144. }
  145. break;
  146. case 'v':
  147. verbose = true;
  148. break;
  149. case 1:
  150. concurrently = true;
  151. break;
  152. case 2:
  153. maintenance_db = pg_strdup(optarg);
  154. break;
  155. default:
  156. fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  157. exit(1);
  158. }
  159. }
  160. /*
  161. * Non-option argument specifies database name as long as it wasn't
  162. * already specified with -d / --dbname
  163. */
  164. if (optind < argc && dbname == NULL)
  165. {
  166. dbname = argv[optind];
  167. optind++;
  168. }
  169. if (optind < argc)
  170. {
  171. pg_log_error("too many command-line arguments (first is \"%s\")",
  172. argv[optind]);
  173. fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  174. exit(1);
  175. }
  176. setup_cancel_handler(NULL);
  177. if (alldb)
  178. {
  179. if (dbname)
  180. {
  181. pg_log_error("cannot reindex all databases and a specific one at the same time");
  182. exit(1);
  183. }
  184. if (syscatalog)
  185. {
  186. pg_log_error("cannot reindex all databases and system catalogs at the same time");
  187. exit(1);
  188. }
  189. if (schemas.head != NULL)
  190. {
  191. pg_log_error("cannot reindex specific schema(s) in all databases");
  192. exit(1);
  193. }
  194. if (tables.head != NULL)
  195. {
  196. pg_log_error("cannot reindex specific table(s) in all databases");
  197. exit(1);
  198. }
  199. if (indexes.head != NULL)
  200. {
  201. pg_log_error("cannot reindex specific index(es) in all databases");
  202. exit(1);
  203. }
  204. reindex_all_databases(maintenance_db, host, port, username,
  205. prompt_password, progname, echo, quiet, verbose,
  206. concurrently, concurrentCons);
  207. }
  208. else if (syscatalog)
  209. {
  210. if (schemas.head != NULL)
  211. {
  212. pg_log_error("cannot reindex specific schema(s) and system catalogs at the same time");
  213. exit(1);
  214. }
  215. if (tables.head != NULL)
  216. {
  217. pg_log_error("cannot reindex specific table(s) and system catalogs at the same time");
  218. exit(1);
  219. }
  220. if (indexes.head != NULL)
  221. {
  222. pg_log_error("cannot reindex specific index(es) and system catalogs at the same time");
  223. exit(1);
  224. }
  225. if (concurrentCons > 1)
  226. {
  227. pg_log_error("cannot use multiple jobs to reindex system catalogs");
  228. exit(1);
  229. }
  230. if (dbname == NULL)
  231. {
  232. if (getenv("PGDATABASE"))
  233. dbname = getenv("PGDATABASE");
  234. else if (getenv("PGUSER"))
  235. dbname = getenv("PGUSER");
  236. else
  237. dbname = get_user_name_or_exit(progname);
  238. }
  239. reindex_one_database(dbname, REINDEX_SYSTEM, NULL, host,
  240. port, username, prompt_password, progname,
  241. echo, verbose, concurrently, 1);
  242. }
  243. else
  244. {
  245. /*
  246. * Index-level REINDEX is not supported with multiple jobs as we
  247. * cannot control the concurrent processing of multiple indexes
  248. * depending on the same relation.
  249. */
  250. if (concurrentCons > 1 && indexes.head != NULL)
  251. {
  252. pg_log_error("cannot use multiple jobs to reindex indexes");
  253. exit(1);
  254. }
  255. if (dbname == NULL)
  256. {
  257. if (getenv("PGDATABASE"))
  258. dbname = getenv("PGDATABASE");
  259. else if (getenv("PGUSER"))
  260. dbname = getenv("PGUSER");
  261. else
  262. dbname = get_user_name_or_exit(progname);
  263. }
  264. if (schemas.head != NULL)
  265. reindex_one_database(dbname, REINDEX_SCHEMA, &schemas, host,
  266. port, username, prompt_password, progname,
  267. echo, verbose, concurrently, concurrentCons);
  268. if (indexes.head != NULL)
  269. reindex_one_database(dbname, REINDEX_INDEX, &indexes, host,
  270. port, username, prompt_password, progname,
  271. echo, verbose, concurrently, 1);
  272. if (tables.head != NULL)
  273. reindex_one_database(dbname, REINDEX_TABLE, &tables, host,
  274. port, username, prompt_password, progname,
  275. echo, verbose, concurrently,
  276. concurrentCons);
  277. /*
  278. * reindex database only if neither index nor table nor schema is
  279. * specified
  280. */
  281. if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
  282. reindex_one_database(dbname, REINDEX_DATABASE, NULL, host,
  283. port, username, prompt_password, progname,
  284. echo, verbose, concurrently, concurrentCons);
  285. }
  286. exit(0);
  287. }
  288. static void
  289. reindex_one_database(const char *dbname, ReindexType type,
  290. SimpleStringList *user_list, const char *host,
  291. const char *port, const char *username,
  292. enum trivalue prompt_password, const char *progname, bool echo,
  293. bool verbose, bool concurrently, int concurrentCons)
  294. {
  295. PGconn *conn;
  296. SimpleStringListCell *cell;
  297. bool parallel = concurrentCons > 1;
  298. SimpleStringList *process_list = user_list;
  299. ReindexType process_type = type;
  300. ParallelSlot *slots;
  301. bool failed = false;
  302. int items_count = 0;
  303. conn = connectDatabase(dbname, host, port, username, prompt_password,
  304. progname, echo, false, false);
  305. if (concurrently && PQserverVersion(conn) < 120000)
  306. {
  307. PQfinish(conn);
  308. pg_log_error("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
  309. "concurrently", "12");
  310. exit(1);
  311. }
  312. if (!parallel)
  313. {
  314. switch (process_type)
  315. {
  316. case REINDEX_DATABASE:
  317. case REINDEX_SYSTEM:
  318. /*
  319. * Database and system reindexes only need to work on the
  320. * database itself, so build a list with a single entry.
  321. */
  322. Assert(user_list == NULL);
  323. process_list = pg_malloc0(sizeof(SimpleStringList));
  324. simple_string_list_append(process_list, PQdb(conn));
  325. break;
  326. case REINDEX_INDEX:
  327. case REINDEX_SCHEMA:
  328. case REINDEX_TABLE:
  329. Assert(user_list != NULL);
  330. break;
  331. }
  332. }
  333. else
  334. {
  335. switch (process_type)
  336. {
  337. case REINDEX_DATABASE:
  338. /*
  339. * Database-wide parallel reindex requires special processing.
  340. * If multiple jobs were asked, we have to reindex system
  341. * catalogs first as they cannot be processed in parallel.
  342. */
  343. if (concurrently)
  344. pg_log_warning("cannot reindex system catalogs concurrently, skipping all");
  345. else
  346. run_reindex_command(conn, REINDEX_SYSTEM, PQdb(conn), echo,
  347. verbose, concurrently, false);
  348. /* Build a list of relations from the database */
  349. process_list = get_parallel_object_list(conn, process_type,
  350. user_list, echo);
  351. process_type = REINDEX_TABLE;
  352. /* Bail out if nothing to process */
  353. if (process_list == NULL)
  354. return;
  355. break;
  356. case REINDEX_SCHEMA:
  357. Assert(user_list != NULL);
  358. /* Build a list of relations from all the schemas */
  359. process_list = get_parallel_object_list(conn, process_type,
  360. user_list, echo);
  361. process_type = REINDEX_TABLE;
  362. /* Bail out if nothing to process */
  363. if (process_list == NULL)
  364. return;
  365. break;
  366. case REINDEX_SYSTEM:
  367. case REINDEX_INDEX:
  368. /* not supported */
  369. Assert(false);
  370. break;
  371. case REINDEX_TABLE:
  372. /*
  373. * Fall through. The list of items for tables is already
  374. * created.
  375. */
  376. break;
  377. }
  378. }
  379. /*
  380. * Adjust the number of concurrent connections depending on the items in
  381. * the list. We choose the minimum between the number of concurrent
  382. * connections and the number of items in the list.
  383. */
  384. for (cell = process_list->head; cell; cell = cell->next)
  385. {
  386. items_count++;
  387. /* no need to continue if there are more elements than jobs */
  388. if (items_count >= concurrentCons)
  389. break;
  390. }
  391. concurrentCons = Min(concurrentCons, items_count);
  392. Assert(concurrentCons > 0);
  393. Assert(process_list != NULL);
  394. slots = ParallelSlotsSetup(dbname, host, port, username, prompt_password,
  395. progname, echo, conn, concurrentCons);
  396. cell = process_list->head;
  397. do
  398. {
  399. const char *objname = cell->val;
  400. ParallelSlot *free_slot = NULL;
  401. if (CancelRequested)
  402. {
  403. failed = true;
  404. goto finish;
  405. }
  406. free_slot = ParallelSlotsGetIdle(slots, concurrentCons);
  407. if (!free_slot)
  408. {
  409. failed = true;
  410. goto finish;
  411. }
  412. run_reindex_command(free_slot->connection, process_type, objname,
  413. echo, verbose, concurrently, true);
  414. cell = cell->next;
  415. } while (cell != NULL);
  416. if (!ParallelSlotsWaitCompletion(slots, concurrentCons))
  417. failed = true;
  418. finish:
  419. if (process_list != user_list)
  420. {
  421. simple_string_list_destroy(process_list);
  422. pg_free(process_list);
  423. }
  424. ParallelSlotsTerminate(slots, concurrentCons);
  425. pfree(slots);
  426. if (failed)
  427. exit(1);
  428. }
  429. static void
  430. run_reindex_command(PGconn *conn, ReindexType type, const char *name,
  431. bool echo, bool verbose, bool concurrently, bool async)
  432. {
  433. PQExpBufferData sql;
  434. bool status;
  435. Assert(name);
  436. /* build the REINDEX query */
  437. initPQExpBuffer(&sql);
  438. appendPQExpBufferStr(&sql, "REINDEX ");
  439. if (verbose)
  440. appendPQExpBufferStr(&sql, "(VERBOSE) ");
  441. /* object type */
  442. switch (type)
  443. {
  444. case REINDEX_DATABASE:
  445. appendPQExpBufferStr(&sql, "DATABASE ");
  446. break;
  447. case REINDEX_INDEX:
  448. appendPQExpBufferStr(&sql, "INDEX ");
  449. break;
  450. case REINDEX_SCHEMA:
  451. appendPQExpBufferStr(&sql, "SCHEMA ");
  452. break;
  453. case REINDEX_SYSTEM:
  454. appendPQExpBufferStr(&sql, "SYSTEM ");
  455. break;
  456. case REINDEX_TABLE:
  457. appendPQExpBufferStr(&sql, "TABLE ");
  458. break;
  459. }
  460. if (concurrently)
  461. appendPQExpBufferStr(&sql, "CONCURRENTLY ");
  462. /* object name */
  463. switch (type)
  464. {
  465. case REINDEX_DATABASE:
  466. case REINDEX_SYSTEM:
  467. appendPQExpBufferStr(&sql, fmtId(name));
  468. break;
  469. case REINDEX_INDEX:
  470. case REINDEX_TABLE:
  471. appendQualifiedRelation(&sql, name, conn, echo);
  472. break;
  473. case REINDEX_SCHEMA:
  474. appendPQExpBufferStr(&sql, name);
  475. break;
  476. }
  477. /* finish the query */
  478. appendPQExpBufferChar(&sql, ';');
  479. if (async)
  480. {
  481. if (echo)
  482. printf("%s\n", sql.data);
  483. status = PQsendQuery(conn, sql.data) == 1;
  484. }
  485. else
  486. status = executeMaintenanceCommand(conn, sql.data, echo);
  487. if (!status)
  488. {
  489. switch (type)
  490. {
  491. case REINDEX_DATABASE:
  492. pg_log_error("reindexing of database \"%s\" failed: %s",
  493. PQdb(conn), PQerrorMessage(conn));
  494. break;
  495. case REINDEX_INDEX:
  496. pg_log_error("reindexing of index \"%s\" in database \"%s\" failed: %s",
  497. name, PQdb(conn), PQerrorMessage(conn));
  498. break;
  499. case REINDEX_SCHEMA:
  500. pg_log_error("reindexing of schema \"%s\" in database \"%s\" failed: %s",
  501. name, PQdb(conn), PQerrorMessage(conn));
  502. break;
  503. case REINDEX_SYSTEM:
  504. pg_log_error("reindexing of system catalogs on database \"%s\" failed: %s",
  505. PQdb(conn), PQerrorMessage(conn));
  506. break;
  507. case REINDEX_TABLE:
  508. pg_log_error("reindexing of table \"%s\" in database \"%s\" failed: %s",
  509. name, PQdb(conn), PQerrorMessage(conn));
  510. break;
  511. }
  512. if (!async)
  513. {
  514. PQfinish(conn);
  515. exit(1);
  516. }
  517. }
  518. termPQExpBuffer(&sql);
  519. }
  520. /*
  521. * Prepare the list of objects to process by querying the catalogs.
  522. *
  523. * This function will return a SimpleStringList object containing the entire
  524. * list of tables in the given database that should be processed by a parallel
  525. * database-wide reindex (excluding system tables), or NULL if there's no such
  526. * table.
  527. */
  528. static SimpleStringList *
  529. get_parallel_object_list(PGconn *conn, ReindexType type,
  530. SimpleStringList *user_list, bool echo)
  531. {
  532. PQExpBufferData catalog_query;
  533. PQExpBufferData buf;
  534. PGresult *res;
  535. SimpleStringList *tables;
  536. int ntups,
  537. i;
  538. initPQExpBuffer(&catalog_query);
  539. /*
  540. * The queries here are using a safe search_path, so there's no need to
  541. * fully qualify everything.
  542. */
  543. switch (type)
  544. {
  545. case REINDEX_DATABASE:
  546. Assert(user_list == NULL);
  547. appendPQExpBuffer(&catalog_query,
  548. "SELECT c.relname, ns.nspname\n"
  549. " FROM pg_catalog.pg_class c\n"
  550. " JOIN pg_catalog.pg_namespace ns"
  551. " ON c.relnamespace = ns.oid\n"
  552. " WHERE ns.nspname != 'pg_catalog'\n"
  553. " AND c.relkind IN ("
  554. CppAsString2(RELKIND_RELATION) ", "
  555. CppAsString2(RELKIND_MATVIEW) ")\n"
  556. " ORDER BY c.relpages DESC;");
  557. break;
  558. case REINDEX_SCHEMA:
  559. {
  560. SimpleStringListCell *cell;
  561. bool nsp_listed = false;
  562. Assert(user_list != NULL);
  563. /*
  564. * All the tables from all the listed schemas are grabbed at
  565. * once.
  566. */
  567. appendPQExpBuffer(&catalog_query,
  568. "SELECT c.relname, ns.nspname\n"
  569. " FROM pg_catalog.pg_class c\n"
  570. " JOIN pg_catalog.pg_namespace ns"
  571. " ON c.relnamespace = ns.oid\n"
  572. " WHERE c.relkind IN ("
  573. CppAsString2(RELKIND_RELATION) ", "
  574. CppAsString2(RELKIND_MATVIEW) ")\n"
  575. " AND ns.nspname IN (");
  576. for (cell = user_list->head; cell; cell = cell->next)
  577. {
  578. const char *nspname = cell->val;
  579. if (nsp_listed)
  580. appendPQExpBuffer(&catalog_query, ", ");
  581. else
  582. nsp_listed = true;
  583. appendStringLiteralConn(&catalog_query, nspname, conn);
  584. }
  585. appendPQExpBuffer(&catalog_query, ")\n"
  586. " ORDER BY c.relpages DESC;");
  587. }
  588. break;
  589. case REINDEX_SYSTEM:
  590. case REINDEX_INDEX:
  591. case REINDEX_TABLE:
  592. Assert(false);
  593. break;
  594. }
  595. res = executeQuery(conn, catalog_query.data, echo);
  596. termPQExpBuffer(&catalog_query);
  597. /*
  598. * If no rows are returned, there are no matching tables, so we are done.
  599. */
  600. ntups = PQntuples(res);
  601. if (ntups == 0)
  602. {
  603. PQclear(res);
  604. PQfinish(conn);
  605. return NULL;
  606. }
  607. tables = pg_malloc0(sizeof(SimpleStringList));
  608. /* Build qualified identifiers for each table */
  609. initPQExpBuffer(&buf);
  610. for (i = 0; i < ntups; i++)
  611. {
  612. appendPQExpBufferStr(&buf,
  613. fmtQualifiedId(PQgetvalue(res, i, 1),
  614. PQgetvalue(res, i, 0)));
  615. simple_string_list_append(tables, buf.data);
  616. resetPQExpBuffer(&buf);
  617. }
  618. termPQExpBuffer(&buf);
  619. PQclear(res);
  620. return tables;
  621. }
  622. static void
  623. reindex_all_databases(const char *maintenance_db,
  624. const char *host, const char *port,
  625. const char *username, enum trivalue prompt_password,
  626. const char *progname, bool echo, bool quiet, bool verbose,
  627. bool concurrently, int concurrentCons)
  628. {
  629. PGconn *conn;
  630. PGresult *result;
  631. PQExpBufferData connstr;
  632. int i;
  633. conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
  634. prompt_password, progname, echo);
  635. result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", echo);
  636. PQfinish(conn);
  637. initPQExpBuffer(&connstr);
  638. for (i = 0; i < PQntuples(result); i++)
  639. {
  640. char *dbname = PQgetvalue(result, i, 0);
  641. if (!quiet)
  642. {
  643. printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
  644. fflush(stdout);
  645. }
  646. resetPQExpBuffer(&connstr);
  647. appendPQExpBufferStr(&connstr, "dbname=");
  648. appendConnStrVal(&connstr, dbname);
  649. reindex_one_database(connstr.data, REINDEX_DATABASE, NULL, host,
  650. port, username, prompt_password,
  651. progname, echo, verbose, concurrently,
  652. concurrentCons);
  653. }
  654. termPQExpBuffer(&connstr);
  655. PQclear(result);
  656. }
  657. static void
  658. help(const char *progname)
  659. {
  660. printf(_("%s reindexes a PostgreSQL database.\n\n"), progname);
  661. printf(_("Usage:\n"));
  662. printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
  663. printf(_("\nOptions:\n"));
  664. printf(_(" -a, --all reindex all databases\n"));
  665. printf(_(" --concurrently reindex concurrently\n"));
  666. printf(_(" -d, --dbname=DBNAME database to reindex\n"));
  667. printf(_(" -e, --echo show the commands being sent to the server\n"));
  668. printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
  669. printf(_(" -j, --jobs=NUM use this many concurrent connections to reindex\n"));
  670. printf(_(" -q, --quiet don't write any messages\n"));
  671. printf(_(" -s, --system reindex system catalogs\n"));
  672. printf(_(" -S, --schema=SCHEMA reindex specific schema(s) only\n"));
  673. printf(_(" -t, --table=TABLE reindex specific table(s) only\n"));
  674. printf(_(" -v, --verbose write a lot of output\n"));
  675. printf(_(" -V, --version output version information, then exit\n"));
  676. printf(_(" -?, --help show this help, then exit\n"));
  677. printf(_("\nConnection options:\n"));
  678. printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
  679. printf(_(" -p, --port=PORT database server port\n"));
  680. printf(_(" -U, --username=USERNAME user name to connect as\n"));
  681. printf(_(" -w, --no-password never prompt for password\n"));
  682. printf(_(" -W, --password force password prompt\n"));
  683. printf(_(" --maintenance-db=DBNAME alternate maintenance database\n"));
  684. printf(_("\nRead the description of the SQL command REINDEX for details.\n"));
  685. printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
  686. printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
  687. }