1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
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 {"no-password", no_argument
, NULL
, 'w'},
32 {"password", no_argument
, NULL
, 'W'},
33 {"dbname", required_argument
, NULL
, 'd'},
34 {"echo", no_argument
, NULL
, 'e'},
42 bool listlangs
= false;
43 const char *dbname
= NULL
;
46 char *username
= NULL
;
47 enum trivalue prompt_password
= TRI_DEFAULT
;
49 char *langname
= NULL
;
66 progname
= get_progname(argv
[0]);
67 set_pglocale_pgservice(argv
[0], PG_TEXTDOMAIN("pgscripts"));
69 handle_help_version_opts(argc
, argv
, "droplang", help
);
71 while ((c
= getopt_long(argc
, argv
, "lh:p:U:wWd:e", long_options
, &optindex
)) != -1)
88 prompt_password
= TRI_NO
;
91 prompt_password
= TRI_YES
;
100 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
105 if (argc
- optind
> 0)
108 dbname
= argv
[optind
++];
111 langname
= argv
[optind
++];
112 if (argc
- optind
> 0)
113 dbname
= argv
[optind
++];
117 if (argc
- optind
> 0)
119 fprintf(stderr
, _("%s: too many command-line arguments (first is \"%s\")\n"),
120 progname
, argv
[optind
]);
121 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
127 if (getenv("PGDATABASE"))
128 dbname
= getenv("PGDATABASE");
129 else if (getenv("PGUSER"))
130 dbname
= getenv("PGUSER");
132 dbname
= get_user_name(progname
);
135 initPQExpBuffer(&sql
);
143 static const bool translate_columns
[] = {false, true};
145 conn
= connectDatabase(dbname
, host
, port
, username
, prompt_password
,
148 printfPQExpBuffer(&sql
, "SELECT lanname as \"%s\", "
149 "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
150 "FROM pg_catalog.pg_language WHERE lanispl;",
151 gettext_noop("Name"),
152 gettext_noop("yes"), gettext_noop("no"),
153 gettext_noop("Trusted?"));
154 result
= executeQuery(conn
, sql
.data
, progname
, echo
);
156 memset(&popt
, 0, sizeof(popt
));
157 popt
.topt
.format
= PRINT_ALIGNED
;
158 popt
.topt
.border
= 1;
159 popt
.topt
.start_table
= true;
160 popt
.topt
.stop_table
= true;
161 popt
.topt
.encoding
= PQclientEncoding(conn
);
162 popt
.title
= _("Procedural Languages");
163 popt
.translate_header
= true;
164 popt
.translate_columns
= translate_columns
;
165 printQuery(result
, &popt
, stdout
, NULL
);
171 if (langname
== NULL
)
173 fprintf(stderr
, _("%s: missing required argument language name\n"),
175 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
180 for (p
= langname
; *p
; p
++)
181 if (*p
>= 'A' && *p
<= 'Z')
184 conn
= connectDatabase(dbname
, host
, port
, username
, prompt_password
, progname
);
187 * Force schema search path to be just pg_catalog, so that we don't have
188 * to be paranoid about search paths below.
190 executeCommand(conn
, "SET search_path = pg_catalog;", progname
, echo
);
193 * Make sure the language is installed and find the OIDs of the handler
194 * and validator functions
196 printfPQExpBuffer(&sql
, "SELECT lanplcallfoid, lanvalidator "
197 "FROM pg_language WHERE lanname = '%s' AND lanispl;",
199 result
= executeQuery(conn
, sql
.data
, progname
, echo
);
200 if (PQntuples(result
) == 0)
203 fprintf(stderr
, _("%s: language \"%s\" is not installed in "
204 "database \"%s\"\n"),
205 progname
, langname
, dbname
);
208 lanplcallfoid
= atooid(PQgetvalue(result
, 0, 0));
209 lanvalidator
= atooid(PQgetvalue(result
, 0, 1));
213 * Check that there are no functions left defined in that language
215 printfPQExpBuffer(&sql
, "SELECT count(proname) FROM pg_proc P, "
216 "pg_language L WHERE P.prolang = L.oid "
217 "AND L.lanname = '%s';", langname
);
218 result
= executeQuery(conn
, sql
.data
, progname
, echo
);
219 if (strcmp(PQgetvalue(result
, 0, 0), "0") != 0)
223 _("%s: still %s functions declared in language \"%s\"; "
224 "language not removed\n"),
225 progname
, PQgetvalue(result
, 0, 0), langname
);
231 * Check that the handler function isn't used by some other language
233 printfPQExpBuffer(&sql
, "SELECT count(*) FROM pg_language "
234 "WHERE lanplcallfoid = %u AND lanname <> '%s';",
235 lanplcallfoid
, langname
);
236 result
= executeQuery(conn
, sql
.data
, progname
, echo
);
237 if (strcmp(PQgetvalue(result
, 0, 0), "0") == 0)
244 * Find the handler name
248 printfPQExpBuffer(&sql
, "SELECT proname, (SELECT nspname "
249 "FROM pg_namespace ns WHERE ns.oid = pronamespace) "
250 "AS prons FROM pg_proc WHERE oid = %u;",
252 result
= executeQuery(conn
, sql
.data
, progname
, echo
);
253 handler
= strdup(PQgetvalue(result
, 0, 0));
254 handler_ns
= strdup(PQgetvalue(result
, 0, 1));
264 * Check that the validator function isn't used by some other language
266 if (OidIsValid(lanvalidator
))
268 printfPQExpBuffer(&sql
, "SELECT count(*) FROM pg_language "
269 "WHERE lanvalidator = %u AND lanname <> '%s';",
270 lanvalidator
, langname
);
271 result
= executeQuery(conn
, sql
.data
, progname
, echo
);
272 if (strcmp(PQgetvalue(result
, 0, 0), "0") == 0)
273 keepvalidator
= false;
275 keepvalidator
= true;
279 keepvalidator
= true; /* don't try to delete it */
282 * Find the validator name
286 printfPQExpBuffer(&sql
, "SELECT proname, (SELECT nspname "
287 "FROM pg_namespace ns WHERE ns.oid = pronamespace) "
288 "AS prons FROM pg_proc WHERE oid = %u;",
290 result
= executeQuery(conn
, sql
.data
, progname
, echo
);
291 validator
= strdup(PQgetvalue(result
, 0, 0));
292 validator_ns
= strdup(PQgetvalue(result
, 0, 1));
302 * Drop the language and the functions
304 printfPQExpBuffer(&sql
, "DROP LANGUAGE \"%s\";\n", langname
);
306 appendPQExpBuffer(&sql
, "DROP FUNCTION \"%s\".\"%s\" ();\n",
307 handler_ns
, handler
);
309 appendPQExpBuffer(&sql
, "DROP FUNCTION \"%s\".\"%s\" (oid);\n",
310 validator_ns
, validator
);
312 printf("%s", sql
.data
);
313 result
= PQexec(conn
, sql
.data
);
314 if (PQresultStatus(result
) != PGRES_COMMAND_OK
)
316 fprintf(stderr
, _("%s: language removal failed: %s"),
317 progname
, PQerrorMessage(conn
));
329 help(const char *progname
)
331 printf(_("%s removes a procedural language from a database.\n\n"), progname
);
332 printf(_("Usage:\n"));
333 printf(_(" %s [OPTION]... LANGNAME [DBNAME]\n"), progname
);
334 printf(_("\nOptions:\n"));
335 printf(_(" -d, --dbname=DBNAME database from which to remove the language\n"));
336 printf(_(" -e, --echo show the commands being sent to the server\n"));
337 printf(_(" -l, --list show a list of currently installed languages\n"));
338 printf(_(" --help show this help, then exit\n"));
339 printf(_(" --version output version information, then exit\n"));
340 printf(_("\nConnection options:\n"));
341 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
342 printf(_(" -p, --port=PORT database server port\n"));
343 printf(_(" -U, --username=USERNAME user name to connect as\n"));
344 printf(_(" -w, --no-password never prompt for password\n"));
345 printf(_(" -W, --password force password prompt\n"));
346 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));