Age Owner TLA Line data Source code
1 : /*
2 : * psql - the PostgreSQL interactive terminal
3 : *
4 : * Copyright (c) 2000-2023, PostgreSQL Global Development Group
5 : *
6 : * src/bin/psql/startup.c
7 : */
8 : #include "postgres_fe.h"
9 :
10 : #ifndef WIN32
11 : #include <unistd.h>
12 : #else /* WIN32 */
13 : #include <io.h>
14 : #include <win32.h>
15 : #endif /* WIN32 */
16 :
17 : #include "command.h"
18 : #include "common.h"
19 : #include "common/logging.h"
20 : #include "common/string.h"
21 : #include "describe.h"
22 : #include "fe_utils/print.h"
23 : #include "getopt_long.h"
24 : #include "help.h"
25 : #include "input.h"
26 : #include "mainloop.h"
27 : #include "settings.h"
28 :
29 : /*
30 : * Global psql options
31 : */
32 : PsqlSettings pset;
33 :
34 : #ifndef WIN32
35 : #define SYSPSQLRC "psqlrc"
36 : #define PSQLRC ".psqlrc"
37 : #else
38 : #define SYSPSQLRC "psqlrc"
39 : #define PSQLRC "psqlrc.conf"
40 : #endif
41 :
42 : /*
43 : * Structures to pass information between the option parsing routine
44 : * and the main function
45 : */
46 : enum _actions
47 : {
48 : ACT_SINGLE_QUERY,
49 : ACT_SINGLE_SLASH,
50 : ACT_FILE
51 : };
52 :
53 : typedef struct SimpleActionListCell
54 : {
55 : struct SimpleActionListCell *next;
56 : enum _actions action;
57 : char *val;
58 : } SimpleActionListCell;
59 :
60 : typedef struct SimpleActionList
61 : {
62 : SimpleActionListCell *head;
63 : SimpleActionListCell *tail;
64 : } SimpleActionList;
65 :
66 : struct adhoc_opts
67 : {
68 : char *dbname;
69 : char *host;
70 : char *port;
71 : char *username;
72 : char *logfilename;
73 : bool no_readline;
74 : bool no_psqlrc;
75 : bool single_txn;
76 : bool list_dbs;
77 : SimpleActionList actions;
78 : };
79 :
80 : static void parse_psql_options(int argc, char *argv[],
81 : struct adhoc_opts *options);
82 : static void simple_action_list_append(SimpleActionList *list,
83 : enum _actions action, const char *val);
84 : static void process_psqlrc(char *argv0);
85 : static void process_psqlrc_file(char *filename);
86 : static void showVersion(void);
87 : static void EstablishVariableSpace(void);
88 :
89 : #define NOPAGER 0
90 :
91 : static void
1469 peter 92 CBC 27375 : log_pre_callback(void)
93 : {
94 27375 : if (pset.queryFout && pset.queryFout != stdout)
1469 peter 95 UBC 0 : fflush(pset.queryFout);
1469 peter 96 CBC 27375 : }
97 :
98 : static void
99 27375 : log_locus_callback(const char **filename, uint64 *lineno)
100 : {
101 27375 : if (pset.inputfile)
102 : {
103 306 : *filename = pset.inputfile;
1418 tgl 104 306 : *lineno = pset.lineno;
105 : }
106 : else
107 : {
1469 peter 108 27069 : *filename = NULL;
109 27069 : *lineno = 0;
110 : }
111 27375 : }
112 :
113 : #ifndef WIN32
114 : static void
635 tmunro 115 2 : empty_signal_handler(SIGNAL_ARGS)
116 : {
117 2 : }
118 : #endif
119 :
120 : /*
121 : *
122 : * main
123 : *
124 : */
125 : int
8462 peter_e 126 6482 : main(int argc, char *argv[])
127 : {
128 : struct adhoc_opts options;
129 : int successResult;
948 tgl 130 6482 : char *password = NULL;
131 : bool new_pass;
132 :
1469 peter 133 6482 : pg_logging_init(argv[0]);
134 6482 : pg_logging_set_pre_callback(log_pre_callback);
135 6482 : pg_logging_set_locus_callback(log_locus_callback);
5232 peter_e 136 6482 : set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));
137 :
8170 138 6482 : if (argc > 1)
139 : {
3134 andres 140 6482 : if ((strcmp(argv[1], "-?") == 0) || (argc == 2 && (strcmp(argv[1], "--help") == 0)))
141 : {
142 1 : usage(NOPAGER);
8170 peter_e 143 1 : exit(EXIT_SUCCESS);
144 : }
8053 bruce 145 6481 : if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
146 : {
8170 peter_e 147 3 : showVersion();
148 3 : exit(EXIT_SUCCESS);
149 : }
150 : }
151 :
6136 tgl 152 6478 : pset.progname = get_progname(argv[0]);
153 :
6067 154 6478 : pset.db = NULL;
898 155 6478 : pset.dead_conn = NULL;
6478 bruce 156 6478 : setDecimalLocale();
6067 tgl 157 6478 : pset.encoding = PQenv2encoding();
158 6478 : pset.queryFout = stdout;
159 6478 : pset.queryFoutPipe = false;
3317 160 6478 : pset.copyStream = NULL;
2562 161 6478 : pset.last_error_result = NULL;
8486 peter_e 162 6478 : pset.cur_cmd_source = stdin;
163 6478 : pset.cur_cmd_interactive = false;
164 :
165 : /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
166 6478 : pset.popt.topt.format = PRINT_ALIGNED;
167 6478 : pset.popt.topt.border = 1;
7457 bruce 168 6478 : pset.popt.topt.pager = 1;
2934 andrew 169 6478 : pset.popt.topt.pager_min_lines = 0;
6067 tgl 170 6478 : pset.popt.topt.start_table = true;
171 6478 : pset.popt.topt.stop_table = true;
3995 rhaas 172 6478 : pset.popt.topt.default_footer = true;
173 :
1595 tgl 174 6478 : pset.popt.topt.csvFieldSep[0] = DEFAULT_CSV_FIELD_SEP;
175 6478 : pset.popt.topt.csvFieldSep[1] = '\0';
176 :
3131 sfrost 177 6478 : pset.popt.topt.unicode_border_linestyle = UNICODE_LINESTYLE_SINGLE;
178 6478 : pset.popt.topt.unicode_column_linestyle = UNICODE_LINESTYLE_SINGLE;
179 6478 : pset.popt.topt.unicode_header_linestyle = UNICODE_LINESTYLE_SINGLE;
180 :
181 6478 : refresh_utf8format(&(pset.popt.topt));
182 :
183 : /* We must get COLUMNS here before readline() sets it */
5449 bruce 184 6478 : pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
185 :
8486 peter_e 186 6478 : pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
187 :
5155 188 6478 : pset.getPassword = TRI_DEFAULT;
189 :
6067 tgl 190 6478 : EstablishVariableSpace();
191 :
192 : /* Create variables showing psql version number */
193 6478 : SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
2042 194 6478 : SetVariable(pset.vars, "VERSION_NAME", PG_VERSION);
195 6478 : SetVariable(pset.vars, "VERSION_NUM", CppAsString2(PG_VERSION_NUM));
196 :
197 : /* Initialize variables for last error */
2035 198 6478 : SetVariable(pset.vars, "LAST_ERROR_MESSAGE", "");
199 6478 : SetVariable(pset.vars, "LAST_ERROR_SQLSTATE", "00000");
200 :
201 : /* Default values for variables (that don't match the result of \unset) */
6067 202 6478 : SetVariableBool(pset.vars, "AUTOCOMMIT");
203 6478 : SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
204 6478 : SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
205 6478 : SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
370 peter 206 6478 : SetVariableBool(pset.vars, "SHOW_ALL_RESULTS");
207 :
8449 peter_e 208 6478 : parse_psql_options(argc, argv, &options);
209 :
210 : /*
211 : * If no action was specified and we're in non-interactive mode, treat it
212 : * as if the user had specified "-f -". This lets single-transaction mode
213 : * work in this case.
214 : */
2679 rhaas 215 6475 : if (options.actions.head == NULL && pset.notty)
216 2104 : simple_action_list_append(&options.actions, ACT_FILE, NULL);
217 :
218 : /* Bail out if -1 was specified but will be ignored. */
219 6475 : if (options.single_txn && options.actions.head == NULL)
366 tgl 220 UBC 0 : pg_fatal("-1 can only be used in non-interactive mode");
221 :
4077 peter_e 222 CBC 6475 : if (!pset.popt.topt.fieldSep.separator &&
223 6473 : !pset.popt.topt.fieldSep.separator_zero)
224 : {
225 6473 : pset.popt.topt.fieldSep.separator = pg_strdup(DEFAULT_FIELD_SEP);
226 6473 : pset.popt.topt.fieldSep.separator_zero = false;
227 : }
228 6475 : if (!pset.popt.topt.recordSep.separator &&
229 6475 : !pset.popt.topt.recordSep.separator_zero)
230 : {
231 6475 : pset.popt.topt.recordSep.separator = pg_strdup(DEFAULT_RECORD_SEP);
232 6475 : pset.popt.topt.recordSep.separator_zero = false;
233 : }
234 :
5155 235 6475 : if (pset.getPassword == TRI_YES)
236 : {
237 : /*
238 : * We can't be sure yet of the username that will be used, so don't
239 : * offer a potentially wrong one. Typical uses of this option are
240 : * noninteractive anyway. (Note: since we've not yet set up our
241 : * cancel handler, there's no need to use simple_prompt_extended.)
242 : */
948 tgl 243 UBC 0 : password = simple_prompt("Password: ", false);
244 : }
245 :
246 : /* loop until we have a password if requested by backend */
247 : do
248 : {
249 : #define PARAMS_ARRAY_SIZE 8
209 peter 250 GNC 6475 : const char **keywords = pg_malloc_array(const char *, PARAMS_ARRAY_SIZE);
251 6475 : const char **values = pg_malloc_array(const char *, PARAMS_ARRAY_SIZE);
252 :
4790 bruce 253 CBC 6475 : keywords[0] = "host";
254 6475 : values[0] = options.host;
255 6475 : keywords[1] = "port";
256 6475 : values[1] = options.port;
257 6475 : keywords[2] = "user";
258 6475 : values[2] = options.username;
259 6475 : keywords[3] = "password";
948 tgl 260 6475 : values[3] = password;
2435 noah 261 6475 : keywords[4] = "dbname"; /* see do_connect() */
2679 rhaas 262 UBC 0 : values[4] = (options.list_dbs && options.dbname == NULL) ?
4790 bruce 263 CBC 6475 : "postgres" : options.dbname;
264 6475 : keywords[5] = "fallback_application_name";
265 6475 : values[5] = pset.progname;
4432 peter_e 266 6475 : keywords[6] = "client_encoding";
267 6475 : values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
268 6475 : keywords[7] = NULL;
269 6475 : values[7] = NULL;
270 :
4811 mail 271 6475 : new_pass = false;
272 6475 : pset.db = PQconnectdbParams(keywords, values, true);
273 6475 : free(keywords);
274 6475 : free(values);
275 :
8486 peter_e 276 6769 : if (PQstatus(pset.db) == CONNECTION_BAD &&
5600 tgl 277 295 : PQconnectionNeedsPassword(pset.db) &&
948 278 1 : !password &&
5155 peter_e 279 1 : pset.getPassword != TRI_NO)
280 : {
281 : /*
282 : * Before closing the old PGconn, extract the user name that was
283 : * actually connected with --- it might've come out of a URI or
284 : * connstring "database name" rather than options.username.
285 : */
1896 tgl 286 UBC 0 : const char *realusername = PQuser(pset.db);
287 : char *password_prompt;
288 :
289 0 : if (realusername && realusername[0])
290 0 : password_prompt = psprintf(_("Password for user %s: "),
291 : realusername);
292 : else
293 0 : password_prompt = pg_strdup(_("Password: "));
8239 peter_e 294 0 : PQfinish(pset.db);
295 :
948 tgl 296 0 : password = simple_prompt(password_prompt, false);
1896 297 0 : free(password_prompt);
5754 298 0 : new_pass = true;
299 : }
5754 tgl 300 CBC 6475 : } while (new_pass);
301 :
8486 peter_e 302 6475 : if (PQstatus(pset.db) == CONNECTION_BAD)
303 : {
883 peter 304 294 : pg_log_error("%s", PQerrorMessage(pset.db));
8486 peter_e 305 294 : PQfinish(pset.db);
8557 bruce 306 294 : exit(EXIT_BADCONN);
307 : }
308 :
1224 michael 309 6181 : psql_setup_cancel_handler();
310 :
311 : #ifndef WIN32
312 :
313 : /*
314 : * do_watch() needs signal handlers installed (otherwise sigwait() will
315 : * filter them out on some platforms), but doesn't need them to do
316 : * anything, and they shouldn't ever run (unless perhaps a stray SIGALRM
317 : * arrives due to a race when do_watch() cancels an itimer).
318 : */
635 tmunro 319 6181 : pqsignal(SIGCHLD, empty_signal_handler);
320 6181 : pqsignal(SIGALRM, empty_signal_handler);
321 : #endif
322 :
8397 bruce 323 6181 : PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
324 :
7225 tgl 325 6181 : SyncVariables();
326 :
2679 rhaas 327 6181 : if (options.list_dbs)
328 : {
329 : int success;
330 :
4435 peter_e 331 UBC 0 : if (!options.no_psqlrc)
332 0 : process_psqlrc(argv[0]);
333 :
3689 334 0 : success = listAllDbs(NULL, false);
8486 335 0 : PQfinish(pset.db);
8439 336 0 : exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
337 : }
338 :
6508 bruce 339 CBC 6181 : if (options.logfilename)
340 : {
6508 bruce 341 UBC 0 : pset.logfile = fopen(options.logfilename, "a");
342 0 : if (!pset.logfile)
366 tgl 343 0 : pg_fatal("could not open log file \"%s\": %m",
344 : options.logfilename);
345 : }
346 :
2679 rhaas 347 CBC 6181 : if (!options.no_psqlrc)
2679 rhaas 348 UBC 0 : process_psqlrc(argv[0]);
349 :
350 : /*
351 : * If any actions were given by user, process them in the order in which
352 : * they were specified. Note single_txn is only effective in this mode.
353 : */
2679 rhaas 354 CBC 6181 : if (options.actions.head != NULL)
355 : {
356 : PGresult *res;
357 : SimpleActionListCell *cell;
358 :
359 6179 : successResult = EXIT_SUCCESS; /* silence compiler */
360 :
361 6179 : if (options.single_txn)
362 : {
363 7 : if ((res = PSQLexec("BEGIN")) == NULL)
364 : {
2679 rhaas 365 UBC 0 : if (pset.on_error_stop)
366 : {
367 0 : successResult = EXIT_USER;
368 0 : goto error;
369 : }
370 : }
371 : else
2679 rhaas 372 CBC 7 : PQclear(res);
373 : }
374 :
375 12430 : for (cell = options.actions.head; cell; cell = cell->next)
376 : {
377 6295 : if (cell->action == ACT_SINGLE_QUERY)
378 : {
1469 peter 379 326 : pg_logging_config(PG_LOG_FLAG_TERSE);
380 :
2679 rhaas 381 326 : if (pset.echo == PSQL_ECHO_ALL)
2679 rhaas 382 UBC 0 : puts(cell->val);
383 :
2679 rhaas 384 CBC 326 : successResult = SendQuery(cell->val)
385 325 : ? EXIT_SUCCESS : EXIT_FAILURE;
386 : }
387 5969 : else if (cell->action == ACT_SINGLE_SLASH)
388 : {
389 : PsqlScanState scan_state;
390 : ConditionalStack cond_stack;
391 :
1469 peter 392 2 : pg_logging_config(PG_LOG_FLAG_TERSE);
393 :
2679 rhaas 394 2 : if (pset.echo == PSQL_ECHO_ALL)
2679 rhaas 395 UBC 0 : puts(cell->val);
396 :
2578 tgl 397 CBC 2 : scan_state = psql_scan_create(&psqlscan_callbacks);
2679 rhaas 398 2 : psql_scan_setup(scan_state,
2578 tgl 399 2 : cell->val, strlen(cell->val),
400 2 : pset.encoding, standard_strings());
2201 401 2 : cond_stack = conditional_stack_create();
402 2 : psql_scan_set_passthrough(scan_state, (void *) cond_stack);
403 :
404 2 : successResult = HandleSlashCmds(scan_state,
405 : cond_stack,
406 : NULL,
407 : NULL) != PSQL_CMD_ERROR
2679 rhaas 408 2 : ? EXIT_SUCCESS : EXIT_FAILURE;
409 :
410 2 : psql_scan_destroy(scan_state);
2201 tgl 411 2 : conditional_stack_destroy(cond_stack);
412 : }
2679 rhaas 413 5967 : else if (cell->action == ACT_FILE)
414 : {
415 5967 : successResult = process_file(cell->val, false);
416 : }
417 : else
418 : {
419 : /* should never come here */
2674 tgl 420 UBC 0 : Assert(false);
421 : }
422 :
2679 rhaas 423 CBC 6288 : if (successResult != EXIT_SUCCESS && pset.on_error_stop)
424 37 : break;
425 : }
426 :
427 6172 : if (options.single_txn)
428 : {
429 : /*
430 : * Rollback the contents of the single transaction if the caller
431 : * has set ON_ERROR_STOP and one of the steps has failed. This
432 : * check needs to match the one done a couple of lines above.
433 : */
298 michael 434 7 : res = PSQLexec((successResult != EXIT_SUCCESS && pset.on_error_stop) ?
435 : "ROLLBACK" : "COMMIT");
307 436 7 : if (res == NULL)
437 : {
2679 rhaas 438 UBC 0 : if (pset.on_error_stop)
439 : {
440 0 : successResult = EXIT_USER;
441 0 : goto error;
442 : }
443 : }
444 : else
2679 rhaas 445 CBC 7 : PQclear(res);
446 : }
447 :
448 6172 : error:
449 : ;
450 : }
451 :
452 : /*
453 : * or otherwise enter interactive main loop
454 : */
455 : else
456 : {
1373 peter 457 2 : pg_logging_config(PG_LOG_FLAG_TERSE);
4800 bruce 458 2 : connection_warnings(true);
3895 rhaas 459 2 : if (!pset.quiet)
5376 bruce 460 2 : printf(_("Type \"help\" for help.\n\n"));
3895 rhaas 461 2 : initializeInput(options.no_readline ? 0 : 1);
8482 peter_e 462 2 : successResult = MainLoop(stdin);
463 : }
464 :
465 : /* clean up */
6508 bruce 466 6174 : if (pset.logfile)
6508 bruce 467 UBC 0 : fclose(pset.logfile);
898 tgl 468 CBC 6174 : if (pset.db)
469 6174 : PQfinish(pset.db);
470 6174 : if (pset.dead_conn)
898 tgl 471 UBC 0 : PQfinish(pset.dead_conn);
8486 peter_e 472 CBC 6174 : setQFout(NULL);
473 :
8557 bruce 474 6174 : return successResult;
475 : }
476 :
477 :
478 : /*
479 : * Parse command line options
480 : */
481 :
482 : static void
2118 tgl 483 6478 : parse_psql_options(int argc, char *argv[], struct adhoc_opts *options)
484 : {
485 : static struct option long_options[] =
486 : {
487 : {"echo-all", no_argument, NULL, 'a'},
488 : {"no-align", no_argument, NULL, 'A'},
489 : {"command", required_argument, NULL, 'c'},
490 : {"dbname", required_argument, NULL, 'd'},
491 : {"echo-queries", no_argument, NULL, 'e'},
492 : {"echo-errors", no_argument, NULL, 'b'},
493 : {"echo-hidden", no_argument, NULL, 'E'},
494 : {"file", required_argument, NULL, 'f'},
495 : {"field-separator", required_argument, NULL, 'F'},
496 : {"field-separator-zero", no_argument, NULL, 'z'},
497 : {"host", required_argument, NULL, 'h'},
498 : {"html", no_argument, NULL, 'H'},
499 : {"list", no_argument, NULL, 'l'},
500 : {"log-file", required_argument, NULL, 'L'},
501 : {"no-readline", no_argument, NULL, 'n'},
502 : {"single-transaction", no_argument, NULL, '1'},
503 : {"output", required_argument, NULL, 'o'},
504 : {"port", required_argument, NULL, 'p'},
505 : {"pset", required_argument, NULL, 'P'},
506 : {"quiet", no_argument, NULL, 'q'},
507 : {"record-separator", required_argument, NULL, 'R'},
508 : {"record-separator-zero", no_argument, NULL, '0'},
509 : {"single-step", no_argument, NULL, 's'},
510 : {"single-line", no_argument, NULL, 'S'},
511 : {"tuples-only", no_argument, NULL, 't'},
512 : {"table-attr", required_argument, NULL, 'T'},
513 : {"username", required_argument, NULL, 'U'},
514 : {"set", required_argument, NULL, 'v'},
515 : {"variable", required_argument, NULL, 'v'},
516 : {"version", no_argument, NULL, 'V'},
517 : {"no-password", no_argument, NULL, 'w'},
518 : {"password", no_argument, NULL, 'W'},
519 : {"expanded", no_argument, NULL, 'x'},
520 : {"no-psqlrc", no_argument, NULL, 'X'},
521 : {"help", optional_argument, NULL, 1},
522 : {"csv", no_argument, NULL, 2},
523 : {NULL, 0, NULL, 0}
524 : };
525 :
526 : int optindex;
527 : int c;
528 :
8535 bruce 529 6478 : memset(options, 0, sizeof *options);
530 :
3195 fujii 531 46079 : while ((c = getopt_long(argc, argv, "aAbc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
7398 peter_e 532 46079 : long_options, &optindex)) != -1)
533 : {
8557 bruce 534 39604 : switch (c)
535 : {
8456 peter_e 536 916 : case 'a':
537 916 : SetVariable(pset.vars, "ECHO", "all");
538 916 : break;
8557 bruce 539 5107 : case 'A':
8486 peter_e 540 5107 : pset.popt.topt.format = PRINT_UNALIGNED;
8557 bruce 541 5107 : break;
3195 fujii 542 UBC 0 : case 'b':
543 0 : SetVariable(pset.vars, "ECHO", "errors");
544 0 : break;
8557 bruce 545 CBC 332 : case 'c':
546 332 : if (optarg[0] == '\\')
2679 rhaas 547 2 : simple_action_list_append(&options->actions,
548 : ACT_SINGLE_SLASH,
2674 tgl 549 2 : optarg + 1);
550 : else
2679 rhaas 551 330 : simple_action_list_append(&options->actions,
552 : ACT_SINGLE_QUERY,
553 : optarg);
8557 bruce 554 332 : break;
555 6151 : case 'd':
3831 556 6151 : options->dbname = pg_strdup(optarg);
8557 557 6151 : break;
558 1 : case 'e':
8456 peter_e 559 1 : SetVariable(pset.vars, "ECHO", "queries");
8557 bruce 560 1 : break;
8557 bruce 561 UBC 0 : case 'E':
8456 peter_e 562 0 : SetVariableBool(pset.vars, "ECHO_HIDDEN");
8557 bruce 563 0 : break;
8557 bruce 564 CBC 4157 : case 'f':
2679 rhaas 565 4157 : simple_action_list_append(&options->actions,
566 : ACT_FILE,
567 : optarg);
8557 bruce 568 4157 : break;
569 2 : case 'F':
4077 peter_e 570 2 : pset.popt.topt.fieldSep.separator = pg_strdup(optarg);
571 2 : pset.popt.topt.fieldSep.separator_zero = false;
8557 bruce 572 2 : break;
573 1 : case 'h':
3831 574 1 : options->host = pg_strdup(optarg);
8557 575 1 : break;
8557 bruce 576 UBC 0 : case 'H':
8486 peter_e 577 0 : pset.popt.topt.format = PRINT_HTML;
8557 bruce 578 0 : break;
579 0 : case 'l':
2679 rhaas 580 0 : options->list_dbs = true;
8557 bruce 581 0 : break;
6508 582 0 : case 'L':
3831 583 0 : options->logfilename = pg_strdup(optarg);
6508 584 0 : break;
8557 585 0 : case 'n':
586 0 : options->no_readline = true;
587 0 : break;
588 0 : case 'o':
2684 tgl 589 0 : if (!setQFout(optarg))
590 0 : exit(EXIT_FAILURE);
8557 bruce 591 0 : break;
8557 bruce 592 CBC 2 : case 'p':
3831 593 2 : options->port = pg_strdup(optarg);
8557 594 2 : break;
595 2 : case 'P':
596 : {
597 : char *value;
598 : char *equal_loc;
599 : bool result;
600 :
7014 neilc 601 2 : value = pg_strdup(optarg);
8557 bruce 602 2 : equal_loc = strchr(value, '=');
603 2 : if (!equal_loc)
8486 peter_e 604 UBC 0 : result = do_pset(value, NULL, &pset.popt, true);
605 : else
606 : {
8557 bruce 607 CBC 2 : *equal_loc = '\0';
8486 peter_e 608 2 : result = do_pset(value, equal_loc + 1, &pset.popt, true);
609 : }
610 :
8557 bruce 611 2 : if (!result)
366 tgl 612 UBC 0 : pg_fatal("could not set printing parameter \"%s\"", value);
613 :
8557 bruce 614 CBC 2 : free(value);
615 2 : break;
616 : }
617 5267 : case 'q':
8456 peter_e 618 5267 : SetVariableBool(pset.vars, "QUIET");
8557 bruce 619 5267 : break;
8397 bruce 620 UBC 0 : case 'R':
4077 peter_e 621 0 : pset.popt.topt.recordSep.separator = pg_strdup(optarg);
622 0 : pset.popt.topt.recordSep.separator_zero = false;
8397 bruce 623 0 : break;
8557 624 0 : case 's':
8456 peter_e 625 0 : SetVariableBool(pset.vars, "SINGLESTEP");
8557 bruce 626 0 : break;
627 0 : case 'S':
8456 peter_e 628 0 : SetVariableBool(pset.vars, "SINGLELINE");
8557 bruce 629 0 : break;
8557 bruce 630 CBC 5101 : case 't':
8486 peter_e 631 5101 : pset.popt.topt.tuples_only = true;
8557 bruce 632 5101 : break;
8557 bruce 633 UBC 0 : case 'T':
7014 neilc 634 0 : pset.popt.topt.tableAttr = pg_strdup(optarg);
8557 bruce 635 0 : break;
8557 bruce 636 CBC 3 : case 'U':
3831 637 3 : options->username = pg_strdup(optarg);
8557 638 3 : break;
639 5696 : case 'v':
640 : {
641 : char *value;
642 : char *equal_loc;
643 :
7014 neilc 644 5696 : value = pg_strdup(optarg);
8557 bruce 645 5696 : equal_loc = strchr(value, '=');
646 5696 : if (!equal_loc)
647 : {
8486 peter_e 648 UBC 0 : if (!DeleteVariable(pset.vars, value))
2258 tgl 649 0 : exit(EXIT_FAILURE); /* error already printed */
650 : }
651 : else
652 : {
8557 bruce 653 CBC 5696 : *equal_loc = '\0';
8486 peter_e 654 5696 : if (!SetVariable(pset.vars, value, equal_loc + 1))
2258 tgl 655 UBC 0 : exit(EXIT_FAILURE); /* error already printed */
656 : }
657 :
8557 bruce 658 CBC 5696 : free(value);
659 5696 : break;
660 : }
8557 bruce 661 UBC 0 : case 'V':
8488 peter_e 662 0 : showVersion();
663 0 : exit(EXIT_SUCCESS);
5155 peter_e 664 CBC 381 : case 'w':
665 381 : pset.getPassword = TRI_NO;
666 381 : break;
8557 bruce 667 UBC 0 : case 'W':
5155 peter_e 668 0 : pset.getPassword = TRI_YES;
8557 bruce 669 0 : break;
8439 peter_e 670 0 : case 'x':
671 0 : pset.popt.topt.expanded = true;
672 0 : break;
8397 bruce 673 CBC 6475 : case 'X':
674 6475 : options->no_psqlrc = true;
675 6475 : break;
4077 peter_e 676 UBC 0 : case 'z':
677 0 : pset.popt.topt.fieldSep.separator_zero = true;
678 0 : break;
679 0 : case '0':
680 0 : pset.popt.topt.recordSep.separator_zero = true;
681 0 : break;
6265 bruce 682 CBC 7 : case '1':
683 7 : options->single_txn = true;
684 7 : break;
8557 685 1 : case '?':
1323 tgl 686 1 : if (optind <= argc &&
687 1 : strcmp(argv[optind - 1], "-?") == 0)
688 : {
689 : /* actual help option given */
3134 andres 690 UBC 0 : usage(NOPAGER);
8397 bruce 691 0 : exit(EXIT_SUCCESS);
692 : }
693 : else
694 : {
695 : /* getopt error (unknown option or missing argument) */
3134 andres 696 CBC 1 : goto unknown_option;
697 : }
698 : break;
699 2 : case 1:
700 : {
701 2 : if (!optarg || strcmp(optarg, "options") == 0)
3134 andres 702 UBC 0 : usage(NOPAGER);
3134 andres 703 CBC 2 : else if (optarg && strcmp(optarg, "commands") == 0)
704 1 : slashUsage(NOPAGER);
705 1 : else if (optarg && strcmp(optarg, "variables") == 0)
706 1 : helpVariables(NOPAGER);
707 : else
3134 andres 708 UBC 0 : goto unknown_option;
709 :
3134 andres 710 CBC 2 : exit(EXIT_SUCCESS);
711 : }
712 : break;
1595 tgl 713 UBC 0 : case 2:
714 0 : pset.popt.topt.format = PRINT_CSV;
715 0 : break;
716 : default:
2878 bruce 717 CBC 1 : unknown_option:
718 : /* getopt_long already emitted a complaint */
366 tgl 719 1 : pg_log_error_hint("Try \"%s --help\" for more information.",
720 : pset.progname);
8367 bruce 721 1 : exit(EXIT_FAILURE);
722 : }
723 : }
724 :
725 : /*
726 : * if we still have arguments, use it as the database name and username
727 : */
8557 728 6815 : while (argc - optind >= 1)
729 : {
730 340 : if (!options->dbname)
731 340 : options->dbname = argv[optind];
8557 bruce 732 UBC 0 : else if (!options->username)
733 0 : options->username = argv[optind];
6067 tgl 734 0 : else if (!pset.quiet)
1469 peter 735 0 : pg_log_warning("extra command-line argument \"%s\" ignored",
736 : argv[optind]);
737 :
8557 bruce 738 CBC 340 : optind++;
739 : }
740 6475 : }
741 :
742 :
743 : /*
744 : * Append a new item to the end of the SimpleActionList.
745 : * Note that "val" is copied if it's not NULL.
746 : */
747 : static void
2674 tgl 748 6593 : simple_action_list_append(SimpleActionList *list,
749 : enum _actions action, const char *val)
750 : {
751 : SimpleActionListCell *cell;
752 :
209 peter 753 GNC 6593 : cell = pg_malloc_object(SimpleActionListCell);
754 :
2674 tgl 755 CBC 6593 : cell->next = NULL;
756 6593 : cell->action = action;
757 6593 : if (val)
758 4489 : cell->val = pg_strdup(val);
759 : else
760 2104 : cell->val = NULL;
761 :
762 6593 : if (list->tail)
763 120 : list->tail->next = cell;
764 : else
765 6473 : list->head = cell;
766 6593 : list->tail = cell;
767 6593 : }
768 :
769 :
770 : /*
771 : * Load .psqlrc file, if found.
772 : */
773 : static void
4781 magnus 774 UBC 0 : process_psqlrc(char *argv0)
775 : {
776 : char home[MAXPGPATH];
777 : char rc_file[MAXPGPATH];
778 : char my_exec_path[MAXPGPATH];
779 : char etc_path[MAXPGPATH];
3657 bruce 780 0 : char *envrc = getenv("PSQLRC");
781 :
3326 sfrost 782 0 : if (find_my_exec(argv0, my_exec_path) < 0)
366 tgl 783 0 : pg_fatal("could not find own program executable");
784 :
6901 bruce 785 0 : get_etc_path(my_exec_path, etc_path);
786 :
6667 tgl 787 0 : snprintf(rc_file, MAXPGPATH, "%s/%s", etc_path, SYSPSQLRC);
788 0 : process_psqlrc_file(rc_file);
789 :
4054 andrew 790 0 : if (envrc != NULL && strlen(envrc) > 0)
791 0 : {
792 : /* might need to free() this */
3602 bruce 793 0 : char *envrc_alloc = pstrdup(envrc);
794 :
3657 795 0 : expand_tilde(&envrc_alloc);
796 0 : process_psqlrc_file(envrc_alloc);
797 : }
4054 andrew 798 0 : else if (get_home_path(home))
799 : {
6667 tgl 800 0 : snprintf(rc_file, MAXPGPATH, "%s/%s", home, PSQLRC);
801 0 : process_psqlrc_file(rc_file);
802 : }
6926 bruce 803 0 : }
804 :
805 :
806 :
807 : static void
808 0 : process_psqlrc_file(char *filename)
809 : {
810 : char *psqlrc_minor,
811 : *psqlrc_major;
812 :
813 : #if defined(WIN32) && (!defined(__MINGW32__))
814 : #define R_OK 4
815 : #endif
816 :
3456 tgl 817 0 : psqlrc_minor = psprintf("%s-%s", filename, PG_VERSION);
818 0 : psqlrc_major = psprintf("%s-%s", filename, PG_MAJORVERSION);
819 :
820 : /* check for minor version first, then major, then no version */
4195 bruce 821 0 : if (access(psqlrc_minor, R_OK) == 0)
2679 rhaas 822 0 : (void) process_file(psqlrc_minor, false);
4195 bruce 823 0 : else if (access(psqlrc_major, R_OK) == 0)
2679 rhaas 824 0 : (void) process_file(psqlrc_major, false);
6926 bruce 825 0 : else if (access(filename, R_OK) == 0)
2679 rhaas 826 0 : (void) process_file(filename, false);
827 :
4195 bruce 828 0 : free(psqlrc_minor);
829 0 : free(psqlrc_major);
8557 830 0 : }
831 :
832 :
833 :
834 : /* showVersion
835 : *
836 : * This output format is intended to match GNU standards.
837 : */
838 : static void
8488 peter_e 839 CBC 3 : showVersion(void)
840 : {
8316 841 3 : puts("psql (PostgreSQL) " PG_VERSION);
8557 bruce 842 3 : }
843 :
844 :
845 :
846 : /*
847 : * Substitute hooks and assign hooks for psql variables.
848 : *
849 : * This isn't an amazingly good place for them, but neither is anywhere else.
850 : *
851 : * By policy, every special variable that controls any psql behavior should
852 : * have one or both hooks, even if they're just no-ops. This ensures that
853 : * the variable will remain present in variables.c's list even when unset,
854 : * which ensures that it's known to tab completion.
855 : */
856 :
857 : static char *
2258 tgl 858 88798 : bool_substitute_hook(char *newval)
859 : {
860 88798 : if (newval == NULL)
861 : {
862 : /* "\unset FOO" becomes "\set FOO off" */
863 64783 : newval = pg_strdup("off");
864 : }
865 24015 : else if (newval[0] == '\0')
866 : {
867 : /* "\set FOO" becomes "\set FOO on" */
868 3 : pg_free(newval);
869 3 : newval = pg_strdup("on");
870 : }
871 88798 : return newval;
872 : }
873 :
874 : static bool
6067 875 12977 : autocommit_hook(const char *newval)
876 : {
2260 877 12977 : return ParseVariableBool(newval, "AUTOCOMMIT", &pset.autocommit);
878 : }
879 :
880 : static bool
6067 881 10342 : on_error_stop_hook(const char *newval)
882 : {
2260 883 10342 : return ParseVariableBool(newval, "ON_ERROR_STOP", &pset.on_error_stop);
884 : }
885 :
886 : static bool
6067 887 11781 : quiet_hook(const char *newval)
888 : {
2260 889 11781 : return ParseVariableBool(newval, "QUIET", &pset.quiet);
890 : }
891 :
892 : static bool
6067 893 6478 : singleline_hook(const char *newval)
894 : {
2260 895 6478 : return ParseVariableBool(newval, "SINGLELINE", &pset.singleline);
896 : }
897 :
898 : static bool
6067 899 6478 : singlestep_hook(const char *newval)
900 : {
2260 901 6478 : return ParseVariableBool(newval, "SINGLESTEP", &pset.singlestep);
902 : }
903 :
904 : static char *
2257 905 6506 : fetch_count_substitute_hook(char *newval)
906 : {
907 6506 : if (newval == NULL)
908 6490 : newval = pg_strdup("0");
909 6506 : return newval;
910 : }
911 :
912 : static bool
6067 913 6506 : fetch_count_hook(const char *newval)
914 : {
2257 915 6506 : return ParseVariableNum(newval, "FETCH_COUNT", &pset.fetch_count);
916 : }
917 :
918 : static bool
919 6478 : histfile_hook(const char *newval)
920 : {
921 : /*
922 : * Someday we might try to validate the filename, but for now, this is
923 : * just a placeholder to ensure HISTFILE is known to tab completion.
924 : */
2260 925 6478 : return true;
926 : }
927 :
928 : static char *
2257 929 6478 : histsize_substitute_hook(char *newval)
930 : {
931 6478 : if (newval == NULL)
932 6478 : newval = pg_strdup("500");
933 6478 : return newval;
934 : }
935 :
936 : static bool
937 6478 : histsize_hook(const char *newval)
938 : {
939 6478 : return ParseVariableNum(newval, "HISTSIZE", &pset.histsize);
940 : }
941 :
942 : static char *
943 6478 : ignoreeof_substitute_hook(char *newval)
944 : {
945 : int dummy;
946 :
947 : /*
948 : * This tries to mimic the behavior of bash, to wit "If set, the value is
949 : * the number of consecutive EOF characters which must be typed as the
950 : * first characters on an input line before bash exits. If the variable
951 : * exists but does not have a numeric value, or has no value, the default
952 : * value is 10. If it does not exist, EOF signifies the end of input to
953 : * the shell." Unlike bash, however, we insist on the stored value
954 : * actually being a valid integer.
955 : */
956 6478 : if (newval == NULL)
957 6478 : newval = pg_strdup("0");
2257 tgl 958 UBC 0 : else if (!ParseVariableNum(newval, NULL, &dummy))
959 0 : newval = pg_strdup("10");
2257 tgl 960 CBC 6478 : return newval;
961 : }
962 :
963 : static bool
964 6478 : ignoreeof_hook(const char *newval)
965 : {
966 6478 : return ParseVariableNum(newval, "IGNOREEOF", &pset.ignoreeof);
967 : }
968 :
969 : static char *
2258 970 7413 : echo_substitute_hook(char *newval)
971 : {
972 7413 : if (newval == NULL)
973 6478 : newval = pg_strdup("none");
974 7413 : return newval;
975 : }
976 :
977 : static bool
6067 978 7413 : echo_hook(const char *newval)
979 : {
2258 980 7413 : Assert(newval != NULL); /* else substitute hook messed up */
981 7413 : if (pg_strcasecmp(newval, "queries") == 0)
6067 982 1 : pset.echo = PSQL_ECHO_QUERIES;
3021 983 7412 : else if (pg_strcasecmp(newval, "errors") == 0)
3195 fujii 984 3 : pset.echo = PSQL_ECHO_ERRORS;
3021 tgl 985 7409 : else if (pg_strcasecmp(newval, "all") == 0)
6067 986 925 : pset.echo = PSQL_ECHO_ALL;
3021 987 6484 : else if (pg_strcasecmp(newval, "none") == 0)
988 6484 : pset.echo = PSQL_ECHO_NONE;
989 : else
990 : {
2260 tgl 991 UBC 0 : PsqlVarEnumError("ECHO", newval, "none, errors, queries, all");
992 0 : return false;
993 : }
2260 tgl 994 CBC 7413 : return true;
995 : }
996 :
997 : static bool
6067 998 6478 : echo_hidden_hook(const char *newval)
999 : {
2258 1000 6478 : Assert(newval != NULL); /* else substitute hook messed up */
1001 6478 : if (pg_strcasecmp(newval, "noexec") == 0)
6067 tgl 1002 UBC 0 : pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC;
1003 : else
1004 : {
1005 : bool on_off;
1006 :
2260 tgl 1007 CBC 6478 : if (ParseVariableBool(newval, NULL, &on_off))
1008 6478 : pset.echo_hidden = on_off ? PSQL_ECHO_HIDDEN_ON : PSQL_ECHO_HIDDEN_OFF;
1009 : else
1010 : {
2260 tgl 1011 UBC 0 : PsqlVarEnumError("ECHO_HIDDEN", newval, "on, off, noexec");
1012 0 : return false;
1013 : }
1014 : }
2260 tgl 1015 CBC 6478 : return true;
1016 : }
1017 :
1018 : static bool
6067 1019 6502 : on_error_rollback_hook(const char *newval)
1020 : {
2258 1021 6502 : Assert(newval != NULL); /* else substitute hook messed up */
1022 6502 : if (pg_strcasecmp(newval, "interactive") == 0)
6067 tgl 1023 UBC 0 : pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE;
1024 : else
1025 : {
1026 : bool on_off;
1027 :
2260 tgl 1028 CBC 6502 : if (ParseVariableBool(newval, NULL, &on_off))
1029 6499 : pset.on_error_rollback = on_off ? PSQL_ERROR_ROLLBACK_ON : PSQL_ERROR_ROLLBACK_OFF;
1030 : else
1031 : {
1032 3 : PsqlVarEnumError("ON_ERROR_ROLLBACK", newval, "on, off, interactive");
1033 3 : return false;
1034 : }
1035 : }
1036 6499 : return true;
1037 : }
1038 :
1039 : static char *
2258 1040 6482 : comp_keyword_case_substitute_hook(char *newval)
1041 : {
1042 6482 : if (newval == NULL)
1043 6478 : newval = pg_strdup("preserve-upper");
1044 6482 : return newval;
1045 : }
1046 :
1047 : static bool
3021 1048 6482 : comp_keyword_case_hook(const char *newval)
1049 : {
2258 1050 6482 : Assert(newval != NULL); /* else substitute hook messed up */
1051 6482 : if (pg_strcasecmp(newval, "preserve-upper") == 0)
3021 1052 6479 : pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER;
1053 3 : else if (pg_strcasecmp(newval, "preserve-lower") == 0)
1054 1 : pset.comp_case = PSQL_COMP_CASE_PRESERVE_LOWER;
1055 2 : else if (pg_strcasecmp(newval, "upper") == 0)
1056 1 : pset.comp_case = PSQL_COMP_CASE_UPPER;
1057 1 : else if (pg_strcasecmp(newval, "lower") == 0)
1058 1 : pset.comp_case = PSQL_COMP_CASE_LOWER;
1059 : else
1060 : {
2260 tgl 1061 UBC 0 : PsqlVarEnumError("COMP_KEYWORD_CASE", newval,
1062 : "lower, upper, preserve-lower, preserve-upper");
1063 0 : return false;
1064 : }
2260 tgl 1065 CBC 6482 : return true;
1066 : }
1067 :
1068 : static char *
2258 1069 6478 : histcontrol_substitute_hook(char *newval)
1070 : {
1071 6478 : if (newval == NULL)
1072 6478 : newval = pg_strdup("none");
1073 6478 : return newval;
1074 : }
1075 :
1076 : static bool
6067 1077 6478 : histcontrol_hook(const char *newval)
1078 : {
2258 1079 6478 : Assert(newval != NULL); /* else substitute hook messed up */
1080 6478 : if (pg_strcasecmp(newval, "ignorespace") == 0)
6067 tgl 1081 UBC 0 : pset.histcontrol = hctl_ignorespace;
3021 tgl 1082 CBC 6478 : else if (pg_strcasecmp(newval, "ignoredups") == 0)
6067 tgl 1083 UBC 0 : pset.histcontrol = hctl_ignoredups;
3021 tgl 1084 CBC 6478 : else if (pg_strcasecmp(newval, "ignoreboth") == 0)
6067 tgl 1085 UBC 0 : pset.histcontrol = hctl_ignoreboth;
3021 tgl 1086 CBC 6478 : else if (pg_strcasecmp(newval, "none") == 0)
1087 6478 : pset.histcontrol = hctl_none;
1088 : else
1089 : {
2260 tgl 1090 UBC 0 : PsqlVarEnumError("HISTCONTROL", newval,
1091 : "none, ignorespace, ignoredups, ignoreboth");
1092 0 : return false;
1093 : }
2260 tgl 1094 CBC 6478 : return true;
1095 : }
1096 :
1097 : static bool
6067 1098 12956 : prompt1_hook(const char *newval)
1099 : {
1100 12956 : pset.prompt1 = newval ? newval : "";
2260 1101 12956 : return true;
1102 : }
1103 :
1104 : static bool
6067 1105 12956 : prompt2_hook(const char *newval)
1106 : {
1107 12956 : pset.prompt2 = newval ? newval : "";
2260 1108 12956 : return true;
1109 : }
1110 :
1111 : static bool
6067 1112 12956 : prompt3_hook(const char *newval)
1113 : {
1114 12956 : pset.prompt3 = newval ? newval : "";
2260 1115 12956 : return true;
1116 : }
1117 :
1118 : static char *
2258 1119 6553 : verbosity_substitute_hook(char *newval)
1120 : {
1121 6553 : if (newval == NULL)
1122 6478 : newval = pg_strdup("default");
1123 6553 : return newval;
1124 : }
1125 :
1126 : static bool
6067 1127 6553 : verbosity_hook(const char *newval)
1128 : {
2258 1129 6553 : Assert(newval != NULL); /* else substitute hook messed up */
1130 6553 : if (pg_strcasecmp(newval, "default") == 0)
6067 1131 6509 : pset.verbosity = PQERRORS_DEFAULT;
3021 1132 44 : else if (pg_strcasecmp(newval, "verbose") == 0)
6067 tgl 1133 UBC 0 : pset.verbosity = PQERRORS_VERBOSE;
1466 tgl 1134 CBC 44 : else if (pg_strcasecmp(newval, "terse") == 0)
1135 27 : pset.verbosity = PQERRORS_TERSE;
1136 17 : else if (pg_strcasecmp(newval, "sqlstate") == 0)
1137 17 : pset.verbosity = PQERRORS_SQLSTATE;
1138 : else
1139 : {
1466 tgl 1140 UBC 0 : PsqlVarEnumError("VERBOSITY", newval, "default, verbose, terse, sqlstate");
2260 1141 0 : return false;
1142 : }
1143 :
6067 tgl 1144 CBC 6553 : if (pset.db)
1145 75 : PQsetErrorVerbosity(pset.db, pset.verbosity);
2260 1146 6553 : return true;
1147 : }
1148 :
1149 : static bool
370 peter 1150 12962 : show_all_results_hook(const char *newval)
1151 : {
1152 12962 : return ParseVariableBool(newval, "SHOW_ALL_RESULTS", &pset.show_all_results);
1153 : }
1154 :
1155 : static char *
2258 tgl 1156 6499 : show_context_substitute_hook(char *newval)
1157 : {
1158 6499 : if (newval == NULL)
1159 6479 : newval = pg_strdup("errors");
1160 6499 : return newval;
1161 : }
1162 :
1163 : static bool
2773 1164 6499 : show_context_hook(const char *newval)
1165 : {
2258 1166 6499 : Assert(newval != NULL); /* else substitute hook messed up */
1167 6499 : if (pg_strcasecmp(newval, "never") == 0)
2773 1168 8 : pset.show_context = PQSHOW_CONTEXT_NEVER;
1169 6491 : else if (pg_strcasecmp(newval, "errors") == 0)
1170 6486 : pset.show_context = PQSHOW_CONTEXT_ERRORS;
1171 5 : else if (pg_strcasecmp(newval, "always") == 0)
1172 5 : pset.show_context = PQSHOW_CONTEXT_ALWAYS;
1173 : else
1174 : {
2260 tgl 1175 UBC 0 : PsqlVarEnumError("SHOW_CONTEXT", newval, "never, errors, always");
1176 0 : return false;
1177 : }
1178 :
2773 tgl 1179 CBC 6499 : if (pset.db)
1180 21 : PQsetErrorContextVisibility(pset.db, pset.show_context);
2260 1181 6499 : return true;
1182 : }
1183 :
1184 : static bool
751 rhaas 1185 7400 : hide_compression_hook(const char *newval)
1186 : {
1187 7400 : return ParseVariableBool(newval, "HIDE_TOAST_COMPRESSION",
1188 : &pset.hide_compression);
1189 : }
1190 :
1191 : static bool
1495 andres 1192 7400 : hide_tableam_hook(const char *newval)
1193 : {
1194 7400 : return ParseVariableBool(newval, "HIDE_TABLEAM", &pset.hide_tableam);
1195 : }
1196 :
1197 : static void
6067 tgl 1198 6478 : EstablishVariableSpace(void)
1199 : {
1200 6478 : pset.vars = CreateVariableSpace();
1201 :
2258 1202 6478 : SetVariableHooks(pset.vars, "AUTOCOMMIT",
1203 : bool_substitute_hook,
1204 : autocommit_hook);
1205 6478 : SetVariableHooks(pset.vars, "ON_ERROR_STOP",
1206 : bool_substitute_hook,
1207 : on_error_stop_hook);
1208 6478 : SetVariableHooks(pset.vars, "QUIET",
1209 : bool_substitute_hook,
1210 : quiet_hook);
1211 6478 : SetVariableHooks(pset.vars, "SINGLELINE",
1212 : bool_substitute_hook,
1213 : singleline_hook);
1214 6478 : SetVariableHooks(pset.vars, "SINGLESTEP",
1215 : bool_substitute_hook,
1216 : singlestep_hook);
1217 6478 : SetVariableHooks(pset.vars, "FETCH_COUNT",
1218 : fetch_count_substitute_hook,
1219 : fetch_count_hook);
2257 1220 6478 : SetVariableHooks(pset.vars, "HISTFILE",
1221 : NULL,
1222 : histfile_hook);
1223 6478 : SetVariableHooks(pset.vars, "HISTSIZE",
1224 : histsize_substitute_hook,
1225 : histsize_hook);
1226 6478 : SetVariableHooks(pset.vars, "IGNOREEOF",
1227 : ignoreeof_substitute_hook,
1228 : ignoreeof_hook);
2258 1229 6478 : SetVariableHooks(pset.vars, "ECHO",
1230 : echo_substitute_hook,
1231 : echo_hook);
1232 6478 : SetVariableHooks(pset.vars, "ECHO_HIDDEN",
1233 : bool_substitute_hook,
1234 : echo_hidden_hook);
1235 6478 : SetVariableHooks(pset.vars, "ON_ERROR_ROLLBACK",
1236 : bool_substitute_hook,
1237 : on_error_rollback_hook);
1238 6478 : SetVariableHooks(pset.vars, "COMP_KEYWORD_CASE",
1239 : comp_keyword_case_substitute_hook,
1240 : comp_keyword_case_hook);
1241 6478 : SetVariableHooks(pset.vars, "HISTCONTROL",
1242 : histcontrol_substitute_hook,
1243 : histcontrol_hook);
1244 6478 : SetVariableHooks(pset.vars, "PROMPT1",
1245 : NULL,
1246 : prompt1_hook);
1247 6478 : SetVariableHooks(pset.vars, "PROMPT2",
1248 : NULL,
1249 : prompt2_hook);
1250 6478 : SetVariableHooks(pset.vars, "PROMPT3",
1251 : NULL,
1252 : prompt3_hook);
1253 6478 : SetVariableHooks(pset.vars, "VERBOSITY",
1254 : verbosity_substitute_hook,
1255 : verbosity_hook);
370 peter 1256 6478 : SetVariableHooks(pset.vars, "SHOW_ALL_RESULTS",
1257 : bool_substitute_hook,
1258 : show_all_results_hook);
2258 tgl 1259 6478 : SetVariableHooks(pset.vars, "SHOW_CONTEXT",
1260 : show_context_substitute_hook,
1261 : show_context_hook);
751 rhaas 1262 6478 : SetVariableHooks(pset.vars, "HIDE_TOAST_COMPRESSION",
1263 : bool_substitute_hook,
1264 : hide_compression_hook);
1495 andres 1265 6478 : SetVariableHooks(pset.vars, "HIDE_TABLEAM",
1266 : bool_substitute_hook,
1267 : hide_tableam_hook);
6067 tgl 1268 6478 : }
|