]> granicus.if.org Git - postgresql/blob - src/bin/scripts/createlang.c
5897bfe747559f836c79892e77213a7930d4977f
[postgresql] / src / bin / scripts / createlang.c
1 /*-------------------------------------------------------------------------
2  *
3  * createlang
4  *
5  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  * src/bin/scripts/createlang.c
9  *
10  *-------------------------------------------------------------------------
11  */
12 #include "postgres_fe.h"
13
14 #include "common.h"
15 #include "fe_utils/print.h"
16
17 static void help(const char *progname);
18
19
20 int
21 main(int argc, char *argv[])
22 {
23         static struct option long_options[] = {
24                 {"list", no_argument, NULL, 'l'},
25                 {"host", required_argument, NULL, 'h'},
26                 {"port", required_argument, NULL, 'p'},
27                 {"username", required_argument, NULL, 'U'},
28                 {"no-password", no_argument, NULL, 'w'},
29                 {"password", no_argument, NULL, 'W'},
30                 {"dbname", required_argument, NULL, 'd'},
31                 {"echo", no_argument, NULL, 'e'},
32                 {NULL, 0, NULL, 0}
33         };
34
35         const char *progname;
36         int                     optindex;
37         int                     c;
38
39         bool            listlangs = false;
40         const char *dbname = NULL;
41         char       *host = NULL;
42         char       *port = NULL;
43         char       *username = NULL;
44         enum trivalue prompt_password = TRI_DEFAULT;
45         bool            echo = false;
46         char       *langname = NULL;
47
48         char       *p;
49
50         PQExpBufferData sql;
51
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, "createlang", 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         initPQExpBuffer(&sql);
134
135         /*
136          * List option
137          */
138         if (listlangs)
139         {
140                 printQueryOpt popt;
141                 static const bool translate_columns[] = {false, true};
142
143                 conn = connectDatabase(dbname, host, port, username, prompt_password,
144                                                            progname, false, false);
145
146                 printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
147                                 "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
148                                                   "FROM pg_catalog.pg_language WHERE lanispl;",
149                                                   gettext_noop("Name"),
150                                                   gettext_noop("yes"), gettext_noop("no"),
151                                                   gettext_noop("Trusted?"));
152                 result = executeQuery(conn, sql.data, progname, echo);
153
154                 memset(&popt, 0, sizeof(popt));
155                 popt.topt.format = PRINT_ALIGNED;
156                 popt.topt.border = 1;
157                 popt.topt.start_table = true;
158                 popt.topt.stop_table = true;
159                 popt.topt.encoding = PQclientEncoding(conn);
160                 popt.title = _("Procedural Languages");
161                 popt.translate_header = true;
162                 popt.translate_columns = translate_columns;
163                 popt.n_translate_columns = lengthof(translate_columns);
164
165                 printQuery(result, &popt, stdout, false, NULL);
166
167                 PQfinish(conn);
168                 exit(0);
169         }
170
171         if (langname == NULL)
172         {
173                 fprintf(stderr, _("%s: missing required argument language name\n"), progname);
174                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
175                 exit(1);
176         }
177
178         /* lower case language name */
179         for (p = langname; *p; p++)
180                 if (*p >= 'A' && *p <= 'Z')
181                         *p += ('a' - 'A');
182
183         conn = connectDatabase(dbname, host, port, username, prompt_password,
184                                                    progname, false, false);
185
186         /*
187          * Make sure the language isn't already installed
188          */
189         printfPQExpBuffer(&sql,
190                           "SELECT oid FROM pg_catalog.pg_language WHERE lanname = '%s';",
191                                           langname);
192         result = executeQuery(conn, sql.data, progname, echo);
193         if (PQntuples(result) > 0)
194         {
195                 fprintf(stderr,
196                   _("%s: language \"%s\" is already installed in database \"%s\"\n"),
197                                 progname, langname, PQdb(conn));
198                 PQfinish(conn);
199                 /* separate exit status for "already installed" */
200                 exit(2);
201         }
202         PQclear(result);
203
204         /*
205          * In 9.1 and up, assume that languages should be installed using CREATE
206          * EXTENSION.  However, it's possible this tool could be used against an
207          * older server, and it's easy enough to continue supporting the old way.
208          */
209         if (PQserverVersion(conn) >= 90100)
210                 printfPQExpBuffer(&sql, "CREATE EXTENSION \"%s\";", langname);
211         else
212                 printfPQExpBuffer(&sql, "CREATE LANGUAGE \"%s\";", langname);
213
214         if (echo)
215                 printf("%s\n", sql.data);
216         result = PQexec(conn, sql.data);
217         if (PQresultStatus(result) != PGRES_COMMAND_OK)
218         {
219                 fprintf(stderr, _("%s: language installation failed: %s"),
220                                 progname, PQerrorMessage(conn));
221                 PQfinish(conn);
222                 exit(1);
223         }
224
225         PQclear(result);
226         PQfinish(conn);
227         exit(0);
228 }
229
230
231
232 static void
233 help(const char *progname)
234 {
235         printf(_("%s installs a procedural language into a PostgreSQL database.\n\n"), progname);
236         printf(_("Usage:\n"));
237         printf(_("  %s [OPTION]... LANGNAME [DBNAME]\n"), progname);
238         printf(_("\nOptions:\n"));
239         printf(_("  -d, --dbname=DBNAME       database to install language in\n"));
240         printf(_("  -e, --echo                show the commands being sent to the server\n"));
241         printf(_("  -l, --list                show a list of currently installed languages\n"));
242         printf(_("  -V, --version             output version information, then exit\n"));
243         printf(_("  -?, --help                show this help, then exit\n"));
244         printf(_("\nConnection options:\n"));
245         printf(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));
246         printf(_("  -p, --port=PORT           database server port\n"));
247         printf(_("  -U, --username=USERNAME   user name to connect as\n"));
248         printf(_("  -w, --no-password         never prompt for password\n"));
249         printf(_("  -W, --password            force password prompt\n"));
250         printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
251 }