Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #ifndef HAVE_GETOPT_LONG
15 : # include "monet_getopt.h"
16 : #else
17 : # ifdef HAVE_GETOPT_H
18 : # include "getopt.h"
19 : # endif
20 : #endif
21 : #include "mapi.h"
22 : #include <unistd.h>
23 : #include <sys/stat.h>
24 : #include <string.h>
25 : #include <time.h>
26 :
27 : #include "stream.h"
28 : #include "msqldump.h"
29 : #define LIBMUTILS 1
30 : #include "mprompt.h"
31 : #include "mutils.h" /* mercurial_revision */
32 : #include "dotmonetdb.h"
33 :
34 : static _Noreturn void usage(const char *prog, int xit);
35 :
36 : static void
37 0 : usage(const char *prog, int xit)
38 : {
39 0 : fprintf(stderr, "Usage: %s [ options ] [ dbname ]\n", prog);
40 0 : fprintf(stderr, "\nOptions are:\n");
41 0 : fprintf(stderr, " -h hostname | --host=hostname host to connect to\n");
42 0 : fprintf(stderr, " -p portnr | --port=portnr port to connect to\n");
43 0 : fprintf(stderr, " -u user | --user=user user id\n");
44 0 : fprintf(stderr, " -d database | --database=database database to connect to\n");
45 0 : fprintf(stderr, " -f | --functions dump functions\n");
46 0 : fprintf(stderr, " -t table | --table=table dump a database table\n");
47 0 : fprintf(stderr, " -D | --describe describe database\n");
48 0 : fprintf(stderr, " -N | --inserts use INSERT INTO statements\n");
49 0 : fprintf(stderr, " -e | --noescape use NO ESCAPE\n");
50 0 : fprintf(stderr, " -q | --quiet don't print welcome message\n");
51 0 : fprintf(stderr, " -X | --Xdebug trace mapi network interaction\n");
52 0 : fprintf(stderr, " -? | --help show this usage message\n");
53 0 : fprintf(stderr, "--functions and --table are mutually exclusive\n");
54 0 : exit(xit);
55 : }
56 :
57 : int
58 : #ifdef _MSC_VER
59 : wmain(int argc, wchar_t **wargv)
60 : #else
61 23 : main(int argc, char **argv)
62 : #endif
63 : {
64 23 : int port = 0;
65 23 : const char *user = NULL;
66 23 : const char *passwd = NULL;
67 23 : const char *host = NULL;
68 23 : const char *dbname = NULL;
69 23 : DotMonetdb dotfile = {0};
70 23 : bool trace = false;
71 23 : bool describe = false;
72 23 : bool functions = false;
73 23 : bool useinserts = false;
74 23 : bool noescape = false;
75 23 : int c;
76 23 : Mapi mid;
77 23 : bool quiet = false;
78 23 : stream *out;
79 23 : bool user_set_as_flag = false;
80 23 : char *table = NULL;
81 23 : static struct option long_options[] = {
82 : {"host", 1, 0, 'h'},
83 : {"port", 1, 0, 'p'},
84 : {"database", 1, 0, 'd'},
85 : {"describe", 0, 0, 'D'},
86 : {"functions", 0, 0, 'f'},
87 : {"table", 1, 0, 't'},
88 : {"inserts", 0, 0, 'N'},
89 : {"noescape", 0, 0, 'e'},
90 : {"Xdebug", 0, 0, 'X'},
91 : {"user", 1, 0, 'u'},
92 : {"quiet", 0, 0, 'q'},
93 : {"version", 0, 0, 'v'},
94 : {"help", 0, 0, '?'},
95 : {0, 0, 0, 0}
96 : };
97 : #ifdef _MSC_VER
98 : char **argv = malloc((argc + 1) * sizeof(char *));
99 : if (argv == NULL) {
100 : fprintf(stderr, "cannot allocate memory for argument conversion\n");
101 : exit(1);
102 : }
103 : for (int i = 0; i < argc; i++) {
104 : if ((argv[i] = wchartoutf8(wargv[i])) == NULL) {
105 : fprintf(stderr, "cannot convert argument to UTF-8\n");
106 : exit(1);
107 : }
108 : }
109 : argv[argc] = NULL;
110 : #endif
111 :
112 23 : parse_dotmonetdb(&dotfile);
113 23 : user = dotfile.user;
114 23 : passwd = dotfile.passwd;
115 23 : dbname = dotfile.dbname;
116 23 : host = dotfile.host;
117 23 : port = dotfile.port;
118 :
119 112 : while ((c = getopt_long(argc, argv, "h:p:d:Dft:NeXu:qv?", long_options, NULL)) != -1) {
120 90 : switch (c) {
121 0 : case 'u':
122 0 : user = optarg;
123 0 : user_set_as_flag = true;
124 0 : break;
125 22 : case 'h':
126 22 : host = optarg;
127 22 : break;
128 22 : case 'p':
129 22 : assert(optarg != NULL);
130 22 : port = atoi(optarg);
131 22 : break;
132 22 : case 'd':
133 22 : dbname = optarg;
134 22 : break;
135 : case 'D':
136 : describe = true;
137 : break;
138 1 : case 'N':
139 1 : useinserts = true;
140 1 : break;
141 0 : case 'e':
142 0 : noescape = true;
143 0 : break;
144 0 : case 'f':
145 0 : if (table)
146 0 : usage(argv[0], -1);
147 : functions = true;
148 : break;
149 0 : case 't':
150 0 : if (table || functions)
151 0 : usage(argv[0], -1);
152 0 : table = optarg;
153 0 : break;
154 22 : case 'q':
155 22 : quiet = true;
156 22 : break;
157 0 : case 'X':
158 0 : trace = true;
159 0 : break;
160 1 : case 'v': {
161 1 : printf("msqldump, the MonetDB interactive database "
162 : "dump tool, version %s", MONETDB_VERSION);
163 : #ifdef MONETDB_RELEASE
164 : printf(" (%s)", MONETDB_RELEASE);
165 : #else
166 1 : const char *rev = mercurial_revision();
167 1 : if (strcmp(rev, "Unknown") != 0)
168 0 : printf(" (hg id: %s)", rev);
169 : #endif
170 1 : printf("\n");
171 1 : destroy_dotmonetdb(&dotfile);
172 1 : return 0;
173 : }
174 0 : case '?':
175 : /* a bit of a hack: look at the option that the
176 : current `c' is based on and see if we recognize
177 : it: if -? or --help, exit with 0, else with -1 */
178 0 : usage(argv[0], strcmp(argv[optind - 1], "-?") == 0 || strcmp(argv[optind - 1], "--help") == 0 ? 0 : -1);
179 0 : default:
180 0 : usage(argv[0], -1);
181 : }
182 : }
183 :
184 22 : if (optind == argc - 1)
185 0 : dbname = argv[optind];
186 22 : else if (optind != argc)
187 0 : usage(argv[0], -1);
188 :
189 : /* when config file would provide defaults */
190 22 : if (user_set_as_flag)
191 0 : passwd = NULL;
192 :
193 22 : if(dbname == NULL){
194 0 : printf("msqldump, please specify a database\n");
195 0 : usage(argv[0], -1);
196 : }
197 22 : char *user_allocated = NULL;
198 22 : if (user == NULL) {
199 0 : user_allocated = simple_prompt("user", BUFSIZ, 1, prompt_getlogin());
200 0 : user = user_allocated;
201 : }
202 22 : char *passwd_allocated = NULL;
203 22 : if (passwd == NULL) {
204 0 : passwd_allocated = simple_prompt("password", BUFSIZ, 0, NULL);
205 0 : passwd = passwd_allocated;
206 : }
207 :
208 22 : if (dbname != NULL && strchr(dbname, ':') != NULL) {
209 0 : mid = mapi_mapiuri(dbname, user, passwd, "sql");
210 : } else {
211 22 : mid = mapi_mapi(host, port, user, passwd, "sql", dbname);
212 : }
213 22 : free(user_allocated);
214 22 : user_allocated = NULL;
215 22 : free(passwd_allocated);
216 22 : passwd_allocated = NULL;
217 22 : user = NULL;
218 22 : passwd = NULL;
219 22 : dbname = NULL;
220 22 : if (mid == NULL) {
221 0 : fprintf(stderr, "failed to allocate Mapi structure\n");
222 0 : exit(2);
223 : }
224 22 : if (mapi_error(mid)) {
225 0 : mapi_explain(mid, stderr);
226 0 : exit(2);
227 : }
228 22 : mapi_set_time_zone(mid, 0);
229 22 : mapi_reconnect(mid);
230 22 : if (mapi_error(mid)) {
231 0 : mapi_explain(mid, stderr);
232 0 : exit(2);
233 : }
234 22 : if (!quiet) {
235 0 : const char *motd = mapi_get_motd(mid);
236 :
237 0 : if (motd)
238 0 : fprintf(stderr, "%s", motd);
239 : }
240 22 : mapi_trace(mid, trace);
241 22 : mapi_cache_limit(mid, -1);
242 :
243 22 : out = stdout_wastream();
244 22 : if (out == NULL) {
245 0 : fprintf(stderr, "failed to allocate stream: %s\n", mnstr_peek_error(NULL));
246 0 : exit(2);
247 : }
248 22 : if (!quiet) {
249 0 : char buf[27];
250 0 : time_t t = time(0);
251 0 : char *p;
252 :
253 : #ifdef HAVE_CTIME_R3
254 : ctime_r(&t, buf, sizeof(buf));
255 : #else
256 : #ifdef HAVE_CTIME_R
257 0 : ctime_r(&t, buf);
258 : #else
259 : strcpy_len(buf, ctime(&t), sizeof(buf));
260 : #endif
261 : #endif
262 0 : if ((p = strrchr(buf, '\n')) != NULL)
263 0 : *p = 0;
264 :
265 0 : mnstr_printf(out,
266 : "-- msqldump version %s", MONETDB_VERSION);
267 : #ifdef MONETDB_RELEASE
268 : mnstr_printf(out, " (%s)", MONETDB_RELEASE);
269 : #else
270 0 : const char *rev = mercurial_revision();
271 0 : if (strcmp(rev, "Unknown") != 0)
272 0 : mnstr_printf(out, " (hg id: %s)", rev);
273 : #endif
274 0 : mnstr_printf(out, " %s %s%s\n",
275 : describe ? "describe" : "dump",
276 0 : functions ? "functions" : table ? "table " : "database",
277 : table ? table : "");
278 0 : dump_version(mid, out, "-- server:");
279 0 : mnstr_printf(out, "-- %s\n", buf);
280 : }
281 22 : if (functions) {
282 0 : mnstr_printf(out, "START TRANSACTION;\n");
283 0 : c = dump_functions(mid, out, true, NULL, NULL, NULL);
284 0 : mnstr_printf(out, "COMMIT;\n");
285 22 : } else if (table) {
286 0 : mnstr_printf(out, "START TRANSACTION;\n");
287 0 : c = dump_table(mid, NULL, table, out, describe, true, useinserts, false, noescape);
288 0 : mnstr_printf(out, "COMMIT;\n");
289 : } else
290 22 : c = dump_database(mid, out, describe, useinserts, noescape);
291 22 : mnstr_flush(out, MNSTR_FLUSH_DATA);
292 :
293 22 : mapi_destroy(mid);
294 22 : if (mnstr_errnr(out) != MNSTR_NO__ERROR) {
295 0 : fprintf(stderr, "%s: %s\n", argv[0], mnstr_peek_error(out));
296 0 : c = 1;
297 : }
298 :
299 22 : mnstr_destroy(out);
300 :
301 22 : destroy_dotmonetdb(&dotfile);
302 :
303 22 : return c;
304 : }
|