]> granicus.if.org Git - postgresql/blob - src/bin/scripts/clusterdb.c
In our source code, make a copy of getopt's 'optarg' string arguments,
[postgresql] / src / bin / scripts / clusterdb.c
1 /*-------------------------------------------------------------------------
2  *
3  * clusterdb
4  *
5  * Portions Copyright (c) 2002-2012, PostgreSQL Global Development Group
6  *
7  * src/bin/scripts/clusterdb.c
8  *
9  *-------------------------------------------------------------------------
10  */
11
12 #include "postgres_fe.h"
13 #include "common.h"
14 #include "dumputils.h"
15
16
17 static void cluster_one_database(const char *dbname, bool verbose, const char *table,
18                                          const char *host, const char *port,
19                                          const char *username, enum trivalue prompt_password,
20                                          const char *progname, bool echo);
21 static void cluster_all_databases(bool verbose, const char *maintenance_db,
22                                           const char *host, const char *port,
23                                           const char *username, enum trivalue prompt_password,
24                                           const char *progname, bool echo, bool quiet);
25
26 static void help(const char *progname);
27
28
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                 {"table", required_argument, NULL, 't'},
43                 {"verbose", no_argument, NULL, 'v'},
44                 {"maintenance-db", required_argument, NULL, 2},
45                 {NULL, 0, NULL, 0}
46         };
47
48         const char *progname;
49         int                     optindex;
50         int                     c;
51
52         const char *dbname = NULL;
53         const char *maintenance_db = NULL;
54         char       *host = NULL;
55         char       *port = NULL;
56         char       *username = NULL;
57         enum trivalue prompt_password = TRI_DEFAULT;
58         bool            echo = false;
59         bool            quiet = false;
60         bool            alldb = false;
61         char       *table = NULL;
62         bool            verbose = false;
63
64         progname = get_progname(argv[0]);
65         set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
66
67         handle_help_version_opts(argc, argv, "clusterdb", help);
68
69         while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:at:v", long_options, &optindex)) != -1)
70         {
71                 switch (c)
72                 {
73                         case 'h':
74                                 host = pg_strdup(optarg);
75                                 break;
76                         case 'p':
77                                 port = pg_strdup(optarg);
78                                 break;
79                         case 'U':
80                                 username = pg_strdup(optarg);
81                                 break;
82                         case 'w':
83                                 prompt_password = TRI_NO;
84                                 break;
85                         case 'W':
86                                 prompt_password = TRI_YES;
87                                 break;
88                         case 'e':
89                                 echo = true;
90                                 break;
91                         case 'q':
92                                 quiet = true;
93                                 break;
94                         case 'd':
95                                 dbname = pg_strdup(optarg);
96                                 break;
97                         case 'a':
98                                 alldb = true;
99                                 break;
100                         case 't':
101                                 table = pg_strdup(optarg);
102                                 break;
103                         case 'v':
104                                 verbose = true;
105                                 break;
106                         case 2:
107                                 maintenance_db = pg_strdup(optarg);
108                                 break;
109                         default:
110                                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
111                                 exit(1);
112                 }
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
125         if (optind < argc)
126         {
127                 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
128                                 progname, argv[optind]);
129                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
130                 exit(1);
131         }
132
133         setup_cancel_handler();
134
135         if (alldb)
136         {
137                 if (dbname)
138                 {
139                         fprintf(stderr, _("%s: cannot cluster all databases and a specific one at the same time\n"),
140                                         progname);
141                         exit(1);
142                 }
143                 if (table)
144                 {
145                         fprintf(stderr, _("%s: cannot cluster a specific table in all databases\n"),
146                                         progname);
147                         exit(1);
148                 }
149
150                 cluster_all_databases(verbose, maintenance_db, host, port, username, prompt_password,
151                                                           progname, echo, quiet);
152         }
153         else
154         {
155                 if (dbname == NULL)
156                 {
157                         if (getenv("PGDATABASE"))
158                                 dbname = getenv("PGDATABASE");
159                         else if (getenv("PGUSER"))
160                                 dbname = getenv("PGUSER");
161                         else
162                                 dbname = get_user_name(progname);
163                 }
164
165                 cluster_one_database(dbname, verbose, table,
166                                                          host, port, username, prompt_password,
167                                                          progname, echo);
168         }
169
170         exit(0);
171 }
172
173
174 static void
175 cluster_one_database(const char *dbname, bool verbose, const char *table,
176                                          const char *host, const char *port,
177                                          const char *username, enum trivalue prompt_password,
178                                          const char *progname, bool echo)
179 {
180         PQExpBufferData sql;
181
182         PGconn     *conn;
183
184         initPQExpBuffer(&sql);
185
186         appendPQExpBuffer(&sql, "CLUSTER");
187         if (verbose)
188                 appendPQExpBuffer(&sql, " VERBOSE");
189         if (table)
190                 appendPQExpBuffer(&sql, " %s", table);
191         appendPQExpBuffer(&sql, ";\n");
192
193         conn = connectDatabase(dbname, host, port, username, prompt_password,
194                                                    progname, false);
195         if (!executeMaintenanceCommand(conn, sql.data, echo))
196         {
197                 if (table)
198                         fprintf(stderr, _("%s: clustering of table \"%s\" in database \"%s\" failed: %s"),
199                                         progname, table, dbname, PQerrorMessage(conn));
200                 else
201                         fprintf(stderr, _("%s: clustering of database \"%s\" failed: %s"),
202                                         progname, dbname, PQerrorMessage(conn));
203                 PQfinish(conn);
204                 exit(1);
205         }
206         PQfinish(conn);
207         termPQExpBuffer(&sql);
208 }
209
210
211 static void
212 cluster_all_databases(bool verbose, const char *maintenance_db,
213                                           const char *host, const char *port,
214                                           const char *username, enum trivalue prompt_password,
215                                           const char *progname, bool echo, bool quiet)
216 {
217         PGconn     *conn;
218         PGresult   *result;
219         int                     i;
220
221         conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
222                                                                           prompt_password, progname);
223         result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
224         PQfinish(conn);
225
226         for (i = 0; i < PQntuples(result); i++)
227         {
228                 char       *dbname = PQgetvalue(result, i, 0);
229
230                 if (!quiet)
231                 {
232                         printf(_("%s: clustering database \"%s\"\n"), progname, dbname);
233                         fflush(stdout);
234                 }
235
236                 cluster_one_database(dbname, verbose, NULL,
237                                                          host, port, username, prompt_password,
238                                                          progname, echo);
239         }
240
241         PQclear(result);
242 }
243
244
245 static void
246 help(const char *progname)
247 {
248         printf(_("%s clusters all previously clustered tables in a database.\n\n"), progname);
249         printf(_("Usage:\n"));
250         printf(_("  %s [OPTION]... [DBNAME]\n"), progname);
251         printf(_("\nOptions:\n"));
252         printf(_("  -a, --all                 cluster all databases\n"));
253         printf(_("  -d, --dbname=DBNAME       database to cluster\n"));
254         printf(_("  -e, --echo                show the commands being sent to the server\n"));
255         printf(_("  -q, --quiet               don't write any messages\n"));
256         printf(_("  -t, --table=TABLE         cluster specific table only\n"));
257         printf(_("  -v, --verbose             write a lot of output\n"));
258         printf(_("  -V, --version             output version information, then exit\n"));
259         printf(_("  -?, --help                show this help, then exit\n"));
260         printf(_("\nConnection options:\n"));
261         printf(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));
262         printf(_("  -p, --port=PORT           database server port\n"));
263         printf(_("  -U, --username=USERNAME   user name to connect as\n"));
264         printf(_("  -w, --no-password         never prompt for password\n"));
265         printf(_("  -W, --password            force password prompt\n"));
266         printf(_("  --maintenance-db=DBNAME   alternate maintenance database\n"));
267         printf(_("\nRead the description of the SQL command CLUSTER for details.\n"));
268         printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
269 }