PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/bin/scripts/reindexdb.c

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