]> granicus.if.org Git - postgresql/blob - src/bin/scripts/droplang.c
Append major version number and for libraries soname major version number
[postgresql] / src / bin / scripts / droplang.c
1 /*-------------------------------------------------------------------------
2  *
3  * droplang
4  *
5  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  * $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.28 2008/12/11 07:34:08 petere Exp $
9  *
10  *-------------------------------------------------------------------------
11  */
12
13 #include "postgres_fe.h"
14 #include "common.h"
15 #include "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
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                 {"password", no_argument, NULL, 'W'},
32                 {"dbname", required_argument, NULL, 'd'},
33                 {"echo", no_argument, NULL, 'e'},
34                 {NULL, 0, NULL, 0}
35         };
36
37         const char *progname;
38         int                     optindex;
39         int                     c;
40
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;
49
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;
59
60         PQExpBufferData sql;
61
62         PGconn     *conn;
63         PGresult   *result;
64
65         progname = get_progname(argv[0]);
66         set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
67
68         handle_help_version_opts(argc, argv, "droplang", help);
69
70         while ((c = getopt_long(argc, argv, "lh:p:U:Wd:e", long_options, &optindex)) != -1)
71         {
72                 switch (c)
73                 {
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);
98                 }
99         }
100
101         if (argc - optind > 0)
102         {
103                 if (listlangs)
104                         dbname = argv[optind++];
105                 else
106                 {
107                         langname = argv[optind++];
108                         if (argc - optind > 0)
109                                 dbname = argv[optind++];
110                 }
111         }
112
113         if (argc - optind > 0)
114         {
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);
119         }
120
121         if (dbname == NULL)
122         {
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);
129         }
130
131         initPQExpBuffer(&sql);
132
133         /*
134          * List option
135          */
136         if (listlangs)
137         {
138                 printQueryOpt popt;
139                 static const bool translate_columns[] = {false, true};
140
141                 conn = connectDatabase(dbname, host, port, username, password,
142                                                            progname);
143
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);
151
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);
162
163                 PQfinish(conn);
164                 exit(0);
165         }
166
167         if (langname == NULL)
168         {
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);
174         }
175
176         for (p = langname; *p; p++)
177                 if (*p >= 'A' && *p <= 'Z')
178                         *p += ('a' - 'A');
179
180         conn = connectDatabase(dbname, host, port, username, password, progname);
181
182         /*
183          * Force schema search path to be just pg_catalog, so that we don't have
184          * to be paranoid about search paths below.
185          */
186         executeCommand(conn, "SET search_path = pg_catalog;", progname, echo);
187
188         /*
189          * Make sure the language is installed and find the OIDs of the handler
190          * and validator functions
191          */
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)
197         {
198                 PQfinish(conn);
199                 fprintf(stderr, _("%s: language \"%s\" is not installed in "
200                                                   "database \"%s\"\n"),
201                                 progname, langname, dbname);
202                 exit(1);
203         }
204         lanplcallfoid = atooid(PQgetvalue(result, 0, 0));
205         lanvalidator = atooid(PQgetvalue(result, 0, 1));
206         PQclear(result);
207
208         /*
209          * Check that there are no functions left defined in that language
210          */
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)
216         {
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);
223         }
224         PQclear(result);
225
226         /*
227          * Check that the handler function isn't used by some other language
228          */
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);
238
239         /*
240          * Find the handler name
241          */
242         if (!keephandler)
243         {
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);
252         }
253         else
254         {
255                 handler = NULL;
256                 handler_ns = NULL;
257         }
258
259         /*
260          * Check that the validator function isn't used by some other language
261          */
262         if (OidIsValid(lanvalidator))
263         {
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);
273         }
274         else
275                 keepvalidator = true;   /* don't try to delete it */
276
277         /*
278          * Find the validator name
279          */
280         if (!keepvalidator)
281         {
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);
290         }
291         else
292         {
293                 validator = NULL;
294                 validator_ns = NULL;
295         }
296
297         /*
298          * Drop the language and the functions
299          */
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)
311         {
312                 fprintf(stderr, _("%s: language removal failed: %s"),
313                                 progname, PQerrorMessage(conn));
314                 PQfinish(conn);
315                 exit(1);
316         }
317
318         PQclear(result);
319         PQfinish(conn);
320         exit(0);
321 }
322
323
324 static void
325 help(const char *progname)
326 {
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(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));
335         printf(_("  -p, --port=PORT           database server port\n"));
336         printf(_("  -U, --username=USERNAME   user name to connect as\n"));
337         printf(_("  -W, --password            force password prompt\n"));
338         printf(_("  --help                    show this help, then exit\n"));
339         printf(_("  --version                 output version information, then exit\n"));
340         printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
341 }