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