1 /*
2 * psql - the PostgreSQL interactive terminal
3 *
4 * Copyright (c) 2000-2021, PostgreSQL Global Development Group
5 *
6 * src/bin/psql/command.c
7 */
8 #include "postgres_fe.h"
9
10 #include <ctype.h>
11 #include <time.h>
12 #include <pwd.h>
13 #include <utime.h>
14 #ifndef WIN32
15 #include <sys/stat.h> /* for stat() */
16 #include <fcntl.h> /* open() flags */
17 #include <unistd.h> /* for geteuid(), getpid(), stat() */
18 #else
19 #include <win32.h>
20 #include <io.h>
21 #include <fcntl.h>
22 #include <direct.h>
23 #include <sys/stat.h> /* for stat() */
24 #endif
25
26 #include "catalog/pg_class_d.h"
27 #include "command.h"
28 #include "common.h"
29 #include "common/logging.h"
30 #include "common/string.h"
31 #include "copy.h"
32 #include "crosstabview.h"
33 #include "describe.h"
34 #include "fe_utils/cancel.h"
35 #include "fe_utils/print.h"
36 #include "fe_utils/string_utils.h"
37 #include "help.h"
38 #include "input.h"
39 #include "large_obj.h"
40 #include "libpq-fe.h"
41 #include "libpq/pqcomm.h"
42 #include "mainloop.h"
43 #include "portability/instr_time.h"
44 #include "pqexpbuffer.h"
45 #include "psqlscanslash.h"
46 #include "settings.h"
47 #include "variables.h"
48
49 /*
50 * Editable database object types.
51 */
52 typedef enum EditableObjectType
53 {
54 EditableFunction,
55 EditableView
56 } EditableObjectType;
57
58 /* local function declarations */
59 static backslashResult exec_command(const char *cmd,
60 PsqlScanState scan_state,
61 ConditionalStack cstack,
62 PQExpBuffer query_buf,
63 PQExpBuffer previous_buf);
64 static backslashResult exec_command_a(PsqlScanState scan_state, bool active_branch);
65 static backslashResult exec_command_C(PsqlScanState scan_state, bool active_branch);
66 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
67 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
68 const char *cmd);
69 static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
70 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
71 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
72 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
73 static backslashResult exec_command_d(PsqlScanState scan_state, bool active_branch,
74 const char *cmd);
75 static bool exec_command_dfo(PsqlScanState scan_state, const char *cmd,
76 const char *pattern,
77 bool show_verbose, bool show_system);
78 static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch,
79 PQExpBuffer query_buf, PQExpBuffer previous_buf);
80 static backslashResult exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
81 PQExpBuffer query_buf, bool is_func);
82 static backslashResult exec_command_echo(PsqlScanState scan_state, bool active_branch,
83 const char *cmd);
84 static backslashResult exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
85 PQExpBuffer query_buf);
86 static backslashResult exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
87 PQExpBuffer query_buf);
88 static backslashResult exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
89 PQExpBuffer query_buf);
90 static backslashResult exec_command_encoding(PsqlScanState scan_state, bool active_branch);
91 static backslashResult exec_command_errverbose(PsqlScanState scan_state, bool active_branch);
92 static backslashResult exec_command_f(PsqlScanState scan_state, bool active_branch);
93 static backslashResult exec_command_g(PsqlScanState scan_state, bool active_branch,
94 const char *cmd);
95 static backslashResult process_command_g_options(char *first_option,
96 PsqlScanState scan_state,
97 bool active_branch,
98 const char *cmd);
99 static backslashResult exec_command_gdesc(PsqlScanState scan_state, bool active_branch);
100 static backslashResult exec_command_gexec(PsqlScanState scan_state, bool active_branch);
101 static backslashResult exec_command_gset(PsqlScanState scan_state, bool active_branch);
102 static backslashResult exec_command_help(PsqlScanState scan_state, bool active_branch);
103 static backslashResult exec_command_html(PsqlScanState scan_state, bool active_branch);
104 static backslashResult exec_command_include(PsqlScanState scan_state, bool active_branch,
105 const char *cmd);
106 static backslashResult exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
107 PQExpBuffer query_buf);
108 static backslashResult exec_command_list(PsqlScanState scan_state, bool active_branch,
109 const char *cmd);
110 static backslashResult exec_command_lo(PsqlScanState scan_state, bool active_branch,
111 const char *cmd);
112 static backslashResult exec_command_out(PsqlScanState scan_state, bool active_branch);
113 static backslashResult exec_command_print(PsqlScanState scan_state, bool active_branch,
114 PQExpBuffer query_buf, PQExpBuffer previous_buf);
115 static backslashResult exec_command_password(PsqlScanState scan_state, bool active_branch);
116 static backslashResult exec_command_prompt(PsqlScanState scan_state, bool active_branch,
117 const char *cmd);
118 static backslashResult exec_command_pset(PsqlScanState scan_state, bool active_branch);
119 static backslashResult exec_command_quit(PsqlScanState scan_state, bool active_branch);
120 static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch,
121 PQExpBuffer query_buf);
122 static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch);
123 static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch);
124 static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch,
125 const char *cmd);
126 static backslashResult exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
127 const char *cmd, bool is_func);
128 static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch);
129 static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch);
130 static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch);
131 static backslashResult exec_command_unset(PsqlScanState scan_state, bool active_branch,
132 const char *cmd);
133 static backslashResult exec_command_write(PsqlScanState scan_state, bool active_branch,
134 const char *cmd,
135 PQExpBuffer query_buf, PQExpBuffer previous_buf);
136 static backslashResult exec_command_watch(PsqlScanState scan_state, bool active_branch,
137 PQExpBuffer query_buf, PQExpBuffer previous_buf);
138 static backslashResult exec_command_x(PsqlScanState scan_state, bool active_branch);
139 static backslashResult exec_command_z(PsqlScanState scan_state, bool active_branch);
140 static backslashResult exec_command_shell_escape(PsqlScanState scan_state, bool active_branch);
141 static backslashResult exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch);
142 static char *read_connect_arg(PsqlScanState scan_state);
143 static PQExpBuffer gather_boolean_expression(PsqlScanState scan_state);
144 static bool is_true_boolean_expression(PsqlScanState scan_state, const char *name);
145 static void ignore_boolean_expression(PsqlScanState scan_state);
146 static void ignore_slash_options(PsqlScanState scan_state);
147 static void ignore_slash_filepipe(PsqlScanState scan_state);
148 static void ignore_slash_whole_line(PsqlScanState scan_state);
149 static bool is_branching_command(const char *cmd);
150 static void save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
151 PQExpBuffer query_buf);
152 static void discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
153 PQExpBuffer query_buf);
154 static bool copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf);
155 static bool do_connect(enum trivalue reuse_previous_specification,
156 char *dbname, char *user, char *host, char *port);
157 static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
158 int lineno, bool discard_on_quit, bool *edited);
159 static bool do_shell(const char *command);
160 static bool do_watch(PQExpBuffer query_buf, double sleep);
161 static bool lookup_object_oid(EditableObjectType obj_type, const char *desc,
162 Oid *obj_oid);
163 static bool get_create_object_cmd(EditableObjectType obj_type, Oid oid,
164 PQExpBuffer buf);
165 static int strip_lineno_from_objdesc(char *obj);
166 static int count_lines_in_buf(PQExpBuffer buf);
167 static void print_with_linenumbers(FILE *output, char *lines,
168 const char *header_keyword);
169 static void minimal_error_message(PGresult *res);
170
171 static void printSSLInfo(void);
172 static void printGSSInfo(void);
173 static bool printPsetInfo(const char *param, printQueryOpt *popt);
174 static char *pset_value_string(const char *param, printQueryOpt *popt);
175
176 #ifdef WIN32
177 static void checkWin32Codepage(void);
178 #endif
179
180
181
182 /*----------
183 * HandleSlashCmds:
184 *
185 * Handles all the different commands that start with '\'.
186 * Ordinarily called by MainLoop().
187 *
188 * scan_state is a lexer working state that is set to continue scanning
189 * just after the '\'. The lexer is advanced past the command and all
190 * arguments on return.
191 *
192 * cstack is the current \if stack state. This will be examined, and
193 * possibly modified by conditional commands.
194 *
195 * query_buf contains the query-so-far, which may be modified by
196 * execution of the backslash command (for example, \r clears it).
197 *
198 * previous_buf contains the query most recently sent to the server
199 * (empty if none yet). This should not be modified here, but some
200 * commands copy its content into query_buf.
201 *
202 * query_buf and previous_buf will be NULL when executing a "-c"
203 * command-line option.
204 *
205 * Returns a status code indicating what action is desired, see command.h.
206 *----------
207 */
208
209 backslashResult
HandleSlashCmds(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf,PQExpBuffer previous_buf)210 HandleSlashCmds(PsqlScanState scan_state,
211 ConditionalStack cstack,
212 PQExpBuffer query_buf,
213 PQExpBuffer previous_buf)
214 {
215 backslashResult status;
216 char *cmd;
217 char *arg;
218
219 Assert(scan_state != NULL);
220 Assert(cstack != NULL);
221
222 /* Parse off the command name */
223 cmd = psql_scan_slash_command(scan_state);
224
225 /* And try to execute it */
226 status = exec_command(cmd, scan_state, cstack, query_buf, previous_buf);
227
228 if (status == PSQL_CMD_UNKNOWN)
229 {
230 pg_log_error("invalid command \\%s", cmd);
231 if (pset.cur_cmd_interactive)
232 pg_log_info("Try \\? for help.");
233 status = PSQL_CMD_ERROR;
234 }
235
236 if (status != PSQL_CMD_ERROR)
237 {
238 /*
239 * Eat any remaining arguments after a valid command. We want to
240 * suppress evaluation of backticks in this situation, so transiently
241 * push an inactive conditional-stack entry.
242 */
243 bool active_branch = conditional_active(cstack);
244
245 conditional_stack_push(cstack, IFSTATE_IGNORED);
246 while ((arg = psql_scan_slash_option(scan_state,
247 OT_NORMAL, NULL, false)))
248 {
249 if (active_branch)
250 pg_log_warning("\\%s: extra argument \"%s\" ignored", cmd, arg);
251 free(arg);
252 }
253 conditional_stack_pop(cstack);
254 }
255 else
256 {
257 /* silently throw away rest of line after an erroneous command */
258 while ((arg = psql_scan_slash_option(scan_state,
259 OT_WHOLE_LINE, NULL, false)))
260 free(arg);
261 }
262
263 /* if there is a trailing \\, swallow it */
264 psql_scan_slash_command_end(scan_state);
265
266 free(cmd);
267
268 /* some commands write to queryFout, so make sure output is sent */
269 fflush(pset.queryFout);
270
271 return status;
272 }
273
274
275 /*
276 * Subroutine to actually try to execute a backslash command.
277 *
278 * The typical "success" result code is PSQL_CMD_SKIP_LINE, although some
279 * commands return something else. Failure results are PSQL_CMD_ERROR,
280 * unless PSQL_CMD_UNKNOWN is more appropriate.
281 */
282 static backslashResult
exec_command(const char * cmd,PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf,PQExpBuffer previous_buf)283 exec_command(const char *cmd,
284 PsqlScanState scan_state,
285 ConditionalStack cstack,
286 PQExpBuffer query_buf,
287 PQExpBuffer previous_buf)
288 {
289 backslashResult status;
290 bool active_branch = conditional_active(cstack);
291
292 /*
293 * In interactive mode, warn when we're ignoring a command within a false
294 * \if-branch. But we continue on, so as to parse and discard the right
295 * amount of parameter text. Each individual backslash command subroutine
296 * is responsible for doing nothing after discarding appropriate
297 * arguments, if !active_branch.
298 */
299 if (pset.cur_cmd_interactive && !active_branch &&
300 !is_branching_command(cmd))
301 {
302 pg_log_warning("\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block",
303 cmd);
304 }
305
306 if (strcmp(cmd, "a") == 0)
307 status = exec_command_a(scan_state, active_branch);
308 else if (strcmp(cmd, "C") == 0)
309 status = exec_command_C(scan_state, active_branch);
310 else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
311 status = exec_command_connect(scan_state, active_branch);
312 else if (strcmp(cmd, "cd") == 0)
313 status = exec_command_cd(scan_state, active_branch, cmd);
314 else if (strcmp(cmd, "conninfo") == 0)
315 status = exec_command_conninfo(scan_state, active_branch);
316 else if (pg_strcasecmp(cmd, "copy") == 0)
317 status = exec_command_copy(scan_state, active_branch);
318 else if (strcmp(cmd, "copyright") == 0)
319 status = exec_command_copyright(scan_state, active_branch);
320 else if (strcmp(cmd, "crosstabview") == 0)
321 status = exec_command_crosstabview(scan_state, active_branch);
322 else if (cmd[0] == 'd')
323 status = exec_command_d(scan_state, active_branch, cmd);
324 else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
325 status = exec_command_edit(scan_state, active_branch,
326 query_buf, previous_buf);
327 else if (strcmp(cmd, "ef") == 0)
328 status = exec_command_ef_ev(scan_state, active_branch, query_buf, true);
329 else if (strcmp(cmd, "ev") == 0)
330 status = exec_command_ef_ev(scan_state, active_branch, query_buf, false);
331 else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0 ||
332 strcmp(cmd, "warn") == 0)
333 status = exec_command_echo(scan_state, active_branch, cmd);
334 else if (strcmp(cmd, "elif") == 0)
335 status = exec_command_elif(scan_state, cstack, query_buf);
336 else if (strcmp(cmd, "else") == 0)
337 status = exec_command_else(scan_state, cstack, query_buf);
338 else if (strcmp(cmd, "endif") == 0)
339 status = exec_command_endif(scan_state, cstack, query_buf);
340 else if (strcmp(cmd, "encoding") == 0)
341 status = exec_command_encoding(scan_state, active_branch);
342 else if (strcmp(cmd, "errverbose") == 0)
343 status = exec_command_errverbose(scan_state, active_branch);
344 else if (strcmp(cmd, "f") == 0)
345 status = exec_command_f(scan_state, active_branch);
346 else if (strcmp(cmd, "g") == 0 || strcmp(cmd, "gx") == 0)
347 status = exec_command_g(scan_state, active_branch, cmd);
348 else if (strcmp(cmd, "gdesc") == 0)
349 status = exec_command_gdesc(scan_state, active_branch);
350 else if (strcmp(cmd, "gexec") == 0)
351 status = exec_command_gexec(scan_state, active_branch);
352 else if (strcmp(cmd, "gset") == 0)
353 status = exec_command_gset(scan_state, active_branch);
354 else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
355 status = exec_command_help(scan_state, active_branch);
356 else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
357 status = exec_command_html(scan_state, active_branch);
358 else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0 ||
359 strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
360 status = exec_command_include(scan_state, active_branch, cmd);
361 else if (strcmp(cmd, "if") == 0)
362 status = exec_command_if(scan_state, cstack, query_buf);
363 else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 ||
364 strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
365 status = exec_command_list(scan_state, active_branch, cmd);
366 else if (strncmp(cmd, "lo_", 3) == 0)
367 status = exec_command_lo(scan_state, active_branch, cmd);
368 else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
369 status = exec_command_out(scan_state, active_branch);
370 else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
371 status = exec_command_print(scan_state, active_branch,
372 query_buf, previous_buf);
373 else if (strcmp(cmd, "password") == 0)
374 status = exec_command_password(scan_state, active_branch);
375 else if (strcmp(cmd, "prompt") == 0)
376 status = exec_command_prompt(scan_state, active_branch, cmd);
377 else if (strcmp(cmd, "pset") == 0)
378 status = exec_command_pset(scan_state, active_branch);
379 else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
380 status = exec_command_quit(scan_state, active_branch);
381 else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
382 status = exec_command_reset(scan_state, active_branch, query_buf);
383 else if (strcmp(cmd, "s") == 0)
384 status = exec_command_s(scan_state, active_branch);
385 else if (strcmp(cmd, "set") == 0)
386 status = exec_command_set(scan_state, active_branch);
387 else if (strcmp(cmd, "setenv") == 0)
388 status = exec_command_setenv(scan_state, active_branch, cmd);
389 else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
390 status = exec_command_sf_sv(scan_state, active_branch, cmd, true);
391 else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0)
392 status = exec_command_sf_sv(scan_state, active_branch, cmd, false);
393 else if (strcmp(cmd, "t") == 0)
394 status = exec_command_t(scan_state, active_branch);
395 else if (strcmp(cmd, "T") == 0)
396 status = exec_command_T(scan_state, active_branch);
397 else if (strcmp(cmd, "timing") == 0)
398 status = exec_command_timing(scan_state, active_branch);
399 else if (strcmp(cmd, "unset") == 0)
400 status = exec_command_unset(scan_state, active_branch, cmd);
401 else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
402 status = exec_command_write(scan_state, active_branch, cmd,
403 query_buf, previous_buf);
404 else if (strcmp(cmd, "watch") == 0)
405 status = exec_command_watch(scan_state, active_branch,
406 query_buf, previous_buf);
407 else if (strcmp(cmd, "x") == 0)
408 status = exec_command_x(scan_state, active_branch);
409 else if (strcmp(cmd, "z") == 0)
410 status = exec_command_z(scan_state, active_branch);
411 else if (strcmp(cmd, "!") == 0)
412 status = exec_command_shell_escape(scan_state, active_branch);
413 else if (strcmp(cmd, "?") == 0)
414 status = exec_command_slash_command_help(scan_state, active_branch);
415 else
416 status = PSQL_CMD_UNKNOWN;
417
418 /*
419 * All the commands that return PSQL_CMD_SEND want to execute previous_buf
420 * if query_buf is empty. For convenience we implement that here, not in
421 * the individual command subroutines.
422 */
423 if (status == PSQL_CMD_SEND)
424 (void) copy_previous_query(query_buf, previous_buf);
425
426 return status;
427 }
428
429
430 /*
431 * \a -- toggle field alignment
432 *
433 * This makes little sense but we keep it around.
434 */
435 static backslashResult
exec_command_a(PsqlScanState scan_state,bool active_branch)436 exec_command_a(PsqlScanState scan_state, bool active_branch)
437 {
438 bool success = true;
439
440 if (active_branch)
441 {
442 if (pset.popt.topt.format != PRINT_ALIGNED)
443 success = do_pset("format", "aligned", &pset.popt, pset.quiet);
444 else
445 success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
446 }
447
448 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
449 }
450
451 /*
452 * \C -- override table title (formerly change HTML caption)
453 */
454 static backslashResult
exec_command_C(PsqlScanState scan_state,bool active_branch)455 exec_command_C(PsqlScanState scan_state, bool active_branch)
456 {
457 bool success = true;
458
459 if (active_branch)
460 {
461 char *opt = psql_scan_slash_option(scan_state,
462 OT_NORMAL, NULL, true);
463
464 success = do_pset("title", opt, &pset.popt, pset.quiet);
465 free(opt);
466 }
467 else
468 ignore_slash_options(scan_state);
469
470 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
471 }
472
473 /*
474 * \c or \connect -- connect to database using the specified parameters.
475 *
476 * \c [-reuse-previous=BOOL] dbname user host port
477 *
478 * Specifying a parameter as '-' is equivalent to omitting it. Examples:
479 *
480 * \c - - hst Connect to current database on current port of
481 * host "hst" as current user.
482 * \c - usr - prt Connect to current database on port "prt" of current host
483 * as user "usr".
484 * \c dbs Connect to database "dbs" on current port of current host
485 * as current user.
486 */
487 static backslashResult
exec_command_connect(PsqlScanState scan_state,bool active_branch)488 exec_command_connect(PsqlScanState scan_state, bool active_branch)
489 {
490 bool success = true;
491
492 if (active_branch)
493 {
494 static const char prefix[] = "-reuse-previous=";
495 char *opt1,
496 *opt2,
497 *opt3,
498 *opt4;
499 enum trivalue reuse_previous = TRI_DEFAULT;
500
501 opt1 = read_connect_arg(scan_state);
502 if (opt1 != NULL && strncmp(opt1, prefix, sizeof(prefix) - 1) == 0)
503 {
504 bool on_off;
505
506 success = ParseVariableBool(opt1 + sizeof(prefix) - 1,
507 "-reuse-previous",
508 &on_off);
509 if (success)
510 {
511 reuse_previous = on_off ? TRI_YES : TRI_NO;
512 free(opt1);
513 opt1 = read_connect_arg(scan_state);
514 }
515 }
516
517 if (success) /* give up if reuse_previous was invalid */
518 {
519 opt2 = read_connect_arg(scan_state);
520 opt3 = read_connect_arg(scan_state);
521 opt4 = read_connect_arg(scan_state);
522
523 success = do_connect(reuse_previous, opt1, opt2, opt3, opt4);
524
525 free(opt2);
526 free(opt3);
527 free(opt4);
528 }
529 free(opt1);
530 }
531 else
532 ignore_slash_options(scan_state);
533
534 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
535 }
536
537 /*
538 * \cd -- change directory
539 */
540 static backslashResult
exec_command_cd(PsqlScanState scan_state,bool active_branch,const char * cmd)541 exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
542 {
543 bool success = true;
544
545 if (active_branch)
546 {
547 char *opt = psql_scan_slash_option(scan_state,
548 OT_NORMAL, NULL, true);
549 char *dir;
550
551 if (opt)
552 dir = opt;
553 else
554 {
555 #ifndef WIN32
556 struct passwd *pw;
557 uid_t user_id = geteuid();
558
559 errno = 0; /* clear errno before call */
560 pw = getpwuid(user_id);
561 if (!pw)
562 {
563 pg_log_error("could not get home directory for user ID %ld: %s",
564 (long) user_id,
565 errno ? strerror(errno) : _("user does not exist"));
566 exit(EXIT_FAILURE);
567 }
568 dir = pw->pw_dir;
569 #else /* WIN32 */
570
571 /*
572 * On Windows, 'cd' without arguments prints the current
573 * directory, so if someone wants to code this here instead...
574 */
575 dir = "/";
576 #endif /* WIN32 */
577 }
578
579 if (chdir(dir) == -1)
580 {
581 pg_log_error("\\%s: could not change directory to \"%s\": %m",
582 cmd, dir);
583 success = false;
584 }
585
586 if (opt)
587 free(opt);
588 }
589 else
590 ignore_slash_options(scan_state);
591
592 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
593 }
594
595 /*
596 * \conninfo -- display information about the current connection
597 */
598 static backslashResult
exec_command_conninfo(PsqlScanState scan_state,bool active_branch)599 exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
600 {
601 if (active_branch)
602 {
603 char *db = PQdb(pset.db);
604
605 if (db == NULL)
606 printf(_("You are currently not connected to a database.\n"));
607 else
608 {
609 char *host = PQhost(pset.db);
610 char *hostaddr = PQhostaddr(pset.db);
611
612 if (is_unixsock_path(host))
613 {
614 /* hostaddr overrides host */
615 if (hostaddr && *hostaddr)
616 printf(_("You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"),
617 db, PQuser(pset.db), hostaddr, PQport(pset.db));
618 else
619 printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
620 db, PQuser(pset.db), host, PQport(pset.db));
621 }
622 else
623 {
624 if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0)
625 printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"),
626 db, PQuser(pset.db), host, hostaddr, PQport(pset.db));
627 else
628 printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
629 db, PQuser(pset.db), host, PQport(pset.db));
630 }
631 printSSLInfo();
632 printGSSInfo();
633 }
634 }
635
636 return PSQL_CMD_SKIP_LINE;
637 }
638
639 /*
640 * \copy -- run a COPY command
641 */
642 static backslashResult
exec_command_copy(PsqlScanState scan_state,bool active_branch)643 exec_command_copy(PsqlScanState scan_state, bool active_branch)
644 {
645 bool success = true;
646
647 if (active_branch)
648 {
649 char *opt = psql_scan_slash_option(scan_state,
650 OT_WHOLE_LINE, NULL, false);
651
652 success = do_copy(opt);
653 free(opt);
654 }
655 else
656 ignore_slash_whole_line(scan_state);
657
658 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
659 }
660
661 /*
662 * \copyright -- print copyright notice
663 */
664 static backslashResult
exec_command_copyright(PsqlScanState scan_state,bool active_branch)665 exec_command_copyright(PsqlScanState scan_state, bool active_branch)
666 {
667 if (active_branch)
668 print_copyright();
669
670 return PSQL_CMD_SKIP_LINE;
671 }
672
673 /*
674 * \crosstabview -- execute a query and display results in crosstab
675 */
676 static backslashResult
exec_command_crosstabview(PsqlScanState scan_state,bool active_branch)677 exec_command_crosstabview(PsqlScanState scan_state, bool active_branch)
678 {
679 backslashResult status = PSQL_CMD_SKIP_LINE;
680
681 if (active_branch)
682 {
683 int i;
684
685 for (i = 0; i < lengthof(pset.ctv_args); i++)
686 pset.ctv_args[i] = psql_scan_slash_option(scan_state,
687 OT_NORMAL, NULL, true);
688 pset.crosstab_flag = true;
689 status = PSQL_CMD_SEND;
690 }
691 else
692 ignore_slash_options(scan_state);
693
694 return status;
695 }
696
697 /*
698 * \d* commands
699 */
700 static backslashResult
exec_command_d(PsqlScanState scan_state,bool active_branch,const char * cmd)701 exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
702 {
703 backslashResult status = PSQL_CMD_SKIP_LINE;
704 bool success = true;
705
706 if (active_branch)
707 {
708 char *pattern;
709 bool show_verbose,
710 show_system;
711
712 /* We don't do SQLID reduction on the pattern yet */
713 pattern = psql_scan_slash_option(scan_state,
714 OT_NORMAL, NULL, true);
715
716 show_verbose = strchr(cmd, '+') ? true : false;
717 show_system = strchr(cmd, 'S') ? true : false;
718
719 switch (cmd[1])
720 {
721 case '\0':
722 case '+':
723 case 'S':
724 if (pattern)
725 success = describeTableDetails(pattern, show_verbose, show_system);
726 else
727 /* standard listing of interesting things */
728 success = listTables("tvmsE", NULL, show_verbose, show_system);
729 break;
730 case 'A':
731 {
732 char *pattern2 = NULL;
733
734 if (pattern && cmd[2] != '\0' && cmd[2] != '+')
735 pattern2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
736
737 switch (cmd[2])
738 {
739 case '\0':
740 case '+':
741 success = describeAccessMethods(pattern, show_verbose);
742 break;
743 case 'c':
744 success = listOperatorClasses(pattern, pattern2, show_verbose);
745 break;
746 case 'f':
747 success = listOperatorFamilies(pattern, pattern2, show_verbose);
748 break;
749 case 'o':
750 success = listOpFamilyOperators(pattern, pattern2, show_verbose);
751 break;
752 case 'p':
753 success = listOpFamilyFunctions(pattern, pattern2, show_verbose);
754 break;
755 default:
756 status = PSQL_CMD_UNKNOWN;
757 break;
758 }
759
760 if (pattern2)
761 free(pattern2);
762 }
763 break;
764 case 'a':
765 success = describeAggregates(pattern, show_verbose, show_system);
766 break;
767 case 'b':
768 success = describeTablespaces(pattern, show_verbose);
769 break;
770 case 'c':
771 success = listConversions(pattern, show_verbose, show_system);
772 break;
773 case 'C':
774 success = listCasts(pattern, show_verbose);
775 break;
776 case 'd':
777 if (strncmp(cmd, "ddp", 3) == 0)
778 success = listDefaultACLs(pattern);
779 else
780 success = objectDescription(pattern, show_system);
781 break;
782 case 'D':
783 success = listDomains(pattern, show_verbose, show_system);
784 break;
785 case 'f': /* function subsystem */
786 switch (cmd[2])
787 {
788 case '\0':
789 case '+':
790 case 'S':
791 case 'a':
792 case 'n':
793 case 'p':
794 case 't':
795 case 'w':
796 success = exec_command_dfo(scan_state, cmd, pattern,
797 show_verbose, show_system);
798 break;
799 default:
800 status = PSQL_CMD_UNKNOWN;
801 break;
802 }
803 break;
804 case 'g':
805 /* no longer distinct from \du */
806 success = describeRoles(pattern, show_verbose, show_system);
807 break;
808 case 'l':
809 success = do_lo_list();
810 break;
811 case 'L':
812 success = listLanguages(pattern, show_verbose, show_system);
813 break;
814 case 'n':
815 success = listSchemas(pattern, show_verbose, show_system);
816 break;
817 case 'o':
818 success = exec_command_dfo(scan_state, cmd, pattern,
819 show_verbose, show_system);
820 break;
821 case 'O':
822 success = listCollations(pattern, show_verbose, show_system);
823 break;
824 case 'p':
825 success = permissionsList(pattern);
826 break;
827 case 'P':
828 {
829 switch (cmd[2])
830 {
831 case '\0':
832 case '+':
833 case 't':
834 case 'i':
835 case 'n':
836 success = listPartitionedTables(&cmd[2], pattern, show_verbose);
837 break;
838 default:
839 status = PSQL_CMD_UNKNOWN;
840 break;
841 }
842 }
843 break;
844 case 'T':
845 success = describeTypes(pattern, show_verbose, show_system);
846 break;
847 case 't':
848 case 'v':
849 case 'm':
850 case 'i':
851 case 's':
852 case 'E':
853 success = listTables(&cmd[1], pattern, show_verbose, show_system);
854 break;
855 case 'r':
856 if (cmd[2] == 'd' && cmd[3] == 's')
857 {
858 char *pattern2 = NULL;
859
860 if (pattern)
861 pattern2 = psql_scan_slash_option(scan_state,
862 OT_NORMAL, NULL, true);
863 success = listDbRoleSettings(pattern, pattern2);
864
865 if (pattern2)
866 free(pattern2);
867 }
868 else
869 status = PSQL_CMD_UNKNOWN;
870 break;
871 case 'R':
872 switch (cmd[2])
873 {
874 case 'p':
875 if (show_verbose)
876 success = describePublications(pattern);
877 else
878 success = listPublications(pattern);
879 break;
880 case 's':
881 success = describeSubscriptions(pattern, show_verbose);
882 break;
883 default:
884 status = PSQL_CMD_UNKNOWN;
885 }
886 break;
887 case 'u':
888 success = describeRoles(pattern, show_verbose, show_system);
889 break;
890 case 'F': /* text search subsystem */
891 switch (cmd[2])
892 {
893 case '\0':
894 case '+':
895 success = listTSConfigs(pattern, show_verbose);
896 break;
897 case 'p':
898 success = listTSParsers(pattern, show_verbose);
899 break;
900 case 'd':
901 success = listTSDictionaries(pattern, show_verbose);
902 break;
903 case 't':
904 success = listTSTemplates(pattern, show_verbose);
905 break;
906 default:
907 status = PSQL_CMD_UNKNOWN;
908 break;
909 }
910 break;
911 case 'e': /* SQL/MED subsystem */
912 switch (cmd[2])
913 {
914 case 's':
915 success = listForeignServers(pattern, show_verbose);
916 break;
917 case 'u':
918 success = listUserMappings(pattern, show_verbose);
919 break;
920 case 'w':
921 success = listForeignDataWrappers(pattern, show_verbose);
922 break;
923 case 't':
924 success = listForeignTables(pattern, show_verbose);
925 break;
926 default:
927 status = PSQL_CMD_UNKNOWN;
928 break;
929 }
930 break;
931 case 'x': /* Extensions */
932 if (show_verbose)
933 success = listExtensionContents(pattern);
934 else
935 success = listExtensions(pattern);
936 break;
937 case 'X': /* Extended Statistics */
938 success = listExtendedStats(pattern);
939 break;
940 case 'y': /* Event Triggers */
941 success = listEventTriggers(pattern, show_verbose);
942 break;
943 default:
944 status = PSQL_CMD_UNKNOWN;
945 }
946
947 if (pattern)
948 free(pattern);
949 }
950 else
951 ignore_slash_options(scan_state);
952
953 if (!success)
954 status = PSQL_CMD_ERROR;
955
956 return status;
957 }
958
959 /* \df and \do; messy enough to split out of exec_command_d */
960 static bool
exec_command_dfo(PsqlScanState scan_state,const char * cmd,const char * pattern,bool show_verbose,bool show_system)961 exec_command_dfo(PsqlScanState scan_state, const char *cmd,
962 const char *pattern,
963 bool show_verbose, bool show_system)
964 {
965 bool success;
966 char *arg_patterns[FUNC_MAX_ARGS];
967 int num_arg_patterns = 0;
968
969 /* Collect argument-type patterns too */
970 if (pattern) /* otherwise it was just \df or \do */
971 {
972 char *ap;
973
974 while ((ap = psql_scan_slash_option(scan_state,
975 OT_NORMAL, NULL, true)) != NULL)
976 {
977 arg_patterns[num_arg_patterns++] = ap;
978 if (num_arg_patterns >= FUNC_MAX_ARGS)
979 break; /* protect limited-size array */
980 }
981 }
982
983 if (cmd[1] == 'f')
984 success = describeFunctions(&cmd[2], pattern,
985 arg_patterns, num_arg_patterns,
986 show_verbose, show_system);
987 else
988 success = describeOperators(pattern,
989 arg_patterns, num_arg_patterns,
990 show_verbose, show_system);
991
992 while (--num_arg_patterns >= 0)
993 free(arg_patterns[num_arg_patterns]);
994
995 return success;
996 }
997
998 /*
999 * \e or \edit -- edit the current query buffer, or edit a file and
1000 * make it the query buffer
1001 */
1002 static backslashResult
exec_command_edit(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,PQExpBuffer previous_buf)1003 exec_command_edit(PsqlScanState scan_state, bool active_branch,
1004 PQExpBuffer query_buf, PQExpBuffer previous_buf)
1005 {
1006 backslashResult status = PSQL_CMD_SKIP_LINE;
1007
1008 if (active_branch)
1009 {
1010 if (!query_buf)
1011 {
1012 pg_log_error("no query buffer");
1013 status = PSQL_CMD_ERROR;
1014 }
1015 else
1016 {
1017 char *fname;
1018 char *ln = NULL;
1019 int lineno = -1;
1020
1021 fname = psql_scan_slash_option(scan_state,
1022 OT_NORMAL, NULL, true);
1023 if (fname)
1024 {
1025 /* try to get separate lineno arg */
1026 ln = psql_scan_slash_option(scan_state,
1027 OT_NORMAL, NULL, true);
1028 if (ln == NULL)
1029 {
1030 /* only one arg; maybe it is lineno not fname */
1031 if (fname[0] &&
1032 strspn(fname, "0123456789") == strlen(fname))
1033 {
1034 /* all digits, so assume it is lineno */
1035 ln = fname;
1036 fname = NULL;
1037 }
1038 }
1039 }
1040 if (ln)
1041 {
1042 lineno = atoi(ln);
1043 if (lineno < 1)
1044 {
1045 pg_log_error("invalid line number: %s", ln);
1046 status = PSQL_CMD_ERROR;
1047 }
1048 }
1049 if (status != PSQL_CMD_ERROR)
1050 {
1051 bool discard_on_quit;
1052
1053 expand_tilde(&fname);
1054 if (fname)
1055 {
1056 canonicalize_path(fname);
1057 /* Always clear buffer if the file isn't modified */
1058 discard_on_quit = true;
1059 }
1060 else
1061 {
1062 /*
1063 * If query_buf is empty, recall previous query for
1064 * editing. But in that case, the query buffer should be
1065 * emptied if editing doesn't modify the file.
1066 */
1067 discard_on_quit = copy_previous_query(query_buf,
1068 previous_buf);
1069 }
1070
1071 if (do_edit(fname, query_buf, lineno, discard_on_quit, NULL))
1072 status = PSQL_CMD_NEWEDIT;
1073 else
1074 status = PSQL_CMD_ERROR;
1075 }
1076 if (fname)
1077 free(fname);
1078 if (ln)
1079 free(ln);
1080 }
1081 }
1082 else
1083 ignore_slash_options(scan_state);
1084
1085 return status;
1086 }
1087
1088 /*
1089 * \ef/\ev -- edit the named function/view, or
1090 * present a blank CREATE FUNCTION/VIEW template if no argument is given
1091 */
1092 static backslashResult
exec_command_ef_ev(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,bool is_func)1093 exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
1094 PQExpBuffer query_buf, bool is_func)
1095 {
1096 backslashResult status = PSQL_CMD_SKIP_LINE;
1097
1098 if (active_branch)
1099 {
1100 char *obj_desc = psql_scan_slash_option(scan_state,
1101 OT_WHOLE_LINE,
1102 NULL, true);
1103 int lineno = -1;
1104
1105 if (pset.sversion < (is_func ? 80400 : 70400))
1106 {
1107 char sverbuf[32];
1108
1109 formatPGVersionNumber(pset.sversion, false,
1110 sverbuf, sizeof(sverbuf));
1111 if (is_func)
1112 pg_log_error("The server (version %s) does not support editing function source.",
1113 sverbuf);
1114 else
1115 pg_log_error("The server (version %s) does not support editing view definitions.",
1116 sverbuf);
1117 status = PSQL_CMD_ERROR;
1118 }
1119 else if (!query_buf)
1120 {
1121 pg_log_error("no query buffer");
1122 status = PSQL_CMD_ERROR;
1123 }
1124 else
1125 {
1126 Oid obj_oid = InvalidOid;
1127 EditableObjectType eot = is_func ? EditableFunction : EditableView;
1128
1129 lineno = strip_lineno_from_objdesc(obj_desc);
1130 if (lineno == 0)
1131 {
1132 /* error already reported */
1133 status = PSQL_CMD_ERROR;
1134 }
1135 else if (!obj_desc)
1136 {
1137 /* set up an empty command to fill in */
1138 resetPQExpBuffer(query_buf);
1139 if (is_func)
1140 appendPQExpBufferStr(query_buf,
1141 "CREATE FUNCTION ( )\n"
1142 " RETURNS \n"
1143 " LANGUAGE \n"
1144 " -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n"
1145 "AS $function$\n"
1146 "\n$function$\n");
1147 else
1148 appendPQExpBufferStr(query_buf,
1149 "CREATE VIEW AS\n"
1150 " SELECT \n"
1151 " -- something...\n");
1152 }
1153 else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
1154 {
1155 /* error already reported */
1156 status = PSQL_CMD_ERROR;
1157 }
1158 else if (!get_create_object_cmd(eot, obj_oid, query_buf))
1159 {
1160 /* error already reported */
1161 status = PSQL_CMD_ERROR;
1162 }
1163 else if (is_func && lineno > 0)
1164 {
1165 /*
1166 * lineno "1" should correspond to the first line of the
1167 * function body. We expect that pg_get_functiondef() will
1168 * emit that on a line beginning with "AS ", and that there
1169 * can be no such line before the real start of the function
1170 * body. Increment lineno by the number of lines before that
1171 * line, so that it becomes relative to the first line of the
1172 * function definition.
1173 */
1174 const char *lines = query_buf->data;
1175
1176 while (*lines != '\0')
1177 {
1178 if (strncmp(lines, "AS ", 3) == 0)
1179 break;
1180 lineno++;
1181 /* find start of next line */
1182 lines = strchr(lines, '\n');
1183 if (!lines)
1184 break;
1185 lines++;
1186 }
1187 }
1188 }
1189
1190 if (status != PSQL_CMD_ERROR)
1191 {
1192 bool edited = false;
1193
1194 if (!do_edit(NULL, query_buf, lineno, true, &edited))
1195 status = PSQL_CMD_ERROR;
1196 else if (!edited)
1197 puts(_("No changes"));
1198 else
1199 status = PSQL_CMD_NEWEDIT;
1200 }
1201
1202 if (obj_desc)
1203 free(obj_desc);
1204 }
1205 else
1206 ignore_slash_whole_line(scan_state);
1207
1208 return status;
1209 }
1210
1211 /*
1212 * \echo, \qecho, and \warn -- echo arguments to stdout, query output, or stderr
1213 */
1214 static backslashResult
exec_command_echo(PsqlScanState scan_state,bool active_branch,const char * cmd)1215 exec_command_echo(PsqlScanState scan_state, bool active_branch, const char *cmd)
1216 {
1217 if (active_branch)
1218 {
1219 char *value;
1220 char quoted;
1221 bool no_newline = false;
1222 bool first = true;
1223 FILE *fout;
1224
1225 if (strcmp(cmd, "qecho") == 0)
1226 fout = pset.queryFout;
1227 else if (strcmp(cmd, "warn") == 0)
1228 fout = stderr;
1229 else
1230 fout = stdout;
1231
1232 while ((value = psql_scan_slash_option(scan_state,
1233 OT_NORMAL, "ed, false)))
1234 {
1235 if (first && !no_newline && !quoted && strcmp(value, "-n") == 0)
1236 no_newline = true;
1237 else
1238 {
1239 if (first)
1240 first = false;
1241 else
1242 fputc(' ', fout);
1243 fputs(value, fout);
1244 }
1245 free(value);
1246 }
1247 if (!no_newline)
1248 fputs("\n", fout);
1249 }
1250 else
1251 ignore_slash_options(scan_state);
1252
1253 return PSQL_CMD_SKIP_LINE;
1254 }
1255
1256 /*
1257 * \encoding -- set/show client side encoding
1258 */
1259 static backslashResult
exec_command_encoding(PsqlScanState scan_state,bool active_branch)1260 exec_command_encoding(PsqlScanState scan_state, bool active_branch)
1261 {
1262 if (active_branch)
1263 {
1264 char *encoding = psql_scan_slash_option(scan_state,
1265 OT_NORMAL, NULL, false);
1266
1267 if (!encoding)
1268 {
1269 /* show encoding */
1270 puts(pg_encoding_to_char(pset.encoding));
1271 }
1272 else
1273 {
1274 /* set encoding */
1275 if (PQsetClientEncoding(pset.db, encoding) == -1)
1276 pg_log_error("%s: invalid encoding name or conversion procedure not found", encoding);
1277 else
1278 {
1279 /* save encoding info into psql internal data */
1280 pset.encoding = PQclientEncoding(pset.db);
1281 pset.popt.topt.encoding = pset.encoding;
1282 SetVariable(pset.vars, "ENCODING",
1283 pg_encoding_to_char(pset.encoding));
1284 }
1285 free(encoding);
1286 }
1287 }
1288 else
1289 ignore_slash_options(scan_state);
1290
1291 return PSQL_CMD_SKIP_LINE;
1292 }
1293
1294 /*
1295 * \errverbose -- display verbose message from last failed query
1296 */
1297 static backslashResult
exec_command_errverbose(PsqlScanState scan_state,bool active_branch)1298 exec_command_errverbose(PsqlScanState scan_state, bool active_branch)
1299 {
1300 if (active_branch)
1301 {
1302 if (pset.last_error_result)
1303 {
1304 char *msg;
1305
1306 msg = PQresultVerboseErrorMessage(pset.last_error_result,
1307 PQERRORS_VERBOSE,
1308 PQSHOW_CONTEXT_ALWAYS);
1309 if (msg)
1310 {
1311 pg_log_error("%s", msg);
1312 PQfreemem(msg);
1313 }
1314 else
1315 puts(_("out of memory"));
1316 }
1317 else
1318 puts(_("There is no previous error."));
1319 }
1320
1321 return PSQL_CMD_SKIP_LINE;
1322 }
1323
1324 /*
1325 * \f -- change field separator
1326 */
1327 static backslashResult
exec_command_f(PsqlScanState scan_state,bool active_branch)1328 exec_command_f(PsqlScanState scan_state, bool active_branch)
1329 {
1330 bool success = true;
1331
1332 if (active_branch)
1333 {
1334 char *fname = psql_scan_slash_option(scan_state,
1335 OT_NORMAL, NULL, false);
1336
1337 success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
1338 free(fname);
1339 }
1340 else
1341 ignore_slash_options(scan_state);
1342
1343 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1344 }
1345
1346 /*
1347 * \g [(pset-option[=pset-value] ...)] [filename/shell-command]
1348 * \gx [(pset-option[=pset-value] ...)] [filename/shell-command]
1349 *
1350 * Send the current query. If pset options are specified, they are made
1351 * active just for this query. If a filename or pipe command is given,
1352 * the query output goes there. \gx implicitly sets "expanded=on" along
1353 * with any other pset options that are specified.
1354 */
1355 static backslashResult
exec_command_g(PsqlScanState scan_state,bool active_branch,const char * cmd)1356 exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
1357 {
1358 backslashResult status = PSQL_CMD_SKIP_LINE;
1359 char *fname;
1360
1361 /*
1362 * Because the option processing for this is fairly complicated, we do it
1363 * and then decide whether the branch is active.
1364 */
1365 fname = psql_scan_slash_option(scan_state,
1366 OT_FILEPIPE, NULL, false);
1367
1368 if (fname && fname[0] == '(')
1369 {
1370 /* Consume pset options through trailing ')' ... */
1371 status = process_command_g_options(fname + 1, scan_state,
1372 active_branch, cmd);
1373 free(fname);
1374 /* ... and again attempt to scan the filename. */
1375 fname = psql_scan_slash_option(scan_state,
1376 OT_FILEPIPE, NULL, false);
1377 }
1378
1379 if (status == PSQL_CMD_SKIP_LINE && active_branch)
1380 {
1381 if (!fname)
1382 pset.gfname = NULL;
1383 else
1384 {
1385 expand_tilde(&fname);
1386 pset.gfname = pg_strdup(fname);
1387 }
1388 if (strcmp(cmd, "gx") == 0)
1389 {
1390 /* save settings if not done already, then force expanded=on */
1391 if (pset.gsavepopt == NULL)
1392 pset.gsavepopt = savePsetInfo(&pset.popt);
1393 pset.popt.topt.expanded = 1;
1394 }
1395 status = PSQL_CMD_SEND;
1396 }
1397
1398 free(fname);
1399
1400 return status;
1401 }
1402
1403 /*
1404 * Process parenthesized pset options for \g
1405 *
1406 * Note: okay to modify first_option, but not to free it; caller does that
1407 */
1408 static backslashResult
process_command_g_options(char * first_option,PsqlScanState scan_state,bool active_branch,const char * cmd)1409 process_command_g_options(char *first_option, PsqlScanState scan_state,
1410 bool active_branch, const char *cmd)
1411 {
1412 bool success = true;
1413 bool found_r_paren = false;
1414
1415 do
1416 {
1417 char *option;
1418 size_t optlen;
1419
1420 /* If not first time through, collect a new option */
1421 if (first_option)
1422 option = first_option;
1423 else
1424 {
1425 option = psql_scan_slash_option(scan_state,
1426 OT_NORMAL, NULL, false);
1427 if (!option)
1428 {
1429 if (active_branch)
1430 {
1431 pg_log_error("\\%s: missing right parenthesis", cmd);
1432 success = false;
1433 }
1434 break;
1435 }
1436 }
1437
1438 /* Check for terminating right paren, and remove it from string */
1439 optlen = strlen(option);
1440 if (optlen > 0 && option[optlen - 1] == ')')
1441 {
1442 option[--optlen] = '\0';
1443 found_r_paren = true;
1444 }
1445
1446 /* If there was anything besides parentheses, parse/execute it */
1447 if (optlen > 0)
1448 {
1449 /* We can have either "name" or "name=value" */
1450 char *valptr = strchr(option, '=');
1451
1452 if (valptr)
1453 *valptr++ = '\0';
1454 if (active_branch)
1455 {
1456 /* save settings if not done already, then apply option */
1457 if (pset.gsavepopt == NULL)
1458 pset.gsavepopt = savePsetInfo(&pset.popt);
1459 success &= do_pset(option, valptr, &pset.popt, true);
1460 }
1461 }
1462
1463 /* Clean up after this option. We should not free first_option. */
1464 if (first_option)
1465 first_option = NULL;
1466 else
1467 free(option);
1468 } while (!found_r_paren);
1469
1470 /* If we failed after already changing some options, undo side-effects */
1471 if (!success && active_branch && pset.gsavepopt)
1472 {
1473 restorePsetInfo(&pset.popt, pset.gsavepopt);
1474 pset.gsavepopt = NULL;
1475 }
1476
1477 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1478 }
1479
1480 /*
1481 * \gdesc -- describe query result
1482 */
1483 static backslashResult
exec_command_gdesc(PsqlScanState scan_state,bool active_branch)1484 exec_command_gdesc(PsqlScanState scan_state, bool active_branch)
1485 {
1486 backslashResult status = PSQL_CMD_SKIP_LINE;
1487
1488 if (active_branch)
1489 {
1490 pset.gdesc_flag = true;
1491 status = PSQL_CMD_SEND;
1492 }
1493
1494 return status;
1495 }
1496
1497 /*
1498 * \gexec -- send query and execute each field of result
1499 */
1500 static backslashResult
exec_command_gexec(PsqlScanState scan_state,bool active_branch)1501 exec_command_gexec(PsqlScanState scan_state, bool active_branch)
1502 {
1503 backslashResult status = PSQL_CMD_SKIP_LINE;
1504
1505 if (active_branch)
1506 {
1507 pset.gexec_flag = true;
1508 status = PSQL_CMD_SEND;
1509 }
1510
1511 return status;
1512 }
1513
1514 /*
1515 * \gset [prefix] -- send query and store result into variables
1516 */
1517 static backslashResult
exec_command_gset(PsqlScanState scan_state,bool active_branch)1518 exec_command_gset(PsqlScanState scan_state, bool active_branch)
1519 {
1520 backslashResult status = PSQL_CMD_SKIP_LINE;
1521
1522 if (active_branch)
1523 {
1524 char *prefix = psql_scan_slash_option(scan_state,
1525 OT_NORMAL, NULL, false);
1526
1527 if (prefix)
1528 pset.gset_prefix = prefix;
1529 else
1530 {
1531 /* we must set a non-NULL prefix to trigger storing */
1532 pset.gset_prefix = pg_strdup("");
1533 }
1534 /* gset_prefix is freed later */
1535 status = PSQL_CMD_SEND;
1536 }
1537 else
1538 ignore_slash_options(scan_state);
1539
1540 return status;
1541 }
1542
1543 /*
1544 * \help [topic] -- print help about SQL commands
1545 */
1546 static backslashResult
exec_command_help(PsqlScanState scan_state,bool active_branch)1547 exec_command_help(PsqlScanState scan_state, bool active_branch)
1548 {
1549 if (active_branch)
1550 {
1551 char *opt = psql_scan_slash_option(scan_state,
1552 OT_WHOLE_LINE, NULL, false);
1553 size_t len;
1554
1555 /* strip any trailing spaces and semicolons */
1556 if (opt)
1557 {
1558 len = strlen(opt);
1559 while (len > 0 &&
1560 (isspace((unsigned char) opt[len - 1])
1561 || opt[len - 1] == ';'))
1562 opt[--len] = '\0';
1563 }
1564
1565 helpSQL(opt, pset.popt.topt.pager);
1566 free(opt);
1567 }
1568 else
1569 ignore_slash_whole_line(scan_state);
1570
1571 return PSQL_CMD_SKIP_LINE;
1572 }
1573
1574 /*
1575 * \H and \html -- toggle HTML formatting
1576 */
1577 static backslashResult
exec_command_html(PsqlScanState scan_state,bool active_branch)1578 exec_command_html(PsqlScanState scan_state, bool active_branch)
1579 {
1580 bool success = true;
1581
1582 if (active_branch)
1583 {
1584 if (pset.popt.topt.format != PRINT_HTML)
1585 success = do_pset("format", "html", &pset.popt, pset.quiet);
1586 else
1587 success = do_pset("format", "aligned", &pset.popt, pset.quiet);
1588 }
1589
1590 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1591 }
1592
1593 /*
1594 * \i and \ir -- include a file
1595 */
1596 static backslashResult
exec_command_include(PsqlScanState scan_state,bool active_branch,const char * cmd)1597 exec_command_include(PsqlScanState scan_state, bool active_branch, const char *cmd)
1598 {
1599 bool success = true;
1600
1601 if (active_branch)
1602 {
1603 char *fname = psql_scan_slash_option(scan_state,
1604 OT_NORMAL, NULL, true);
1605
1606 if (!fname)
1607 {
1608 pg_log_error("\\%s: missing required argument", cmd);
1609 success = false;
1610 }
1611 else
1612 {
1613 bool include_relative;
1614
1615 include_relative = (strcmp(cmd, "ir") == 0
1616 || strcmp(cmd, "include_relative") == 0);
1617 expand_tilde(&fname);
1618 success = (process_file(fname, include_relative) == EXIT_SUCCESS);
1619 free(fname);
1620 }
1621 }
1622 else
1623 ignore_slash_options(scan_state);
1624
1625 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1626 }
1627
1628 /*
1629 * \if <expr> -- beginning of an \if..\endif block
1630 *
1631 * <expr> is parsed as a boolean expression. Invalid expressions will emit a
1632 * warning and be treated as false. Statements that follow a false expression
1633 * will be parsed but ignored. Note that in the case where an \if statement
1634 * is itself within an inactive section of a block, then the entire inner
1635 * \if..\endif block will be parsed but ignored.
1636 */
1637 static backslashResult
exec_command_if(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1638 exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
1639 PQExpBuffer query_buf)
1640 {
1641 if (conditional_active(cstack))
1642 {
1643 /*
1644 * First, push a new active stack entry; this ensures that the lexer
1645 * will perform variable substitution and backtick evaluation while
1646 * scanning the expression. (That should happen anyway, since we know
1647 * we're in an active outer branch, but let's be sure.)
1648 */
1649 conditional_stack_push(cstack, IFSTATE_TRUE);
1650
1651 /* Remember current query state in case we need to restore later */
1652 save_query_text_state(scan_state, cstack, query_buf);
1653
1654 /*
1655 * Evaluate the expression; if it's false, change to inactive state.
1656 */
1657 if (!is_true_boolean_expression(scan_state, "\\if expression"))
1658 conditional_stack_poke(cstack, IFSTATE_FALSE);
1659 }
1660 else
1661 {
1662 /*
1663 * We're within an inactive outer branch, so this entire \if block
1664 * will be ignored. We don't want to evaluate the expression, so push
1665 * the "ignored" stack state before scanning it.
1666 */
1667 conditional_stack_push(cstack, IFSTATE_IGNORED);
1668
1669 /* Remember current query state in case we need to restore later */
1670 save_query_text_state(scan_state, cstack, query_buf);
1671
1672 ignore_boolean_expression(scan_state);
1673 }
1674
1675 return PSQL_CMD_SKIP_LINE;
1676 }
1677
1678 /*
1679 * \elif <expr> -- alternative branch in an \if..\endif block
1680 *
1681 * <expr> is evaluated the same as in \if <expr>.
1682 */
1683 static backslashResult
exec_command_elif(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1684 exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
1685 PQExpBuffer query_buf)
1686 {
1687 bool success = true;
1688
1689 switch (conditional_stack_peek(cstack))
1690 {
1691 case IFSTATE_TRUE:
1692
1693 /*
1694 * Just finished active branch of this \if block. Update saved
1695 * state so we will keep whatever data was put in query_buf by the
1696 * active branch.
1697 */
1698 save_query_text_state(scan_state, cstack, query_buf);
1699
1700 /*
1701 * Discard \elif expression and ignore the rest until \endif.
1702 * Switch state before reading expression to ensure proper lexer
1703 * behavior.
1704 */
1705 conditional_stack_poke(cstack, IFSTATE_IGNORED);
1706 ignore_boolean_expression(scan_state);
1707 break;
1708 case IFSTATE_FALSE:
1709
1710 /*
1711 * Discard any query text added by the just-skipped branch.
1712 */
1713 discard_query_text(scan_state, cstack, query_buf);
1714
1715 /*
1716 * Have not yet found a true expression in this \if block, so this
1717 * might be the first. We have to change state before examining
1718 * the expression, or the lexer won't do the right thing.
1719 */
1720 conditional_stack_poke(cstack, IFSTATE_TRUE);
1721 if (!is_true_boolean_expression(scan_state, "\\elif expression"))
1722 conditional_stack_poke(cstack, IFSTATE_FALSE);
1723 break;
1724 case IFSTATE_IGNORED:
1725
1726 /*
1727 * Discard any query text added by the just-skipped branch.
1728 */
1729 discard_query_text(scan_state, cstack, query_buf);
1730
1731 /*
1732 * Skip expression and move on. Either the \if block already had
1733 * an active section, or whole block is being skipped.
1734 */
1735 ignore_boolean_expression(scan_state);
1736 break;
1737 case IFSTATE_ELSE_TRUE:
1738 case IFSTATE_ELSE_FALSE:
1739 pg_log_error("\\elif: cannot occur after \\else");
1740 success = false;
1741 break;
1742 case IFSTATE_NONE:
1743 /* no \if to elif from */
1744 pg_log_error("\\elif: no matching \\if");
1745 success = false;
1746 break;
1747 }
1748
1749 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1750 }
1751
1752 /*
1753 * \else -- final alternative in an \if..\endif block
1754 *
1755 * Statements within an \else branch will only be executed if
1756 * all previous \if and \elif expressions evaluated to false
1757 * and the block was not itself being ignored.
1758 */
1759 static backslashResult
exec_command_else(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1760 exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
1761 PQExpBuffer query_buf)
1762 {
1763 bool success = true;
1764
1765 switch (conditional_stack_peek(cstack))
1766 {
1767 case IFSTATE_TRUE:
1768
1769 /*
1770 * Just finished active branch of this \if block. Update saved
1771 * state so we will keep whatever data was put in query_buf by the
1772 * active branch.
1773 */
1774 save_query_text_state(scan_state, cstack, query_buf);
1775
1776 /* Now skip the \else branch */
1777 conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
1778 break;
1779 case IFSTATE_FALSE:
1780
1781 /*
1782 * Discard any query text added by the just-skipped branch.
1783 */
1784 discard_query_text(scan_state, cstack, query_buf);
1785
1786 /*
1787 * We've not found any true \if or \elif expression, so execute
1788 * the \else branch.
1789 */
1790 conditional_stack_poke(cstack, IFSTATE_ELSE_TRUE);
1791 break;
1792 case IFSTATE_IGNORED:
1793
1794 /*
1795 * Discard any query text added by the just-skipped branch.
1796 */
1797 discard_query_text(scan_state, cstack, query_buf);
1798
1799 /*
1800 * Either we previously processed the active branch of this \if,
1801 * or the whole \if block is being skipped. Either way, skip the
1802 * \else branch.
1803 */
1804 conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
1805 break;
1806 case IFSTATE_ELSE_TRUE:
1807 case IFSTATE_ELSE_FALSE:
1808 pg_log_error("\\else: cannot occur after \\else");
1809 success = false;
1810 break;
1811 case IFSTATE_NONE:
1812 /* no \if to else from */
1813 pg_log_error("\\else: no matching \\if");
1814 success = false;
1815 break;
1816 }
1817
1818 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1819 }
1820
1821 /*
1822 * \endif -- ends an \if...\endif block
1823 */
1824 static backslashResult
exec_command_endif(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1825 exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
1826 PQExpBuffer query_buf)
1827 {
1828 bool success = true;
1829
1830 switch (conditional_stack_peek(cstack))
1831 {
1832 case IFSTATE_TRUE:
1833 case IFSTATE_ELSE_TRUE:
1834 /* Close the \if block, keeping the query text */
1835 success = conditional_stack_pop(cstack);
1836 Assert(success);
1837 break;
1838 case IFSTATE_FALSE:
1839 case IFSTATE_IGNORED:
1840 case IFSTATE_ELSE_FALSE:
1841
1842 /*
1843 * Discard any query text added by the just-skipped branch.
1844 */
1845 discard_query_text(scan_state, cstack, query_buf);
1846
1847 /* Close the \if block */
1848 success = conditional_stack_pop(cstack);
1849 Assert(success);
1850 break;
1851 case IFSTATE_NONE:
1852 /* no \if to end */
1853 pg_log_error("\\endif: no matching \\if");
1854 success = false;
1855 break;
1856 }
1857
1858 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1859 }
1860
1861 /*
1862 * \l -- list databases
1863 */
1864 static backslashResult
exec_command_list(PsqlScanState scan_state,bool active_branch,const char * cmd)1865 exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd)
1866 {
1867 bool success = true;
1868
1869 if (active_branch)
1870 {
1871 char *pattern;
1872 bool show_verbose;
1873
1874 pattern = psql_scan_slash_option(scan_state,
1875 OT_NORMAL, NULL, true);
1876
1877 show_verbose = strchr(cmd, '+') ? true : false;
1878
1879 success = listAllDbs(pattern, show_verbose);
1880
1881 if (pattern)
1882 free(pattern);
1883 }
1884 else
1885 ignore_slash_options(scan_state);
1886
1887 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1888 }
1889
1890 /*
1891 * \lo_* -- large object operations
1892 */
1893 static backslashResult
exec_command_lo(PsqlScanState scan_state,bool active_branch,const char * cmd)1894 exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
1895 {
1896 backslashResult status = PSQL_CMD_SKIP_LINE;
1897 bool success = true;
1898
1899 if (active_branch)
1900 {
1901 char *opt1,
1902 *opt2;
1903
1904 opt1 = psql_scan_slash_option(scan_state,
1905 OT_NORMAL, NULL, true);
1906 opt2 = psql_scan_slash_option(scan_state,
1907 OT_NORMAL, NULL, true);
1908
1909 if (strcmp(cmd + 3, "export") == 0)
1910 {
1911 if (!opt2)
1912 {
1913 pg_log_error("\\%s: missing required argument", cmd);
1914 success = false;
1915 }
1916 else
1917 {
1918 expand_tilde(&opt2);
1919 success = do_lo_export(opt1, opt2);
1920 }
1921 }
1922
1923 else if (strcmp(cmd + 3, "import") == 0)
1924 {
1925 if (!opt1)
1926 {
1927 pg_log_error("\\%s: missing required argument", cmd);
1928 success = false;
1929 }
1930 else
1931 {
1932 expand_tilde(&opt1);
1933 success = do_lo_import(opt1, opt2);
1934 }
1935 }
1936
1937 else if (strcmp(cmd + 3, "list") == 0)
1938 success = do_lo_list();
1939
1940 else if (strcmp(cmd + 3, "unlink") == 0)
1941 {
1942 if (!opt1)
1943 {
1944 pg_log_error("\\%s: missing required argument", cmd);
1945 success = false;
1946 }
1947 else
1948 success = do_lo_unlink(opt1);
1949 }
1950
1951 else
1952 status = PSQL_CMD_UNKNOWN;
1953
1954 free(opt1);
1955 free(opt2);
1956 }
1957 else
1958 ignore_slash_options(scan_state);
1959
1960 if (!success)
1961 status = PSQL_CMD_ERROR;
1962
1963 return status;
1964 }
1965
1966 /*
1967 * \o -- set query output
1968 */
1969 static backslashResult
exec_command_out(PsqlScanState scan_state,bool active_branch)1970 exec_command_out(PsqlScanState scan_state, bool active_branch)
1971 {
1972 bool success = true;
1973
1974 if (active_branch)
1975 {
1976 char *fname = psql_scan_slash_option(scan_state,
1977 OT_FILEPIPE, NULL, true);
1978
1979 expand_tilde(&fname);
1980 success = setQFout(fname);
1981 free(fname);
1982 }
1983 else
1984 ignore_slash_filepipe(scan_state);
1985
1986 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1987 }
1988
1989 /*
1990 * \p -- print the current query buffer
1991 */
1992 static backslashResult
exec_command_print(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,PQExpBuffer previous_buf)1993 exec_command_print(PsqlScanState scan_state, bool active_branch,
1994 PQExpBuffer query_buf, PQExpBuffer previous_buf)
1995 {
1996 if (active_branch)
1997 {
1998 /*
1999 * We want to print the same thing \g would execute, but not to change
2000 * the query buffer state; so we can't use copy_previous_query().
2001 * Also, beware of possibility that buffer pointers are NULL.
2002 */
2003 if (query_buf && query_buf->len > 0)
2004 puts(query_buf->data);
2005 else if (previous_buf && previous_buf->len > 0)
2006 puts(previous_buf->data);
2007 else if (!pset.quiet)
2008 puts(_("Query buffer is empty."));
2009 fflush(stdout);
2010 }
2011
2012 return PSQL_CMD_SKIP_LINE;
2013 }
2014
2015 /*
2016 * \password -- set user password
2017 */
2018 static backslashResult
exec_command_password(PsqlScanState scan_state,bool active_branch)2019 exec_command_password(PsqlScanState scan_state, bool active_branch)
2020 {
2021 bool success = true;
2022
2023 if (active_branch)
2024 {
2025 char *opt0 = psql_scan_slash_option(scan_state,
2026 OT_SQLID, NULL, true);
2027 char *pw1;
2028 char *pw2;
2029
2030 pw1 = simple_prompt("Enter new password: ", false);
2031 pw2 = simple_prompt("Enter it again: ", false);
2032
2033 if (strcmp(pw1, pw2) != 0)
2034 {
2035 pg_log_error("Passwords didn't match.");
2036 success = false;
2037 }
2038 else
2039 {
2040 char *user;
2041 char *encrypted_password;
2042
2043 if (opt0)
2044 user = opt0;
2045 else
2046 user = PQuser(pset.db);
2047
2048 encrypted_password = PQencryptPasswordConn(pset.db, pw1, user, NULL);
2049
2050 if (!encrypted_password)
2051 {
2052 pg_log_info("%s", PQerrorMessage(pset.db));
2053 success = false;
2054 }
2055 else
2056 {
2057 PQExpBufferData buf;
2058 PGresult *res;
2059
2060 initPQExpBuffer(&buf);
2061 printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
2062 fmtId(user));
2063 appendStringLiteralConn(&buf, encrypted_password, pset.db);
2064 res = PSQLexec(buf.data);
2065 termPQExpBuffer(&buf);
2066 if (!res)
2067 success = false;
2068 else
2069 PQclear(res);
2070 PQfreemem(encrypted_password);
2071 }
2072 }
2073
2074 if (opt0)
2075 free(opt0);
2076 free(pw1);
2077 free(pw2);
2078 }
2079 else
2080 ignore_slash_options(scan_state);
2081
2082 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2083 }
2084
2085 /*
2086 * \prompt -- prompt and set variable
2087 */
2088 static backslashResult
exec_command_prompt(PsqlScanState scan_state,bool active_branch,const char * cmd)2089 exec_command_prompt(PsqlScanState scan_state, bool active_branch,
2090 const char *cmd)
2091 {
2092 bool success = true;
2093
2094 if (active_branch)
2095 {
2096 char *opt,
2097 *prompt_text = NULL;
2098 char *arg1,
2099 *arg2;
2100
2101 arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
2102 arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
2103
2104 if (!arg1)
2105 {
2106 pg_log_error("\\%s: missing required argument", cmd);
2107 success = false;
2108 }
2109 else
2110 {
2111 char *result;
2112
2113 if (arg2)
2114 {
2115 prompt_text = arg1;
2116 opt = arg2;
2117 }
2118 else
2119 opt = arg1;
2120
2121 if (!pset.inputfile)
2122 {
2123 result = simple_prompt(prompt_text, true);
2124 }
2125 else
2126 {
2127 if (prompt_text)
2128 {
2129 fputs(prompt_text, stdout);
2130 fflush(stdout);
2131 }
2132 result = gets_fromFile(stdin);
2133 if (!result)
2134 {
2135 pg_log_error("\\%s: could not read value for variable",
2136 cmd);
2137 success = false;
2138 }
2139 }
2140
2141 if (result &&
2142 !SetVariable(pset.vars, opt, result))
2143 success = false;
2144
2145 if (result)
2146 free(result);
2147 if (prompt_text)
2148 free(prompt_text);
2149 free(opt);
2150 }
2151 }
2152 else
2153 ignore_slash_options(scan_state);
2154
2155 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2156 }
2157
2158 /*
2159 * \pset -- set printing parameters
2160 */
2161 static backslashResult
exec_command_pset(PsqlScanState scan_state,bool active_branch)2162 exec_command_pset(PsqlScanState scan_state, bool active_branch)
2163 {
2164 bool success = true;
2165
2166 if (active_branch)
2167 {
2168 char *opt0 = psql_scan_slash_option(scan_state,
2169 OT_NORMAL, NULL, false);
2170 char *opt1 = psql_scan_slash_option(scan_state,
2171 OT_NORMAL, NULL, false);
2172
2173 if (!opt0)
2174 {
2175 /* list all variables */
2176
2177 int i;
2178 static const char *const my_list[] = {
2179 "border", "columns", "csv_fieldsep", "expanded", "fieldsep",
2180 "fieldsep_zero", "footer", "format", "linestyle", "null",
2181 "numericlocale", "pager", "pager_min_lines",
2182 "recordsep", "recordsep_zero",
2183 "tableattr", "title", "tuples_only",
2184 "unicode_border_linestyle",
2185 "unicode_column_linestyle",
2186 "unicode_header_linestyle",
2187 NULL
2188 };
2189
2190 for (i = 0; my_list[i] != NULL; i++)
2191 {
2192 char *val = pset_value_string(my_list[i], &pset.popt);
2193
2194 printf("%-24s %s\n", my_list[i], val);
2195 free(val);
2196 }
2197
2198 success = true;
2199 }
2200 else
2201 success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
2202
2203 free(opt0);
2204 free(opt1);
2205 }
2206 else
2207 ignore_slash_options(scan_state);
2208
2209 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2210 }
2211
2212 /*
2213 * \q or \quit -- exit psql
2214 */
2215 static backslashResult
exec_command_quit(PsqlScanState scan_state,bool active_branch)2216 exec_command_quit(PsqlScanState scan_state, bool active_branch)
2217 {
2218 backslashResult status = PSQL_CMD_SKIP_LINE;
2219
2220 if (active_branch)
2221 status = PSQL_CMD_TERMINATE;
2222
2223 return status;
2224 }
2225
2226 /*
2227 * \r -- reset (clear) the query buffer
2228 */
2229 static backslashResult
exec_command_reset(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf)2230 exec_command_reset(PsqlScanState scan_state, bool active_branch,
2231 PQExpBuffer query_buf)
2232 {
2233 if (active_branch)
2234 {
2235 resetPQExpBuffer(query_buf);
2236 psql_scan_reset(scan_state);
2237 if (!pset.quiet)
2238 puts(_("Query buffer reset (cleared)."));
2239 }
2240
2241 return PSQL_CMD_SKIP_LINE;
2242 }
2243
2244 /*
2245 * \s -- save history in a file or show it on the screen
2246 */
2247 static backslashResult
exec_command_s(PsqlScanState scan_state,bool active_branch)2248 exec_command_s(PsqlScanState scan_state, bool active_branch)
2249 {
2250 bool success = true;
2251
2252 if (active_branch)
2253 {
2254 char *fname = psql_scan_slash_option(scan_state,
2255 OT_NORMAL, NULL, true);
2256
2257 expand_tilde(&fname);
2258 success = printHistory(fname, pset.popt.topt.pager);
2259 if (success && !pset.quiet && fname)
2260 printf(_("Wrote history to file \"%s\".\n"), fname);
2261 if (!fname)
2262 putchar('\n');
2263 free(fname);
2264 }
2265 else
2266 ignore_slash_options(scan_state);
2267
2268 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2269 }
2270
2271 /*
2272 * \set -- set variable
2273 */
2274 static backslashResult
exec_command_set(PsqlScanState scan_state,bool active_branch)2275 exec_command_set(PsqlScanState scan_state, bool active_branch)
2276 {
2277 bool success = true;
2278
2279 if (active_branch)
2280 {
2281 char *opt0 = psql_scan_slash_option(scan_state,
2282 OT_NORMAL, NULL, false);
2283
2284 if (!opt0)
2285 {
2286 /* list all variables */
2287 PrintVariables(pset.vars);
2288 success = true;
2289 }
2290 else
2291 {
2292 /*
2293 * Set variable to the concatenation of the arguments.
2294 */
2295 char *newval;
2296 char *opt;
2297
2298 opt = psql_scan_slash_option(scan_state,
2299 OT_NORMAL, NULL, false);
2300 newval = pg_strdup(opt ? opt : "");
2301 free(opt);
2302
2303 while ((opt = psql_scan_slash_option(scan_state,
2304 OT_NORMAL, NULL, false)))
2305 {
2306 newval = pg_realloc(newval, strlen(newval) + strlen(opt) + 1);
2307 strcat(newval, opt);
2308 free(opt);
2309 }
2310
2311 if (!SetVariable(pset.vars, opt0, newval))
2312 success = false;
2313
2314 free(newval);
2315 }
2316 free(opt0);
2317 }
2318 else
2319 ignore_slash_options(scan_state);
2320
2321 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2322 }
2323
2324 /*
2325 * \setenv -- set environment variable
2326 */
2327 static backslashResult
exec_command_setenv(PsqlScanState scan_state,bool active_branch,const char * cmd)2328 exec_command_setenv(PsqlScanState scan_state, bool active_branch,
2329 const char *cmd)
2330 {
2331 bool success = true;
2332
2333 if (active_branch)
2334 {
2335 char *envvar = psql_scan_slash_option(scan_state,
2336 OT_NORMAL, NULL, false);
2337 char *envval = psql_scan_slash_option(scan_state,
2338 OT_NORMAL, NULL, false);
2339
2340 if (!envvar)
2341 {
2342 pg_log_error("\\%s: missing required argument", cmd);
2343 success = false;
2344 }
2345 else if (strchr(envvar, '=') != NULL)
2346 {
2347 pg_log_error("\\%s: environment variable name must not contain \"=\"",
2348 cmd);
2349 success = false;
2350 }
2351 else if (!envval)
2352 {
2353 /* No argument - unset the environment variable */
2354 unsetenv(envvar);
2355 success = true;
2356 }
2357 else
2358 {
2359 /* Set variable to the value of the next argument */
2360 setenv(envvar, envval, 1);
2361 success = true;
2362 }
2363 free(envvar);
2364 free(envval);
2365 }
2366 else
2367 ignore_slash_options(scan_state);
2368
2369 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2370 }
2371
2372 /*
2373 * \sf/\sv -- show a function/view's source code
2374 */
2375 static backslashResult
exec_command_sf_sv(PsqlScanState scan_state,bool active_branch,const char * cmd,bool is_func)2376 exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
2377 const char *cmd, bool is_func)
2378 {
2379 backslashResult status = PSQL_CMD_SKIP_LINE;
2380
2381 if (active_branch)
2382 {
2383 bool show_linenumbers = (strchr(cmd, '+') != NULL);
2384 PQExpBuffer buf;
2385 char *obj_desc;
2386 Oid obj_oid = InvalidOid;
2387 EditableObjectType eot = is_func ? EditableFunction : EditableView;
2388
2389 buf = createPQExpBuffer();
2390 obj_desc = psql_scan_slash_option(scan_state,
2391 OT_WHOLE_LINE, NULL, true);
2392 if (pset.sversion < (is_func ? 80400 : 70400))
2393 {
2394 char sverbuf[32];
2395
2396 formatPGVersionNumber(pset.sversion, false,
2397 sverbuf, sizeof(sverbuf));
2398 if (is_func)
2399 pg_log_error("The server (version %s) does not support showing function source.",
2400 sverbuf);
2401 else
2402 pg_log_error("The server (version %s) does not support showing view definitions.",
2403 sverbuf);
2404 status = PSQL_CMD_ERROR;
2405 }
2406 else if (!obj_desc)
2407 {
2408 if (is_func)
2409 pg_log_error("function name is required");
2410 else
2411 pg_log_error("view name is required");
2412 status = PSQL_CMD_ERROR;
2413 }
2414 else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
2415 {
2416 /* error already reported */
2417 status = PSQL_CMD_ERROR;
2418 }
2419 else if (!get_create_object_cmd(eot, obj_oid, buf))
2420 {
2421 /* error already reported */
2422 status = PSQL_CMD_ERROR;
2423 }
2424 else
2425 {
2426 FILE *output;
2427 bool is_pager;
2428
2429 /* Select output stream: stdout, pager, or file */
2430 if (pset.queryFout == stdout)
2431 {
2432 /* count lines in function to see if pager is needed */
2433 int lineno = count_lines_in_buf(buf);
2434
2435 output = PageOutput(lineno, &(pset.popt.topt));
2436 is_pager = true;
2437 }
2438 else
2439 {
2440 /* use previously set output file, without pager */
2441 output = pset.queryFout;
2442 is_pager = false;
2443 }
2444
2445 if (show_linenumbers)
2446 {
2447 /*
2448 * For functions, lineno "1" should correspond to the first
2449 * line of the function body. We expect that
2450 * pg_get_functiondef() will emit that on a line beginning
2451 * with "AS ", and that there can be no such line before the
2452 * real start of the function body.
2453 */
2454 print_with_linenumbers(output, buf->data,
2455 is_func ? "AS " : NULL);
2456 }
2457 else
2458 {
2459 /* just send the definition to output */
2460 fputs(buf->data, output);
2461 }
2462
2463 if (is_pager)
2464 ClosePager(output);
2465 }
2466
2467 if (obj_desc)
2468 free(obj_desc);
2469 destroyPQExpBuffer(buf);
2470 }
2471 else
2472 ignore_slash_whole_line(scan_state);
2473
2474 return status;
2475 }
2476
2477 /*
2478 * \t -- turn off table headers and row count
2479 */
2480 static backslashResult
exec_command_t(PsqlScanState scan_state,bool active_branch)2481 exec_command_t(PsqlScanState scan_state, bool active_branch)
2482 {
2483 bool success = true;
2484
2485 if (active_branch)
2486 {
2487 char *opt = psql_scan_slash_option(scan_state,
2488 OT_NORMAL, NULL, true);
2489
2490 success = do_pset("tuples_only", opt, &pset.popt, pset.quiet);
2491 free(opt);
2492 }
2493 else
2494 ignore_slash_options(scan_state);
2495
2496 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2497 }
2498
2499 /*
2500 * \T -- define html <table ...> attributes
2501 */
2502 static backslashResult
exec_command_T(PsqlScanState scan_state,bool active_branch)2503 exec_command_T(PsqlScanState scan_state, bool active_branch)
2504 {
2505 bool success = true;
2506
2507 if (active_branch)
2508 {
2509 char *value = psql_scan_slash_option(scan_state,
2510 OT_NORMAL, NULL, false);
2511
2512 success = do_pset("tableattr", value, &pset.popt, pset.quiet);
2513 free(value);
2514 }
2515 else
2516 ignore_slash_options(scan_state);
2517
2518 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2519 }
2520
2521 /*
2522 * \timing -- enable/disable timing of queries
2523 */
2524 static backslashResult
exec_command_timing(PsqlScanState scan_state,bool active_branch)2525 exec_command_timing(PsqlScanState scan_state, bool active_branch)
2526 {
2527 bool success = true;
2528
2529 if (active_branch)
2530 {
2531 char *opt = psql_scan_slash_option(scan_state,
2532 OT_NORMAL, NULL, false);
2533
2534 if (opt)
2535 success = ParseVariableBool(opt, "\\timing", &pset.timing);
2536 else
2537 pset.timing = !pset.timing;
2538 if (!pset.quiet)
2539 {
2540 if (pset.timing)
2541 puts(_("Timing is on."));
2542 else
2543 puts(_("Timing is off."));
2544 }
2545 free(opt);
2546 }
2547 else
2548 ignore_slash_options(scan_state);
2549
2550 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2551 }
2552
2553 /*
2554 * \unset -- unset variable
2555 */
2556 static backslashResult
exec_command_unset(PsqlScanState scan_state,bool active_branch,const char * cmd)2557 exec_command_unset(PsqlScanState scan_state, bool active_branch,
2558 const char *cmd)
2559 {
2560 bool success = true;
2561
2562 if (active_branch)
2563 {
2564 char *opt = psql_scan_slash_option(scan_state,
2565 OT_NORMAL, NULL, false);
2566
2567 if (!opt)
2568 {
2569 pg_log_error("\\%s: missing required argument", cmd);
2570 success = false;
2571 }
2572 else if (!SetVariable(pset.vars, opt, NULL))
2573 success = false;
2574
2575 free(opt);
2576 }
2577 else
2578 ignore_slash_options(scan_state);
2579
2580 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2581 }
2582
2583 /*
2584 * \w -- write query buffer to file
2585 */
2586 static backslashResult
exec_command_write(PsqlScanState scan_state,bool active_branch,const char * cmd,PQExpBuffer query_buf,PQExpBuffer previous_buf)2587 exec_command_write(PsqlScanState scan_state, bool active_branch,
2588 const char *cmd,
2589 PQExpBuffer query_buf, PQExpBuffer previous_buf)
2590 {
2591 backslashResult status = PSQL_CMD_SKIP_LINE;
2592
2593 if (active_branch)
2594 {
2595 char *fname = psql_scan_slash_option(scan_state,
2596 OT_FILEPIPE, NULL, true);
2597 FILE *fd = NULL;
2598 bool is_pipe = false;
2599
2600 if (!query_buf)
2601 {
2602 pg_log_error("no query buffer");
2603 status = PSQL_CMD_ERROR;
2604 }
2605 else
2606 {
2607 if (!fname)
2608 {
2609 pg_log_error("\\%s: missing required argument", cmd);
2610 status = PSQL_CMD_ERROR;
2611 }
2612 else
2613 {
2614 expand_tilde(&fname);
2615 if (fname[0] == '|')
2616 {
2617 is_pipe = true;
2618 disable_sigpipe_trap();
2619 fd = popen(&fname[1], "w");
2620 }
2621 else
2622 {
2623 canonicalize_path(fname);
2624 fd = fopen(fname, "w");
2625 }
2626 if (!fd)
2627 {
2628 pg_log_error("%s: %m", fname);
2629 status = PSQL_CMD_ERROR;
2630 }
2631 }
2632 }
2633
2634 if (fd)
2635 {
2636 int result;
2637
2638 /*
2639 * We want to print the same thing \g would execute, but not to
2640 * change the query buffer state; so we can't use
2641 * copy_previous_query(). Also, beware of possibility that buffer
2642 * pointers are NULL.
2643 */
2644 if (query_buf && query_buf->len > 0)
2645 fprintf(fd, "%s\n", query_buf->data);
2646 else if (previous_buf && previous_buf->len > 0)
2647 fprintf(fd, "%s\n", previous_buf->data);
2648
2649 if (is_pipe)
2650 result = pclose(fd);
2651 else
2652 result = fclose(fd);
2653
2654 if (result == EOF)
2655 {
2656 pg_log_error("%s: %m", fname);
2657 status = PSQL_CMD_ERROR;
2658 }
2659 }
2660
2661 if (is_pipe)
2662 restore_sigpipe_trap();
2663
2664 free(fname);
2665 }
2666 else
2667 ignore_slash_filepipe(scan_state);
2668
2669 return status;
2670 }
2671
2672 /*
2673 * \watch -- execute a query every N seconds
2674 */
2675 static backslashResult
exec_command_watch(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,PQExpBuffer previous_buf)2676 exec_command_watch(PsqlScanState scan_state, bool active_branch,
2677 PQExpBuffer query_buf, PQExpBuffer previous_buf)
2678 {
2679 bool success = true;
2680
2681 if (active_branch)
2682 {
2683 char *opt = psql_scan_slash_option(scan_state,
2684 OT_NORMAL, NULL, true);
2685 double sleep = 2;
2686
2687 /* Convert optional sleep-length argument */
2688 if (opt)
2689 {
2690 sleep = strtod(opt, NULL);
2691 if (sleep <= 0)
2692 sleep = 1;
2693 free(opt);
2694 }
2695
2696 /* If query_buf is empty, recall and execute previous query */
2697 (void) copy_previous_query(query_buf, previous_buf);
2698
2699 success = do_watch(query_buf, sleep);
2700
2701 /* Reset the query buffer as though for \r */
2702 resetPQExpBuffer(query_buf);
2703 psql_scan_reset(scan_state);
2704 }
2705 else
2706 ignore_slash_options(scan_state);
2707
2708 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2709 }
2710
2711 /*
2712 * \x -- set or toggle expanded table representation
2713 */
2714 static backslashResult
exec_command_x(PsqlScanState scan_state,bool active_branch)2715 exec_command_x(PsqlScanState scan_state, bool active_branch)
2716 {
2717 bool success = true;
2718
2719 if (active_branch)
2720 {
2721 char *opt = psql_scan_slash_option(scan_state,
2722 OT_NORMAL, NULL, true);
2723
2724 success = do_pset("expanded", opt, &pset.popt, pset.quiet);
2725 free(opt);
2726 }
2727 else
2728 ignore_slash_options(scan_state);
2729
2730 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2731 }
2732
2733 /*
2734 * \z -- list table privileges (equivalent to \dp)
2735 */
2736 static backslashResult
exec_command_z(PsqlScanState scan_state,bool active_branch)2737 exec_command_z(PsqlScanState scan_state, bool active_branch)
2738 {
2739 bool success = true;
2740
2741 if (active_branch)
2742 {
2743 char *pattern = psql_scan_slash_option(scan_state,
2744 OT_NORMAL, NULL, true);
2745
2746 success = permissionsList(pattern);
2747 if (pattern)
2748 free(pattern);
2749 }
2750 else
2751 ignore_slash_options(scan_state);
2752
2753 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2754 }
2755
2756 /*
2757 * \! -- execute shell command
2758 */
2759 static backslashResult
exec_command_shell_escape(PsqlScanState scan_state,bool active_branch)2760 exec_command_shell_escape(PsqlScanState scan_state, bool active_branch)
2761 {
2762 bool success = true;
2763
2764 if (active_branch)
2765 {
2766 char *opt = psql_scan_slash_option(scan_state,
2767 OT_WHOLE_LINE, NULL, false);
2768
2769 success = do_shell(opt);
2770 free(opt);
2771 }
2772 else
2773 ignore_slash_whole_line(scan_state);
2774
2775 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2776 }
2777
2778 /*
2779 * \? -- print help about backslash commands
2780 */
2781 static backslashResult
exec_command_slash_command_help(PsqlScanState scan_state,bool active_branch)2782 exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch)
2783 {
2784 if (active_branch)
2785 {
2786 char *opt0 = psql_scan_slash_option(scan_state,
2787 OT_NORMAL, NULL, false);
2788
2789 if (!opt0 || strcmp(opt0, "commands") == 0)
2790 slashUsage(pset.popt.topt.pager);
2791 else if (strcmp(opt0, "options") == 0)
2792 usage(pset.popt.topt.pager);
2793 else if (strcmp(opt0, "variables") == 0)
2794 helpVariables(pset.popt.topt.pager);
2795 else
2796 slashUsage(pset.popt.topt.pager);
2797
2798 if (opt0)
2799 free(opt0);
2800 }
2801 else
2802 ignore_slash_options(scan_state);
2803
2804 return PSQL_CMD_SKIP_LINE;
2805 }
2806
2807
2808 /*
2809 * Read and interpret an argument to the \connect slash command.
2810 *
2811 * Returns a malloc'd string, or NULL if no/empty argument.
2812 */
2813 static char *
read_connect_arg(PsqlScanState scan_state)2814 read_connect_arg(PsqlScanState scan_state)
2815 {
2816 char *result;
2817 char quote;
2818
2819 /*
2820 * Ideally we should treat the arguments as SQL identifiers. But for
2821 * backwards compatibility with 7.2 and older pg_dump files, we have to
2822 * take unquoted arguments verbatim (don't downcase them). For now,
2823 * double-quoted arguments may be stripped of double quotes (as if SQL
2824 * identifiers). By 7.4 or so, pg_dump files can be expected to
2825 * double-quote all mixed-case \connect arguments, and then we can get rid
2826 * of OT_SQLIDHACK.
2827 */
2828 result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, "e, true);
2829
2830 if (!result)
2831 return NULL;
2832
2833 if (quote)
2834 return result;
2835
2836 if (*result == '\0' || strcmp(result, "-") == 0)
2837 {
2838 free(result);
2839 return NULL;
2840 }
2841
2842 return result;
2843 }
2844
2845 /*
2846 * Read a boolean expression, return it as a PQExpBuffer string.
2847 *
2848 * Note: anything more or less than one token will certainly fail to be
2849 * parsed by ParseVariableBool, so we don't worry about complaining here.
2850 * This routine's return data structure will need to be rethought anyway
2851 * to support likely future extensions such as "\if defined VARNAME".
2852 */
2853 static PQExpBuffer
gather_boolean_expression(PsqlScanState scan_state)2854 gather_boolean_expression(PsqlScanState scan_state)
2855 {
2856 PQExpBuffer exp_buf = createPQExpBuffer();
2857 int num_options = 0;
2858 char *value;
2859
2860 /* collect all arguments for the conditional command into exp_buf */
2861 while ((value = psql_scan_slash_option(scan_state,
2862 OT_NORMAL, NULL, false)) != NULL)
2863 {
2864 /* add spaces between tokens */
2865 if (num_options > 0)
2866 appendPQExpBufferChar(exp_buf, ' ');
2867 appendPQExpBufferStr(exp_buf, value);
2868 num_options++;
2869 free(value);
2870 }
2871
2872 return exp_buf;
2873 }
2874
2875 /*
2876 * Read a boolean expression, return true if the expression
2877 * was a valid boolean expression that evaluated to true.
2878 * Otherwise return false.
2879 *
2880 * Note: conditional stack's top state must be active, else lexer will
2881 * fail to expand variables and backticks.
2882 */
2883 static bool
is_true_boolean_expression(PsqlScanState scan_state,const char * name)2884 is_true_boolean_expression(PsqlScanState scan_state, const char *name)
2885 {
2886 PQExpBuffer buf = gather_boolean_expression(scan_state);
2887 bool value = false;
2888 bool success = ParseVariableBool(buf->data, name, &value);
2889
2890 destroyPQExpBuffer(buf);
2891 return success && value;
2892 }
2893
2894 /*
2895 * Read a boolean expression, but do nothing with it.
2896 *
2897 * Note: conditional stack's top state must be INACTIVE, else lexer will
2898 * expand variables and backticks, which we do not want here.
2899 */
2900 static void
ignore_boolean_expression(PsqlScanState scan_state)2901 ignore_boolean_expression(PsqlScanState scan_state)
2902 {
2903 PQExpBuffer buf = gather_boolean_expression(scan_state);
2904
2905 destroyPQExpBuffer(buf);
2906 }
2907
2908 /*
2909 * Read and discard "normal" slash command options.
2910 *
2911 * This should be used for inactive-branch processing of any slash command
2912 * that eats one or more OT_NORMAL, OT_SQLID, or OT_SQLIDHACK parameters.
2913 * We don't need to worry about exactly how many it would eat, since the
2914 * cleanup logic in HandleSlashCmds would silently discard any extras anyway.
2915 */
2916 static void
ignore_slash_options(PsqlScanState scan_state)2917 ignore_slash_options(PsqlScanState scan_state)
2918 {
2919 char *arg;
2920
2921 while ((arg = psql_scan_slash_option(scan_state,
2922 OT_NORMAL, NULL, false)) != NULL)
2923 free(arg);
2924 }
2925
2926 /*
2927 * Read and discard FILEPIPE slash command argument.
2928 *
2929 * This *MUST* be used for inactive-branch processing of any slash command
2930 * that takes an OT_FILEPIPE option. Otherwise we might consume a different
2931 * amount of option text in active and inactive cases.
2932 */
2933 static void
ignore_slash_filepipe(PsqlScanState scan_state)2934 ignore_slash_filepipe(PsqlScanState scan_state)
2935 {
2936 char *arg = psql_scan_slash_option(scan_state,
2937 OT_FILEPIPE, NULL, false);
2938
2939 if (arg)
2940 free(arg);
2941 }
2942
2943 /*
2944 * Read and discard whole-line slash command argument.
2945 *
2946 * This *MUST* be used for inactive-branch processing of any slash command
2947 * that takes an OT_WHOLE_LINE option. Otherwise we might consume a different
2948 * amount of option text in active and inactive cases.
2949 */
2950 static void
ignore_slash_whole_line(PsqlScanState scan_state)2951 ignore_slash_whole_line(PsqlScanState scan_state)
2952 {
2953 char *arg = psql_scan_slash_option(scan_state,
2954 OT_WHOLE_LINE, NULL, false);
2955
2956 if (arg)
2957 free(arg);
2958 }
2959
2960 /*
2961 * Return true if the command given is a branching command.
2962 */
2963 static bool
is_branching_command(const char * cmd)2964 is_branching_command(const char *cmd)
2965 {
2966 return (strcmp(cmd, "if") == 0 ||
2967 strcmp(cmd, "elif") == 0 ||
2968 strcmp(cmd, "else") == 0 ||
2969 strcmp(cmd, "endif") == 0);
2970 }
2971
2972 /*
2973 * Prepare to possibly restore query buffer to its current state
2974 * (cf. discard_query_text).
2975 *
2976 * We need to remember the length of the query buffer, and the lexer's
2977 * notion of the parenthesis nesting depth.
2978 */
2979 static void
save_query_text_state(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)2980 save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
2981 PQExpBuffer query_buf)
2982 {
2983 if (query_buf)
2984 conditional_stack_set_query_len(cstack, query_buf->len);
2985 conditional_stack_set_paren_depth(cstack,
2986 psql_scan_get_paren_depth(scan_state));
2987 }
2988
2989 /*
2990 * Discard any query text absorbed during an inactive conditional branch.
2991 *
2992 * We must discard data that was appended to query_buf during an inactive
2993 * \if branch. We don't have to do anything there if there's no query_buf.
2994 *
2995 * Also, reset the lexer state to the same paren depth there was before.
2996 * (The rest of its state doesn't need attention, since we could not be
2997 * inside a comment or literal or partial token.)
2998 */
2999 static void
discard_query_text(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)3000 discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
3001 PQExpBuffer query_buf)
3002 {
3003 if (query_buf)
3004 {
3005 int new_len = conditional_stack_get_query_len(cstack);
3006
3007 Assert(new_len >= 0 && new_len <= query_buf->len);
3008 query_buf->len = new_len;
3009 query_buf->data[new_len] = '\0';
3010 }
3011 psql_scan_set_paren_depth(scan_state,
3012 conditional_stack_get_paren_depth(cstack));
3013 }
3014
3015 /*
3016 * If query_buf is empty, copy previous_buf into it.
3017 *
3018 * This is used by various slash commands for which re-execution of a
3019 * previous query is a common usage. For convenience, we allow the
3020 * case of query_buf == NULL (and do nothing).
3021 *
3022 * Returns "true" if the previous query was copied into the query
3023 * buffer, else "false".
3024 */
3025 static bool
copy_previous_query(PQExpBuffer query_buf,PQExpBuffer previous_buf)3026 copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf)
3027 {
3028 if (query_buf && query_buf->len == 0)
3029 {
3030 appendPQExpBufferStr(query_buf, previous_buf->data);
3031 return true;
3032 }
3033 return false;
3034 }
3035
3036 /*
3037 * Ask the user for a password; 'username' is the username the
3038 * password is for, if one has been explicitly specified. Returns a
3039 * malloc'd string.
3040 */
3041 static char *
prompt_for_password(const char * username)3042 prompt_for_password(const char *username)
3043 {
3044 char *result;
3045
3046 if (username == NULL || username[0] == '\0')
3047 result = simple_prompt("Password: ", false);
3048 else
3049 {
3050 char *prompt_text;
3051
3052 prompt_text = psprintf(_("Password for user %s: "), username);
3053 result = simple_prompt(prompt_text, false);
3054 free(prompt_text);
3055 }
3056 return result;
3057 }
3058
3059 static bool
param_is_newly_set(const char * old_val,const char * new_val)3060 param_is_newly_set(const char *old_val, const char *new_val)
3061 {
3062 if (new_val == NULL)
3063 return false;
3064
3065 if (old_val == NULL || strcmp(old_val, new_val) != 0)
3066 return true;
3067
3068 return false;
3069 }
3070
3071 /*
3072 * do_connect -- handler for \connect
3073 *
3074 * Connects to a database with given parameters. If we are told to re-use
3075 * parameters, parameters from the previous connection are used where the
3076 * command's own options do not supply a value. Otherwise, libpq defaults
3077 * are used.
3078 *
3079 * In interactive mode, if connection fails with the given parameters,
3080 * the old connection will be kept.
3081 */
3082 static bool
do_connect(enum trivalue reuse_previous_specification,char * dbname,char * user,char * host,char * port)3083 do_connect(enum trivalue reuse_previous_specification,
3084 char *dbname, char *user, char *host, char *port)
3085 {
3086 PGconn *o_conn = pset.db,
3087 *n_conn = NULL;
3088 PQconninfoOption *cinfo;
3089 int nconnopts = 0;
3090 bool same_host = false;
3091 char *password = NULL;
3092 char *client_encoding;
3093 bool success = true;
3094 bool keep_password = true;
3095 bool has_connection_string;
3096 bool reuse_previous;
3097
3098 has_connection_string = dbname ?
3099 recognized_connection_string(dbname) : false;
3100
3101 /* Complain if we have additional arguments after a connection string. */
3102 if (has_connection_string && (user || host || port))
3103 {
3104 pg_log_error("Do not give user, host, or port separately when using a connection string");
3105 return false;
3106 }
3107
3108 switch (reuse_previous_specification)
3109 {
3110 case TRI_YES:
3111 reuse_previous = true;
3112 break;
3113 case TRI_NO:
3114 reuse_previous = false;
3115 break;
3116 default:
3117 reuse_previous = !has_connection_string;
3118 break;
3119 }
3120
3121 /*
3122 * If we intend to re-use connection parameters, collect them out of the
3123 * old connection, then replace individual values as necessary. (We may
3124 * need to resort to looking at pset.dead_conn, if the connection died
3125 * previously.) Otherwise, obtain a PQconninfoOption array containing
3126 * libpq's defaults, and modify that. Note this function assumes that
3127 * PQconninfo, PQconndefaults, and PQconninfoParse will all produce arrays
3128 * containing the same options in the same order.
3129 */
3130 if (reuse_previous)
3131 {
3132 if (o_conn)
3133 cinfo = PQconninfo(o_conn);
3134 else if (pset.dead_conn)
3135 cinfo = PQconninfo(pset.dead_conn);
3136 else
3137 {
3138 /* This is reachable after a non-interactive \connect failure */
3139 pg_log_error("No database connection exists to re-use parameters from");
3140 return false;
3141 }
3142 }
3143 else
3144 cinfo = PQconndefaults();
3145
3146 if (cinfo)
3147 {
3148 if (has_connection_string)
3149 {
3150 /* Parse the connstring and insert values into cinfo */
3151 PQconninfoOption *replcinfo;
3152 char *errmsg;
3153
3154 replcinfo = PQconninfoParse(dbname, &errmsg);
3155 if (replcinfo)
3156 {
3157 PQconninfoOption *ci;
3158 PQconninfoOption *replci;
3159 bool have_password = false;
3160
3161 for (ci = cinfo, replci = replcinfo;
3162 ci->keyword && replci->keyword;
3163 ci++, replci++)
3164 {
3165 Assert(strcmp(ci->keyword, replci->keyword) == 0);
3166 /* Insert value from connstring if one was provided */
3167 if (replci->val)
3168 {
3169 /*
3170 * We know that both val strings were allocated by
3171 * libpq, so the least messy way to avoid memory leaks
3172 * is to swap them.
3173 */
3174 char *swap = replci->val;
3175
3176 replci->val = ci->val;
3177 ci->val = swap;
3178
3179 /*
3180 * Check whether connstring provides options affecting
3181 * password re-use. While any change in user, host,
3182 * hostaddr, or port causes us to ignore the old
3183 * connection's password, we don't force that for
3184 * dbname, since passwords aren't database-specific.
3185 */
3186 if (replci->val == NULL ||
3187 strcmp(ci->val, replci->val) != 0)
3188 {
3189 if (strcmp(replci->keyword, "user") == 0 ||
3190 strcmp(replci->keyword, "host") == 0 ||
3191 strcmp(replci->keyword, "hostaddr") == 0 ||
3192 strcmp(replci->keyword, "port") == 0)
3193 keep_password = false;
3194 }
3195 /* Also note whether connstring contains a password. */
3196 if (strcmp(replci->keyword, "password") == 0)
3197 have_password = true;
3198 }
3199 else if (!reuse_previous)
3200 {
3201 /*
3202 * When we have a connstring and are not re-using
3203 * parameters, swap *all* entries, even those not set
3204 * by the connstring. This avoids absorbing
3205 * environment-dependent defaults from the result of
3206 * PQconndefaults(). We don't want to do that because
3207 * they'd override service-file entries if the
3208 * connstring specifies a service parameter, whereas
3209 * the priority should be the other way around. libpq
3210 * can certainly recompute any defaults we don't pass
3211 * here. (In this situation, it's a bit wasteful to
3212 * have called PQconndefaults() at all, but not doing
3213 * so would require yet another major code path here.)
3214 */
3215 replci->val = ci->val;
3216 ci->val = NULL;
3217 }
3218 }
3219 Assert(ci->keyword == NULL && replci->keyword == NULL);
3220
3221 /* While here, determine how many option slots there are */
3222 nconnopts = ci - cinfo;
3223
3224 PQconninfoFree(replcinfo);
3225
3226 /*
3227 * If the connstring contains a password, tell the loop below
3228 * that we may use it, regardless of other settings (i.e.,
3229 * cinfo's password is no longer an "old" password).
3230 */
3231 if (have_password)
3232 keep_password = true;
3233
3234 /* Don't let code below try to inject dbname into params. */
3235 dbname = NULL;
3236 }
3237 else
3238 {
3239 /* PQconninfoParse failed */
3240 if (errmsg)
3241 {
3242 pg_log_error("%s", errmsg);
3243 PQfreemem(errmsg);
3244 }
3245 else
3246 pg_log_error("out of memory");
3247 success = false;
3248 }
3249 }
3250 else
3251 {
3252 /*
3253 * If dbname isn't a connection string, then we'll inject it and
3254 * the other parameters into the keyword array below. (We can't
3255 * easily insert them into the cinfo array because of memory
3256 * management issues: PQconninfoFree would misbehave on Windows.)
3257 * However, to avoid dependencies on the order in which parameters
3258 * appear in the array, make a preliminary scan to set
3259 * keep_password and same_host correctly.
3260 *
3261 * While any change in user, host, or port causes us to ignore the
3262 * old connection's password, we don't force that for dbname,
3263 * since passwords aren't database-specific.
3264 */
3265 PQconninfoOption *ci;
3266
3267 for (ci = cinfo; ci->keyword; ci++)
3268 {
3269 if (user && strcmp(ci->keyword, "user") == 0)
3270 {
3271 if (!(ci->val && strcmp(user, ci->val) == 0))
3272 keep_password = false;
3273 }
3274 else if (host && strcmp(ci->keyword, "host") == 0)
3275 {
3276 if (ci->val && strcmp(host, ci->val) == 0)
3277 same_host = true;
3278 else
3279 keep_password = false;
3280 }
3281 else if (port && strcmp(ci->keyword, "port") == 0)
3282 {
3283 if (!(ci->val && strcmp(port, ci->val) == 0))
3284 keep_password = false;
3285 }
3286 }
3287
3288 /* While here, determine how many option slots there are */
3289 nconnopts = ci - cinfo;
3290 }
3291 }
3292 else
3293 {
3294 /* We failed to create the cinfo structure */
3295 pg_log_error("out of memory");
3296 success = false;
3297 }
3298
3299 /*
3300 * If the user asked to be prompted for a password, ask for one now. If
3301 * not, use the password from the old connection, provided the username
3302 * etc have not changed. Otherwise, try to connect without a password
3303 * first, and then ask for a password if needed.
3304 *
3305 * XXX: this behavior leads to spurious connection attempts recorded in
3306 * the postmaster's log. But libpq offers no API that would let us obtain
3307 * a password and then continue with the first connection attempt.
3308 */
3309 if (pset.getPassword == TRI_YES && success)
3310 {
3311 /*
3312 * If a connstring or URI is provided, we don't know which username
3313 * will be used, since we haven't dug that out of the connstring.
3314 * Don't risk issuing a misleading prompt. As in startup.c, it does
3315 * not seem worth working harder, since this getPassword setting is
3316 * normally only used in noninteractive cases.
3317 */
3318 password = prompt_for_password(has_connection_string ? NULL : user);
3319 }
3320
3321 /*
3322 * Consider whether to force client_encoding to "auto" (overriding
3323 * anything in the connection string). We do so if we have a terminal
3324 * connection and there is no PGCLIENTENCODING environment setting.
3325 */
3326 if (pset.notty || getenv("PGCLIENTENCODING"))
3327 client_encoding = NULL;
3328 else
3329 client_encoding = "auto";
3330
3331 /* Loop till we have a connection or fail, which we might've already */
3332 while (success)
3333 {
3334 const char **keywords = pg_malloc((nconnopts + 1) * sizeof(*keywords));
3335 const char **values = pg_malloc((nconnopts + 1) * sizeof(*values));
3336 int paramnum = 0;
3337 PQconninfoOption *ci;
3338
3339 /*
3340 * Copy non-default settings into the PQconnectdbParams parameter
3341 * arrays; but inject any values specified old-style, as well as any
3342 * interactively-obtained password, and a couple of fields we want to
3343 * set forcibly.
3344 *
3345 * If you change this code, see also the initial-connection code in
3346 * main().
3347 */
3348 for (ci = cinfo; ci->keyword; ci++)
3349 {
3350 keywords[paramnum] = ci->keyword;
3351
3352 if (dbname && strcmp(ci->keyword, "dbname") == 0)
3353 values[paramnum++] = dbname;
3354 else if (user && strcmp(ci->keyword, "user") == 0)
3355 values[paramnum++] = user;
3356 else if (host && strcmp(ci->keyword, "host") == 0)
3357 values[paramnum++] = host;
3358 else if (host && !same_host && strcmp(ci->keyword, "hostaddr") == 0)
3359 {
3360 /* If we're changing the host value, drop any old hostaddr */
3361 values[paramnum++] = NULL;
3362 }
3363 else if (port && strcmp(ci->keyword, "port") == 0)
3364 values[paramnum++] = port;
3365 /* If !keep_password, we unconditionally drop old password */
3366 else if ((password || !keep_password) &&
3367 strcmp(ci->keyword, "password") == 0)
3368 values[paramnum++] = password;
3369 else if (strcmp(ci->keyword, "fallback_application_name") == 0)
3370 values[paramnum++] = pset.progname;
3371 else if (client_encoding &&
3372 strcmp(ci->keyword, "client_encoding") == 0)
3373 values[paramnum++] = client_encoding;
3374 else if (ci->val)
3375 values[paramnum++] = ci->val;
3376 /* else, don't bother making libpq parse this keyword */
3377 }
3378 /* add array terminator */
3379 keywords[paramnum] = NULL;
3380 values[paramnum] = NULL;
3381
3382 /* Note we do not want libpq to re-expand the dbname parameter */
3383 n_conn = PQconnectdbParams(keywords, values, false);
3384
3385 pg_free(keywords);
3386 pg_free(values);
3387
3388 if (PQstatus(n_conn) == CONNECTION_OK)
3389 break;
3390
3391 /*
3392 * Connection attempt failed; either retry the connection attempt with
3393 * a new password, or give up.
3394 */
3395 if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
3396 {
3397 /*
3398 * Prompt for password using the username we actually connected
3399 * with --- it might've come out of "dbname" rather than "user".
3400 */
3401 password = prompt_for_password(PQuser(n_conn));
3402 PQfinish(n_conn);
3403 n_conn = NULL;
3404 continue;
3405 }
3406
3407 /*
3408 * We'll report the error below ... unless n_conn is NULL, indicating
3409 * that libpq didn't have enough memory to make a PGconn.
3410 */
3411 if (n_conn == NULL)
3412 pg_log_error("out of memory");
3413
3414 success = false;
3415 } /* end retry loop */
3416
3417 /* Release locally allocated data, whether we succeeded or not */
3418 if (password)
3419 pg_free(password);
3420 if (cinfo)
3421 PQconninfoFree(cinfo);
3422
3423 if (!success)
3424 {
3425 /*
3426 * Failed to connect to the database. In interactive mode, keep the
3427 * previous connection to the DB; in scripting mode, close our
3428 * previous connection as well.
3429 */
3430 if (pset.cur_cmd_interactive)
3431 {
3432 if (n_conn)
3433 {
3434 pg_log_info("%s", PQerrorMessage(n_conn));
3435 PQfinish(n_conn);
3436 }
3437
3438 /* pset.db is left unmodified */
3439 if (o_conn)
3440 pg_log_info("Previous connection kept");
3441 }
3442 else
3443 {
3444 if (n_conn)
3445 {
3446 pg_log_error("\\connect: %s", PQerrorMessage(n_conn));
3447 PQfinish(n_conn);
3448 }
3449
3450 if (o_conn)
3451 {
3452 /*
3453 * Transition to having no connection.
3454 *
3455 * Unlike CheckConnection(), we close the old connection
3456 * immediately to prevent its parameters from being re-used.
3457 * This is so that a script cannot accidentally reuse
3458 * parameters it did not expect to. Otherwise, the state
3459 * cleanup should be the same as in CheckConnection().
3460 */
3461 PQfinish(o_conn);
3462 pset.db = NULL;
3463 ResetCancelConn();
3464 UnsyncVariables();
3465 }
3466
3467 /* On the same reasoning, release any dead_conn to prevent reuse */
3468 if (pset.dead_conn)
3469 {
3470 PQfinish(pset.dead_conn);
3471 pset.dead_conn = NULL;
3472 }
3473 }
3474
3475 return false;
3476 }
3477
3478 /*
3479 * Replace the old connection with the new one, and update
3480 * connection-dependent variables. Keep the resynchronization logic in
3481 * sync with CheckConnection().
3482 */
3483 PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
3484 pset.db = n_conn;
3485 SyncVariables();
3486 connection_warnings(false); /* Must be after SyncVariables */
3487
3488 /* Tell the user about the new connection */
3489 if (!pset.quiet)
3490 {
3491 if (!o_conn ||
3492 param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
3493 param_is_newly_set(PQport(o_conn), PQport(pset.db)))
3494 {
3495 char *host = PQhost(pset.db);
3496 char *hostaddr = PQhostaddr(pset.db);
3497
3498 if (is_unixsock_path(host))
3499 {
3500 /* hostaddr overrides host */
3501 if (hostaddr && *hostaddr)
3502 printf(_("You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"),
3503 PQdb(pset.db), PQuser(pset.db), hostaddr, PQport(pset.db));
3504 else
3505 printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
3506 PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
3507 }
3508 else
3509 {
3510 if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0)
3511 printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"),
3512 PQdb(pset.db), PQuser(pset.db), host, hostaddr, PQport(pset.db));
3513 else
3514 printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
3515 PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
3516 }
3517 }
3518 else
3519 printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
3520 PQdb(pset.db), PQuser(pset.db));
3521 }
3522
3523 /* Drop no-longer-needed connection(s) */
3524 if (o_conn)
3525 PQfinish(o_conn);
3526 if (pset.dead_conn)
3527 {
3528 PQfinish(pset.dead_conn);
3529 pset.dead_conn = NULL;
3530 }
3531
3532 return true;
3533 }
3534
3535
3536 void
connection_warnings(bool in_startup)3537 connection_warnings(bool in_startup)
3538 {
3539 if (!pset.quiet && !pset.notty)
3540 {
3541 int client_ver = PG_VERSION_NUM;
3542 char cverbuf[32];
3543 char sverbuf[32];
3544
3545 if (pset.sversion != client_ver)
3546 {
3547 const char *server_version;
3548
3549 /* Try to get full text form, might include "devel" etc */
3550 server_version = PQparameterStatus(pset.db, "server_version");
3551 /* Otherwise fall back on pset.sversion */
3552 if (!server_version)
3553 {
3554 formatPGVersionNumber(pset.sversion, true,
3555 sverbuf, sizeof(sverbuf));
3556 server_version = sverbuf;
3557 }
3558
3559 printf(_("%s (%s, server %s)\n"),
3560 pset.progname, PG_VERSION, server_version);
3561 }
3562 /* For version match, only print psql banner on startup. */
3563 else if (in_startup)
3564 printf("%s (%s)\n", pset.progname, PG_VERSION);
3565
3566 if (pset.sversion / 100 > client_ver / 100)
3567 printf(_("WARNING: %s major version %s, server major version %s.\n"
3568 " Some psql features might not work.\n"),
3569 pset.progname,
3570 formatPGVersionNumber(client_ver, false,
3571 cverbuf, sizeof(cverbuf)),
3572 formatPGVersionNumber(pset.sversion, false,
3573 sverbuf, sizeof(sverbuf)));
3574
3575 #ifdef WIN32
3576 if (in_startup)
3577 checkWin32Codepage();
3578 #endif
3579 printSSLInfo();
3580 printGSSInfo();
3581 }
3582 }
3583
3584
3585 /*
3586 * printSSLInfo
3587 *
3588 * Prints information about the current SSL connection, if SSL is in use
3589 */
3590 static void
printSSLInfo(void)3591 printSSLInfo(void)
3592 {
3593 const char *protocol;
3594 const char *cipher;
3595 const char *bits;
3596 const char *compression;
3597
3598 if (!PQsslInUse(pset.db))
3599 return; /* no SSL */
3600
3601 protocol = PQsslAttribute(pset.db, "protocol");
3602 cipher = PQsslAttribute(pset.db, "cipher");
3603 bits = PQsslAttribute(pset.db, "key_bits");
3604 compression = PQsslAttribute(pset.db, "compression");
3605
3606 printf(_("SSL connection (protocol: %s, cipher: %s, bits: %s, compression: %s)\n"),
3607 protocol ? protocol : _("unknown"),
3608 cipher ? cipher : _("unknown"),
3609 bits ? bits : _("unknown"),
3610 (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
3611 }
3612
3613 /*
3614 * printGSSInfo
3615 *
3616 * Prints information about the current GSSAPI connection, if GSSAPI encryption is in use
3617 */
3618 static void
printGSSInfo(void)3619 printGSSInfo(void)
3620 {
3621 if (!PQgssEncInUse(pset.db))
3622 return; /* no GSSAPI encryption in use */
3623
3624 printf(_("GSSAPI-encrypted connection\n"));
3625 }
3626
3627
3628 /*
3629 * checkWin32Codepage
3630 *
3631 * Prints a warning when win32 console codepage differs from Windows codepage
3632 */
3633 #ifdef WIN32
3634 static void
checkWin32Codepage(void)3635 checkWin32Codepage(void)
3636 {
3637 unsigned int wincp,
3638 concp;
3639
3640 wincp = GetACP();
3641 concp = GetConsoleCP();
3642 if (wincp != concp)
3643 {
3644 printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n"
3645 " 8-bit characters might not work correctly. See psql reference\n"
3646 " page \"Notes for Windows users\" for details.\n"),
3647 concp, wincp);
3648 }
3649 }
3650 #endif
3651
3652
3653 /*
3654 * SyncVariables
3655 *
3656 * Make psql's internal variables agree with connection state upon
3657 * establishing a new connection.
3658 */
3659 void
SyncVariables(void)3660 SyncVariables(void)
3661 {
3662 char vbuf[32];
3663 const char *server_version;
3664
3665 /* get stuff from connection */
3666 pset.encoding = PQclientEncoding(pset.db);
3667 pset.popt.topt.encoding = pset.encoding;
3668 pset.sversion = PQserverVersion(pset.db);
3669
3670 SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
3671 SetVariable(pset.vars, "USER", PQuser(pset.db));
3672 SetVariable(pset.vars, "HOST", PQhost(pset.db));
3673 SetVariable(pset.vars, "PORT", PQport(pset.db));
3674 SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
3675
3676 /* this bit should match connection_warnings(): */
3677 /* Try to get full text form of version, might include "devel" etc */
3678 server_version = PQparameterStatus(pset.db, "server_version");
3679 /* Otherwise fall back on pset.sversion */
3680 if (!server_version)
3681 {
3682 formatPGVersionNumber(pset.sversion, true, vbuf, sizeof(vbuf));
3683 server_version = vbuf;
3684 }
3685 SetVariable(pset.vars, "SERVER_VERSION_NAME", server_version);
3686
3687 snprintf(vbuf, sizeof(vbuf), "%d", pset.sversion);
3688 SetVariable(pset.vars, "SERVER_VERSION_NUM", vbuf);
3689
3690 /* send stuff to it, too */
3691 PQsetErrorVerbosity(pset.db, pset.verbosity);
3692 PQsetErrorContextVisibility(pset.db, pset.show_context);
3693 }
3694
3695 /*
3696 * UnsyncVariables
3697 *
3698 * Clear variables that should be not be set when there is no connection.
3699 */
3700 void
UnsyncVariables(void)3701 UnsyncVariables(void)
3702 {
3703 SetVariable(pset.vars, "DBNAME", NULL);
3704 SetVariable(pset.vars, "USER", NULL);
3705 SetVariable(pset.vars, "HOST", NULL);
3706 SetVariable(pset.vars, "PORT", NULL);
3707 SetVariable(pset.vars, "ENCODING", NULL);
3708 SetVariable(pset.vars, "SERVER_VERSION_NAME", NULL);
3709 SetVariable(pset.vars, "SERVER_VERSION_NUM", NULL);
3710 }
3711
3712
3713 /*
3714 * helper for do_edit(): actually invoke the editor
3715 *
3716 * Returns true on success, false if we failed to invoke the editor or
3717 * it returned nonzero status. (An error message is printed for failed-
3718 * to-invoke cases, but not if the editor returns nonzero status.)
3719 */
3720 static bool
editFile(const char * fname,int lineno)3721 editFile(const char *fname, int lineno)
3722 {
3723 const char *editorName;
3724 const char *editor_lineno_arg = NULL;
3725 char *sys;
3726 int result;
3727
3728 Assert(fname != NULL);
3729
3730 /* Find an editor to use */
3731 editorName = getenv("PSQL_EDITOR");
3732 if (!editorName)
3733 editorName = getenv("EDITOR");
3734 if (!editorName)
3735 editorName = getenv("VISUAL");
3736 if (!editorName)
3737 editorName = DEFAULT_EDITOR;
3738
3739 /* Get line number argument, if we need it. */
3740 if (lineno > 0)
3741 {
3742 editor_lineno_arg = getenv("PSQL_EDITOR_LINENUMBER_ARG");
3743 #ifdef DEFAULT_EDITOR_LINENUMBER_ARG
3744 if (!editor_lineno_arg)
3745 editor_lineno_arg = DEFAULT_EDITOR_LINENUMBER_ARG;
3746 #endif
3747 if (!editor_lineno_arg)
3748 {
3749 pg_log_error("environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number");
3750 return false;
3751 }
3752 }
3753
3754 /*
3755 * On Unix the EDITOR value should *not* be quoted, since it might include
3756 * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
3757 * if necessary. But this policy is not very workable on Windows, due to
3758 * severe brain damage in their command shell plus the fact that standard
3759 * program paths include spaces.
3760 */
3761 #ifndef WIN32
3762 if (lineno > 0)
3763 sys = psprintf("exec %s %s%d '%s'",
3764 editorName, editor_lineno_arg, lineno, fname);
3765 else
3766 sys = psprintf("exec %s '%s'",
3767 editorName, fname);
3768 #else
3769 if (lineno > 0)
3770 sys = psprintf("\"%s\" %s%d \"%s\"",
3771 editorName, editor_lineno_arg, lineno, fname);
3772 else
3773 sys = psprintf("\"%s\" \"%s\"",
3774 editorName, fname);
3775 #endif
3776 result = system(sys);
3777 if (result == -1)
3778 pg_log_error("could not start editor \"%s\"", editorName);
3779 else if (result == 127)
3780 pg_log_error("could not start /bin/sh");
3781 free(sys);
3782
3783 return result == 0;
3784 }
3785
3786
3787 /*
3788 * do_edit -- handler for \e
3789 *
3790 * If you do not specify a filename, the current query buffer will be copied
3791 * into a temporary file.
3792 *
3793 * After this function is done, the resulting file will be copied back into the
3794 * query buffer. As an exception to this, the query buffer will be emptied
3795 * if the file was not modified (or the editor failed) and the caller passes
3796 * "discard_on_quit" = true.
3797 *
3798 * If "edited" isn't NULL, *edited will be set to true if the query buffer
3799 * is successfully replaced.
3800 */
3801 static bool
do_edit(const char * filename_arg,PQExpBuffer query_buf,int lineno,bool discard_on_quit,bool * edited)3802 do_edit(const char *filename_arg, PQExpBuffer query_buf,
3803 int lineno, bool discard_on_quit, bool *edited)
3804 {
3805 char fnametmp[MAXPGPATH];
3806 FILE *stream = NULL;
3807 const char *fname;
3808 bool error = false;
3809 int fd;
3810 struct stat before,
3811 after;
3812
3813 if (filename_arg)
3814 fname = filename_arg;
3815 else
3816 {
3817 /* make a temp file to edit */
3818 #ifndef WIN32
3819 const char *tmpdir = getenv("TMPDIR");
3820
3821 if (!tmpdir)
3822 tmpdir = "/tmp";
3823 #else
3824 char tmpdir[MAXPGPATH];
3825 int ret;
3826
3827 ret = GetTempPath(MAXPGPATH, tmpdir);
3828 if (ret == 0 || ret > MAXPGPATH)
3829 {
3830 pg_log_error("could not locate temporary directory: %s",
3831 !ret ? strerror(errno) : "");
3832 return false;
3833 }
3834 #endif
3835
3836 /*
3837 * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
3838 * current directory to the supplied path unless we use only
3839 * backslashes, so we do that.
3840 */
3841 #ifndef WIN32
3842 snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
3843 "/", (int) getpid());
3844 #else
3845 snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
3846 "" /* trailing separator already present */ , (int) getpid());
3847 #endif
3848
3849 fname = (const char *) fnametmp;
3850
3851 fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
3852 if (fd != -1)
3853 stream = fdopen(fd, "w");
3854
3855 if (fd == -1 || !stream)
3856 {
3857 pg_log_error("could not open temporary file \"%s\": %m", fname);
3858 error = true;
3859 }
3860 else
3861 {
3862 unsigned int ql = query_buf->len;
3863
3864 /* force newline-termination of what we send to editor */
3865 if (ql > 0 && query_buf->data[ql - 1] != '\n')
3866 {
3867 appendPQExpBufferChar(query_buf, '\n');
3868 ql++;
3869 }
3870
3871 if (fwrite(query_buf->data, 1, ql, stream) != ql)
3872 {
3873 pg_log_error("%s: %m", fname);
3874
3875 if (fclose(stream) != 0)
3876 pg_log_error("%s: %m", fname);
3877
3878 if (remove(fname) != 0)
3879 pg_log_error("%s: %m", fname);
3880
3881 error = true;
3882 }
3883 else if (fclose(stream) != 0)
3884 {
3885 pg_log_error("%s: %m", fname);
3886 if (remove(fname) != 0)
3887 pg_log_error("%s: %m", fname);
3888 error = true;
3889 }
3890 else
3891 {
3892 struct utimbuf ut;
3893
3894 /*
3895 * Try to set the file modification time of the temporary file
3896 * a few seconds in the past. Otherwise, the low granularity
3897 * (one second, or even worse on some filesystems) that we can
3898 * portably measure with stat(2) could lead us to not
3899 * recognize a modification, if the user typed very quickly.
3900 *
3901 * This is a rather unlikely race condition, so don't error
3902 * out if the utime(2) call fails --- that would make the cure
3903 * worse than the disease.
3904 */
3905 ut.modtime = ut.actime = time(NULL) - 2;
3906 (void) utime(fname, &ut);
3907 }
3908 }
3909 }
3910
3911 if (!error && stat(fname, &before) != 0)
3912 {
3913 pg_log_error("%s: %m", fname);
3914 error = true;
3915 }
3916
3917 /* call editor */
3918 if (!error)
3919 error = !editFile(fname, lineno);
3920
3921 if (!error && stat(fname, &after) != 0)
3922 {
3923 pg_log_error("%s: %m", fname);
3924 error = true;
3925 }
3926
3927 /* file was edited if the size or modification time has changed */
3928 if (!error &&
3929 (before.st_size != after.st_size ||
3930 before.st_mtime != after.st_mtime))
3931 {
3932 stream = fopen(fname, PG_BINARY_R);
3933 if (!stream)
3934 {
3935 pg_log_error("%s: %m", fname);
3936 error = true;
3937 }
3938 else
3939 {
3940 /* read file back into query_buf */
3941 char line[1024];
3942
3943 resetPQExpBuffer(query_buf);
3944 while (fgets(line, sizeof(line), stream) != NULL)
3945 appendPQExpBufferStr(query_buf, line);
3946
3947 if (ferror(stream))
3948 {
3949 pg_log_error("%s: %m", fname);
3950 error = true;
3951 resetPQExpBuffer(query_buf);
3952 }
3953 else if (edited)
3954 {
3955 *edited = true;
3956 }
3957
3958 fclose(stream);
3959 }
3960 }
3961 else
3962 {
3963 /*
3964 * If the file was not modified, and the caller requested it, discard
3965 * the query buffer.
3966 */
3967 if (discard_on_quit)
3968 resetPQExpBuffer(query_buf);
3969 }
3970
3971 /* remove temp file */
3972 if (!filename_arg)
3973 {
3974 if (remove(fname) == -1)
3975 {
3976 pg_log_error("%s: %m", fname);
3977 error = true;
3978 }
3979 }
3980
3981 return !error;
3982 }
3983
3984
3985
3986 /*
3987 * process_file
3988 *
3989 * Reads commands from filename and passes them to the main processing loop.
3990 * Handler for \i and \ir, but can be used for other things as well. Returns
3991 * MainLoop() error code.
3992 *
3993 * If use_relative_path is true and filename is not an absolute path, then open
3994 * the file from where the currently processed file (if any) is located.
3995 */
3996 int
process_file(char * filename,bool use_relative_path)3997 process_file(char *filename, bool use_relative_path)
3998 {
3999 FILE *fd;
4000 int result;
4001 char *oldfilename;
4002 char relpath[MAXPGPATH];
4003
4004 if (!filename)
4005 {
4006 fd = stdin;
4007 filename = NULL;
4008 }
4009 else if (strcmp(filename, "-") != 0)
4010 {
4011 canonicalize_path(filename);
4012
4013 /*
4014 * If we were asked to resolve the pathname relative to the location
4015 * of the currently executing script, and there is one, and this is a
4016 * relative pathname, then prepend all but the last pathname component
4017 * of the current script to this pathname.
4018 */
4019 if (use_relative_path && pset.inputfile &&
4020 !is_absolute_path(filename) && !has_drive_prefix(filename))
4021 {
4022 strlcpy(relpath, pset.inputfile, sizeof(relpath));
4023 get_parent_directory(relpath);
4024 join_path_components(relpath, relpath, filename);
4025 canonicalize_path(relpath);
4026
4027 filename = relpath;
4028 }
4029
4030 fd = fopen(filename, PG_BINARY_R);
4031
4032 if (!fd)
4033 {
4034 pg_log_error("%s: %m", filename);
4035 return EXIT_FAILURE;
4036 }
4037 }
4038 else
4039 {
4040 fd = stdin;
4041 filename = "<stdin>"; /* for future error messages */
4042 }
4043
4044 oldfilename = pset.inputfile;
4045 pset.inputfile = filename;
4046
4047 pg_logging_config(pset.inputfile ? 0 : PG_LOG_FLAG_TERSE);
4048
4049 result = MainLoop(fd);
4050
4051 if (fd != stdin)
4052 fclose(fd);
4053
4054 pset.inputfile = oldfilename;
4055
4056 pg_logging_config(pset.inputfile ? 0 : PG_LOG_FLAG_TERSE);
4057
4058 return result;
4059 }
4060
4061
4062
4063 static const char *
_align2string(enum printFormat in)4064 _align2string(enum printFormat in)
4065 {
4066 switch (in)
4067 {
4068 case PRINT_NOTHING:
4069 return "nothing";
4070 break;
4071 case PRINT_ALIGNED:
4072 return "aligned";
4073 break;
4074 case PRINT_ASCIIDOC:
4075 return "asciidoc";
4076 break;
4077 case PRINT_CSV:
4078 return "csv";
4079 break;
4080 case PRINT_HTML:
4081 return "html";
4082 break;
4083 case PRINT_LATEX:
4084 return "latex";
4085 break;
4086 case PRINT_LATEX_LONGTABLE:
4087 return "latex-longtable";
4088 break;
4089 case PRINT_TROFF_MS:
4090 return "troff-ms";
4091 break;
4092 case PRINT_UNALIGNED:
4093 return "unaligned";
4094 break;
4095 case PRINT_WRAPPED:
4096 return "wrapped";
4097 break;
4098 }
4099 return "unknown";
4100 }
4101
4102 /*
4103 * Parse entered Unicode linestyle. If ok, update *linestyle and return
4104 * true, else return false.
4105 */
4106 static bool
set_unicode_line_style(const char * value,size_t vallen,unicode_linestyle * linestyle)4107 set_unicode_line_style(const char *value, size_t vallen,
4108 unicode_linestyle *linestyle)
4109 {
4110 if (pg_strncasecmp("single", value, vallen) == 0)
4111 *linestyle = UNICODE_LINESTYLE_SINGLE;
4112 else if (pg_strncasecmp("double", value, vallen) == 0)
4113 *linestyle = UNICODE_LINESTYLE_DOUBLE;
4114 else
4115 return false;
4116 return true;
4117 }
4118
4119 static const char *
_unicode_linestyle2string(int linestyle)4120 _unicode_linestyle2string(int linestyle)
4121 {
4122 switch (linestyle)
4123 {
4124 case UNICODE_LINESTYLE_SINGLE:
4125 return "single";
4126 break;
4127 case UNICODE_LINESTYLE_DOUBLE:
4128 return "double";
4129 break;
4130 }
4131 return "unknown";
4132 }
4133
4134 /*
4135 * do_pset
4136 *
4137 * Performs the assignment "param = value", where value could be NULL;
4138 * for some params that has an effect such as inversion, for others
4139 * it does nothing.
4140 *
4141 * Adjusts the state of the formatting options at *popt. (In practice that
4142 * is always pset.popt, but maybe someday it could be different.)
4143 *
4144 * If successful and quiet is false, then invokes printPsetInfo() to report
4145 * the change.
4146 *
4147 * Returns true if successful, else false (eg for invalid param or value).
4148 */
4149 bool
do_pset(const char * param,const char * value,printQueryOpt * popt,bool quiet)4150 do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
4151 {
4152 size_t vallen = 0;
4153
4154 Assert(param != NULL);
4155
4156 if (value)
4157 vallen = strlen(value);
4158
4159 /* set format */
4160 if (strcmp(param, "format") == 0)
4161 {
4162 static const struct fmt
4163 {
4164 const char *name;
4165 enum printFormat number;
4166 } formats[] =
4167 {
4168 /* remember to update error message below when adding more */
4169 {"aligned", PRINT_ALIGNED},
4170 {"asciidoc", PRINT_ASCIIDOC},
4171 {"csv", PRINT_CSV},
4172 {"html", PRINT_HTML},
4173 {"latex", PRINT_LATEX},
4174 {"troff-ms", PRINT_TROFF_MS},
4175 {"unaligned", PRINT_UNALIGNED},
4176 {"wrapped", PRINT_WRAPPED}
4177 };
4178
4179 if (!value)
4180 ;
4181 else
4182 {
4183 int match_pos = -1;
4184
4185 for (int i = 0; i < lengthof(formats); i++)
4186 {
4187 if (pg_strncasecmp(formats[i].name, value, vallen) == 0)
4188 {
4189 if (match_pos < 0)
4190 match_pos = i;
4191 else
4192 {
4193 pg_log_error("\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"",
4194 value,
4195 formats[match_pos].name, formats[i].name);
4196 return false;
4197 }
4198 }
4199 }
4200 if (match_pos >= 0)
4201 popt->topt.format = formats[match_pos].number;
4202 else if (pg_strncasecmp("latex-longtable", value, vallen) == 0)
4203 {
4204 /*
4205 * We must treat latex-longtable specially because latex is a
4206 * prefix of it; if both were in the table above, we'd think
4207 * "latex" is ambiguous.
4208 */
4209 popt->topt.format = PRINT_LATEX_LONGTABLE;
4210 }
4211 else
4212 {
4213 pg_log_error("\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped");
4214 return false;
4215 }
4216 }
4217 }
4218
4219 /* set table line style */
4220 else if (strcmp(param, "linestyle") == 0)
4221 {
4222 if (!value)
4223 ;
4224 else if (pg_strncasecmp("ascii", value, vallen) == 0)
4225 popt->topt.line_style = &pg_asciiformat;
4226 else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
4227 popt->topt.line_style = &pg_asciiformat_old;
4228 else if (pg_strncasecmp("unicode", value, vallen) == 0)
4229 popt->topt.line_style = &pg_utf8format;
4230 else
4231 {
4232 pg_log_error("\\pset: allowed line styles are ascii, old-ascii, unicode");
4233 return false;
4234 }
4235 }
4236
4237 /* set unicode border line style */
4238 else if (strcmp(param, "unicode_border_linestyle") == 0)
4239 {
4240 if (!value)
4241 ;
4242 else if (set_unicode_line_style(value, vallen,
4243 &popt->topt.unicode_border_linestyle))
4244 refresh_utf8format(&(popt->topt));
4245 else
4246 {
4247 pg_log_error("\\pset: allowed Unicode border line styles are single, double");
4248 return false;
4249 }
4250 }
4251
4252 /* set unicode column line style */
4253 else if (strcmp(param, "unicode_column_linestyle") == 0)
4254 {
4255 if (!value)
4256 ;
4257 else if (set_unicode_line_style(value, vallen,
4258 &popt->topt.unicode_column_linestyle))
4259 refresh_utf8format(&(popt->topt));
4260 else
4261 {
4262 pg_log_error("\\pset: allowed Unicode column line styles are single, double");
4263 return false;
4264 }
4265 }
4266
4267 /* set unicode header line style */
4268 else if (strcmp(param, "unicode_header_linestyle") == 0)
4269 {
4270 if (!value)
4271 ;
4272 else if (set_unicode_line_style(value, vallen,
4273 &popt->topt.unicode_header_linestyle))
4274 refresh_utf8format(&(popt->topt));
4275 else
4276 {
4277 pg_log_error("\\pset: allowed Unicode header line styles are single, double");
4278 return false;
4279 }
4280 }
4281
4282 /* set border style/width */
4283 else if (strcmp(param, "border") == 0)
4284 {
4285 if (value)
4286 popt->topt.border = atoi(value);
4287 }
4288
4289 /* set expanded/vertical mode */
4290 else if (strcmp(param, "x") == 0 ||
4291 strcmp(param, "expanded") == 0 ||
4292 strcmp(param, "vertical") == 0)
4293 {
4294 if (value && pg_strcasecmp(value, "auto") == 0)
4295 popt->topt.expanded = 2;
4296 else if (value)
4297 {
4298 bool on_off;
4299
4300 if (ParseVariableBool(value, NULL, &on_off))
4301 popt->topt.expanded = on_off ? 1 : 0;
4302 else
4303 {
4304 PsqlVarEnumError(param, value, "on, off, auto");
4305 return false;
4306 }
4307 }
4308 else
4309 popt->topt.expanded = !popt->topt.expanded;
4310 }
4311
4312 /* field separator for CSV format */
4313 else if (strcmp(param, "csv_fieldsep") == 0)
4314 {
4315 if (value)
4316 {
4317 /* CSV separator has to be a one-byte character */
4318 if (strlen(value) != 1)
4319 {
4320 pg_log_error("\\pset: csv_fieldsep must be a single one-byte character");
4321 return false;
4322 }
4323 if (value[0] == '"' || value[0] == '\n' || value[0] == '\r')
4324 {
4325 pg_log_error("\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return");
4326 return false;
4327 }
4328 popt->topt.csvFieldSep[0] = value[0];
4329 }
4330 }
4331
4332 /* locale-aware numeric output */
4333 else if (strcmp(param, "numericlocale") == 0)
4334 {
4335 if (value)
4336 return ParseVariableBool(value, param, &popt->topt.numericLocale);
4337 else
4338 popt->topt.numericLocale = !popt->topt.numericLocale;
4339 }
4340
4341 /* null display */
4342 else if (strcmp(param, "null") == 0)
4343 {
4344 if (value)
4345 {
4346 free(popt->nullPrint);
4347 popt->nullPrint = pg_strdup(value);
4348 }
4349 }
4350
4351 /* field separator for unaligned text */
4352 else if (strcmp(param, "fieldsep") == 0)
4353 {
4354 if (value)
4355 {
4356 free(popt->topt.fieldSep.separator);
4357 popt->topt.fieldSep.separator = pg_strdup(value);
4358 popt->topt.fieldSep.separator_zero = false;
4359 }
4360 }
4361
4362 else if (strcmp(param, "fieldsep_zero") == 0)
4363 {
4364 free(popt->topt.fieldSep.separator);
4365 popt->topt.fieldSep.separator = NULL;
4366 popt->topt.fieldSep.separator_zero = true;
4367 }
4368
4369 /* record separator for unaligned text */
4370 else if (strcmp(param, "recordsep") == 0)
4371 {
4372 if (value)
4373 {
4374 free(popt->topt.recordSep.separator);
4375 popt->topt.recordSep.separator = pg_strdup(value);
4376 popt->topt.recordSep.separator_zero = false;
4377 }
4378 }
4379
4380 else if (strcmp(param, "recordsep_zero") == 0)
4381 {
4382 free(popt->topt.recordSep.separator);
4383 popt->topt.recordSep.separator = NULL;
4384 popt->topt.recordSep.separator_zero = true;
4385 }
4386
4387 /* toggle between full and tuples-only format */
4388 else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
4389 {
4390 if (value)
4391 return ParseVariableBool(value, param, &popt->topt.tuples_only);
4392 else
4393 popt->topt.tuples_only = !popt->topt.tuples_only;
4394 }
4395
4396 /* set title override */
4397 else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
4398 {
4399 free(popt->title);
4400 if (!value)
4401 popt->title = NULL;
4402 else
4403 popt->title = pg_strdup(value);
4404 }
4405
4406 /* set HTML table tag options */
4407 else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
4408 {
4409 free(popt->topt.tableAttr);
4410 if (!value)
4411 popt->topt.tableAttr = NULL;
4412 else
4413 popt->topt.tableAttr = pg_strdup(value);
4414 }
4415
4416 /* toggle use of pager */
4417 else if (strcmp(param, "pager") == 0)
4418 {
4419 if (value && pg_strcasecmp(value, "always") == 0)
4420 popt->topt.pager = 2;
4421 else if (value)
4422 {
4423 bool on_off;
4424
4425 if (!ParseVariableBool(value, NULL, &on_off))
4426 {
4427 PsqlVarEnumError(param, value, "on, off, always");
4428 return false;
4429 }
4430 popt->topt.pager = on_off ? 1 : 0;
4431 }
4432 else if (popt->topt.pager == 1)
4433 popt->topt.pager = 0;
4434 else
4435 popt->topt.pager = 1;
4436 }
4437
4438 /* set minimum lines for pager use */
4439 else if (strcmp(param, "pager_min_lines") == 0)
4440 {
4441 if (value)
4442 popt->topt.pager_min_lines = atoi(value);
4443 }
4444
4445 /* disable "(x rows)" footer */
4446 else if (strcmp(param, "footer") == 0)
4447 {
4448 if (value)
4449 return ParseVariableBool(value, param, &popt->topt.default_footer);
4450 else
4451 popt->topt.default_footer = !popt->topt.default_footer;
4452 }
4453
4454 /* set border style/width */
4455 else if (strcmp(param, "columns") == 0)
4456 {
4457 if (value)
4458 popt->topt.columns = atoi(value);
4459 }
4460 else
4461 {
4462 pg_log_error("\\pset: unknown option: %s", param);
4463 return false;
4464 }
4465
4466 if (!quiet)
4467 printPsetInfo(param, &pset.popt);
4468
4469 return true;
4470 }
4471
4472 /*
4473 * printPsetInfo: print the state of the "param" formatting parameter in popt.
4474 */
4475 static bool
printPsetInfo(const char * param,printQueryOpt * popt)4476 printPsetInfo(const char *param, printQueryOpt *popt)
4477 {
4478 Assert(param != NULL);
4479
4480 /* show border style/width */
4481 if (strcmp(param, "border") == 0)
4482 printf(_("Border style is %d.\n"), popt->topt.border);
4483
4484 /* show the target width for the wrapped format */
4485 else if (strcmp(param, "columns") == 0)
4486 {
4487 if (!popt->topt.columns)
4488 printf(_("Target width is unset.\n"));
4489 else
4490 printf(_("Target width is %d.\n"), popt->topt.columns);
4491 }
4492
4493 /* show expanded/vertical mode */
4494 else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
4495 {
4496 if (popt->topt.expanded == 1)
4497 printf(_("Expanded display is on.\n"));
4498 else if (popt->topt.expanded == 2)
4499 printf(_("Expanded display is used automatically.\n"));
4500 else
4501 printf(_("Expanded display is off.\n"));
4502 }
4503
4504 /* show field separator for CSV format */
4505 else if (strcmp(param, "csv_fieldsep") == 0)
4506 {
4507 printf(_("Field separator for CSV is \"%s\".\n"),
4508 popt->topt.csvFieldSep);
4509 }
4510
4511 /* show field separator for unaligned text */
4512 else if (strcmp(param, "fieldsep") == 0)
4513 {
4514 if (popt->topt.fieldSep.separator_zero)
4515 printf(_("Field separator is zero byte.\n"));
4516 else
4517 printf(_("Field separator is \"%s\".\n"),
4518 popt->topt.fieldSep.separator);
4519 }
4520
4521 else if (strcmp(param, "fieldsep_zero") == 0)
4522 {
4523 printf(_("Field separator is zero byte.\n"));
4524 }
4525
4526 /* show disable "(x rows)" footer */
4527 else if (strcmp(param, "footer") == 0)
4528 {
4529 if (popt->topt.default_footer)
4530 printf(_("Default footer is on.\n"));
4531 else
4532 printf(_("Default footer is off.\n"));
4533 }
4534
4535 /* show format */
4536 else if (strcmp(param, "format") == 0)
4537 {
4538 printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
4539 }
4540
4541 /* show table line style */
4542 else if (strcmp(param, "linestyle") == 0)
4543 {
4544 printf(_("Line style is %s.\n"),
4545 get_line_style(&popt->topt)->name);
4546 }
4547
4548 /* show null display */
4549 else if (strcmp(param, "null") == 0)
4550 {
4551 printf(_("Null display is \"%s\".\n"),
4552 popt->nullPrint ? popt->nullPrint : "");
4553 }
4554
4555 /* show locale-aware numeric output */
4556 else if (strcmp(param, "numericlocale") == 0)
4557 {
4558 if (popt->topt.numericLocale)
4559 printf(_("Locale-adjusted numeric output is on.\n"));
4560 else
4561 printf(_("Locale-adjusted numeric output is off.\n"));
4562 }
4563
4564 /* show toggle use of pager */
4565 else if (strcmp(param, "pager") == 0)
4566 {
4567 if (popt->topt.pager == 1)
4568 printf(_("Pager is used for long output.\n"));
4569 else if (popt->topt.pager == 2)
4570 printf(_("Pager is always used.\n"));
4571 else
4572 printf(_("Pager usage is off.\n"));
4573 }
4574
4575 /* show minimum lines for pager use */
4576 else if (strcmp(param, "pager_min_lines") == 0)
4577 {
4578 printf(ngettext("Pager won't be used for less than %d line.\n",
4579 "Pager won't be used for less than %d lines.\n",
4580 popt->topt.pager_min_lines),
4581 popt->topt.pager_min_lines);
4582 }
4583
4584 /* show record separator for unaligned text */
4585 else if (strcmp(param, "recordsep") == 0)
4586 {
4587 if (popt->topt.recordSep.separator_zero)
4588 printf(_("Record separator is zero byte.\n"));
4589 else if (strcmp(popt->topt.recordSep.separator, "\n") == 0)
4590 printf(_("Record separator is <newline>.\n"));
4591 else
4592 printf(_("Record separator is \"%s\".\n"),
4593 popt->topt.recordSep.separator);
4594 }
4595
4596 else if (strcmp(param, "recordsep_zero") == 0)
4597 {
4598 printf(_("Record separator is zero byte.\n"));
4599 }
4600
4601 /* show HTML table tag options */
4602 else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
4603 {
4604 if (popt->topt.tableAttr)
4605 printf(_("Table attributes are \"%s\".\n"),
4606 popt->topt.tableAttr);
4607 else
4608 printf(_("Table attributes unset.\n"));
4609 }
4610
4611 /* show title override */
4612 else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
4613 {
4614 if (popt->title)
4615 printf(_("Title is \"%s\".\n"), popt->title);
4616 else
4617 printf(_("Title is unset.\n"));
4618 }
4619
4620 /* show toggle between full and tuples-only format */
4621 else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
4622 {
4623 if (popt->topt.tuples_only)
4624 printf(_("Tuples only is on.\n"));
4625 else
4626 printf(_("Tuples only is off.\n"));
4627 }
4628
4629 /* Unicode style formatting */
4630 else if (strcmp(param, "unicode_border_linestyle") == 0)
4631 {
4632 printf(_("Unicode border line style is \"%s\".\n"),
4633 _unicode_linestyle2string(popt->topt.unicode_border_linestyle));
4634 }
4635
4636 else if (strcmp(param, "unicode_column_linestyle") == 0)
4637 {
4638 printf(_("Unicode column line style is \"%s\".\n"),
4639 _unicode_linestyle2string(popt->topt.unicode_column_linestyle));
4640 }
4641
4642 else if (strcmp(param, "unicode_header_linestyle") == 0)
4643 {
4644 printf(_("Unicode header line style is \"%s\".\n"),
4645 _unicode_linestyle2string(popt->topt.unicode_header_linestyle));
4646 }
4647
4648 else
4649 {
4650 pg_log_error("\\pset: unknown option: %s", param);
4651 return false;
4652 }
4653
4654 return true;
4655 }
4656
4657 /*
4658 * savePsetInfo: make a malloc'd copy of the data in *popt.
4659 *
4660 * Possibly this should be somewhere else, but it's a bit specific to psql.
4661 */
4662 printQueryOpt *
savePsetInfo(const printQueryOpt * popt)4663 savePsetInfo(const printQueryOpt *popt)
4664 {
4665 printQueryOpt *save;
4666
4667 save = (printQueryOpt *) pg_malloc(sizeof(printQueryOpt));
4668
4669 /* Flat-copy all the scalar fields, then duplicate sub-structures. */
4670 memcpy(save, popt, sizeof(printQueryOpt));
4671
4672 /* topt.line_style points to const data that need not be duplicated */
4673 if (popt->topt.fieldSep.separator)
4674 save->topt.fieldSep.separator = pg_strdup(popt->topt.fieldSep.separator);
4675 if (popt->topt.recordSep.separator)
4676 save->topt.recordSep.separator = pg_strdup(popt->topt.recordSep.separator);
4677 if (popt->topt.tableAttr)
4678 save->topt.tableAttr = pg_strdup(popt->topt.tableAttr);
4679 if (popt->nullPrint)
4680 save->nullPrint = pg_strdup(popt->nullPrint);
4681 if (popt->title)
4682 save->title = pg_strdup(popt->title);
4683
4684 /*
4685 * footers and translate_columns are never set in psql's print settings,
4686 * so we needn't write code to duplicate them.
4687 */
4688 Assert(popt->footers == NULL);
4689 Assert(popt->translate_columns == NULL);
4690
4691 return save;
4692 }
4693
4694 /*
4695 * restorePsetInfo: restore *popt from the previously-saved copy *save,
4696 * then free *save.
4697 */
4698 void
restorePsetInfo(printQueryOpt * popt,printQueryOpt * save)4699 restorePsetInfo(printQueryOpt *popt, printQueryOpt *save)
4700 {
4701 /* Free all the old data we're about to overwrite the pointers to. */
4702
4703 /* topt.line_style points to const data that need not be duplicated */
4704 if (popt->topt.fieldSep.separator)
4705 free(popt->topt.fieldSep.separator);
4706 if (popt->topt.recordSep.separator)
4707 free(popt->topt.recordSep.separator);
4708 if (popt->topt.tableAttr)
4709 free(popt->topt.tableAttr);
4710 if (popt->nullPrint)
4711 free(popt->nullPrint);
4712 if (popt->title)
4713 free(popt->title);
4714
4715 /*
4716 * footers and translate_columns are never set in psql's print settings,
4717 * so we needn't write code to duplicate them.
4718 */
4719 Assert(popt->footers == NULL);
4720 Assert(popt->translate_columns == NULL);
4721
4722 /* Now we may flat-copy all the fields, including pointers. */
4723 memcpy(popt, save, sizeof(printQueryOpt));
4724
4725 /* Lastly, free "save" ... but its sub-structures now belong to popt. */
4726 free(save);
4727 }
4728
4729 static const char *
pset_bool_string(bool val)4730 pset_bool_string(bool val)
4731 {
4732 return val ? "on" : "off";
4733 }
4734
4735
4736 static char *
pset_quoted_string(const char * str)4737 pset_quoted_string(const char *str)
4738 {
4739 char *ret = pg_malloc(strlen(str) * 2 + 3);
4740 char *r = ret;
4741
4742 *r++ = '\'';
4743
4744 for (; *str; str++)
4745 {
4746 if (*str == '\n')
4747 {
4748 *r++ = '\\';
4749 *r++ = 'n';
4750 }
4751 else if (*str == '\'')
4752 {
4753 *r++ = '\\';
4754 *r++ = '\'';
4755 }
4756 else
4757 *r++ = *str;
4758 }
4759
4760 *r++ = '\'';
4761 *r = '\0';
4762
4763 return ret;
4764 }
4765
4766
4767 /*
4768 * Return a malloc'ed string for the \pset value.
4769 *
4770 * Note that for some string parameters, print.c distinguishes between unset
4771 * and empty string, but for others it doesn't. This function should produce
4772 * output that produces the correct setting when fed back into \pset.
4773 */
4774 static char *
pset_value_string(const char * param,printQueryOpt * popt)4775 pset_value_string(const char *param, printQueryOpt *popt)
4776 {
4777 Assert(param != NULL);
4778
4779 if (strcmp(param, "border") == 0)
4780 return psprintf("%d", popt->topt.border);
4781 else if (strcmp(param, "columns") == 0)
4782 return psprintf("%d", popt->topt.columns);
4783 else if (strcmp(param, "csv_fieldsep") == 0)
4784 return pset_quoted_string(popt->topt.csvFieldSep);
4785 else if (strcmp(param, "expanded") == 0)
4786 return pstrdup(popt->topt.expanded == 2
4787 ? "auto"
4788 : pset_bool_string(popt->topt.expanded));
4789 else if (strcmp(param, "fieldsep") == 0)
4790 return pset_quoted_string(popt->topt.fieldSep.separator
4791 ? popt->topt.fieldSep.separator
4792 : "");
4793 else if (strcmp(param, "fieldsep_zero") == 0)
4794 return pstrdup(pset_bool_string(popt->topt.fieldSep.separator_zero));
4795 else if (strcmp(param, "footer") == 0)
4796 return pstrdup(pset_bool_string(popt->topt.default_footer));
4797 else if (strcmp(param, "format") == 0)
4798 return psprintf("%s", _align2string(popt->topt.format));
4799 else if (strcmp(param, "linestyle") == 0)
4800 return psprintf("%s", get_line_style(&popt->topt)->name);
4801 else if (strcmp(param, "null") == 0)
4802 return pset_quoted_string(popt->nullPrint
4803 ? popt->nullPrint
4804 : "");
4805 else if (strcmp(param, "numericlocale") == 0)
4806 return pstrdup(pset_bool_string(popt->topt.numericLocale));
4807 else if (strcmp(param, "pager") == 0)
4808 return psprintf("%d", popt->topt.pager);
4809 else if (strcmp(param, "pager_min_lines") == 0)
4810 return psprintf("%d", popt->topt.pager_min_lines);
4811 else if (strcmp(param, "recordsep") == 0)
4812 return pset_quoted_string(popt->topt.recordSep.separator
4813 ? popt->topt.recordSep.separator
4814 : "");
4815 else if (strcmp(param, "recordsep_zero") == 0)
4816 return pstrdup(pset_bool_string(popt->topt.recordSep.separator_zero));
4817 else if (strcmp(param, "tableattr") == 0)
4818 return popt->topt.tableAttr ? pset_quoted_string(popt->topt.tableAttr) : pstrdup("");
4819 else if (strcmp(param, "title") == 0)
4820 return popt->title ? pset_quoted_string(popt->title) : pstrdup("");
4821 else if (strcmp(param, "tuples_only") == 0)
4822 return pstrdup(pset_bool_string(popt->topt.tuples_only));
4823 else if (strcmp(param, "unicode_border_linestyle") == 0)
4824 return pstrdup(_unicode_linestyle2string(popt->topt.unicode_border_linestyle));
4825 else if (strcmp(param, "unicode_column_linestyle") == 0)
4826 return pstrdup(_unicode_linestyle2string(popt->topt.unicode_column_linestyle));
4827 else if (strcmp(param, "unicode_header_linestyle") == 0)
4828 return pstrdup(_unicode_linestyle2string(popt->topt.unicode_header_linestyle));
4829 else
4830 return pstrdup("ERROR");
4831 }
4832
4833
4834
4835 #ifndef WIN32
4836 #define DEFAULT_SHELL "/bin/sh"
4837 #else
4838 /*
4839 * CMD.EXE is in different places in different Win32 releases so we
4840 * have to rely on the path to find it.
4841 */
4842 #define DEFAULT_SHELL "cmd.exe"
4843 #endif
4844
4845 static bool
do_shell(const char * command)4846 do_shell(const char *command)
4847 {
4848 int result;
4849
4850 if (!command)
4851 {
4852 char *sys;
4853 const char *shellName;
4854
4855 shellName = getenv("SHELL");
4856 #ifdef WIN32
4857 if (shellName == NULL)
4858 shellName = getenv("COMSPEC");
4859 #endif
4860 if (shellName == NULL)
4861 shellName = DEFAULT_SHELL;
4862
4863 /* See EDITOR handling comment for an explanation */
4864 #ifndef WIN32
4865 sys = psprintf("exec %s", shellName);
4866 #else
4867 sys = psprintf("\"%s\"", shellName);
4868 #endif
4869 result = system(sys);
4870 free(sys);
4871 }
4872 else
4873 result = system(command);
4874
4875 if (result == 127 || result == -1)
4876 {
4877 pg_log_error("\\!: failed");
4878 return false;
4879 }
4880 return true;
4881 }
4882
4883 /*
4884 * do_watch -- handler for \watch
4885 *
4886 * We break this out of exec_command to avoid having to plaster "volatile"
4887 * onto a bunch of exec_command's variables to silence stupider compilers.
4888 */
4889 static bool
do_watch(PQExpBuffer query_buf,double sleep)4890 do_watch(PQExpBuffer query_buf, double sleep)
4891 {
4892 long sleep_ms = (long) (sleep * 1000);
4893 printQueryOpt myopt = pset.popt;
4894 const char *strftime_fmt;
4895 const char *user_title;
4896 char *title;
4897 int title_len;
4898 int res = 0;
4899
4900 if (!query_buf || query_buf->len <= 0)
4901 {
4902 pg_log_error("\\watch cannot be used with an empty query");
4903 return false;
4904 }
4905
4906 /*
4907 * Choose format for timestamps. We might eventually make this a \pset
4908 * option. In the meantime, using a variable for the format suppresses
4909 * overly-anal-retentive gcc warnings about %c being Y2K sensitive.
4910 */
4911 strftime_fmt = "%c";
4912
4913 /*
4914 * Set up rendering options, in particular, disable the pager, because
4915 * nobody wants to be prompted while watching the output of 'watch'.
4916 */
4917 myopt.topt.pager = 0;
4918
4919 /*
4920 * If there's a title in the user configuration, make sure we have room
4921 * for it in the title buffer. Allow 128 bytes for the timestamp plus 128
4922 * bytes for the rest.
4923 */
4924 user_title = myopt.title;
4925 title_len = (user_title ? strlen(user_title) : 0) + 256;
4926 title = pg_malloc(title_len);
4927
4928 for (;;)
4929 {
4930 time_t timer;
4931 char timebuf[128];
4932 long i;
4933
4934 /*
4935 * Prepare title for output. Note that we intentionally include a
4936 * newline at the end of the title; this is somewhat historical but it
4937 * makes for reasonably nicely formatted output in simple cases.
4938 */
4939 timer = time(NULL);
4940 strftime(timebuf, sizeof(timebuf), strftime_fmt, localtime(&timer));
4941
4942 if (user_title)
4943 snprintf(title, title_len, _("%s\t%s (every %gs)\n"),
4944 user_title, timebuf, sleep);
4945 else
4946 snprintf(title, title_len, _("%s (every %gs)\n"),
4947 timebuf, sleep);
4948 myopt.title = title;
4949
4950 /* Run the query and print out the results */
4951 res = PSQLexecWatch(query_buf->data, &myopt);
4952
4953 /*
4954 * PSQLexecWatch handles the case where we can no longer repeat the
4955 * query, and returns 0 or -1.
4956 */
4957 if (res <= 0)
4958 break;
4959
4960 /*
4961 * Set up cancellation of 'watch' via SIGINT. We redo this each time
4962 * through the loop since it's conceivable something inside
4963 * PSQLexecWatch could change sigint_interrupt_jmp.
4964 */
4965 if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
4966 break;
4967
4968 /*
4969 * Enable 'watch' cancellations and wait a while before running the
4970 * query again. Break the sleep into short intervals (at most 1s)
4971 * since pg_usleep isn't interruptible on some platforms.
4972 */
4973 sigint_interrupt_enabled = true;
4974 i = sleep_ms;
4975 while (i > 0)
4976 {
4977 long s = Min(i, 1000L);
4978
4979 pg_usleep(s * 1000L);
4980 if (cancel_pressed)
4981 break;
4982 i -= s;
4983 }
4984 sigint_interrupt_enabled = false;
4985 }
4986
4987 pg_free(title);
4988 return (res >= 0);
4989 }
4990
4991 /*
4992 * a little code borrowed from PSQLexec() to manage ECHO_HIDDEN output.
4993 * returns true unless we have ECHO_HIDDEN_NOEXEC.
4994 */
4995 static bool
echo_hidden_command(const char * query)4996 echo_hidden_command(const char *query)
4997 {
4998 if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
4999 {
5000 printf(_("********* QUERY **********\n"
5001 "%s\n"
5002 "**************************\n\n"), query);
5003 fflush(stdout);
5004 if (pset.logfile)
5005 {
5006 fprintf(pset.logfile,
5007 _("********* QUERY **********\n"
5008 "%s\n"
5009 "**************************\n\n"), query);
5010 fflush(pset.logfile);
5011 }
5012
5013 if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
5014 return false;
5015 }
5016 return true;
5017 }
5018
5019 /*
5020 * Look up the object identified by obj_type and desc. If successful,
5021 * store its OID in *obj_oid and return true, else return false.
5022 *
5023 * Note that we'll fail if the object doesn't exist OR if there are multiple
5024 * matching candidates OR if there's something syntactically wrong with the
5025 * object description; unfortunately it can be hard to tell the difference.
5026 */
5027 static bool
lookup_object_oid(EditableObjectType obj_type,const char * desc,Oid * obj_oid)5028 lookup_object_oid(EditableObjectType obj_type, const char *desc,
5029 Oid *obj_oid)
5030 {
5031 bool result = true;
5032 PQExpBuffer query = createPQExpBuffer();
5033 PGresult *res;
5034
5035 switch (obj_type)
5036 {
5037 case EditableFunction:
5038
5039 /*
5040 * We have a function description, e.g. "x" or "x(int)". Issue a
5041 * query to retrieve the function's OID using a cast to regproc or
5042 * regprocedure (as appropriate).
5043 */
5044 appendPQExpBufferStr(query, "SELECT ");
5045 appendStringLiteralConn(query, desc, pset.db);
5046 appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
5047 strchr(desc, '(') ? "regprocedure" : "regproc");
5048 break;
5049
5050 case EditableView:
5051
5052 /*
5053 * Convert view name (possibly schema-qualified) to OID. Note:
5054 * this code doesn't check if the relation is actually a view.
5055 * We'll detect that in get_create_object_cmd().
5056 */
5057 appendPQExpBufferStr(query, "SELECT ");
5058 appendStringLiteralConn(query, desc, pset.db);
5059 appendPQExpBufferStr(query, "::pg_catalog.regclass::pg_catalog.oid");
5060 break;
5061 }
5062
5063 if (!echo_hidden_command(query->data))
5064 {
5065 destroyPQExpBuffer(query);
5066 return false;
5067 }
5068 res = PQexec(pset.db, query->data);
5069 if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
5070 *obj_oid = atooid(PQgetvalue(res, 0, 0));
5071 else
5072 {
5073 minimal_error_message(res);
5074 result = false;
5075 }
5076
5077 PQclear(res);
5078 destroyPQExpBuffer(query);
5079
5080 return result;
5081 }
5082
5083 /*
5084 * Construct a "CREATE OR REPLACE ..." command that describes the specified
5085 * database object. If successful, the result is stored in buf.
5086 */
5087 static bool
get_create_object_cmd(EditableObjectType obj_type,Oid oid,PQExpBuffer buf)5088 get_create_object_cmd(EditableObjectType obj_type, Oid oid,
5089 PQExpBuffer buf)
5090 {
5091 bool result = true;
5092 PQExpBuffer query = createPQExpBuffer();
5093 PGresult *res;
5094
5095 switch (obj_type)
5096 {
5097 case EditableFunction:
5098 printfPQExpBuffer(query,
5099 "SELECT pg_catalog.pg_get_functiondef(%u)",
5100 oid);
5101 break;
5102
5103 case EditableView:
5104
5105 /*
5106 * pg_get_viewdef() just prints the query, so we must prepend
5107 * CREATE for ourselves. We must fully qualify the view name to
5108 * ensure the right view gets replaced. Also, check relation kind
5109 * to be sure it's a view.
5110 *
5111 * Starting with 9.2, views may have reloptions (security_barrier)
5112 * and from 9.4 onwards they may also have WITH [LOCAL|CASCADED]
5113 * CHECK OPTION. These are not part of the view definition
5114 * returned by pg_get_viewdef() and so need to be retrieved
5115 * separately. Materialized views (introduced in 9.3) may have
5116 * arbitrary storage parameter reloptions.
5117 */
5118 if (pset.sversion >= 90400)
5119 {
5120 printfPQExpBuffer(query,
5121 "SELECT nspname, relname, relkind, "
5122 "pg_catalog.pg_get_viewdef(c.oid, true), "
5123 "pg_catalog.array_remove(pg_catalog.array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
5124 "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
5125 "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption "
5126 "FROM pg_catalog.pg_class c "
5127 "LEFT JOIN pg_catalog.pg_namespace n "
5128 "ON c.relnamespace = n.oid WHERE c.oid = %u",
5129 oid);
5130 }
5131 else if (pset.sversion >= 90200)
5132 {
5133 printfPQExpBuffer(query,
5134 "SELECT nspname, relname, relkind, "
5135 "pg_catalog.pg_get_viewdef(c.oid, true), "
5136 "c.reloptions AS reloptions, "
5137 "NULL AS checkoption "
5138 "FROM pg_catalog.pg_class c "
5139 "LEFT JOIN pg_catalog.pg_namespace n "
5140 "ON c.relnamespace = n.oid WHERE c.oid = %u",
5141 oid);
5142 }
5143 else
5144 {
5145 printfPQExpBuffer(query,
5146 "SELECT nspname, relname, relkind, "
5147 "pg_catalog.pg_get_viewdef(c.oid, true), "
5148 "NULL AS reloptions, "
5149 "NULL AS checkoption "
5150 "FROM pg_catalog.pg_class c "
5151 "LEFT JOIN pg_catalog.pg_namespace n "
5152 "ON c.relnamespace = n.oid WHERE c.oid = %u",
5153 oid);
5154 }
5155 break;
5156 }
5157
5158 if (!echo_hidden_command(query->data))
5159 {
5160 destroyPQExpBuffer(query);
5161 return false;
5162 }
5163 res = PQexec(pset.db, query->data);
5164 if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
5165 {
5166 resetPQExpBuffer(buf);
5167 switch (obj_type)
5168 {
5169 case EditableFunction:
5170 appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
5171 break;
5172
5173 case EditableView:
5174 {
5175 char *nspname = PQgetvalue(res, 0, 0);
5176 char *relname = PQgetvalue(res, 0, 1);
5177 char *relkind = PQgetvalue(res, 0, 2);
5178 char *viewdef = PQgetvalue(res, 0, 3);
5179 char *reloptions = PQgetvalue(res, 0, 4);
5180 char *checkoption = PQgetvalue(res, 0, 5);
5181
5182 /*
5183 * If the backend ever supports CREATE OR REPLACE
5184 * MATERIALIZED VIEW, allow that here; but as of today it
5185 * does not, so editing a matview definition in this way
5186 * is impossible.
5187 */
5188 switch (relkind[0])
5189 {
5190 #ifdef NOT_USED
5191 case RELKIND_MATVIEW:
5192 appendPQExpBufferStr(buf, "CREATE OR REPLACE MATERIALIZED VIEW ");
5193 break;
5194 #endif
5195 case RELKIND_VIEW:
5196 appendPQExpBufferStr(buf, "CREATE OR REPLACE VIEW ");
5197 break;
5198 default:
5199 pg_log_error("\"%s.%s\" is not a view",
5200 nspname, relname);
5201 result = false;
5202 break;
5203 }
5204 appendPQExpBuffer(buf, "%s.", fmtId(nspname));
5205 appendPQExpBufferStr(buf, fmtId(relname));
5206
5207 /* reloptions, if not an empty array "{}" */
5208 if (reloptions != NULL && strlen(reloptions) > 2)
5209 {
5210 appendPQExpBufferStr(buf, "\n WITH (");
5211 if (!appendReloptionsArray(buf, reloptions, "",
5212 pset.encoding,
5213 standard_strings()))
5214 {
5215 pg_log_error("could not parse reloptions array");
5216 result = false;
5217 }
5218 appendPQExpBufferChar(buf, ')');
5219 }
5220
5221 /* View definition from pg_get_viewdef (a SELECT query) */
5222 appendPQExpBuffer(buf, " AS\n%s", viewdef);
5223
5224 /* Get rid of the semicolon that pg_get_viewdef appends */
5225 if (buf->len > 0 && buf->data[buf->len - 1] == ';')
5226 buf->data[--(buf->len)] = '\0';
5227
5228 /* WITH [LOCAL|CASCADED] CHECK OPTION */
5229 if (checkoption && checkoption[0] != '\0')
5230 appendPQExpBuffer(buf, "\n WITH %s CHECK OPTION",
5231 checkoption);
5232 }
5233 break;
5234 }
5235 /* Make sure result ends with a newline */
5236 if (buf->len > 0 && buf->data[buf->len - 1] != '\n')
5237 appendPQExpBufferChar(buf, '\n');
5238 }
5239 else
5240 {
5241 minimal_error_message(res);
5242 result = false;
5243 }
5244
5245 PQclear(res);
5246 destroyPQExpBuffer(query);
5247
5248 return result;
5249 }
5250
5251 /*
5252 * If the given argument of \ef or \ev ends with a line number, delete the line
5253 * number from the argument string and return it as an integer. (We need
5254 * this kluge because we're too lazy to parse \ef's function or \ev's view
5255 * argument carefully --- we just slop it up in OT_WHOLE_LINE mode.)
5256 *
5257 * Returns -1 if no line number is present, 0 on error, or a positive value
5258 * on success.
5259 */
5260 static int
strip_lineno_from_objdesc(char * obj)5261 strip_lineno_from_objdesc(char *obj)
5262 {
5263 char *c;
5264 int lineno;
5265
5266 if (!obj || obj[0] == '\0')
5267 return -1;
5268
5269 c = obj + strlen(obj) - 1;
5270
5271 /*
5272 * This business of parsing backwards is dangerous as can be in a
5273 * multibyte environment: there is no reason to believe that we are
5274 * looking at the first byte of a character, nor are we necessarily
5275 * working in a "safe" encoding. Fortunately the bitpatterns we are
5276 * looking for are unlikely to occur as non-first bytes, but beware of
5277 * trying to expand the set of cases that can be recognized. We must
5278 * guard the <ctype.h> macros by using isascii() first, too.
5279 */
5280
5281 /* skip trailing whitespace */
5282 while (c > obj && isascii((unsigned char) *c) && isspace((unsigned char) *c))
5283 c--;
5284
5285 /* must have a digit as last non-space char */
5286 if (c == obj || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c))
5287 return -1;
5288
5289 /* find start of digit string */
5290 while (c > obj && isascii((unsigned char) *c) && isdigit((unsigned char) *c))
5291 c--;
5292
5293 /* digits must be separated from object name by space or closing paren */
5294 /* notice also that we are not allowing an empty object name ... */
5295 if (c == obj || !isascii((unsigned char) *c) ||
5296 !(isspace((unsigned char) *c) || *c == ')'))
5297 return -1;
5298
5299 /* parse digit string */
5300 c++;
5301 lineno = atoi(c);
5302 if (lineno < 1)
5303 {
5304 pg_log_error("invalid line number: %s", c);
5305 return 0;
5306 }
5307
5308 /* strip digit string from object name */
5309 *c = '\0';
5310
5311 return lineno;
5312 }
5313
5314 /*
5315 * Count number of lines in the buffer.
5316 * This is used to test if pager is needed or not.
5317 */
5318 static int
count_lines_in_buf(PQExpBuffer buf)5319 count_lines_in_buf(PQExpBuffer buf)
5320 {
5321 int lineno = 0;
5322 const char *lines = buf->data;
5323
5324 while (*lines != '\0')
5325 {
5326 lineno++;
5327 /* find start of next line */
5328 lines = strchr(lines, '\n');
5329 if (!lines)
5330 break;
5331 lines++;
5332 }
5333
5334 return lineno;
5335 }
5336
5337 /*
5338 * Write text at *lines to output with line numbers.
5339 *
5340 * If header_keyword isn't NULL, then line 1 should be the first line beginning
5341 * with header_keyword; lines before that are unnumbered.
5342 *
5343 * Caution: this scribbles on *lines.
5344 */
5345 static void
print_with_linenumbers(FILE * output,char * lines,const char * header_keyword)5346 print_with_linenumbers(FILE *output, char *lines,
5347 const char *header_keyword)
5348 {
5349 bool in_header = (header_keyword != NULL);
5350 size_t header_sz = in_header ? strlen(header_keyword) : 0;
5351 int lineno = 0;
5352
5353 while (*lines != '\0')
5354 {
5355 char *eol;
5356
5357 if (in_header && strncmp(lines, header_keyword, header_sz) == 0)
5358 in_header = false;
5359
5360 /* increment lineno only for body's lines */
5361 if (!in_header)
5362 lineno++;
5363
5364 /* find and mark end of current line */
5365 eol = strchr(lines, '\n');
5366 if (eol != NULL)
5367 *eol = '\0';
5368
5369 /* show current line as appropriate */
5370 if (in_header)
5371 fprintf(output, " %s\n", lines);
5372 else
5373 fprintf(output, "%-7d %s\n", lineno, lines);
5374
5375 /* advance to next line, if any */
5376 if (eol == NULL)
5377 break;
5378 lines = ++eol;
5379 }
5380 }
5381
5382 /*
5383 * Report just the primary error; this is to avoid cluttering the output
5384 * with, for instance, a redisplay of the internally generated query
5385 */
5386 static void
minimal_error_message(PGresult * res)5387 minimal_error_message(PGresult *res)
5388 {
5389 PQExpBuffer msg;
5390 const char *fld;
5391
5392 msg = createPQExpBuffer();
5393
5394 fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
5395 if (fld)
5396 printfPQExpBuffer(msg, "%s: ", fld);
5397 else
5398 printfPQExpBuffer(msg, "ERROR: ");
5399 fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
5400 if (fld)
5401 appendPQExpBufferStr(msg, fld);
5402 else
5403 appendPQExpBufferStr(msg, "(not available)");
5404 appendPQExpBufferChar(msg, '\n');
5405
5406 pg_log_error("%s", msg->data);
5407
5408 destroyPQExpBuffer(msg);
5409 }
5410