1 /*-------------------------------------------------------------------------
2  *
3  * dropdb
4  *
5  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  * src/bin/scripts/dropdb.c
9  *
10  *-------------------------------------------------------------------------
11  */
12 
13 #include "postgres_fe.h"
14 #include "common.h"
15 #include "fe_utils/string_utils.h"
16 
17 
18 static void help(const char *progname);
19 
20 
21 int
main(int argc,char * argv[])22 main(int argc, char *argv[])
23 {
24 	static int	if_exists = 0;
25 
26 	static struct option long_options[] = {
27 		{"host", required_argument, NULL, 'h'},
28 		{"port", required_argument, NULL, 'p'},
29 		{"username", required_argument, NULL, 'U'},
30 		{"no-password", no_argument, NULL, 'w'},
31 		{"password", no_argument, NULL, 'W'},
32 		{"echo", no_argument, NULL, 'e'},
33 		{"interactive", no_argument, NULL, 'i'},
34 		{"if-exists", no_argument, &if_exists, 1},
35 		{"maintenance-db", required_argument, NULL, 2},
36 		{NULL, 0, NULL, 0}
37 	};
38 
39 	const char *progname;
40 	int			optindex;
41 	int			c;
42 
43 	char	   *dbname = NULL;
44 	char	   *maintenance_db = NULL;
45 	char	   *host = NULL;
46 	char	   *port = NULL;
47 	char	   *username = NULL;
48 	enum trivalue prompt_password = TRI_DEFAULT;
49 	ConnParams	cparams;
50 	bool		echo = false;
51 	bool		interactive = false;
52 
53 	PQExpBufferData sql;
54 
55 	PGconn	   *conn;
56 	PGresult   *result;
57 
58 	progname = get_progname(argv[0]);
59 	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
60 
61 	handle_help_version_opts(argc, argv, "dropdb", help);
62 
63 	while ((c = getopt_long(argc, argv, "h:p:U:wWei", long_options, &optindex)) != -1)
64 	{
65 		switch (c)
66 		{
67 			case 'h':
68 				host = pg_strdup(optarg);
69 				break;
70 			case 'p':
71 				port = pg_strdup(optarg);
72 				break;
73 			case 'U':
74 				username = pg_strdup(optarg);
75 				break;
76 			case 'w':
77 				prompt_password = TRI_NO;
78 				break;
79 			case 'W':
80 				prompt_password = TRI_YES;
81 				break;
82 			case 'e':
83 				echo = true;
84 				break;
85 			case 'i':
86 				interactive = true;
87 				break;
88 			case 0:
89 				/* this covers the long options */
90 				break;
91 			case 2:
92 				maintenance_db = pg_strdup(optarg);
93 				break;
94 			default:
95 				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
96 				exit(1);
97 		}
98 	}
99 
100 	switch (argc - optind)
101 	{
102 		case 0:
103 			fprintf(stderr, _("%s: missing required argument database name\n"), progname);
104 			fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
105 			exit(1);
106 		case 1:
107 			dbname = argv[optind];
108 			break;
109 		default:
110 			fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
111 					progname, argv[optind + 1]);
112 			fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
113 			exit(1);
114 	}
115 
116 	if (interactive)
117 	{
118 		printf(_("Database \"%s\" will be permanently removed.\n"), dbname);
119 		if (!yesno_prompt("Are you sure?"))
120 			exit(0);
121 	}
122 
123 	initPQExpBuffer(&sql);
124 
125 	appendPQExpBuffer(&sql, "DROP DATABASE %s%s;",
126 					  (if_exists ? "IF EXISTS " : ""), fmtId(dbname));
127 
128 	/* Avoid trying to drop postgres db while we are connected to it. */
129 	if (maintenance_db == NULL && strcmp(dbname, "postgres") == 0)
130 		maintenance_db = "template1";
131 
132 	cparams.dbname = maintenance_db;
133 	cparams.pghost = host;
134 	cparams.pgport = port;
135 	cparams.pguser = username;
136 	cparams.prompt_password = prompt_password;
137 	cparams.override_dbname = NULL;
138 
139 	conn = connectMaintenanceDatabase(&cparams, progname, echo);
140 
141 	if (echo)
142 		printf("%s\n", sql.data);
143 	result = PQexec(conn, sql.data);
144 	if (PQresultStatus(result) != PGRES_COMMAND_OK)
145 	{
146 		fprintf(stderr, _("%s: database removal failed: %s"),
147 				progname, PQerrorMessage(conn));
148 		PQfinish(conn);
149 		exit(1);
150 	}
151 
152 	PQclear(result);
153 	PQfinish(conn);
154 	exit(0);
155 }
156 
157 
158 static void
help(const char * progname)159 help(const char *progname)
160 {
161 	printf(_("%s removes a PostgreSQL database.\n\n"), progname);
162 	printf(_("Usage:\n"));
163 	printf(_("  %s [OPTION]... DBNAME\n"), progname);
164 	printf(_("\nOptions:\n"));
165 	printf(_("  -e, --echo                show the commands being sent to the server\n"));
166 	printf(_("  -i, --interactive         prompt before deleting anything\n"));
167 	printf(_("  -V, --version             output version information, then exit\n"));
168 	printf(_("  --if-exists               don't report error if database doesn't exist\n"));
169 	printf(_("  -?, --help                show this help, then exit\n"));
170 	printf(_("\nConnection options:\n"));
171 	printf(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));
172 	printf(_("  -p, --port=PORT           database server port\n"));
173 	printf(_("  -U, --username=USERNAME   user name to connect as\n"));
174 	printf(_("  -w, --no-password         never prompt for password\n"));
175 	printf(_("  -W, --password            force password prompt\n"));
176 	printf(_("  --maintenance-db=DBNAME   alternate maintenance database\n"));
177 	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
178 }
179