1 /*-------------------------------------------------------------------------
2 *
3 * createlang
4 *
5 * Portions Copyright (c) 1996-2016, 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
main(int argc,char * argv[])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 ConnParams cparams;
46 bool echo = false;
47 char *langname = NULL;
48
49 char *p;
50
51 PQExpBufferData sql;
52
53 PGconn *conn;
54 PGresult *result;
55
56 progname = get_progname(argv[0]);
57 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
58
59 handle_help_version_opts(argc, argv, "createlang", help);
60
61 while ((c = getopt_long(argc, argv, "lh:p:U:wWd:e", long_options, &optindex)) != -1)
62 {
63 switch (c)
64 {
65 case 'l':
66 listlangs = true;
67 break;
68 case 'h':
69 host = pg_strdup(optarg);
70 break;
71 case 'p':
72 port = pg_strdup(optarg);
73 break;
74 case 'U':
75 username = pg_strdup(optarg);
76 break;
77 case 'w':
78 prompt_password = TRI_NO;
79 break;
80 case 'W':
81 prompt_password = TRI_YES;
82 break;
83 case 'd':
84 dbname = pg_strdup(optarg);
85 break;
86 case 'e':
87 echo = true;
88 break;
89 default:
90 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
91 exit(1);
92 }
93 }
94
95 /*
96 * We set dbname from positional arguments if it is not already set by
97 * option arguments -d. If not doing listlangs, positional dbname must
98 * follow positional langname.
99 */
100
101 if (argc - optind > 0)
102 {
103 if (listlangs)
104 {
105 if (dbname == NULL)
106 dbname = argv[optind++];
107 }
108 else
109 {
110 langname = argv[optind++];
111 if (argc - optind > 0 && dbname == NULL)
112 dbname = argv[optind++];
113 }
114 }
115
116 if (argc - optind > 0)
117 {
118 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
119 progname, argv[optind]);
120 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
121 exit(1);
122 }
123
124 if (dbname == NULL)
125 {
126 if (getenv("PGDATABASE"))
127 dbname = getenv("PGDATABASE");
128 else if (getenv("PGUSER"))
129 dbname = getenv("PGUSER");
130 else
131 dbname = get_user_name_or_exit(progname);
132 }
133
134 cparams.dbname = dbname;
135 cparams.pghost = host;
136 cparams.pgport = port;
137 cparams.pguser = username;
138 cparams.prompt_password = prompt_password;
139 cparams.override_dbname = NULL;
140
141 initPQExpBuffer(&sql);
142
143 /*
144 * List option
145 */
146 if (listlangs)
147 {
148 printQueryOpt popt;
149 static const bool translate_columns[] = {false, true};
150
151 conn = connectDatabase(&cparams,
152 progname, echo, false, false);
153
154 printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
155 "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
156 "FROM pg_catalog.pg_language WHERE lanispl;",
157 gettext_noop("Name"),
158 gettext_noop("yes"), gettext_noop("no"),
159 gettext_noop("Trusted?"));
160 result = executeQuery(conn, sql.data, progname, echo);
161
162 memset(&popt, 0, sizeof(popt));
163 popt.topt.format = PRINT_ALIGNED;
164 popt.topt.border = 1;
165 popt.topt.start_table = true;
166 popt.topt.stop_table = true;
167 popt.topt.encoding = PQclientEncoding(conn);
168 popt.title = _("Procedural Languages");
169 popt.translate_header = true;
170 popt.translate_columns = translate_columns;
171 popt.n_translate_columns = lengthof(translate_columns);
172
173 printQuery(result, &popt, stdout, false, NULL);
174
175 PQfinish(conn);
176 exit(0);
177 }
178
179 if (langname == NULL)
180 {
181 fprintf(stderr, _("%s: missing required argument language name\n"), progname);
182 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
183 exit(1);
184 }
185
186 /* lower case language name */
187 for (p = langname; *p; p++)
188 if (*p >= 'A' && *p <= 'Z')
189 *p += ('a' - 'A');
190
191 conn = connectDatabase(&cparams,
192 progname, echo, false, false);
193
194 /*
195 * Make sure the language isn't already installed
196 */
197 printfPQExpBuffer(&sql,
198 "SELECT oid FROM pg_catalog.pg_language WHERE lanname = '%s';",
199 langname);
200 result = executeQuery(conn, sql.data, progname, echo);
201 if (PQntuples(result) > 0)
202 {
203 fprintf(stderr,
204 _("%s: language \"%s\" is already installed in database \"%s\"\n"),
205 progname, langname, PQdb(conn));
206 PQfinish(conn);
207 /* separate exit status for "already installed" */
208 exit(2);
209 }
210 PQclear(result);
211
212 /*
213 * In 9.1 and up, assume that languages should be installed using CREATE
214 * EXTENSION. However, it's possible this tool could be used against an
215 * older server, and it's easy enough to continue supporting the old way.
216 */
217 if (PQserverVersion(conn) >= 90100)
218 printfPQExpBuffer(&sql, "CREATE EXTENSION \"%s\";", langname);
219 else
220 printfPQExpBuffer(&sql, "CREATE LANGUAGE \"%s\";", langname);
221
222 if (echo)
223 printf("%s\n", sql.data);
224 result = PQexec(conn, sql.data);
225 if (PQresultStatus(result) != PGRES_COMMAND_OK)
226 {
227 fprintf(stderr, _("%s: language installation failed: %s"),
228 progname, PQerrorMessage(conn));
229 PQfinish(conn);
230 exit(1);
231 }
232
233 PQclear(result);
234 PQfinish(conn);
235 exit(0);
236 }
237
238
239
240 static void
help(const char * progname)241 help(const char *progname)
242 {
243 printf(_("%s installs a procedural language into a PostgreSQL database.\n\n"), progname);
244 printf(_("Usage:\n"));
245 printf(_(" %s [OPTION]... LANGNAME [DBNAME]\n"), progname);
246 printf(_("\nOptions:\n"));
247 printf(_(" -d, --dbname=DBNAME database to install language in\n"));
248 printf(_(" -e, --echo show the commands being sent to the server\n"));
249 printf(_(" -l, --list show a list of currently installed languages\n"));
250 printf(_(" -V, --version output version information, then exit\n"));
251 printf(_(" -?, --help show this help, then exit\n"));
252 printf(_("\nConnection options:\n"));
253 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
254 printf(_(" -p, --port=PORT database server port\n"));
255 printf(_(" -U, --username=USERNAME user name to connect as\n"));
256 printf(_(" -w, --no-password never prompt for password\n"));
257 printf(_(" -W, --password force password prompt\n"));
258 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
259 }
260