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