mirror of
https://github.com/postgres/postgres.git
synced 2025-08-11 04:22:52 +03:00
A number of utility programs were rather careless about paremeters that can be set via both an option argument and a positional argument. This leads to results which can violate the Principal Of Least Astonishment. These changes refuse to use positional arguments to override settings that have been made via positional arguments. The changes are backpatched to all live branches.
260 lines
6.7 KiB
C
260 lines
6.7 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* clusterdb
|
|
*
|
|
* Portions Copyright (c) 2002-2011, PostgreSQL Global Development Group
|
|
*
|
|
* src/bin/scripts/clusterdb.c
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres_fe.h"
|
|
#include "common.h"
|
|
#include "dumputils.h"
|
|
|
|
|
|
static void cluster_one_database(const char *dbname, bool verbose, const char *table,
|
|
const char *host, const char *port,
|
|
const char *username, enum trivalue prompt_password,
|
|
const char *progname, bool echo);
|
|
static void cluster_all_databases(bool verbose, 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);
|
|
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
static struct option long_options[] = {
|
|
{"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'},
|
|
{NULL, 0, NULL, 0}
|
|
};
|
|
|
|
const char *progname;
|
|
int optindex;
|
|
int c;
|
|
|
|
const char *dbname = NULL;
|
|
char *host = NULL;
|
|
char *port = NULL;
|
|
char *username = NULL;
|
|
enum trivalue prompt_password = TRI_DEFAULT;
|
|
bool echo = false;
|
|
bool quiet = false;
|
|
bool alldb = false;
|
|
char *table = NULL;
|
|
bool verbose = false;
|
|
|
|
progname = get_progname(argv[0]);
|
|
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:wWeqd:at:v", long_options, &optindex)) != -1)
|
|
{
|
|
switch (c)
|
|
{
|
|
case 'h':
|
|
host = optarg;
|
|
break;
|
|
case 'p':
|
|
port = optarg;
|
|
break;
|
|
case 'U':
|
|
username = optarg;
|
|
break;
|
|
case 'w':
|
|
prompt_password = TRI_NO;
|
|
break;
|
|
case 'W':
|
|
prompt_password = TRI_YES;
|
|
break;
|
|
case 'e':
|
|
echo = true;
|
|
break;
|
|
case 'q':
|
|
quiet = true;
|
|
break;
|
|
case 'd':
|
|
dbname = optarg;
|
|
break;
|
|
case 'a':
|
|
alldb = true;
|
|
break;
|
|
case 't':
|
|
table = optarg;
|
|
break;
|
|
case 'v':
|
|
verbose = true;
|
|
break;
|
|
default:
|
|
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Non-option argument specifies database name
|
|
* as long as it wasn't already specified with -d / --dbname
|
|
*/
|
|
if (optind < argc && dbname == NULL)
|
|
{
|
|
dbname = argv[optind];
|
|
optind++;
|
|
}
|
|
|
|
if (optind < argc)
|
|
{
|
|
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);
|
|
}
|
|
|
|
setup_cancel_handler();
|
|
|
|
if (alldb)
|
|
{
|
|
if (dbname)
|
|
{
|
|
fprintf(stderr, _("%s: cannot cluster all databases and a specific one at the same time\n"),
|
|
progname);
|
|
exit(1);
|
|
}
|
|
if (table)
|
|
{
|
|
fprintf(stderr, _("%s: cannot cluster a specific table in all databases\n"),
|
|
progname);
|
|
exit(1);
|
|
}
|
|
|
|
cluster_all_databases(verbose, host, port, username, prompt_password,
|
|
progname, echo, quiet);
|
|
}
|
|
else
|
|
{
|
|
if (dbname == NULL)
|
|
{
|
|
if (getenv("PGDATABASE"))
|
|
dbname = getenv("PGDATABASE");
|
|
else if (getenv("PGUSER"))
|
|
dbname = getenv("PGUSER");
|
|
else
|
|
dbname = get_user_name(progname);
|
|
}
|
|
|
|
cluster_one_database(dbname, verbose, table,
|
|
host, port, username, prompt_password,
|
|
progname, echo);
|
|
}
|
|
|
|
exit(0);
|
|
}
|
|
|
|
|
|
static void
|
|
cluster_one_database(const char *dbname, bool verbose, const char *table,
|
|
const char *host, const char *port,
|
|
const char *username, enum trivalue prompt_password,
|
|
const char *progname, bool echo)
|
|
{
|
|
PQExpBufferData sql;
|
|
|
|
PGconn *conn;
|
|
|
|
initPQExpBuffer(&sql);
|
|
|
|
appendPQExpBuffer(&sql, "CLUSTER");
|
|
if (verbose)
|
|
appendPQExpBuffer(&sql, " VERBOSE");
|
|
if (table)
|
|
appendPQExpBuffer(&sql, " %s", fmtId(table));
|
|
appendPQExpBuffer(&sql, ";\n");
|
|
|
|
conn = connectDatabase(dbname, host, port, username, prompt_password, progname);
|
|
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));
|
|
else
|
|
fprintf(stderr, _("%s: clustering of database \"%s\" failed: %s"),
|
|
progname, dbname, PQerrorMessage(conn));
|
|
PQfinish(conn);
|
|
exit(1);
|
|
}
|
|
PQfinish(conn);
|
|
termPQExpBuffer(&sql);
|
|
}
|
|
|
|
|
|
static void
|
|
cluster_all_databases(bool verbose, const char *host, const char *port,
|
|
const char *username, enum trivalue prompt_password,
|
|
const char *progname, bool echo, bool quiet)
|
|
{
|
|
PGconn *conn;
|
|
PGresult *result;
|
|
int i;
|
|
|
|
conn = connectDatabase("postgres", host, port, username, prompt_password, progname);
|
|
result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
|
|
PQfinish(conn);
|
|
|
|
for (i = 0; i < PQntuples(result); i++)
|
|
{
|
|
char *dbname = PQgetvalue(result, i, 0);
|
|
|
|
if (!quiet)
|
|
{
|
|
printf(_("%s: clustering database \"%s\"\n"), progname, dbname);
|
|
fflush(stdout);
|
|
}
|
|
|
|
cluster_one_database(dbname, verbose, NULL,
|
|
host, port, username, prompt_password,
|
|
progname, echo);
|
|
}
|
|
|
|
PQclear(result);
|
|
}
|
|
|
|
|
|
static void
|
|
help(const char *progname)
|
|
{
|
|
printf(_("%s clusters all previously clustered tables in a database.\n\n"), progname);
|
|
printf(_("Usage:\n"));
|
|
printf(_(" %s [OPTION]... [DBNAME]\n"), progname);
|
|
printf(_("\nOptions:\n"));
|
|
printf(_(" -a, --all cluster all databases\n"));
|
|
printf(_(" -d, --dbname=DBNAME database to cluster\n"));
|
|
printf(_(" -e, --echo show the commands being sent to the server\n"));
|
|
printf(_(" -q, --quiet don't write any messages\n"));
|
|
printf(_(" -t, --table=TABLE cluster specific table only\n"));
|
|
printf(_(" -v, --verbose write a lot of output\n"));
|
|
printf(_(" --help show this help, then exit\n"));
|
|
printf(_(" --version output version information, 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, --no-password never prompt for password\n"));
|
|
printf(_(" -W, --password force password prompt\n"));
|
|
printf(_("\nRead the description of the SQL command CLUSTER for details.\n"));
|
|
printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
|
|
}
|