1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * createdb |
4 | * |
5 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
6 | * Portions Copyright (c) 1994, Regents of the University of California |
7 | * |
8 | * src/bin/scripts/createdb.c |
9 | * |
10 | *------------------------------------------------------------------------- |
11 | */ |
12 | #include "postgres_fe.h" |
13 | |
14 | #include "common.h" |
15 | #include "common/logging.h" |
16 | #include "fe_utils/string_utils.h" |
17 | |
18 | |
19 | static void help(const char *progname); |
20 | |
21 | |
22 | int |
23 | main(int argc, char *argv[]) |
24 | { |
25 | static struct option long_options[] = { |
26 | {"host" , required_argument, NULL, 'h'}, |
27 | {"port" , required_argument, NULL, 'p'}, |
28 | {"username" , required_argument, NULL, 'U'}, |
29 | {"no-password" , no_argument, NULL, 'w'}, |
30 | {"password" , no_argument, NULL, 'W'}, |
31 | {"echo" , no_argument, NULL, 'e'}, |
32 | {"owner" , required_argument, NULL, 'O'}, |
33 | {"tablespace" , required_argument, NULL, 'D'}, |
34 | {"template" , required_argument, NULL, 'T'}, |
35 | {"encoding" , required_argument, NULL, 'E'}, |
36 | {"lc-collate" , required_argument, NULL, 1}, |
37 | {"lc-ctype" , required_argument, NULL, 2}, |
38 | {"locale" , required_argument, NULL, 'l'}, |
39 | {"maintenance-db" , required_argument, NULL, 3}, |
40 | {NULL, 0, NULL, 0} |
41 | }; |
42 | |
43 | const char *progname; |
44 | int optindex; |
45 | int c; |
46 | |
47 | const char *dbname = NULL; |
48 | const char *maintenance_db = NULL; |
49 | char * = NULL; |
50 | char *host = NULL; |
51 | char *port = NULL; |
52 | char *username = NULL; |
53 | enum trivalue prompt_password = TRI_DEFAULT; |
54 | bool echo = false; |
55 | char *owner = NULL; |
56 | char *tablespace = NULL; |
57 | char *template = NULL; |
58 | char *encoding = NULL; |
59 | char *lc_collate = NULL; |
60 | char *lc_ctype = NULL; |
61 | char *locale = NULL; |
62 | |
63 | PQExpBufferData sql; |
64 | |
65 | PGconn *conn; |
66 | PGresult *result; |
67 | |
68 | pg_logging_init(argv[0]); |
69 | progname = get_progname(argv[0]); |
70 | set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts" )); |
71 | |
72 | handle_help_version_opts(argc, argv, "createdb" , help); |
73 | |
74 | while ((c = getopt_long(argc, argv, "h:p:U:wWeO:D:T:E:l:" , long_options, &optindex)) != -1) |
75 | { |
76 | switch (c) |
77 | { |
78 | case 'h': |
79 | host = pg_strdup(optarg); |
80 | break; |
81 | case 'p': |
82 | port = pg_strdup(optarg); |
83 | break; |
84 | case 'U': |
85 | username = pg_strdup(optarg); |
86 | break; |
87 | case 'w': |
88 | prompt_password = TRI_NO; |
89 | break; |
90 | case 'W': |
91 | prompt_password = TRI_YES; |
92 | break; |
93 | case 'e': |
94 | echo = true; |
95 | break; |
96 | case 'O': |
97 | owner = pg_strdup(optarg); |
98 | break; |
99 | case 'D': |
100 | tablespace = pg_strdup(optarg); |
101 | break; |
102 | case 'T': |
103 | template = pg_strdup(optarg); |
104 | break; |
105 | case 'E': |
106 | encoding = pg_strdup(optarg); |
107 | break; |
108 | case 1: |
109 | lc_collate = pg_strdup(optarg); |
110 | break; |
111 | case 2: |
112 | lc_ctype = pg_strdup(optarg); |
113 | break; |
114 | case 'l': |
115 | locale = pg_strdup(optarg); |
116 | break; |
117 | case 3: |
118 | maintenance_db = pg_strdup(optarg); |
119 | break; |
120 | default: |
121 | fprintf(stderr, _("Try \"%s --help\" for more information.\n" ), progname); |
122 | exit(1); |
123 | } |
124 | } |
125 | |
126 | switch (argc - optind) |
127 | { |
128 | case 0: |
129 | break; |
130 | case 1: |
131 | dbname = argv[optind]; |
132 | break; |
133 | case 2: |
134 | dbname = argv[optind]; |
135 | comment = argv[optind + 1]; |
136 | break; |
137 | default: |
138 | pg_log_error("too many command-line arguments (first is \"%s\")" , |
139 | argv[optind + 2]); |
140 | fprintf(stderr, _("Try \"%s --help\" for more information.\n" ), progname); |
141 | exit(1); |
142 | } |
143 | |
144 | if (locale) |
145 | { |
146 | if (lc_ctype) |
147 | { |
148 | pg_log_error("only one of --locale and --lc-ctype can be specified" ); |
149 | exit(1); |
150 | } |
151 | if (lc_collate) |
152 | { |
153 | pg_log_error("only one of --locale and --lc-collate can be specified" ); |
154 | exit(1); |
155 | } |
156 | lc_ctype = locale; |
157 | lc_collate = locale; |
158 | } |
159 | |
160 | if (encoding) |
161 | { |
162 | if (pg_char_to_encoding(encoding) < 0) |
163 | { |
164 | pg_log_error("\"%s\" is not a valid encoding name" , encoding); |
165 | exit(1); |
166 | } |
167 | } |
168 | |
169 | if (dbname == NULL) |
170 | { |
171 | if (getenv("PGDATABASE" )) |
172 | dbname = getenv("PGDATABASE" ); |
173 | else if (getenv("PGUSER" )) |
174 | dbname = getenv("PGUSER" ); |
175 | else |
176 | dbname = get_user_name_or_exit(progname); |
177 | } |
178 | |
179 | initPQExpBuffer(&sql); |
180 | |
181 | appendPQExpBuffer(&sql, "CREATE DATABASE %s" , |
182 | fmtId(dbname)); |
183 | |
184 | if (owner) |
185 | appendPQExpBuffer(&sql, " OWNER %s" , fmtId(owner)); |
186 | if (tablespace) |
187 | appendPQExpBuffer(&sql, " TABLESPACE %s" , fmtId(tablespace)); |
188 | if (encoding) |
189 | appendPQExpBuffer(&sql, " ENCODING '%s'" , encoding); |
190 | if (template) |
191 | appendPQExpBuffer(&sql, " TEMPLATE %s" , fmtId(template)); |
192 | if (lc_collate) |
193 | appendPQExpBuffer(&sql, " LC_COLLATE '%s'" , lc_collate); |
194 | if (lc_ctype) |
195 | appendPQExpBuffer(&sql, " LC_CTYPE '%s'" , lc_ctype); |
196 | |
197 | appendPQExpBufferChar(&sql, ';'); |
198 | |
199 | /* No point in trying to use postgres db when creating postgres db. */ |
200 | if (maintenance_db == NULL && strcmp(dbname, "postgres" ) == 0) |
201 | maintenance_db = "template1" ; |
202 | |
203 | conn = connectMaintenanceDatabase(maintenance_db, host, port, username, |
204 | prompt_password, progname, echo); |
205 | |
206 | if (echo) |
207 | printf("%s\n" , sql.data); |
208 | result = PQexec(conn, sql.data); |
209 | |
210 | if (PQresultStatus(result) != PGRES_COMMAND_OK) |
211 | { |
212 | pg_log_error("database creation failed: %s" , PQerrorMessage(conn)); |
213 | PQfinish(conn); |
214 | exit(1); |
215 | } |
216 | |
217 | PQclear(result); |
218 | |
219 | if (comment) |
220 | { |
221 | printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS " , fmtId(dbname)); |
222 | appendStringLiteralConn(&sql, comment, conn); |
223 | appendPQExpBufferChar(&sql, ';'); |
224 | |
225 | if (echo) |
226 | printf("%s\n" , sql.data); |
227 | result = PQexec(conn, sql.data); |
228 | |
229 | if (PQresultStatus(result) != PGRES_COMMAND_OK) |
230 | { |
231 | pg_log_error("comment creation failed (database was created): %s" , |
232 | PQerrorMessage(conn)); |
233 | PQfinish(conn); |
234 | exit(1); |
235 | } |
236 | |
237 | PQclear(result); |
238 | } |
239 | |
240 | PQfinish(conn); |
241 | |
242 | exit(0); |
243 | } |
244 | |
245 | |
246 | static void |
247 | help(const char *progname) |
248 | { |
249 | printf(_("%s creates a PostgreSQL database.\n\n" ), progname); |
250 | printf(_("Usage:\n" )); |
251 | printf(_(" %s [OPTION]... [DBNAME] [DESCRIPTION]\n" ), progname); |
252 | printf(_("\nOptions:\n" )); |
253 | printf(_(" -D, --tablespace=TABLESPACE default tablespace for the database\n" )); |
254 | printf(_(" -e, --echo show the commands being sent to the server\n" )); |
255 | printf(_(" -E, --encoding=ENCODING encoding for the database\n" )); |
256 | printf(_(" -l, --locale=LOCALE locale settings for the database\n" )); |
257 | printf(_(" --lc-collate=LOCALE LC_COLLATE setting for the database\n" )); |
258 | printf(_(" --lc-ctype=LOCALE LC_CTYPE setting for the database\n" )); |
259 | printf(_(" -O, --owner=OWNER database user to own the new database\n" )); |
260 | printf(_(" -T, --template=TEMPLATE template database to copy\n" )); |
261 | printf(_(" -V, --version output version information, then exit\n" )); |
262 | printf(_(" -?, --help show this help, then exit\n" )); |
263 | printf(_("\nConnection options:\n" )); |
264 | printf(_(" -h, --host=HOSTNAME database server host or socket directory\n" )); |
265 | printf(_(" -p, --port=PORT database server port\n" )); |
266 | printf(_(" -U, --username=USERNAME user name to connect as\n" )); |
267 | printf(_(" -w, --no-password never prompt for password\n" )); |
268 | printf(_(" -W, --password force password prompt\n" )); |
269 | printf(_(" --maintenance-db=DBNAME alternate maintenance database\n" )); |
270 | printf(_("\nBy default, a database with the same name as the current user is created.\n" )); |
271 | printf(_("\nReport bugs to <pgsql-bugs@lists.postgresql.org>.\n" )); |
272 | } |
273 | |