2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2022, PostgreSQL Global Development Group
6 * src/bin/psql/startup.c
8 #include "postgres_fe.h"
19 #include "common/logging.h"
20 #include "common/string.h"
22 #include "fe_utils/print.h"
23 #include "getopt_long.h"
35 #define SYSPSQLRC "psqlrc"
36 #define PSQLRC ".psqlrc"
38 #define SYSPSQLRC "psqlrc"
39 #define PSQLRC "psqlrc.conf"
43 * Structures to pass information between the option parsing routine
44 * and the main function
53 typedef struct SimpleActionListCell
55 struct SimpleActionListCell
*next
;
58 } SimpleActionListCell
;
60 typedef struct SimpleActionList
62 SimpleActionListCell
*head
;
63 SimpleActionListCell
*tail
;
77 SimpleActionList actions
;
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);
92 log_pre_callback(void)
94 if (pset
.queryFout
&& pset
.queryFout
!= stdout
)
95 fflush(pset
.queryFout
);
99 log_locus_callback(const char **filename
, uint64
*lineno
)
103 *filename
= pset
.inputfile
;
104 *lineno
= pset
.lineno
;
113 #ifdef HAVE_POSIX_DECL_SIGWAIT
115 empty_signal_handler(SIGNAL_ARGS
)
126 main(int argc
, char *argv
[])
128 struct adhoc_opts options
;
130 char *password
= NULL
;
133 pg_logging_init(argv
[0]);
134 pg_logging_set_pre_callback(log_pre_callback
);
135 pg_logging_set_locus_callback(log_locus_callback
);
136 set_pglocale_pgservice(argv
[0], PG_TEXTDOMAIN("psql"));
140 if ((strcmp(argv
[1], "-?") == 0) || (argc
== 2 && (strcmp(argv
[1], "--help") == 0)))
145 if (strcmp(argv
[1], "--version") == 0 || strcmp(argv
[1], "-V") == 0)
152 pset
.progname
= get_progname(argv
[0]);
155 pset
.dead_conn
= NULL
;
157 pset
.encoding
= PQenv2encoding();
158 pset
.queryFout
= stdout
;
159 pset
.queryFoutPipe
= false;
160 pset
.copyStream
= NULL
;
161 pset
.last_error_result
= NULL
;
162 pset
.cur_cmd_source
= stdin
;
163 pset
.cur_cmd_interactive
= false;
165 /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
166 pset
.popt
.topt
.format
= PRINT_ALIGNED
;
167 pset
.popt
.topt
.border
= 1;
168 pset
.popt
.topt
.pager
= 1;
169 pset
.popt
.topt
.pager_min_lines
= 0;
170 pset
.popt
.topt
.start_table
= true;
171 pset
.popt
.topt
.stop_table
= true;
172 pset
.popt
.topt
.default_footer
= true;
174 pset
.popt
.topt
.csvFieldSep
[0] = DEFAULT_CSV_FIELD_SEP
;
175 pset
.popt
.topt
.csvFieldSep
[1] = '\0';
177 pset
.popt
.topt
.unicode_border_linestyle
= UNICODE_LINESTYLE_SINGLE
;
178 pset
.popt
.topt
.unicode_column_linestyle
= UNICODE_LINESTYLE_SINGLE
;
179 pset
.popt
.topt
.unicode_header_linestyle
= UNICODE_LINESTYLE_SINGLE
;
181 refresh_utf8format(&(pset
.popt
.topt
));
183 /* We must get COLUMNS here before readline() sets it */
184 pset
.popt
.topt
.env_columns
= getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
186 pset
.notty
= (!isatty(fileno(stdin
)) || !isatty(fileno(stdout
)));
188 pset
.getPassword
= TRI_DEFAULT
;
190 EstablishVariableSpace();
192 /* Create variables showing psql version number */
193 SetVariable(pset
.vars
, "VERSION", PG_VERSION_STR
);
194 SetVariable(pset
.vars
, "VERSION_NAME", PG_VERSION
);
195 SetVariable(pset
.vars
, "VERSION_NUM", CppAsString2(PG_VERSION_NUM
));
197 /* Initialize variables for last error */
198 SetVariable(pset
.vars
, "LAST_ERROR_MESSAGE", "");
199 SetVariable(pset
.vars
, "LAST_ERROR_SQLSTATE", "00000");
201 /* Default values for variables (that don't match the result of \unset) */
202 SetVariableBool(pset
.vars
, "AUTOCOMMIT");
203 SetVariable(pset
.vars
, "PROMPT1", DEFAULT_PROMPT1
);
204 SetVariable(pset
.vars
, "PROMPT2", DEFAULT_PROMPT2
);
205 SetVariable(pset
.vars
, "PROMPT3", DEFAULT_PROMPT3
);
207 parse_psql_options(argc
, argv
, &options
);
210 * If no action was specified and we're in non-interactive mode, treat it
211 * as if the user had specified "-f -". This lets single-transaction mode
214 if (options
.actions
.head
== NULL
&& pset
.notty
)
215 simple_action_list_append(&options
.actions
, ACT_FILE
, NULL
);
217 /* Bail out if -1 was specified but will be ignored. */
218 if (options
.single_txn
&& options
.actions
.head
== NULL
)
220 pg_log_fatal("-1 can only be used in non-interactive mode");
224 if (!pset
.popt
.topt
.fieldSep
.separator
&&
225 !pset
.popt
.topt
.fieldSep
.separator_zero
)
227 pset
.popt
.topt
.fieldSep
.separator
= pg_strdup(DEFAULT_FIELD_SEP
);
228 pset
.popt
.topt
.fieldSep
.separator_zero
= false;
230 if (!pset
.popt
.topt
.recordSep
.separator
&&
231 !pset
.popt
.topt
.recordSep
.separator_zero
)
233 pset
.popt
.topt
.recordSep
.separator
= pg_strdup(DEFAULT_RECORD_SEP
);
234 pset
.popt
.topt
.recordSep
.separator_zero
= false;
237 if (pset
.getPassword
== TRI_YES
)
240 * We can't be sure yet of the username that will be used, so don't
241 * offer a potentially wrong one. Typical uses of this option are
242 * noninteractive anyway. (Note: since we've not yet set up our
243 * cancel handler, there's no need to use simple_prompt_extended.)
245 password
= simple_prompt("Password: ", false);
248 /* loop until we have a password if requested by backend */
251 #define PARAMS_ARRAY_SIZE 8
252 const char **keywords
= pg_malloc(PARAMS_ARRAY_SIZE
* sizeof(*keywords
));
253 const char **values
= pg_malloc(PARAMS_ARRAY_SIZE
* sizeof(*values
));
255 keywords
[0] = "host";
256 values
[0] = options
.host
;
257 keywords
[1] = "port";
258 values
[1] = options
.port
;
259 keywords
[2] = "user";
260 values
[2] = options
.username
;
261 keywords
[3] = "password";
262 values
[3] = password
;
263 keywords
[4] = "dbname"; /* see do_connect() */
264 values
[4] = (options
.list_dbs
&& options
.dbname
== NULL
) ?
265 "postgres" : options
.dbname
;
266 keywords
[5] = "fallback_application_name";
267 values
[5] = pset
.progname
;
268 keywords
[6] = "client_encoding";
269 values
[6] = (pset
.notty
|| getenv("PGCLIENTENCODING")) ? NULL
: "auto";
274 pset
.db
= PQconnectdbParams(keywords
, values
, true);
278 if (PQstatus(pset
.db
) == CONNECTION_BAD
&&
279 PQconnectionNeedsPassword(pset
.db
) &&
281 pset
.getPassword
!= TRI_NO
)
284 * Before closing the old PGconn, extract the user name that was
285 * actually connected with --- it might've come out of a URI or
286 * connstring "database name" rather than options.username.
288 const char *realusername
= PQuser(pset
.db
);
289 char *password_prompt
;
291 if (realusername
&& realusername
[0])
292 password_prompt
= psprintf(_("Password for user %s: "),
295 password_prompt
= pg_strdup(_("Password: "));
298 password
= simple_prompt(password_prompt
, false);
299 free(password_prompt
);
304 if (PQstatus(pset
.db
) == CONNECTION_BAD
)
306 pg_log_error("%s", PQerrorMessage(pset
.db
));
311 psql_setup_cancel_handler();
313 #ifdef HAVE_POSIX_DECL_SIGWAIT
316 * do_watch() needs signal handlers installed (otherwise sigwait() will
317 * filter them out on some platforms), but doesn't need them to do
318 * anything, and they shouldn't ever run (unless perhaps a stray SIGALRM
319 * arrives due to a race when do_watch() cancels an itimer).
321 pqsignal(SIGCHLD
, empty_signal_handler
);
322 pqsignal(SIGALRM
, empty_signal_handler
);
325 PQsetNoticeProcessor(pset
.db
, NoticeProcessor
, NULL
);
329 if (options
.list_dbs
)
333 if (!options
.no_psqlrc
)
334 process_psqlrc(argv
[0]);
336 success
= listAllDbs(NULL
, false);
338 exit(success
? EXIT_SUCCESS
: EXIT_FAILURE
);
341 if (options
.logfilename
)
343 pset
.logfile
= fopen(options
.logfilename
, "a");
346 pg_log_fatal("could not open log file \"%s\": %m",
347 options
.logfilename
);
352 if (!options
.no_psqlrc
)
353 process_psqlrc(argv
[0]);
356 * If any actions were given by user, process them in the order in which
357 * they were specified. Note single_txn is only effective in this mode.
359 if (options
.actions
.head
!= NULL
)
362 SimpleActionListCell
*cell
;
364 successResult
= EXIT_SUCCESS
; /* silence compiler */
366 if (options
.single_txn
)
368 if ((res
= PSQLexec("BEGIN")) == NULL
)
370 if (pset
.on_error_stop
)
372 successResult
= EXIT_USER
;
380 for (cell
= options
.actions
.head
; cell
; cell
= cell
->next
)
382 if (cell
->action
== ACT_SINGLE_QUERY
)
384 pg_logging_config(PG_LOG_FLAG_TERSE
);
386 if (pset
.echo
== PSQL_ECHO_ALL
)
389 successResult
= SendQuery(cell
->val
)
390 ? EXIT_SUCCESS
: EXIT_FAILURE
;
392 else if (cell
->action
== ACT_SINGLE_SLASH
)
394 PsqlScanState scan_state
;
395 ConditionalStack cond_stack
;
397 pg_logging_config(PG_LOG_FLAG_TERSE
);
399 if (pset
.echo
== PSQL_ECHO_ALL
)
402 scan_state
= psql_scan_create(&psqlscan_callbacks
);
403 psql_scan_setup(scan_state
,
404 cell
->val
, strlen(cell
->val
),
405 pset
.encoding
, standard_strings());
406 cond_stack
= conditional_stack_create();
407 psql_scan_set_passthrough(scan_state
, (void *) cond_stack
);
409 successResult
= HandleSlashCmds(scan_state
,
412 NULL
) != PSQL_CMD_ERROR
413 ? EXIT_SUCCESS
: EXIT_FAILURE
;
415 psql_scan_destroy(scan_state
);
416 conditional_stack_destroy(cond_stack
);
418 else if (cell
->action
== ACT_FILE
)
420 successResult
= process_file(cell
->val
, false);
424 /* should never come here */
428 if (successResult
!= EXIT_SUCCESS
&& pset
.on_error_stop
)
432 if (options
.single_txn
)
434 if ((res
= PSQLexec("COMMIT")) == NULL
)
436 if (pset
.on_error_stop
)
438 successResult
= EXIT_USER
;
451 * or otherwise enter interactive main loop
455 pg_logging_config(PG_LOG_FLAG_TERSE
);
456 connection_warnings(true);
458 printf(_("Type \"help\" for help.\n\n"));
459 initializeInput(options
.no_readline
? 0 : 1);
460 successResult
= MainLoop(stdin
);
465 fclose(pset
.logfile
);
469 PQfinish(pset
.dead_conn
);
472 return successResult
;
477 * Parse command line options
481 parse_psql_options(int argc
, char *argv
[], struct adhoc_opts
*options
)
483 static struct option long_options
[] =
485 {"echo-all", no_argument
, NULL
, 'a'},
486 {"no-align", no_argument
, NULL
, 'A'},
487 {"command", required_argument
, NULL
, 'c'},
488 {"dbname", required_argument
, NULL
, 'd'},
489 {"echo-queries", no_argument
, NULL
, 'e'},
490 {"echo-errors", no_argument
, NULL
, 'b'},
491 {"echo-hidden", no_argument
, NULL
, 'E'},
492 {"file", required_argument
, NULL
, 'f'},
493 {"field-separator", required_argument
, NULL
, 'F'},
494 {"field-separator-zero", no_argument
, NULL
, 'z'},
495 {"host", required_argument
, NULL
, 'h'},
496 {"html", no_argument
, NULL
, 'H'},
497 {"list", no_argument
, NULL
, 'l'},
498 {"log-file", required_argument
, NULL
, 'L'},
499 {"no-readline", no_argument
, NULL
, 'n'},
500 {"single-transaction", no_argument
, NULL
, '1'},
501 {"output", required_argument
, NULL
, 'o'},
502 {"port", required_argument
, NULL
, 'p'},
503 {"pset", required_argument
, NULL
, 'P'},
504 {"quiet", no_argument
, NULL
, 'q'},
505 {"record-separator", required_argument
, NULL
, 'R'},
506 {"record-separator-zero", no_argument
, NULL
, '0'},
507 {"single-step", no_argument
, NULL
, 's'},
508 {"single-line", no_argument
, NULL
, 'S'},
509 {"tuples-only", no_argument
, NULL
, 't'},
510 {"table-attr", required_argument
, NULL
, 'T'},
511 {"username", required_argument
, NULL
, 'U'},
512 {"set", required_argument
, NULL
, 'v'},
513 {"variable", required_argument
, NULL
, 'v'},
514 {"version", no_argument
, NULL
, 'V'},
515 {"no-password", no_argument
, NULL
, 'w'},
516 {"password", no_argument
, NULL
, 'W'},
517 {"expanded", no_argument
, NULL
, 'x'},
518 {"no-psqlrc", no_argument
, NULL
, 'X'},
519 {"help", optional_argument
, NULL
, 1},
520 {"csv", no_argument
, NULL
, 2},
527 memset(options
, 0, sizeof *options
);
529 while ((c
= getopt_long(argc
, argv
, "aAbc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
530 long_options
, &optindex
)) != -1)
535 SetVariable(pset
.vars
, "ECHO", "all");
538 pset
.popt
.topt
.format
= PRINT_UNALIGNED
;
541 SetVariable(pset
.vars
, "ECHO", "errors");
544 if (optarg
[0] == '\\')
545 simple_action_list_append(&options
->actions
,
549 simple_action_list_append(&options
->actions
,
554 options
->dbname
= pg_strdup(optarg
);
557 SetVariable(pset
.vars
, "ECHO", "queries");
560 SetVariableBool(pset
.vars
, "ECHO_HIDDEN");
563 simple_action_list_append(&options
->actions
,
568 pset
.popt
.topt
.fieldSep
.separator
= pg_strdup(optarg
);
569 pset
.popt
.topt
.fieldSep
.separator_zero
= false;
572 options
->host
= pg_strdup(optarg
);
575 pset
.popt
.topt
.format
= PRINT_HTML
;
578 options
->list_dbs
= true;
581 options
->logfilename
= pg_strdup(optarg
);
584 options
->no_readline
= true;
587 if (!setQFout(optarg
))
591 options
->port
= pg_strdup(optarg
);
599 value
= pg_strdup(optarg
);
600 equal_loc
= strchr(value
, '=');
602 result
= do_pset(value
, NULL
, &pset
.popt
, true);
606 result
= do_pset(value
, equal_loc
+ 1, &pset
.popt
, true);
611 pg_log_fatal("could not set printing parameter \"%s\"", value
);
619 SetVariableBool(pset
.vars
, "QUIET");
622 pset
.popt
.topt
.recordSep
.separator
= pg_strdup(optarg
);
623 pset
.popt
.topt
.recordSep
.separator_zero
= false;
626 SetVariableBool(pset
.vars
, "SINGLESTEP");
629 SetVariableBool(pset
.vars
, "SINGLELINE");
632 pset
.popt
.topt
.tuples_only
= true;
635 pset
.popt
.topt
.tableAttr
= pg_strdup(optarg
);
638 options
->username
= pg_strdup(optarg
);
645 value
= pg_strdup(optarg
);
646 equal_loc
= strchr(value
, '=');
649 if (!DeleteVariable(pset
.vars
, value
))
650 exit(EXIT_FAILURE
); /* error already printed */
655 if (!SetVariable(pset
.vars
, value
, equal_loc
+ 1))
656 exit(EXIT_FAILURE
); /* error already printed */
666 pset
.getPassword
= TRI_NO
;
669 pset
.getPassword
= TRI_YES
;
672 pset
.popt
.topt
.expanded
= true;
675 options
->no_psqlrc
= true;
678 pset
.popt
.topt
.fieldSep
.separator_zero
= true;
681 pset
.popt
.topt
.recordSep
.separator_zero
= true;
684 options
->single_txn
= true;
687 if (optind
<= argc
&&
688 strcmp(argv
[optind
- 1], "-?") == 0)
690 /* actual help option given */
696 /* getopt error (unknown option or missing argument) */
702 if (!optarg
|| strcmp(optarg
, "options") == 0)
704 else if (optarg
&& strcmp(optarg
, "commands") == 0)
706 else if (optarg
&& strcmp(optarg
, "variables") == 0)
707 helpVariables(NOPAGER
);
715 pset
.popt
.topt
.format
= PRINT_CSV
;
719 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
727 * if we still have arguments, use it as the database name and username
729 while (argc
- optind
>= 1)
731 if (!options
->dbname
)
732 options
->dbname
= argv
[optind
];
733 else if (!options
->username
)
734 options
->username
= argv
[optind
];
735 else if (!pset
.quiet
)
736 pg_log_warning("extra command-line argument \"%s\" ignored",
745 * Append a new item to the end of the SimpleActionList.
746 * Note that "val" is copied if it's not NULL.
749 simple_action_list_append(SimpleActionList
*list
,
750 enum _actions action
, const char *val
)
752 SimpleActionListCell
*cell
;
754 cell
= (SimpleActionListCell
*) pg_malloc(sizeof(SimpleActionListCell
));
757 cell
->action
= action
;
759 cell
->val
= pg_strdup(val
);
764 list
->tail
->next
= cell
;
772 * Load .psqlrc file, if found.
775 process_psqlrc(char *argv0
)
777 char home
[MAXPGPATH
];
778 char rc_file
[MAXPGPATH
];
779 char my_exec_path
[MAXPGPATH
];
780 char etc_path
[MAXPGPATH
];
781 char *envrc
= getenv("PSQLRC");
783 if (find_my_exec(argv0
, my_exec_path
) < 0)
785 pg_log_fatal("could not find own program executable");
789 get_etc_path(my_exec_path
, etc_path
);
791 snprintf(rc_file
, MAXPGPATH
, "%s/%s", etc_path
, SYSPSQLRC
);
792 process_psqlrc_file(rc_file
);
794 if (envrc
!= NULL
&& strlen(envrc
) > 0)
796 /* might need to free() this */
797 char *envrc_alloc
= pstrdup(envrc
);
799 expand_tilde(&envrc_alloc
);
800 process_psqlrc_file(envrc_alloc
);
802 else if (get_home_path(home
))
804 snprintf(rc_file
, MAXPGPATH
, "%s/%s", home
, PSQLRC
);
805 process_psqlrc_file(rc_file
);
812 process_psqlrc_file(char *filename
)
817 #if defined(WIN32) && (!defined(__MINGW32__))
821 psqlrc_minor
= psprintf("%s-%s", filename
, PG_VERSION
);
822 psqlrc_major
= psprintf("%s-%s", filename
, PG_MAJORVERSION
);
824 /* check for minor version first, then major, then no version */
825 if (access(psqlrc_minor
, R_OK
) == 0)
826 (void) process_file(psqlrc_minor
, false);
827 else if (access(psqlrc_major
, R_OK
) == 0)
828 (void) process_file(psqlrc_major
, false);
829 else if (access(filename
, R_OK
) == 0)
830 (void) process_file(filename
, false);
840 * This output format is intended to match GNU standards.
845 puts("psql (PostgreSQL) " PG_VERSION
);
851 * Substitute hooks and assign hooks for psql variables.
853 * This isn't an amazingly good place for them, but neither is anywhere else.
855 * By policy, every special variable that controls any psql behavior should
856 * have one or both hooks, even if they're just no-ops. This ensures that
857 * the variable will remain present in variables.c's list even when unset,
858 * which ensures that it's known to tab completion.
862 bool_substitute_hook(char *newval
)
866 /* "\unset FOO" becomes "\set FOO off" */
867 newval
= pg_strdup("off");
869 else if (newval
[0] == '\0')
871 /* "\set FOO" becomes "\set FOO on" */
873 newval
= pg_strdup("on");
879 autocommit_hook(const char *newval
)
881 return ParseVariableBool(newval
, "AUTOCOMMIT", &pset
.autocommit
);
885 on_error_stop_hook(const char *newval
)
887 return ParseVariableBool(newval
, "ON_ERROR_STOP", &pset
.on_error_stop
);
891 quiet_hook(const char *newval
)
893 return ParseVariableBool(newval
, "QUIET", &pset
.quiet
);
897 singleline_hook(const char *newval
)
899 return ParseVariableBool(newval
, "SINGLELINE", &pset
.singleline
);
903 singlestep_hook(const char *newval
)
905 return ParseVariableBool(newval
, "SINGLESTEP", &pset
.singlestep
);
909 fetch_count_substitute_hook(char *newval
)
912 newval
= pg_strdup("0");
917 fetch_count_hook(const char *newval
)
919 return ParseVariableNum(newval
, "FETCH_COUNT", &pset
.fetch_count
);
923 histfile_hook(const char *newval
)
926 * Someday we might try to validate the filename, but for now, this is
927 * just a placeholder to ensure HISTFILE is known to tab completion.
933 histsize_substitute_hook(char *newval
)
936 newval
= pg_strdup("500");
941 histsize_hook(const char *newval
)
943 return ParseVariableNum(newval
, "HISTSIZE", &pset
.histsize
);
947 ignoreeof_substitute_hook(char *newval
)
952 * This tries to mimic the behavior of bash, to wit "If set, the value is
953 * the number of consecutive EOF characters which must be typed as the
954 * first characters on an input line before bash exits. If the variable
955 * exists but does not have a numeric value, or has no value, the default
956 * value is 10. If it does not exist, EOF signifies the end of input to
957 * the shell." Unlike bash, however, we insist on the stored value
958 * actually being a valid integer.
961 newval
= pg_strdup("0");
962 else if (!ParseVariableNum(newval
, NULL
, &dummy
))
963 newval
= pg_strdup("10");
968 ignoreeof_hook(const char *newval
)
970 return ParseVariableNum(newval
, "IGNOREEOF", &pset
.ignoreeof
);
974 echo_substitute_hook(char *newval
)
977 newval
= pg_strdup("none");
982 echo_hook(const char *newval
)
984 Assert(newval
!= NULL
); /* else substitute hook messed up */
985 if (pg_strcasecmp(newval
, "queries") == 0)
986 pset
.echo
= PSQL_ECHO_QUERIES
;
987 else if (pg_strcasecmp(newval
, "errors") == 0)
988 pset
.echo
= PSQL_ECHO_ERRORS
;
989 else if (pg_strcasecmp(newval
, "all") == 0)
990 pset
.echo
= PSQL_ECHO_ALL
;
991 else if (pg_strcasecmp(newval
, "none") == 0)
992 pset
.echo
= PSQL_ECHO_NONE
;
995 PsqlVarEnumError("ECHO", newval
, "none, errors, queries, all");
1002 echo_hidden_hook(const char *newval
)
1004 Assert(newval
!= NULL
); /* else substitute hook messed up */
1005 if (pg_strcasecmp(newval
, "noexec") == 0)
1006 pset
.echo_hidden
= PSQL_ECHO_HIDDEN_NOEXEC
;
1011 if (ParseVariableBool(newval
, NULL
, &on_off
))
1012 pset
.echo_hidden
= on_off
? PSQL_ECHO_HIDDEN_ON
: PSQL_ECHO_HIDDEN_OFF
;
1015 PsqlVarEnumError("ECHO_HIDDEN", newval
, "on, off, noexec");
1023 on_error_rollback_hook(const char *newval
)
1025 Assert(newval
!= NULL
); /* else substitute hook messed up */
1026 if (pg_strcasecmp(newval
, "interactive") == 0)
1027 pset
.on_error_rollback
= PSQL_ERROR_ROLLBACK_INTERACTIVE
;
1032 if (ParseVariableBool(newval
, NULL
, &on_off
))
1033 pset
.on_error_rollback
= on_off
? PSQL_ERROR_ROLLBACK_ON
: PSQL_ERROR_ROLLBACK_OFF
;
1036 PsqlVarEnumError("ON_ERROR_ROLLBACK", newval
, "on, off, interactive");
1044 comp_keyword_case_substitute_hook(char *newval
)
1047 newval
= pg_strdup("preserve-upper");
1052 comp_keyword_case_hook(const char *newval
)
1054 Assert(newval
!= NULL
); /* else substitute hook messed up */
1055 if (pg_strcasecmp(newval
, "preserve-upper") == 0)
1056 pset
.comp_case
= PSQL_COMP_CASE_PRESERVE_UPPER
;
1057 else if (pg_strcasecmp(newval
, "preserve-lower") == 0)
1058 pset
.comp_case
= PSQL_COMP_CASE_PRESERVE_LOWER
;
1059 else if (pg_strcasecmp(newval
, "upper") == 0)
1060 pset
.comp_case
= PSQL_COMP_CASE_UPPER
;
1061 else if (pg_strcasecmp(newval
, "lower") == 0)
1062 pset
.comp_case
= PSQL_COMP_CASE_LOWER
;
1065 PsqlVarEnumError("COMP_KEYWORD_CASE", newval
,
1066 "lower, upper, preserve-lower, preserve-upper");
1073 histcontrol_substitute_hook(char *newval
)
1076 newval
= pg_strdup("none");
1081 histcontrol_hook(const char *newval
)
1083 Assert(newval
!= NULL
); /* else substitute hook messed up */
1084 if (pg_strcasecmp(newval
, "ignorespace") == 0)
1085 pset
.histcontrol
= hctl_ignorespace
;
1086 else if (pg_strcasecmp(newval
, "ignoredups") == 0)
1087 pset
.histcontrol
= hctl_ignoredups
;
1088 else if (pg_strcasecmp(newval
, "ignoreboth") == 0)
1089 pset
.histcontrol
= hctl_ignoreboth
;
1090 else if (pg_strcasecmp(newval
, "none") == 0)
1091 pset
.histcontrol
= hctl_none
;
1094 PsqlVarEnumError("HISTCONTROL", newval
,
1095 "none, ignorespace, ignoredups, ignoreboth");
1102 prompt1_hook(const char *newval
)
1104 pset
.prompt1
= newval
? newval
: "";
1109 prompt2_hook(const char *newval
)
1111 pset
.prompt2
= newval
? newval
: "";
1116 prompt3_hook(const char *newval
)
1118 pset
.prompt3
= newval
? newval
: "";
1123 verbosity_substitute_hook(char *newval
)
1126 newval
= pg_strdup("default");
1131 verbosity_hook(const char *newval
)
1133 Assert(newval
!= NULL
); /* else substitute hook messed up */
1134 if (pg_strcasecmp(newval
, "default") == 0)
1135 pset
.verbosity
= PQERRORS_DEFAULT
;
1136 else if (pg_strcasecmp(newval
, "verbose") == 0)
1137 pset
.verbosity
= PQERRORS_VERBOSE
;
1138 else if (pg_strcasecmp(newval
, "terse") == 0)
1139 pset
.verbosity
= PQERRORS_TERSE
;
1140 else if (pg_strcasecmp(newval
, "sqlstate") == 0)
1141 pset
.verbosity
= PQERRORS_SQLSTATE
;
1144 PsqlVarEnumError("VERBOSITY", newval
, "default, verbose, terse, sqlstate");
1149 PQsetErrorVerbosity(pset
.db
, pset
.verbosity
);
1154 show_context_substitute_hook(char *newval
)
1157 newval
= pg_strdup("errors");
1162 show_context_hook(const char *newval
)
1164 Assert(newval
!= NULL
); /* else substitute hook messed up */
1165 if (pg_strcasecmp(newval
, "never") == 0)
1166 pset
.show_context
= PQSHOW_CONTEXT_NEVER
;
1167 else if (pg_strcasecmp(newval
, "errors") == 0)
1168 pset
.show_context
= PQSHOW_CONTEXT_ERRORS
;
1169 else if (pg_strcasecmp(newval
, "always") == 0)
1170 pset
.show_context
= PQSHOW_CONTEXT_ALWAYS
;
1173 PsqlVarEnumError("SHOW_CONTEXT", newval
, "never, errors, always");
1178 PQsetErrorContextVisibility(pset
.db
, pset
.show_context
);
1183 hide_compression_hook(const char *newval
)
1185 return ParseVariableBool(newval
, "HIDE_TOAST_COMPRESSION",
1186 &pset
.hide_compression
);
1190 hide_tableam_hook(const char *newval
)
1192 return ParseVariableBool(newval
, "HIDE_TABLEAM", &pset
.hide_tableam
);
1196 EstablishVariableSpace(void)
1198 pset
.vars
= CreateVariableSpace();
1200 SetVariableHooks(pset
.vars
, "AUTOCOMMIT",
1201 bool_substitute_hook
,
1203 SetVariableHooks(pset
.vars
, "ON_ERROR_STOP",
1204 bool_substitute_hook
,
1205 on_error_stop_hook
);
1206 SetVariableHooks(pset
.vars
, "QUIET",
1207 bool_substitute_hook
,
1209 SetVariableHooks(pset
.vars
, "SINGLELINE",
1210 bool_substitute_hook
,
1212 SetVariableHooks(pset
.vars
, "SINGLESTEP",
1213 bool_substitute_hook
,
1215 SetVariableHooks(pset
.vars
, "FETCH_COUNT",
1216 fetch_count_substitute_hook
,
1218 SetVariableHooks(pset
.vars
, "HISTFILE",
1221 SetVariableHooks(pset
.vars
, "HISTSIZE",
1222 histsize_substitute_hook
,
1224 SetVariableHooks(pset
.vars
, "IGNOREEOF",
1225 ignoreeof_substitute_hook
,
1227 SetVariableHooks(pset
.vars
, "ECHO",
1228 echo_substitute_hook
,
1230 SetVariableHooks(pset
.vars
, "ECHO_HIDDEN",
1231 bool_substitute_hook
,
1233 SetVariableHooks(pset
.vars
, "ON_ERROR_ROLLBACK",
1234 bool_substitute_hook
,
1235 on_error_rollback_hook
);
1236 SetVariableHooks(pset
.vars
, "COMP_KEYWORD_CASE",
1237 comp_keyword_case_substitute_hook
,
1238 comp_keyword_case_hook
);
1239 SetVariableHooks(pset
.vars
, "HISTCONTROL",
1240 histcontrol_substitute_hook
,
1242 SetVariableHooks(pset
.vars
, "PROMPT1",
1245 SetVariableHooks(pset
.vars
, "PROMPT2",
1248 SetVariableHooks(pset
.vars
, "PROMPT3",
1251 SetVariableHooks(pset
.vars
, "VERBOSITY",
1252 verbosity_substitute_hook
,
1254 SetVariableHooks(pset
.vars
, "SHOW_CONTEXT",
1255 show_context_substitute_hook
,
1257 SetVariableHooks(pset
.vars
, "HIDE_TOAST_COMPRESSION",
1258 bool_substitute_hook
,
1259 hide_compression_hook
);
1260 SetVariableHooks(pset
.vars
, "HIDE_TABLEAM",
1261 bool_substitute_hook
,