Sort the output of --help mostly alphabetical, make it align better, make
[PostgreSQL.git] / src / bin / scripts / droplang.c
blob6d24b5e85cb19579dc9e183599569fa1259e03eb
1 /*-------------------------------------------------------------------------
3 * droplang
5 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
8 * $PostgreSQL$
10 *-------------------------------------------------------------------------
13 #include "postgres_fe.h"
14 #include "common.h"
15 #include "print.h"
17 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
20 static void help(const char *progname);
23 int
24 main(int argc, char *argv[])
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 {"password", no_argument, NULL, 'W'},
32 {"dbname", required_argument, NULL, 'd'},
33 {"echo", no_argument, NULL, 'e'},
34 {NULL, 0, NULL, 0}
37 const char *progname;
38 int optindex;
39 int c;
41 bool listlangs = false;
42 const char *dbname = NULL;
43 char *host = NULL;
44 char *port = NULL;
45 char *username = NULL;
46 bool password = false;
47 bool echo = false;
48 char *langname = NULL;
50 char *p;
51 Oid lanplcallfoid;
52 Oid lanvalidator;
53 char *handler;
54 char *validator;
55 char *handler_ns;
56 char *validator_ns;
57 bool keephandler;
58 bool keepvalidator;
60 PQExpBufferData sql;
62 PGconn *conn;
63 PGresult *result;
65 progname = get_progname(argv[0]);
66 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
68 handle_help_version_opts(argc, argv, "droplang", help);
70 while ((c = getopt_long(argc, argv, "lh:p:U:Wd:e", long_options, &optindex)) != -1)
72 switch (c)
74 case 'l':
75 listlangs = true;
76 break;
77 case 'h':
78 host = optarg;
79 break;
80 case 'p':
81 port = optarg;
82 break;
83 case 'U':
84 username = optarg;
85 break;
86 case 'W':
87 password = true;
88 break;
89 case 'd':
90 dbname = optarg;
91 break;
92 case 'e':
93 echo = true;
94 break;
95 default:
96 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
97 exit(1);
101 if (argc - optind > 0)
103 if (listlangs)
104 dbname = argv[optind++];
105 else
107 langname = argv[optind++];
108 if (argc - optind > 0)
109 dbname = argv[optind++];
113 if (argc - optind > 0)
115 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
116 progname, argv[optind]);
117 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
118 exit(1);
121 if (dbname == NULL)
123 if (getenv("PGDATABASE"))
124 dbname = getenv("PGDATABASE");
125 else if (getenv("PGUSER"))
126 dbname = getenv("PGUSER");
127 else
128 dbname = get_user_name(progname);
131 initPQExpBuffer(&sql);
134 * List option
136 if (listlangs)
138 printQueryOpt popt;
139 static const bool translate_columns[] = {false, true};
141 conn = connectDatabase(dbname, host, port, username, password,
142 progname);
144 printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
145 "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
146 "FROM pg_catalog.pg_language WHERE lanispl;",
147 gettext_noop("Name"),
148 gettext_noop("yes"), gettext_noop("no"),
149 gettext_noop("Trusted?"));
150 result = executeQuery(conn, sql.data, progname, echo);
152 memset(&popt, 0, sizeof(popt));
153 popt.topt.format = PRINT_ALIGNED;
154 popt.topt.border = 1;
155 popt.topt.start_table = true;
156 popt.topt.stop_table = true;
157 popt.topt.encoding = PQclientEncoding(conn);
158 popt.title = _("Procedural Languages");
159 popt.translate_header = true;
160 popt.translate_columns = translate_columns;
161 printQuery(result, &popt, stdout, NULL);
163 PQfinish(conn);
164 exit(0);
167 if (langname == NULL)
169 fprintf(stderr, _("%s: missing required argument language name\n"),
170 progname);
171 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
172 progname);
173 exit(1);
176 for (p = langname; *p; p++)
177 if (*p >= 'A' && *p <= 'Z')
178 *p += ('a' - 'A');
180 conn = connectDatabase(dbname, host, port, username, password, progname);
183 * Force schema search path to be just pg_catalog, so that we don't have
184 * to be paranoid about search paths below.
186 executeCommand(conn, "SET search_path = pg_catalog;", progname, echo);
189 * Make sure the language is installed and find the OIDs of the handler
190 * and validator functions
192 printfPQExpBuffer(&sql, "SELECT lanplcallfoid, lanvalidator "
193 "FROM pg_language WHERE lanname = '%s' AND lanispl;",
194 langname);
195 result = executeQuery(conn, sql.data, progname, echo);
196 if (PQntuples(result) == 0)
198 PQfinish(conn);
199 fprintf(stderr, _("%s: language \"%s\" is not installed in "
200 "database \"%s\"\n"),
201 progname, langname, dbname);
202 exit(1);
204 lanplcallfoid = atooid(PQgetvalue(result, 0, 0));
205 lanvalidator = atooid(PQgetvalue(result, 0, 1));
206 PQclear(result);
209 * Check that there are no functions left defined in that language
211 printfPQExpBuffer(&sql, "SELECT count(proname) FROM pg_proc P, "
212 "pg_language L WHERE P.prolang = L.oid "
213 "AND L.lanname = '%s';", langname);
214 result = executeQuery(conn, sql.data, progname, echo);
215 if (strcmp(PQgetvalue(result, 0, 0), "0") != 0)
217 PQfinish(conn);
218 fprintf(stderr,
219 _("%s: still %s functions declared in language \"%s\"; "
220 "language not removed\n"),
221 progname, PQgetvalue(result, 0, 0), langname);
222 exit(1);
224 PQclear(result);
227 * Check that the handler function isn't used by some other language
229 printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language "
230 "WHERE lanplcallfoid = %u AND lanname <> '%s';",
231 lanplcallfoid, langname);
232 result = executeQuery(conn, sql.data, progname, echo);
233 if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)
234 keephandler = false;
235 else
236 keephandler = true;
237 PQclear(result);
240 * Find the handler name
242 if (!keephandler)
244 printfPQExpBuffer(&sql, "SELECT proname, (SELECT nspname "
245 "FROM pg_namespace ns WHERE ns.oid = pronamespace) "
246 "AS prons FROM pg_proc WHERE oid = %u;",
247 lanplcallfoid);
248 result = executeQuery(conn, sql.data, progname, echo);
249 handler = strdup(PQgetvalue(result, 0, 0));
250 handler_ns = strdup(PQgetvalue(result, 0, 1));
251 PQclear(result);
253 else
255 handler = NULL;
256 handler_ns = NULL;
260 * Check that the validator function isn't used by some other language
262 if (OidIsValid(lanvalidator))
264 printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language "
265 "WHERE lanvalidator = %u AND lanname <> '%s';",
266 lanvalidator, langname);
267 result = executeQuery(conn, sql.data, progname, echo);
268 if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)
269 keepvalidator = false;
270 else
271 keepvalidator = true;
272 PQclear(result);
274 else
275 keepvalidator = true; /* don't try to delete it */
278 * Find the validator name
280 if (!keepvalidator)
282 printfPQExpBuffer(&sql, "SELECT proname, (SELECT nspname "
283 "FROM pg_namespace ns WHERE ns.oid = pronamespace) "
284 "AS prons FROM pg_proc WHERE oid = %u;",
285 lanvalidator);
286 result = executeQuery(conn, sql.data, progname, echo);
287 validator = strdup(PQgetvalue(result, 0, 0));
288 validator_ns = strdup(PQgetvalue(result, 0, 1));
289 PQclear(result);
291 else
293 validator = NULL;
294 validator_ns = NULL;
298 * Drop the language and the functions
300 printfPQExpBuffer(&sql, "DROP LANGUAGE \"%s\";\n", langname);
301 if (!keephandler)
302 appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" ();\n",
303 handler_ns, handler);
304 if (!keepvalidator)
305 appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" (oid);\n",
306 validator_ns, validator);
307 if (echo)
308 printf("%s", sql.data);
309 result = PQexec(conn, sql.data);
310 if (PQresultStatus(result) != PGRES_COMMAND_OK)
312 fprintf(stderr, _("%s: language removal failed: %s"),
313 progname, PQerrorMessage(conn));
314 PQfinish(conn);
315 exit(1);
318 PQclear(result);
319 PQfinish(conn);
320 exit(0);
324 static void
325 help(const char *progname)
327 printf(_("%s removes a procedural language from a database.\n\n"), progname);
328 printf(_("Usage:\n"));
329 printf(_(" %s [OPTION]... LANGNAME [DBNAME]\n"), progname);
330 printf(_("\nOptions:\n"));
331 printf(_(" -d, --dbname=DBNAME database from which to remove the language\n"));
332 printf(_(" -e, --echo show the commands being sent to the server\n"));
333 printf(_(" -l, --list show a list of currently installed languages\n"));
334 printf(_(" --help show this help, then exit\n"));
335 printf(_(" --version output version information, then exit\n"));
336 printf(_("\nConnection options:\n"));
337 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
338 printf(_(" -p, --port=PORT database server port\n"));
339 printf(_(" -U, --username=USERNAME user name to connect as\n"));
340 printf(_(" -W, --password force password prompt\n"));
341 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));