2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2025, 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
;
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
);
206 SetVariableBool(pset
.vars
, "SHOW_ALL_RESULTS");
208 parse_psql_options(argc
, argv
, &options
);
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
215 if (options
.actions
.head
== NULL
&& pset
.notty
)
216 simple_action_list_append(&options
.actions
, ACT_FILE
, NULL
);
218 /* Bail out if -1 was specified but will be ignored. */
219 if (options
.single_txn
&& options
.actions
.head
== NULL
)
220 pg_fatal("-1 can only be used in non-interactive mode");
222 if (!pset
.popt
.topt
.fieldSep
.separator
&&
223 !pset
.popt
.topt
.fieldSep
.separator_zero
)
225 pset
.popt
.topt
.fieldSep
.separator
= pg_strdup(DEFAULT_FIELD_SEP
);
226 pset
.popt
.topt
.fieldSep
.separator_zero
= false;
228 if (!pset
.popt
.topt
.recordSep
.separator
&&
229 !pset
.popt
.topt
.recordSep
.separator_zero
)
231 pset
.popt
.topt
.recordSep
.separator
= pg_strdup(DEFAULT_RECORD_SEP
);
232 pset
.popt
.topt
.recordSep
.separator_zero
= false;
235 if (pset
.getPassword
== TRI_YES
)
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.)
243 password
= simple_prompt("Password: ", false);
246 /* loop until we have a password if requested by backend */
249 #define PARAMS_ARRAY_SIZE 8
250 const char **keywords
= pg_malloc_array(const char *, PARAMS_ARRAY_SIZE
);
251 const char **values
= pg_malloc_array(const char *, PARAMS_ARRAY_SIZE
);
253 keywords
[0] = "host";
254 values
[0] = options
.host
;
255 keywords
[1] = "port";
256 values
[1] = options
.port
;
257 keywords
[2] = "user";
258 values
[2] = options
.username
;
259 keywords
[3] = "password";
260 values
[3] = password
;
261 keywords
[4] = "dbname"; /* see do_connect() */
262 values
[4] = (options
.list_dbs
&& options
.dbname
== NULL
) ?
263 "postgres" : options
.dbname
;
264 keywords
[5] = "fallback_application_name";
265 values
[5] = pset
.progname
;
266 keywords
[6] = "client_encoding";
267 values
[6] = (pset
.notty
|| getenv("PGCLIENTENCODING")) ? NULL
: "auto";
272 pset
.db
= PQconnectdbParams(keywords
, values
, true);
276 if (PQstatus(pset
.db
) == CONNECTION_BAD
&&
277 PQconnectionNeedsPassword(pset
.db
) &&
279 pset
.getPassword
!= TRI_NO
)
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.
286 const char *realusername
= PQuser(pset
.db
);
287 char *password_prompt
;
289 if (realusername
&& realusername
[0])
290 password_prompt
= psprintf(_("Password for user %s: "),
293 password_prompt
= pg_strdup(_("Password: "));
296 password
= simple_prompt(password_prompt
, false);
297 free(password_prompt
);
302 if (PQstatus(pset
.db
) == CONNECTION_BAD
)
304 pg_log_error("%s", PQerrorMessage(pset
.db
));
309 psql_setup_cancel_handler();
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).
319 pqsignal(SIGCHLD
, empty_signal_handler
);
320 pqsignal(SIGALRM
, empty_signal_handler
);
323 PQsetNoticeProcessor(pset
.db
, NoticeProcessor
, NULL
);
327 if (options
.list_dbs
)
331 if (!options
.no_psqlrc
)
332 process_psqlrc(argv
[0]);
334 success
= listAllDbs(NULL
, false);
336 exit(success
? EXIT_SUCCESS
: EXIT_FAILURE
);
339 if (options
.logfilename
)
341 pset
.logfile
= fopen(options
.logfilename
, "a");
343 pg_fatal("could not open log file \"%s\": %m",
344 options
.logfilename
);
347 if (!options
.no_psqlrc
)
348 process_psqlrc(argv
[0]);
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.
354 if (options
.actions
.head
!= NULL
)
357 SimpleActionListCell
*cell
;
359 successResult
= EXIT_SUCCESS
; /* silence compiler */
361 if (options
.single_txn
)
363 if ((res
= PSQLexec("BEGIN")) == NULL
)
365 if (pset
.on_error_stop
)
367 successResult
= EXIT_USER
;
375 for (cell
= options
.actions
.head
; cell
; cell
= cell
->next
)
377 if (cell
->action
== ACT_SINGLE_QUERY
)
379 pg_logging_config(PG_LOG_FLAG_TERSE
);
381 if (pset
.echo
== PSQL_ECHO_ALL
)
384 successResult
= SendQuery(cell
->val
)
385 ? EXIT_SUCCESS
: EXIT_FAILURE
;
387 else if (cell
->action
== ACT_SINGLE_SLASH
)
389 PsqlScanState scan_state
;
390 ConditionalStack cond_stack
;
392 pg_logging_config(PG_LOG_FLAG_TERSE
);
394 if (pset
.echo
== PSQL_ECHO_ALL
)
397 scan_state
= psql_scan_create(&psqlscan_callbacks
);
398 psql_scan_setup(scan_state
,
399 cell
->val
, strlen(cell
->val
),
400 pset
.encoding
, standard_strings());
401 cond_stack
= conditional_stack_create();
402 psql_scan_set_passthrough(scan_state
, cond_stack
);
404 successResult
= HandleSlashCmds(scan_state
,
407 NULL
) != PSQL_CMD_ERROR
408 ? EXIT_SUCCESS
: EXIT_FAILURE
;
410 psql_scan_destroy(scan_state
);
411 conditional_stack_destroy(cond_stack
);
413 else if (cell
->action
== ACT_FILE
)
415 successResult
= process_file(cell
->val
, false);
419 /* should never come here */
423 if (successResult
!= EXIT_SUCCESS
&& pset
.on_error_stop
)
427 if (options
.single_txn
)
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.
434 res
= PSQLexec((successResult
!= EXIT_SUCCESS
&& pset
.on_error_stop
) ?
435 "ROLLBACK" : "COMMIT");
438 if (pset
.on_error_stop
)
440 successResult
= EXIT_USER
;
453 * or otherwise enter interactive main loop
457 pg_logging_config(PG_LOG_FLAG_TERSE
);
458 connection_warnings(true);
460 printf(_("Type \"help\" for help.\n\n"));
461 initializeInput(options
.no_readline
? 0 : 1);
462 successResult
= MainLoop(stdin
);
467 fclose(pset
.logfile
);
471 PQfinish(pset
.dead_conn
);
474 return successResult
;
479 * Parse command line options
483 parse_psql_options(int argc
, char *argv
[], struct adhoc_opts
*options
)
485 static struct option long_options
[] =
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},
529 memset(options
, 0, sizeof *options
);
531 while ((c
= getopt_long(argc
, argv
, "aAbc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
532 long_options
, &optindex
)) != -1)
537 SetVariable(pset
.vars
, "ECHO", "all");
540 pset
.popt
.topt
.format
= PRINT_UNALIGNED
;
543 SetVariable(pset
.vars
, "ECHO", "errors");
546 if (optarg
[0] == '\\')
547 simple_action_list_append(&options
->actions
,
551 simple_action_list_append(&options
->actions
,
556 options
->dbname
= pg_strdup(optarg
);
559 SetVariable(pset
.vars
, "ECHO", "queries");
562 SetVariableBool(pset
.vars
, "ECHO_HIDDEN");
565 simple_action_list_append(&options
->actions
,
570 pset
.popt
.topt
.fieldSep
.separator
= pg_strdup(optarg
);
571 pset
.popt
.topt
.fieldSep
.separator_zero
= false;
574 options
->host
= pg_strdup(optarg
);
577 pset
.popt
.topt
.format
= PRINT_HTML
;
580 options
->list_dbs
= true;
583 options
->logfilename
= pg_strdup(optarg
);
586 options
->no_readline
= true;
589 if (!setQFout(optarg
))
593 options
->port
= pg_strdup(optarg
);
601 value
= pg_strdup(optarg
);
602 equal_loc
= strchr(value
, '=');
604 result
= do_pset(value
, NULL
, &pset
.popt
, true);
608 result
= do_pset(value
, equal_loc
+ 1, &pset
.popt
, true);
612 pg_fatal("could not set printing parameter \"%s\"", value
);
618 SetVariableBool(pset
.vars
, "QUIET");
621 pset
.popt
.topt
.recordSep
.separator
= pg_strdup(optarg
);
622 pset
.popt
.topt
.recordSep
.separator_zero
= false;
625 SetVariableBool(pset
.vars
, "SINGLESTEP");
628 SetVariableBool(pset
.vars
, "SINGLELINE");
631 pset
.popt
.topt
.tuples_only
= true;
634 pset
.popt
.topt
.tableAttr
= pg_strdup(optarg
);
637 options
->username
= pg_strdup(optarg
);
644 value
= pg_strdup(optarg
);
645 equal_loc
= strchr(value
, '=');
648 if (!DeleteVariable(pset
.vars
, value
))
649 exit(EXIT_FAILURE
); /* error already printed */
654 if (!SetVariable(pset
.vars
, value
, equal_loc
+ 1))
655 exit(EXIT_FAILURE
); /* error already printed */
665 pset
.getPassword
= TRI_NO
;
668 pset
.getPassword
= TRI_YES
;
671 pset
.popt
.topt
.expanded
= true;
674 options
->no_psqlrc
= true;
677 pset
.popt
.topt
.fieldSep
.separator_zero
= true;
680 pset
.popt
.topt
.recordSep
.separator_zero
= true;
683 options
->single_txn
= true;
686 if (optind
<= argc
&&
687 strcmp(argv
[optind
- 1], "-?") == 0)
689 /* actual help option given */
695 /* getopt error (unknown option or missing argument) */
701 if (!optarg
|| strcmp(optarg
, "options") == 0)
703 else if (optarg
&& strcmp(optarg
, "commands") == 0)
705 else if (optarg
&& strcmp(optarg
, "variables") == 0)
706 helpVariables(NOPAGER
);
714 pset
.popt
.topt
.format
= PRINT_CSV
;
718 /* getopt_long already emitted a complaint */
719 pg_log_error_hint("Try \"%s --help\" for more information.",
726 * if we still have arguments, use it as the database name and username
728 while (argc
- optind
>= 1)
730 if (!options
->dbname
)
731 options
->dbname
= argv
[optind
];
732 else if (!options
->username
)
733 options
->username
= argv
[optind
];
734 else if (!pset
.quiet
)
735 pg_log_warning("extra command-line argument \"%s\" ignored",
744 * Append a new item to the end of the SimpleActionList.
745 * Note that "val" is copied if it's not NULL.
748 simple_action_list_append(SimpleActionList
*list
,
749 enum _actions action
, const char *val
)
751 SimpleActionListCell
*cell
;
753 cell
= pg_malloc_object(SimpleActionListCell
);
756 cell
->action
= action
;
758 cell
->val
= pg_strdup(val
);
763 list
->tail
->next
= cell
;
771 * Load .psqlrc file, if found.
774 process_psqlrc(char *argv0
)
776 char home
[MAXPGPATH
];
777 char rc_file
[MAXPGPATH
];
778 char my_exec_path
[MAXPGPATH
];
779 char etc_path
[MAXPGPATH
];
780 char *envrc
= getenv("PSQLRC");
782 if (find_my_exec(argv0
, my_exec_path
) < 0)
783 pg_fatal("could not find own program executable");
785 get_etc_path(my_exec_path
, etc_path
);
787 snprintf(rc_file
, MAXPGPATH
, "%s/%s", etc_path
, SYSPSQLRC
);
788 process_psqlrc_file(rc_file
);
790 if (envrc
!= NULL
&& strlen(envrc
) > 0)
792 /* might need to free() this */
793 char *envrc_alloc
= pstrdup(envrc
);
795 expand_tilde(&envrc_alloc
);
796 process_psqlrc_file(envrc_alloc
);
798 else if (get_home_path(home
))
800 snprintf(rc_file
, MAXPGPATH
, "%s/%s", home
, PSQLRC
);
801 process_psqlrc_file(rc_file
);
808 process_psqlrc_file(char *filename
)
813 #if defined(WIN32) && (!defined(__MINGW32__))
817 psqlrc_minor
= psprintf("%s-%s", filename
, PG_VERSION
);
818 psqlrc_major
= psprintf("%s-%s", filename
, PG_MAJORVERSION
);
820 /* check for minor version first, then major, then no version */
821 if (access(psqlrc_minor
, R_OK
) == 0)
822 (void) process_file(psqlrc_minor
, false);
823 else if (access(psqlrc_major
, R_OK
) == 0)
824 (void) process_file(psqlrc_major
, false);
825 else if (access(filename
, R_OK
) == 0)
826 (void) process_file(filename
, false);
836 * This output format is intended to match GNU standards.
841 puts("psql (PostgreSQL) " PG_VERSION
);
847 * Substitute hooks and assign hooks for psql variables.
849 * This isn't an amazingly good place for them, but neither is anywhere else.
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.
858 bool_substitute_hook(char *newval
)
862 /* "\unset FOO" becomes "\set FOO off" */
863 newval
= pg_strdup("off");
865 else if (newval
[0] == '\0')
867 /* "\set FOO" becomes "\set FOO on" */
869 newval
= pg_strdup("on");
875 autocommit_hook(const char *newval
)
877 return ParseVariableBool(newval
, "AUTOCOMMIT", &pset
.autocommit
);
881 on_error_stop_hook(const char *newval
)
883 return ParseVariableBool(newval
, "ON_ERROR_STOP", &pset
.on_error_stop
);
887 quiet_hook(const char *newval
)
889 return ParseVariableBool(newval
, "QUIET", &pset
.quiet
);
893 singleline_hook(const char *newval
)
895 return ParseVariableBool(newval
, "SINGLELINE", &pset
.singleline
);
899 singlestep_hook(const char *newval
)
901 return ParseVariableBool(newval
, "SINGLESTEP", &pset
.singlestep
);
905 fetch_count_substitute_hook(char *newval
)
908 newval
= pg_strdup("0");
913 fetch_count_hook(const char *newval
)
915 return ParseVariableNum(newval
, "FETCH_COUNT", &pset
.fetch_count
);
919 histfile_hook(const char *newval
)
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.
929 histsize_substitute_hook(char *newval
)
932 newval
= pg_strdup("500");
937 histsize_hook(const char *newval
)
939 return ParseVariableNum(newval
, "HISTSIZE", &pset
.histsize
);
943 ignoreeof_substitute_hook(char *newval
)
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.
957 newval
= pg_strdup("0");
958 else if (!ParseVariableNum(newval
, NULL
, &dummy
))
959 newval
= pg_strdup("10");
964 ignoreeof_hook(const char *newval
)
966 return ParseVariableNum(newval
, "IGNOREEOF", &pset
.ignoreeof
);
970 echo_substitute_hook(char *newval
)
973 newval
= pg_strdup("none");
978 echo_hook(const char *newval
)
980 Assert(newval
!= NULL
); /* else substitute hook messed up */
981 if (pg_strcasecmp(newval
, "queries") == 0)
982 pset
.echo
= PSQL_ECHO_QUERIES
;
983 else if (pg_strcasecmp(newval
, "errors") == 0)
984 pset
.echo
= PSQL_ECHO_ERRORS
;
985 else if (pg_strcasecmp(newval
, "all") == 0)
986 pset
.echo
= PSQL_ECHO_ALL
;
987 else if (pg_strcasecmp(newval
, "none") == 0)
988 pset
.echo
= PSQL_ECHO_NONE
;
991 PsqlVarEnumError("ECHO", newval
, "none, errors, queries, all");
998 echo_hidden_hook(const char *newval
)
1000 Assert(newval
!= NULL
); /* else substitute hook messed up */
1001 if (pg_strcasecmp(newval
, "noexec") == 0)
1002 pset
.echo_hidden
= PSQL_ECHO_HIDDEN_NOEXEC
;
1007 if (ParseVariableBool(newval
, NULL
, &on_off
))
1008 pset
.echo_hidden
= on_off
? PSQL_ECHO_HIDDEN_ON
: PSQL_ECHO_HIDDEN_OFF
;
1011 PsqlVarEnumError("ECHO_HIDDEN", newval
, "on, off, noexec");
1019 on_error_rollback_hook(const char *newval
)
1021 Assert(newval
!= NULL
); /* else substitute hook messed up */
1022 if (pg_strcasecmp(newval
, "interactive") == 0)
1023 pset
.on_error_rollback
= PSQL_ERROR_ROLLBACK_INTERACTIVE
;
1028 if (ParseVariableBool(newval
, NULL
, &on_off
))
1029 pset
.on_error_rollback
= on_off
? PSQL_ERROR_ROLLBACK_ON
: PSQL_ERROR_ROLLBACK_OFF
;
1032 PsqlVarEnumError("ON_ERROR_ROLLBACK", newval
, "on, off, interactive");
1040 comp_keyword_case_substitute_hook(char *newval
)
1043 newval
= pg_strdup("preserve-upper");
1048 comp_keyword_case_hook(const char *newval
)
1050 Assert(newval
!= NULL
); /* else substitute hook messed up */
1051 if (pg_strcasecmp(newval
, "preserve-upper") == 0)
1052 pset
.comp_case
= PSQL_COMP_CASE_PRESERVE_UPPER
;
1053 else if (pg_strcasecmp(newval
, "preserve-lower") == 0)
1054 pset
.comp_case
= PSQL_COMP_CASE_PRESERVE_LOWER
;
1055 else if (pg_strcasecmp(newval
, "upper") == 0)
1056 pset
.comp_case
= PSQL_COMP_CASE_UPPER
;
1057 else if (pg_strcasecmp(newval
, "lower") == 0)
1058 pset
.comp_case
= PSQL_COMP_CASE_LOWER
;
1061 PsqlVarEnumError("COMP_KEYWORD_CASE", newval
,
1062 "lower, upper, preserve-lower, preserve-upper");
1069 histcontrol_substitute_hook(char *newval
)
1072 newval
= pg_strdup("none");
1077 histcontrol_hook(const char *newval
)
1079 Assert(newval
!= NULL
); /* else substitute hook messed up */
1080 if (pg_strcasecmp(newval
, "ignorespace") == 0)
1081 pset
.histcontrol
= hctl_ignorespace
;
1082 else if (pg_strcasecmp(newval
, "ignoredups") == 0)
1083 pset
.histcontrol
= hctl_ignoredups
;
1084 else if (pg_strcasecmp(newval
, "ignoreboth") == 0)
1085 pset
.histcontrol
= hctl_ignoreboth
;
1086 else if (pg_strcasecmp(newval
, "none") == 0)
1087 pset
.histcontrol
= hctl_none
;
1090 PsqlVarEnumError("HISTCONTROL", newval
,
1091 "none, ignorespace, ignoredups, ignoreboth");
1098 prompt1_hook(const char *newval
)
1100 pset
.prompt1
= newval
? newval
: "";
1105 prompt2_hook(const char *newval
)
1107 pset
.prompt2
= newval
? newval
: "";
1112 prompt3_hook(const char *newval
)
1114 pset
.prompt3
= newval
? newval
: "";
1119 verbosity_substitute_hook(char *newval
)
1122 newval
= pg_strdup("default");
1127 verbosity_hook(const char *newval
)
1129 Assert(newval
!= NULL
); /* else substitute hook messed up */
1130 if (pg_strcasecmp(newval
, "default") == 0)
1131 pset
.verbosity
= PQERRORS_DEFAULT
;
1132 else if (pg_strcasecmp(newval
, "verbose") == 0)
1133 pset
.verbosity
= PQERRORS_VERBOSE
;
1134 else if (pg_strcasecmp(newval
, "terse") == 0)
1135 pset
.verbosity
= PQERRORS_TERSE
;
1136 else if (pg_strcasecmp(newval
, "sqlstate") == 0)
1137 pset
.verbosity
= PQERRORS_SQLSTATE
;
1140 PsqlVarEnumError("VERBOSITY", newval
, "default, verbose, terse, sqlstate");
1145 PQsetErrorVerbosity(pset
.db
, pset
.verbosity
);
1150 show_all_results_hook(const char *newval
)
1152 return ParseVariableBool(newval
, "SHOW_ALL_RESULTS", &pset
.show_all_results
);
1156 show_context_substitute_hook(char *newval
)
1159 newval
= pg_strdup("errors");
1164 show_context_hook(const char *newval
)
1166 Assert(newval
!= NULL
); /* else substitute hook messed up */
1167 if (pg_strcasecmp(newval
, "never") == 0)
1168 pset
.show_context
= PQSHOW_CONTEXT_NEVER
;
1169 else if (pg_strcasecmp(newval
, "errors") == 0)
1170 pset
.show_context
= PQSHOW_CONTEXT_ERRORS
;
1171 else if (pg_strcasecmp(newval
, "always") == 0)
1172 pset
.show_context
= PQSHOW_CONTEXT_ALWAYS
;
1175 PsqlVarEnumError("SHOW_CONTEXT", newval
, "never, errors, always");
1180 PQsetErrorContextVisibility(pset
.db
, pset
.show_context
);
1185 hide_compression_hook(const char *newval
)
1187 return ParseVariableBool(newval
, "HIDE_TOAST_COMPRESSION",
1188 &pset
.hide_compression
);
1192 hide_tableam_hook(const char *newval
)
1194 return ParseVariableBool(newval
, "HIDE_TABLEAM", &pset
.hide_tableam
);
1198 EstablishVariableSpace(void)
1200 pset
.vars
= CreateVariableSpace();
1202 SetVariableHooks(pset
.vars
, "AUTOCOMMIT",
1203 bool_substitute_hook
,
1205 SetVariableHooks(pset
.vars
, "ON_ERROR_STOP",
1206 bool_substitute_hook
,
1207 on_error_stop_hook
);
1208 SetVariableHooks(pset
.vars
, "QUIET",
1209 bool_substitute_hook
,
1211 SetVariableHooks(pset
.vars
, "SINGLELINE",
1212 bool_substitute_hook
,
1214 SetVariableHooks(pset
.vars
, "SINGLESTEP",
1215 bool_substitute_hook
,
1217 SetVariableHooks(pset
.vars
, "FETCH_COUNT",
1218 fetch_count_substitute_hook
,
1220 SetVariableHooks(pset
.vars
, "HISTFILE",
1223 SetVariableHooks(pset
.vars
, "HISTSIZE",
1224 histsize_substitute_hook
,
1226 SetVariableHooks(pset
.vars
, "IGNOREEOF",
1227 ignoreeof_substitute_hook
,
1229 SetVariableHooks(pset
.vars
, "ECHO",
1230 echo_substitute_hook
,
1232 SetVariableHooks(pset
.vars
, "ECHO_HIDDEN",
1233 bool_substitute_hook
,
1235 SetVariableHooks(pset
.vars
, "ON_ERROR_ROLLBACK",
1236 bool_substitute_hook
,
1237 on_error_rollback_hook
);
1238 SetVariableHooks(pset
.vars
, "COMP_KEYWORD_CASE",
1239 comp_keyword_case_substitute_hook
,
1240 comp_keyword_case_hook
);
1241 SetVariableHooks(pset
.vars
, "HISTCONTROL",
1242 histcontrol_substitute_hook
,
1244 SetVariableHooks(pset
.vars
, "PROMPT1",
1247 SetVariableHooks(pset
.vars
, "PROMPT2",
1250 SetVariableHooks(pset
.vars
, "PROMPT3",
1253 SetVariableHooks(pset
.vars
, "VERBOSITY",
1254 verbosity_substitute_hook
,
1256 SetVariableHooks(pset
.vars
, "SHOW_ALL_RESULTS",
1257 bool_substitute_hook
,
1258 show_all_results_hook
);
1259 SetVariableHooks(pset
.vars
, "SHOW_CONTEXT",
1260 show_context_substitute_hook
,
1262 SetVariableHooks(pset
.vars
, "HIDE_TOAST_COMPRESSION",
1263 bool_substitute_hook
,
1264 hide_compression_hook
);
1265 SetVariableHooks(pset
.vars
, "HIDE_TABLEAM",
1266 bool_substitute_hook
,