2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2009, PostgreSQL Global Development Group
8 #include "postgres_fe.h"
10 #include <sys/types.h>
19 #include "getopt_long.h"
39 #define SYSPSQLRC "psqlrc"
40 #define PSQLRC ".psqlrc"
42 #define SYSPSQLRC "psqlrc"
43 #define PSQLRC "psqlrc.conf"
47 * Structures to pass information between the option parsing routine
48 * and the main function
73 static void parse_psql_options(int argc
, char *argv
[],
74 struct adhoc_opts
* options
);
75 static void process_psqlrc(char *argv0
);
76 static void process_psqlrc_file(char *filename
);
77 static void showVersion(void);
78 static void EstablishVariableSpace(void);
86 main(int argc
, char *argv
[])
88 struct adhoc_opts options
;
90 char *password
= NULL
;
91 char *password_prompt
= NULL
;
94 set_pglocale_pgservice(argv
[0], PG_TEXTDOMAIN("psql"));
98 if (strcmp(argv
[1], "--help") == 0 || strcmp(argv
[1], "-?") == 0)
103 if (strcmp(argv
[1], "--version") == 0 || strcmp(argv
[1], "-V") == 0)
111 setvbuf(stderr
, NULL
, _IONBF
, 0);
114 setup_cancel_handler();
116 pset
.progname
= get_progname(argv
[0]);
120 pset
.encoding
= PQenv2encoding();
121 pset
.queryFout
= stdout
;
122 pset
.queryFoutPipe
= false;
123 pset
.cur_cmd_source
= stdin
;
124 pset
.cur_cmd_interactive
= false;
126 /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
127 pset
.popt
.topt
.format
= PRINT_ALIGNED
;
128 pset
.popt
.topt
.border
= 1;
129 pset
.popt
.topt
.pager
= 1;
130 pset
.popt
.topt
.start_table
= true;
131 pset
.popt
.topt
.stop_table
= true;
132 pset
.popt
.default_footer
= true;
133 /* We must get COLUMNS here before readline() sets it */
134 pset
.popt
.topt
.env_columns
= getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
136 pset
.notty
= (!isatty(fileno(stdin
)) || !isatty(fileno(stdout
)));
138 pset
.getPassword
= TRI_DEFAULT
;
140 EstablishVariableSpace();
142 SetVariable(pset
.vars
, "VERSION", PG_VERSION_STR
);
144 /* Default values for variables */
145 SetVariableBool(pset
.vars
, "AUTOCOMMIT");
146 SetVariable(pset
.vars
, "VERBOSITY", "default");
147 SetVariable(pset
.vars
, "PROMPT1", DEFAULT_PROMPT1
);
148 SetVariable(pset
.vars
, "PROMPT2", DEFAULT_PROMPT2
);
149 SetVariable(pset
.vars
, "PROMPT3", DEFAULT_PROMPT3
);
151 parse_psql_options(argc
, argv
, &options
);
153 if (!pset
.popt
.topt
.fieldSep
)
154 pset
.popt
.topt
.fieldSep
= pg_strdup(DEFAULT_FIELD_SEP
);
155 if (!pset
.popt
.topt
.recordSep
)
156 pset
.popt
.topt
.recordSep
= pg_strdup(DEFAULT_RECORD_SEP
);
158 if (options
.username
== NULL
)
159 password_prompt
= pg_strdup(_("Password: "));
162 password_prompt
= malloc(strlen(_("Password for user %s: ")) - 2 +
163 strlen(options
.username
) + 1);
164 sprintf(password_prompt
, _("Password for user %s: "),
168 if (pset
.getPassword
== TRI_YES
)
169 password
= simple_prompt(password_prompt
, 100, false);
171 /* loop until we have a password if requested by backend */
175 pset
.db
= PQsetdbLogin(options
.host
, options
.port
, NULL
, NULL
,
176 options
.action
== ACT_LIST_DB
&& options
.dbname
== NULL
?
177 "postgres" : options
.dbname
,
178 options
.username
, password
);
180 if (PQstatus(pset
.db
) == CONNECTION_BAD
&&
181 PQconnectionNeedsPassword(pset
.db
) &&
183 pset
.getPassword
!= TRI_NO
)
186 password
= simple_prompt(password_prompt
, 100, false);
192 free(password_prompt
);
194 if (PQstatus(pset
.db
) == CONNECTION_BAD
)
196 fprintf(stderr
, "%s: %s", pset
.progname
, PQerrorMessage(pset
.db
));
201 PQsetNoticeProcessor(pset
.db
, NoticeProcessor
, NULL
);
205 if (options
.action
== ACT_LIST_DB
)
207 int success
= listAllDbs(false);
210 exit(success
? EXIT_SUCCESS
: EXIT_FAILURE
);
213 if (options
.logfilename
)
215 pset
.logfile
= fopen(options
.logfilename
, "a");
217 fprintf(stderr
, _("%s: could not open log file \"%s\": %s\n"),
218 pset
.progname
, options
.logfilename
, strerror(errno
));
222 * Now find something to do
226 * process file given by -f
228 if (options
.action
== ACT_FILE
&& strcmp(options
.action_string
, "-") != 0)
230 if (!options
.no_psqlrc
)
231 process_psqlrc(argv
[0]);
233 successResult
= process_file(options
.action_string
, options
.single_txn
);
237 * process slash command if one was given to -c
239 else if (options
.action
== ACT_SINGLE_SLASH
)
241 PsqlScanState scan_state
;
243 if (pset
.echo
== PSQL_ECHO_ALL
)
244 puts(options
.action_string
);
246 scan_state
= psql_scan_create();
247 psql_scan_setup(scan_state
,
248 options
.action_string
,
249 strlen(options
.action_string
));
251 successResult
= HandleSlashCmds(scan_state
, NULL
) != PSQL_CMD_ERROR
252 ? EXIT_SUCCESS
: EXIT_FAILURE
;
254 psql_scan_destroy(scan_state
);
258 * If the query given to -c was a normal one, send it
260 else if (options
.action
== ACT_SINGLE_QUERY
)
262 if (pset
.echo
== PSQL_ECHO_ALL
)
263 puts(options
.action_string
);
265 successResult
= SendQuery(options
.action_string
)
266 ? EXIT_SUCCESS
: EXIT_FAILURE
;
270 * or otherwise enter interactive main loop
274 if (!options
.no_psqlrc
)
275 process_psqlrc(argv
[0]);
277 connection_warnings();
278 if (!pset
.quiet
&& !pset
.notty
)
279 printf(_("Type \"help\" for help.\n\n"));
281 initializeInput(options
.no_readline
? 0 : 1);
282 if (options
.action_string
) /* -f - was used */
283 pset
.inputfile
= "<stdin>";
285 successResult
= MainLoop(stdin
);
290 fclose(pset
.logfile
);
294 return successResult
;
299 * Parse command line options
303 parse_psql_options(int argc
, char *argv
[], struct adhoc_opts
* options
)
305 static struct option long_options
[] =
307 {"echo-all", no_argument
, NULL
, 'a'},
308 {"no-align", no_argument
, NULL
, 'A'},
309 {"command", required_argument
, NULL
, 'c'},
310 {"dbname", required_argument
, NULL
, 'd'},
311 {"echo-queries", no_argument
, NULL
, 'e'},
312 {"echo-hidden", no_argument
, NULL
, 'E'},
313 {"file", required_argument
, NULL
, 'f'},
314 {"field-separator", required_argument
, NULL
, 'F'},
315 {"host", required_argument
, NULL
, 'h'},
316 {"html", no_argument
, NULL
, 'H'},
317 {"list", no_argument
, NULL
, 'l'},
318 {"log-file", required_argument
, NULL
, 'L'},
319 {"no-readline", no_argument
, NULL
, 'n'},
320 {"single-transaction", no_argument
, NULL
, '1'},
321 {"output", required_argument
, NULL
, 'o'},
322 {"port", required_argument
, NULL
, 'p'},
323 {"pset", required_argument
, NULL
, 'P'},
324 {"quiet", no_argument
, NULL
, 'q'},
325 {"record-separator", required_argument
, NULL
, 'R'},
326 {"single-step", no_argument
, NULL
, 's'},
327 {"single-line", no_argument
, NULL
, 'S'},
328 {"tuples-only", no_argument
, NULL
, 't'},
329 {"table-attr", required_argument
, NULL
, 'T'},
330 {"username", required_argument
, NULL
, 'U'},
331 {"set", required_argument
, NULL
, 'v'},
332 {"variable", required_argument
, NULL
, 'v'},
333 {"version", no_argument
, NULL
, 'V'},
334 {"no-password", no_argument
, NULL
, 'w'},
335 {"password", no_argument
, NULL
, 'W'},
336 {"expanded", no_argument
, NULL
, 'x'},
337 {"no-psqlrc", no_argument
, NULL
, 'X'},
338 {"help", no_argument
, NULL
, '?'},
347 memset(options
, 0, sizeof *options
);
349 while ((c
= getopt_long(argc
, argv
, "aAc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxX?1",
350 long_options
, &optindex
)) != -1)
355 SetVariable(pset
.vars
, "ECHO", "all");
358 pset
.popt
.topt
.format
= PRINT_UNALIGNED
;
361 options
->action_string
= optarg
;
362 if (optarg
[0] == '\\')
364 options
->action
= ACT_SINGLE_SLASH
;
365 options
->action_string
++;
368 options
->action
= ACT_SINGLE_QUERY
;
371 options
->dbname
= optarg
;
374 SetVariable(pset
.vars
, "ECHO", "queries");
377 SetVariableBool(pset
.vars
, "ECHO_HIDDEN");
380 options
->action
= ACT_FILE
;
381 options
->action_string
= optarg
;
384 pset
.popt
.topt
.fieldSep
= pg_strdup(optarg
);
387 options
->host
= optarg
;
390 pset
.popt
.topt
.format
= PRINT_HTML
;
393 options
->action
= ACT_LIST_DB
;
396 options
->logfilename
= optarg
;
399 options
->no_readline
= true;
405 options
->port
= optarg
;
413 value
= pg_strdup(optarg
);
414 equal_loc
= strchr(value
, '=');
416 result
= do_pset(value
, NULL
, &pset
.popt
, true);
420 result
= do_pset(value
, equal_loc
+ 1, &pset
.popt
, true);
425 fprintf(stderr
, _("%s: could not set printing parameter \"%s\"\n"), pset
.progname
, value
);
433 SetVariableBool(pset
.vars
, "QUIET");
436 pset
.popt
.topt
.recordSep
= pg_strdup(optarg
);
439 SetVariableBool(pset
.vars
, "SINGLESTEP");
442 SetVariableBool(pset
.vars
, "SINGLELINE");
445 pset
.popt
.topt
.tuples_only
= true;
448 pset
.popt
.topt
.tableAttr
= pg_strdup(optarg
);
451 options
->username
= optarg
;
458 value
= pg_strdup(optarg
);
459 equal_loc
= strchr(value
, '=');
462 if (!DeleteVariable(pset
.vars
, value
))
464 fprintf(stderr
, _("%s: could not delete variable \"%s\"\n"),
465 pset
.progname
, value
);
472 if (!SetVariable(pset
.vars
, value
, equal_loc
+ 1))
474 fprintf(stderr
, _("%s: could not set variable \"%s\"\n"),
475 pset
.progname
, value
);
487 pset
.getPassword
= TRI_NO
;
490 pset
.getPassword
= TRI_YES
;
493 pset
.popt
.topt
.expanded
= true;
496 options
->no_psqlrc
= true;
499 options
->single_txn
= true;
502 /* Actual help option given */
503 if (strcmp(argv
[optind
- 1], "-?") == 0 || strcmp(argv
[optind
- 1], "--help") == 0)
508 /* unknown option reported by getopt */
511 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
517 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
525 * if we still have arguments, use it as the database name and username
527 while (argc
- optind
>= 1)
529 if (!options
->dbname
)
530 options
->dbname
= argv
[optind
];
531 else if (!options
->username
)
532 options
->username
= argv
[optind
];
533 else if (!pset
.quiet
)
534 fprintf(stderr
, _("%s: warning: extra command-line argument \"%s\" ignored\n"),
535 pset
.progname
, argv
[optind
]);
543 * Load .psqlrc file, if found.
546 process_psqlrc(char *argv0
)
548 char home
[MAXPGPATH
];
549 char rc_file
[MAXPGPATH
];
550 char my_exec_path
[MAXPGPATH
];
551 char etc_path
[MAXPGPATH
];
553 find_my_exec(argv0
, my_exec_path
);
554 get_etc_path(my_exec_path
, etc_path
);
556 snprintf(rc_file
, MAXPGPATH
, "%s/%s", etc_path
, SYSPSQLRC
);
557 process_psqlrc_file(rc_file
);
559 if (get_home_path(home
))
561 snprintf(rc_file
, MAXPGPATH
, "%s/%s", home
, PSQLRC
);
562 process_psqlrc_file(rc_file
);
569 process_psqlrc_file(char *filename
)
573 #if defined(WIN32) && (!defined(__MINGW32__))
577 psqlrc
= pg_malloc(strlen(filename
) + 1 + strlen(PG_VERSION
) + 1);
578 sprintf(psqlrc
, "%s-%s", filename
, PG_VERSION
);
580 if (access(psqlrc
, R_OK
) == 0)
581 (void) process_file(psqlrc
, false);
582 else if (access(filename
, R_OK
) == 0)
583 (void) process_file(filename
, false);
591 * This output format is intended to match GNU standards.
596 puts("psql (PostgreSQL) " PG_VERSION
);
598 #if defined(USE_READLINE)
599 puts(_("contains support for command-line editing"));
606 * Assign hooks for psql variables.
608 * This isn't an amazingly good place for them, but neither is anywhere else.
612 autocommit_hook(const char *newval
)
614 pset
.autocommit
= ParseVariableBool(newval
);
618 on_error_stop_hook(const char *newval
)
620 pset
.on_error_stop
= ParseVariableBool(newval
);
624 quiet_hook(const char *newval
)
626 pset
.quiet
= ParseVariableBool(newval
);
630 singleline_hook(const char *newval
)
632 pset
.singleline
= ParseVariableBool(newval
);
636 singlestep_hook(const char *newval
)
638 pset
.singlestep
= ParseVariableBool(newval
);
642 fetch_count_hook(const char *newval
)
644 pset
.fetch_count
= ParseVariableNum(newval
, -1, -1, false);
648 echo_hook(const char *newval
)
651 pset
.echo
= PSQL_ECHO_NONE
;
652 else if (strcmp(newval
, "queries") == 0)
653 pset
.echo
= PSQL_ECHO_QUERIES
;
654 else if (strcmp(newval
, "all") == 0)
655 pset
.echo
= PSQL_ECHO_ALL
;
657 pset
.echo
= PSQL_ECHO_NONE
;
661 echo_hidden_hook(const char *newval
)
664 pset
.echo_hidden
= PSQL_ECHO_HIDDEN_OFF
;
665 else if (strcmp(newval
, "noexec") == 0)
666 pset
.echo_hidden
= PSQL_ECHO_HIDDEN_NOEXEC
;
667 else if (pg_strcasecmp(newval
, "off") == 0)
668 pset
.echo_hidden
= PSQL_ECHO_HIDDEN_OFF
;
670 pset
.echo_hidden
= PSQL_ECHO_HIDDEN_ON
;
674 on_error_rollback_hook(const char *newval
)
677 pset
.on_error_rollback
= PSQL_ERROR_ROLLBACK_OFF
;
678 else if (pg_strcasecmp(newval
, "interactive") == 0)
679 pset
.on_error_rollback
= PSQL_ERROR_ROLLBACK_INTERACTIVE
;
680 else if (pg_strcasecmp(newval
, "off") == 0)
681 pset
.on_error_rollback
= PSQL_ERROR_ROLLBACK_OFF
;
683 pset
.on_error_rollback
= PSQL_ERROR_ROLLBACK_ON
;
687 histcontrol_hook(const char *newval
)
690 pset
.histcontrol
= hctl_none
;
691 else if (strcmp(newval
, "ignorespace") == 0)
692 pset
.histcontrol
= hctl_ignorespace
;
693 else if (strcmp(newval
, "ignoredups") == 0)
694 pset
.histcontrol
= hctl_ignoredups
;
695 else if (strcmp(newval
, "ignoreboth") == 0)
696 pset
.histcontrol
= hctl_ignoreboth
;
698 pset
.histcontrol
= hctl_none
;
702 prompt1_hook(const char *newval
)
704 pset
.prompt1
= newval
? newval
: "";
708 prompt2_hook(const char *newval
)
710 pset
.prompt2
= newval
? newval
: "";
714 prompt3_hook(const char *newval
)
716 pset
.prompt3
= newval
? newval
: "";
720 verbosity_hook(const char *newval
)
723 pset
.verbosity
= PQERRORS_DEFAULT
;
724 else if (strcmp(newval
, "default") == 0)
725 pset
.verbosity
= PQERRORS_DEFAULT
;
726 else if (strcmp(newval
, "terse") == 0)
727 pset
.verbosity
= PQERRORS_TERSE
;
728 else if (strcmp(newval
, "verbose") == 0)
729 pset
.verbosity
= PQERRORS_VERBOSE
;
731 pset
.verbosity
= PQERRORS_DEFAULT
;
734 PQsetErrorVerbosity(pset
.db
, pset
.verbosity
);
739 EstablishVariableSpace(void)
741 pset
.vars
= CreateVariableSpace();
743 SetVariableAssignHook(pset
.vars
, "AUTOCOMMIT", autocommit_hook
);
744 SetVariableAssignHook(pset
.vars
, "ON_ERROR_STOP", on_error_stop_hook
);
745 SetVariableAssignHook(pset
.vars
, "QUIET", quiet_hook
);
746 SetVariableAssignHook(pset
.vars
, "SINGLELINE", singleline_hook
);
747 SetVariableAssignHook(pset
.vars
, "SINGLESTEP", singlestep_hook
);
748 SetVariableAssignHook(pset
.vars
, "FETCH_COUNT", fetch_count_hook
);
749 SetVariableAssignHook(pset
.vars
, "ECHO", echo_hook
);
750 SetVariableAssignHook(pset
.vars
, "ECHO_HIDDEN", echo_hidden_hook
);
751 SetVariableAssignHook(pset
.vars
, "ON_ERROR_ROLLBACK", on_error_rollback_hook
);
752 SetVariableAssignHook(pset
.vars
, "HISTCONTROL", histcontrol_hook
);
753 SetVariableAssignHook(pset
.vars
, "PROMPT1", prompt1_hook
);
754 SetVariableAssignHook(pset
.vars
, "PROMPT2", prompt2_hook
);
755 SetVariableAssignHook(pset
.vars
, "PROMPT3", prompt3_hook
);
756 SetVariableAssignHook(pset
.vars
, "VERBOSITY", verbosity_hook
);