X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Fbin%2Fscripts%2Fclusterdb.c;h=650d2ae261026fd458f0fe5e68be4ef55675c67b;hb=582edc3;hp=0fcab8ec6daca6ebe34d3b581610f9b22c5d103d;hpb=b1ffacddfc2f558ad150d05a79318b7e58c572b2;p=postgresql diff --git a/src/bin/scripts/clusterdb.c b/src/bin/scripts/clusterdb.c index 0fcab8ec6d..650d2ae261 100644 --- a/src/bin/scripts/clusterdb.c +++ b/src/bin/scripts/clusterdb.c @@ -2,26 +2,26 @@ * * clusterdb * - * Portions Copyright (c) 2002-2003, PostgreSQL Global Development Group + * Portions Copyright (c) 2002-2018, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/scripts/clusterdb.c,v 1.6 2004/05/12 13:38:46 momjian Exp $ + * src/bin/scripts/clusterdb.c * *------------------------------------------------------------------------- */ #include "postgres_fe.h" #include "common.h" -#include "dumputils.h" +#include "fe_utils/simple_list.h" +#include "fe_utils/string_utils.h" -static void -cluster_one_database(const char *dbname, const char *table, +static void cluster_one_database(const char *dbname, bool verbose, const char *table, const char *host, const char *port, - const char *username, bool password, - const char *progname, bool echo, bool quiet); -static void -cluster_all_databases(const char *host, const char *port, - const char *username, bool password, + const char *username, enum trivalue prompt_password, + const char *progname, bool echo); +static void cluster_all_databases(bool verbose, const char *maintenance_db, + const char *host, const char *port, + const char *username, enum trivalue prompt_password, const char *progname, bool echo, bool quiet); static void help(const char *progname); @@ -34,12 +34,15 @@ main(int argc, char *argv[]) {"host", required_argument, NULL, 'h'}, {"port", required_argument, NULL, 'p'}, {"username", required_argument, NULL, 'U'}, + {"no-password", no_argument, NULL, 'w'}, {"password", no_argument, NULL, 'W'}, {"echo", no_argument, NULL, 'e'}, {"quiet", no_argument, NULL, 'q'}, {"dbname", required_argument, NULL, 'd'}, {"all", no_argument, NULL, 'a'}, {"table", required_argument, NULL, 't'}, + {"verbose", no_argument, NULL, 'v'}, + {"maintenance-db", required_argument, NULL, 2}, {NULL, 0, NULL, 0} }; @@ -48,34 +51,40 @@ main(int argc, char *argv[]) int c; const char *dbname = NULL; + const char *maintenance_db = NULL; char *host = NULL; char *port = NULL; char *username = NULL; - bool password = false; + enum trivalue prompt_password = TRI_DEFAULT; bool echo = false; bool quiet = false; bool alldb = false; - char *table = NULL; + bool verbose = false; + SimpleStringList tables = {NULL, NULL}; progname = get_progname(argv[0]); - init_nls(); + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts")); + handle_help_version_opts(argc, argv, "clusterdb", help); - while ((c = getopt_long(argc, argv, "h:p:U:Weqd:at:", long_options, &optindex)) != -1) + while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:at:v", long_options, &optindex)) != -1) { switch (c) { case 'h': - host = optarg; + host = pg_strdup(optarg); break; case 'p': - port = optarg; + port = pg_strdup(optarg); break; case 'U': - username = optarg; + username = pg_strdup(optarg); + break; + case 'w': + prompt_password = TRI_NO; break; case 'W': - password = true; + prompt_password = TRI_YES; break; case 'e': echo = true; @@ -84,13 +93,19 @@ main(int argc, char *argv[]) quiet = true; break; case 'd': - dbname = optarg; + dbname = pg_strdup(optarg); break; case 'a': alldb = true; break; case 't': - table = optarg; + simple_string_list_append(&tables, optarg); + break; + case 'v': + verbose = true; + break; + case 2: + maintenance_db = pg_strdup(optarg); break; default: fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); @@ -98,20 +113,26 @@ main(int argc, char *argv[]) } } - switch (argc - optind) + /* + * Non-option argument specifies database name as long as it wasn't + * already specified with -d / --dbname + */ + if (optind < argc && dbname == NULL) { - case 0: - break; - case 1: - dbname = argv[optind]; - break; - default: - fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"), - progname, argv[optind + 1]); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); - exit(1); + dbname = argv[optind]; + optind++; + } + + if (optind < argc) + { + fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"), + progname, argv[optind]); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + exit(1); } + setup_cancel_handler(); + if (alldb) { if (dbname) @@ -120,14 +141,15 @@ main(int argc, char *argv[]) progname); exit(1); } - if (table) + + if (tables.head != NULL) { - fprintf(stderr, _("%s: cannot cluster a specific table in all databases\n"), + fprintf(stderr, _("%s: cannot cluster specific table(s) in all databases\n"), progname); exit(1); } - cluster_all_databases(host, port, username, password, + cluster_all_databases(verbose, maintenance_db, host, port, username, prompt_password, progname, echo, quiet); } else @@ -139,12 +161,24 @@ main(int argc, char *argv[]) else if (getenv("PGUSER")) dbname = getenv("PGUSER"); else - dbname = get_user_name(progname); + dbname = get_user_name_or_exit(progname); } - cluster_one_database(dbname, table, - host, port, username, password, - progname, echo, quiet); + if (tables.head != NULL) + { + SimpleStringListCell *cell; + + for (cell = tables.head; cell; cell = cell->next) + { + cluster_one_database(dbname, verbose, cell->val, + host, port, username, prompt_password, + progname, echo); + } + } + else + cluster_one_database(dbname, verbose, NULL, + host, port, username, prompt_password, + progname, echo); } exit(0); @@ -152,77 +186,82 @@ main(int argc, char *argv[]) static void -cluster_one_database(const char *dbname, const char *table, +cluster_one_database(const char *dbname, bool verbose, const char *table, const char *host, const char *port, - const char *username, bool password, - const char *progname, bool echo, bool quiet) + const char *username, enum trivalue prompt_password, + const char *progname, bool echo) { PQExpBufferData sql; PGconn *conn; - PGresult *result; + + conn = connectDatabase(dbname, host, port, username, prompt_password, + progname, echo, false, false); initPQExpBuffer(&sql); - appendPQExpBuffer(&sql, "CLUSTER"); + appendPQExpBufferStr(&sql, "CLUSTER"); + if (verbose) + appendPQExpBufferStr(&sql, " VERBOSE"); if (table) - appendPQExpBuffer(&sql, " %s", fmtId(table)); - appendPQExpBuffer(&sql, ";\n"); - - conn = connectDatabase(dbname, host, port, username, password, progname); - - if (echo) - printf("%s", sql.data); - result = PQexec(conn, sql.data); + { + appendPQExpBufferChar(&sql, ' '); + appendQualifiedRelation(&sql, table, conn, progname, echo); + } + appendPQExpBufferChar(&sql, ';'); - if (PQresultStatus(result) != PGRES_COMMAND_OK) + if (!executeMaintenanceCommand(conn, sql.data, echo)) { if (table) fprintf(stderr, _("%s: clustering of table \"%s\" in database \"%s\" failed: %s"), - progname, table, dbname, PQerrorMessage(conn)); + progname, table, PQdb(conn), PQerrorMessage(conn)); else fprintf(stderr, _("%s: clustering of database \"%s\" failed: %s"), - progname, dbname, PQerrorMessage(conn)); + progname, PQdb(conn), PQerrorMessage(conn)); PQfinish(conn); exit(1); } - - PQclear(result); PQfinish(conn); termPQExpBuffer(&sql); - - if (!quiet) - { - puts("CLUSTER"); - fflush(stdout); - } } static void -cluster_all_databases(const char *host, const char *port, - const char *username, bool password, +cluster_all_databases(bool verbose, const char *maintenance_db, + const char *host, const char *port, + const char *username, enum trivalue prompt_password, const char *progname, bool echo, bool quiet) { PGconn *conn; PGresult *result; + PQExpBufferData connstr; int i; - conn = connectDatabase("template1", host, port, username, password, progname); - result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn;", progname, echo); + conn = connectMaintenanceDatabase(maintenance_db, host, port, username, + prompt_password, progname, echo); + result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo); PQfinish(conn); + initPQExpBuffer(&connstr); for (i = 0; i < PQntuples(result); i++) { char *dbname = PQgetvalue(result, i, 0); if (!quiet) - fprintf(stderr, _("%s: clustering database \"%s\"\n"), progname, dbname); + { + printf(_("%s: clustering database \"%s\"\n"), progname, dbname); + fflush(stdout); + } + + resetPQExpBuffer(&connstr); + appendPQExpBuffer(&connstr, "dbname="); + appendConnStrVal(&connstr, dbname); - cluster_one_database(dbname, NULL, - host, port, username, password, - progname, echo, quiet); + cluster_one_database(connstr.data, verbose, NULL, + host, port, username, prompt_password, + progname, echo); } + termPQExpBuffer(&connstr); PQclear(result); } @@ -237,16 +276,19 @@ help(const char *progname) printf(_("\nOptions:\n")); printf(_(" -a, --all cluster all databases\n")); printf(_(" -d, --dbname=DBNAME database to cluster\n")); - printf(_(" -t, --table=TABLE cluster specific table only\n")); printf(_(" -e, --echo show the commands being sent to the server\n")); printf(_(" -q, --quiet don't write any messages\n")); - printf(_(" --help show this help, then exit\n")); - printf(_(" --version output version information, then exit\n")); + printf(_(" -t, --table=TABLE cluster specific table(s) only\n")); + printf(_(" -v, --verbose write a lot of output\n")); + printf(_(" -V, --version output version information, then exit\n")); + printf(_(" -?, --help show this help, then exit\n")); printf(_("\nConnection options:\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); printf(_(" -p, --port=PORT database server port\n")); printf(_(" -U, --username=USERNAME user name to connect as\n")); - printf(_(" -W, --password prompt for password\n")); + printf(_(" -w, --no-password never prompt for password\n")); + printf(_(" -W, --password force password prompt\n")); + printf(_(" --maintenance-db=DBNAME alternate maintenance database\n")); printf(_("\nRead the description of the SQL command CLUSTER for details.\n")); printf(_("\nReport bugs to .\n")); }