1 /*-------------------------------------------------------------------------
2 *
3 * droplang
4 *
5 * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
7 *
8 * src/bin/scripts/droplang.c
9 *
10 *-------------------------------------------------------------------------
11 */
12 #include "postgres_fe.h"
13
14 #include "common.h"
15 #include "fe_utils/print.h"
16
17 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
18
19
20 static void help(const char *progname);
21
22
23 int
main(int argc,char * argv[])24 main(int argc, char *argv[])
25 {
26 static struct option long_options[] = {
27 {"list", no_argument, NULL, 'l'},
28 {"host", required_argument, NULL, 'h'},
29 {"port", required_argument, NULL, 'p'},
30 {"username", required_argument, NULL, 'U'},
31 {"no-password", no_argument, NULL, 'w'},
32 {"password", no_argument, NULL, 'W'},
33 {"dbname", required_argument, NULL, 'd'},
34 {"echo", no_argument, NULL, 'e'},
35 {NULL, 0, NULL, 0}
36 };
37
38 const char *progname;
39 int optindex;
40 int c;
41 bool listlangs = false;
42 const char *dbname = NULL;
43 char *host = NULL;
44 char *port = NULL;
45 char *username = NULL;
46 enum trivalue prompt_password = TRI_DEFAULT;
47 ConnParams cparams;
48 bool echo = false;
49 char *langname = NULL;
50 char *p;
51 PQExpBufferData sql;
52 PGconn *conn;
53 PGresult *result;
54
55 progname = get_progname(argv[0]);
56 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
57
58 handle_help_version_opts(argc, argv, "droplang", help);
59
60 while ((c = getopt_long(argc, argv, "lh:p:U:wWd:e", long_options, &optindex)) != -1)
61 {
62 switch (c)
63 {
64 case 'l':
65 listlangs = true;
66 break;
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 'd':
83 dbname = pg_strdup(optarg);
84 break;
85 case 'e':
86 echo = true;
87 break;
88 default:
89 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
90 exit(1);
91 }
92 }
93
94 /*
95 * We set dbname from positional arguments if it is not already set by
96 * option arguments -d. If not doing listlangs, positional dbname must
97 * follow positional langname.
98 */
99
100 if (argc - optind > 0)
101 {
102 if (listlangs)
103 {
104 if (dbname == NULL)
105 dbname = argv[optind++];
106 }
107 else
108 {
109 langname = argv[optind++];
110 if (argc - optind > 0 && dbname == NULL)
111 dbname = argv[optind++];
112 }
113 }
114
115 if (argc - optind > 0)
116 {
117 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
118 progname, argv[optind]);
119 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
120 exit(1);
121 }
122
123 if (dbname == NULL)
124 {
125 if (getenv("PGDATABASE"))
126 dbname = getenv("PGDATABASE");
127 else if (getenv("PGUSER"))
128 dbname = getenv("PGUSER");
129 else
130 dbname = get_user_name_or_exit(progname);
131 }
132
133 cparams.dbname = dbname;
134 cparams.pghost = host;
135 cparams.pgport = port;
136 cparams.pguser = username;
137 cparams.prompt_password = prompt_password;
138 cparams.override_dbname = NULL;
139
140 initPQExpBuffer(&sql);
141
142 /*
143 * List option
144 */
145 if (listlangs)
146 {
147 printQueryOpt popt;
148 static const bool translate_columns[] = {false, true};
149
150 conn = connectDatabase(&cparams,
151 progname, echo, false, false);
152
153 printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
154 "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
155 "FROM pg_catalog.pg_language WHERE lanispl;",
156 gettext_noop("Name"),
157 gettext_noop("yes"), gettext_noop("no"),
158 gettext_noop("Trusted?"));
159 result = executeQuery(conn, sql.data, progname, echo);
160
161 memset(&popt, 0, sizeof(popt));
162 popt.topt.format = PRINT_ALIGNED;
163 popt.topt.border = 1;
164 popt.topt.start_table = true;
165 popt.topt.stop_table = true;
166 popt.topt.encoding = PQclientEncoding(conn);
167 popt.title = _("Procedural Languages");
168 popt.translate_header = true;
169 popt.translate_columns = translate_columns;
170 popt.n_translate_columns = lengthof(translate_columns);
171
172 printQuery(result, &popt, stdout, false, NULL);
173
174 PQfinish(conn);
175 exit(0);
176 }
177
178 if (langname == NULL)
179 {
180 fprintf(stderr, _("%s: missing required argument language name\n"),
181 progname);
182 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
183 progname);
184 exit(1);
185 }
186
187 /* lower case language name */
188 for (p = langname; *p; p++)
189 if (*p >= 'A' && *p <= 'Z')
190 *p += ('a' - 'A');
191
192 conn = connectDatabase(&cparams,
193 progname, echo, false, false);
194
195 /*
196 * Make sure the language is installed
197 */
198 printfPQExpBuffer(&sql, "SELECT oid "
199 "FROM pg_language WHERE lanname = '%s' AND lanispl;",
200 langname);
201 result = executeQuery(conn, sql.data, progname, echo);
202 if (PQntuples(result) == 0)
203 {
204 fprintf(stderr, _("%s: language \"%s\" is not installed in "
205 "database \"%s\"\n"),
206 progname, langname, PQdb(conn));
207 PQfinish(conn);
208 exit(1);
209 }
210 PQclear(result);
211
212 /*
213 * Attempt to drop the language. We do not use CASCADE, so that the drop
214 * will fail if there are any functions in the language.
215 */
216 printfPQExpBuffer(&sql, "DROP EXTENSION \"%s\";", langname);
217
218 if (echo)
219 printf("%s\n", sql.data);
220 result = PQexec(conn, sql.data);
221 if (PQresultStatus(result) != PGRES_COMMAND_OK)
222 {
223 fprintf(stderr, _("%s: language removal failed: %s"),
224 progname, PQerrorMessage(conn));
225 PQfinish(conn);
226 exit(1);
227 }
228
229 PQclear(result);
230 PQfinish(conn);
231 exit(0);
232 }
233
234
235 static void
help(const char * progname)236 help(const char *progname)
237 {
238 printf(_("%s removes a procedural language from a database.\n\n"), progname);
239 printf(_("Usage:\n"));
240 printf(_(" %s [OPTION]... LANGNAME [DBNAME]\n"), progname);
241 printf(_("\nOptions:\n"));
242 printf(_(" -d, --dbname=DBNAME database from which to remove the language\n"));
243 printf(_(" -e, --echo show the commands being sent to the server\n"));
244 printf(_(" -l, --list show a list of currently installed languages\n"));
245 printf(_(" -V, --version output version information, then exit\n"));
246 printf(_(" -?, --help show this help, then exit\n"));
247 printf(_("\nConnection options:\n"));
248 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
249 printf(_(" -p, --port=PORT database server port\n"));
250 printf(_(" -U, --username=USERNAME user name to connect as\n"));
251 printf(_(" -w, --no-password never prompt for password\n"));
252 printf(_(" -W, --password force password prompt\n"));
253 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
254 }
255