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