1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
8 * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.22 2007/01/05 22:19:50 momjian Exp $
10 *-------------------------------------------------------------------------
13 #include "postgres_fe.h"
17 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
20 static void help(const char *progname);
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'},
41 bool listlangs = false;
42 const char *dbname = NULL;
45 char *username = NULL;
46 bool password = false;
48 char *langname = NULL;
65 progname = get_progname(argv[0]);
66 set_pglocale_pgservice(argv[0], "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)
96 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
101 if (argc - optind > 0)
104 dbname = argv[optind++];
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);
123 if (getenv("PGDATABASE"))
124 dbname = getenv("PGDATABASE");
125 else if (getenv("PGUSER"))
126 dbname = getenv("PGUSER");
128 dbname = get_user_name(progname);
131 initPQExpBuffer(&sql);
140 conn = connectDatabase(dbname, host, port, username, password,
143 printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
144 "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
145 "FROM pg_catalog.pg_language WHERE lanispl;",
146 _("Name"), _("yes"), _("no"), _("Trusted?"));
147 result = executeQuery(conn, sql.data, progname, echo);
149 memset(&popt, 0, sizeof(popt));
150 popt.topt.format = PRINT_ALIGNED;
151 popt.topt.border = 1;
152 popt.topt.encoding = PQclientEncoding(conn);
153 popt.title = _("Procedural Languages");
154 printQuery(result, &popt, stdout, NULL);
160 if (langname == NULL)
162 fprintf(stderr, _("%s: missing required argument language name\n"),
164 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
169 for (p = langname; *p; p++)
170 if (*p >= 'A' && *p <= 'Z')
173 conn = connectDatabase(dbname, host, port, username, password, progname);
176 * Force schema search path to be just pg_catalog, so that we don't have
177 * to be paranoid about search paths below.
179 executeCommand(conn, "SET search_path = pg_catalog;", progname, echo);
182 * Make sure the language is installed and find the OIDs of the handler
183 * and validator functions
185 printfPQExpBuffer(&sql, "SELECT lanplcallfoid, lanvalidator "
186 "FROM pg_language WHERE lanname = '%s' AND lanispl;",
188 result = executeQuery(conn, sql.data, progname, echo);
189 if (PQntuples(result) == 0)
192 fprintf(stderr, _("%s: language \"%s\" is not installed in "
193 "database \"%s\"\n"),
194 progname, langname, dbname);
197 lanplcallfoid = atooid(PQgetvalue(result, 0, 0));
198 lanvalidator = atooid(PQgetvalue(result, 0, 1));
202 * Check that there are no functions left defined in that language
204 printfPQExpBuffer(&sql, "SELECT count(proname) FROM pg_proc P, "
205 "pg_language L WHERE P.prolang = L.oid "
206 "AND L.lanname = '%s';", langname);
207 result = executeQuery(conn, sql.data, progname, echo);
208 if (strcmp(PQgetvalue(result, 0, 0), "0") != 0)
212 _("%s: still %s functions declared in language \"%s\"; "
213 "language not removed\n"),
214 progname, PQgetvalue(result, 0, 0), langname);
220 * Check that the handler function isn't used by some other language
222 printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language "
223 "WHERE lanplcallfoid = %u AND lanname <> '%s';",
224 lanplcallfoid, langname);
225 result = executeQuery(conn, sql.data, progname, echo);
226 if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)
233 * Find the handler name
237 printfPQExpBuffer(&sql, "SELECT proname, (SELECT nspname "
238 "FROM pg_namespace ns WHERE ns.oid = pronamespace) "
239 "AS prons FROM pg_proc WHERE oid = %u;",
241 result = executeQuery(conn, sql.data, progname, echo);
242 handler = strdup(PQgetvalue(result, 0, 0));
243 handler_ns = strdup(PQgetvalue(result, 0, 1));
253 * Check that the validator function isn't used by some other language
255 if (OidIsValid(lanvalidator))
257 printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language "
258 "WHERE lanvalidator = %u AND lanname <> '%s';",
259 lanvalidator, langname);
260 result = executeQuery(conn, sql.data, progname, echo);
261 if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)
262 keepvalidator = false;
264 keepvalidator = true;
268 keepvalidator = true; /* don't try to delete it */
271 * Find the validator name
275 printfPQExpBuffer(&sql, "SELECT proname, (SELECT nspname "
276 "FROM pg_namespace ns WHERE ns.oid = pronamespace) "
277 "AS prons FROM pg_proc WHERE oid = %u;",
279 result = executeQuery(conn, sql.data, progname, echo);
280 validator = strdup(PQgetvalue(result, 0, 0));
281 validator_ns = strdup(PQgetvalue(result, 0, 1));
291 * Drop the language and the functions
293 printfPQExpBuffer(&sql, "DROP LANGUAGE \"%s\";\n", langname);
295 appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" ();\n",
296 handler_ns, handler);
298 appendPQExpBuffer(&sql, "DROP FUNCTION \"%s\".\"%s\" (oid);\n",
299 validator_ns, validator);
301 printf("%s", sql.data);
302 result = PQexec(conn, sql.data);
303 if (PQresultStatus(result) != PGRES_COMMAND_OK)
305 fprintf(stderr, _("%s: language removal failed: %s"),
306 progname, PQerrorMessage(conn));
318 help(const char *progname)
320 printf(_("%s removes a procedural language from a database.\n\n"), progname);
321 printf(_("Usage:\n"));
322 printf(_(" %s [OPTION]... LANGNAME [DBNAME]\n"), progname);
323 printf(_("\nOptions:\n"));
324 printf(_(" -d, --dbname=DBNAME database from which to remove the language\n"));
325 printf(_(" -e, --echo show the commands being sent to the server\n"));
326 printf(_(" -l, --list show a list of currently installed languages\n"));
327 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
328 printf(_(" -p, --port=PORT database server port\n"));
329 printf(_(" -U, --username=USERNAME user name to connect as\n"));
330 printf(_(" -W, --password prompt for password\n"));
331 printf(_(" --help show this help, then exit\n"));
332 printf(_(" --version output version information, then exit\n"));
333 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));