2
* psql - the PostgreSQL interactive terminal
4
* Copyright (c) 2000-2011, PostgreSQL Global Development Group
6
* src/bin/psql/command.c
8
#include "postgres_fe.h"
11
#ifdef __BORLANDC__ /* needed for BCC */
20
#include <sys/types.h> /* for umask() */
21
#include <sys/stat.h> /* for stat() */
22
#include <fcntl.h> /* open() flags */
23
#include <unistd.h> /* for geteuid(), getpid(), stat() */
29
#include <sys/types.h> /* for umask() */
30
#include <sys/stat.h> /* for stat() */
33
#include <openssl/ssl.h>
36
#include "portability/instr_time.h"
39
#include "pqexpbuffer.h"
40
#include "dumputils.h"
47
#include "large_obj.h"
52
#include "variables.h"
55
/* functions for use in this file */
56
static backslashResult exec_command(const char *cmd,
57
PsqlScanState scan_state,
58
PQExpBuffer query_buf);
59
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
60
int lineno, bool *edited);
61
static bool do_connect(char *dbname, char *user, char *host, char *port);
62
static bool do_shell(const char *command);
63
static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid);
64
static bool get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf);
65
static int strip_lineno_from_funcdesc(char *func);
66
static void minimal_error_message(PGresult *res);
68
static void printSSLInfo(void);
71
static void checkWin32Codepage(void);
79
* Handles all the different commands that start with '\'.
80
* Ordinarily called by MainLoop().
82
* scan_state is a lexer working state that is set to continue scanning
83
* just after the '\'. The lexer is advanced past the command and all
84
* arguments on return.
86
* 'query_buf' contains the query-so-far, which may be modified by
87
* execution of the backslash command (for example, \r clears it).
88
* query_buf can be NULL if there is no query so far.
90
* Returns a status code indicating what action is desired, see command.h.
95
HandleSlashCmds(PsqlScanState scan_state,
96
PQExpBuffer query_buf)
98
backslashResult status = PSQL_CMD_SKIP_LINE;
102
psql_assert(scan_state);
104
/* Parse off the command name */
105
cmd = psql_scan_slash_command(scan_state);
107
/* And try to execute it */
108
status = exec_command(cmd, scan_state, query_buf);
110
if (status == PSQL_CMD_UNKNOWN)
112
if (pset.cur_cmd_interactive)
113
fprintf(stderr, _("Invalid command \\%s. Try \\? for help.\n"), cmd);
115
psql_error("invalid command \\%s\n", cmd);
116
status = PSQL_CMD_ERROR;
119
if (status != PSQL_CMD_ERROR)
121
/* eat any remaining arguments after a valid command */
122
/* note we suppress evaluation of backticks here */
123
while ((arg = psql_scan_slash_option(scan_state,
124
OT_VERBATIM, NULL, false)))
126
psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
132
/* silently throw away rest of line after an erroneous command */
133
while ((arg = psql_scan_slash_option(scan_state,
134
OT_WHOLE_LINE, NULL, false)))
138
/* if there is a trailing \\, swallow it */
139
psql_scan_slash_command_end(scan_state);
143
/* some commands write to queryFout, so make sure output is sent */
144
fflush(pset.queryFout);
150
* Read and interpret an argument to the \connect slash command.
153
read_connect_arg(PsqlScanState scan_state)
159
* Ideally we should treat the arguments as SQL identifiers. But for
160
* backwards compatibility with 7.2 and older pg_dump files, we have to
161
* take unquoted arguments verbatim (don't downcase them). For now,
162
* double-quoted arguments may be stripped of double quotes (as if SQL
163
* identifiers). By 7.4 or so, pg_dump files can be expected to
164
* double-quote all mixed-case \connect arguments, and then we can get rid
167
result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, "e, true);
175
if (*result == '\0' || strcmp(result, "-") == 0)
183
* Subroutine to actually try to execute a backslash command.
185
static backslashResult
186
exec_command(const char *cmd,
187
PsqlScanState scan_state,
188
PQExpBuffer query_buf)
190
bool success = true; /* indicate here if the command ran ok or
192
backslashResult status = PSQL_CMD_SKIP_LINE;
195
* \a -- toggle field alignment This makes little sense but we keep it
198
if (strcmp(cmd, "a") == 0)
200
if (pset.popt.topt.format != PRINT_ALIGNED)
201
success = do_pset("format", "aligned", &pset.popt, pset.quiet);
203
success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
206
/* \C -- override table title (formerly change HTML caption) */
207
else if (strcmp(cmd, "C") == 0)
209
char *opt = psql_scan_slash_option(scan_state,
210
OT_NORMAL, NULL, true);
212
success = do_pset("title", opt, &pset.popt, pset.quiet);
217
* \c or \connect -- connect to database using the specified parameters.
219
* \c dbname user host port
221
* If any of these parameters are omitted or specified as '-', the current
222
* value of the parameter will be used instead. If the parameter has no
223
* current value, the default value for that parameter will be used. Some
226
* \c - - hst Connect to current database on current port of host
227
* "hst" as current user. \c - usr - prt Connect to current database on
228
* "prt" port of current host as user "usr". \c dbs Connect to
229
* "dbs" database on current port of current host as current user.
231
else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
238
opt1 = read_connect_arg(scan_state);
239
opt2 = read_connect_arg(scan_state);
240
opt3 = read_connect_arg(scan_state);
241
opt4 = read_connect_arg(scan_state);
243
success = do_connect(opt1, opt2, opt3, opt4);
252
else if (strcmp(cmd, "cd") == 0)
254
char *opt = psql_scan_slash_option(scan_state,
255
OT_NORMAL, NULL, true);
265
pw = getpwuid(geteuid());
268
psql_error("could not get home directory: %s\n", strerror(errno));
275
* On Windows, 'cd' without arguments prints the current
276
* directory, so if someone wants to code this here instead...
282
if (chdir(dir) == -1)
284
psql_error("\\%s: could not change directory to \"%s\": %s\n",
285
cmd, dir, strerror(errno));
291
pset.dirname = pg_strdup(dir);
292
canonicalize_path(pset.dirname);
298
/* \conninfo -- display information about the current connection */
299
else if (strcmp(cmd, "conninfo") == 0)
301
char *db = PQdb(pset.db);
302
char *host = PQhost(pset.db);
305
printf(_("You are not connected.\n"));
309
host = DEFAULT_PGSOCKET_DIR;
310
/* If the host is an absolute path, the connection is via socket */
311
if (is_absolute_path(host))
312
printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
313
db, PQuser(pset.db), host, PQport(pset.db));
315
printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
316
db, PQuser(pset.db), host, PQport(pset.db));
321
else if (pg_strcasecmp(cmd, "copy") == 0)
323
/* Default fetch-it-all-and-print mode */
327
char *opt = psql_scan_slash_option(scan_state,
328
OT_WHOLE_LINE, NULL, false);
331
INSTR_TIME_SET_CURRENT(before);
333
success = do_copy(opt);
335
if (pset.timing && success)
337
INSTR_TIME_SET_CURRENT(after);
338
INSTR_TIME_SUBTRACT(after, before);
339
printf(_("Time: %.3f ms\n"), INSTR_TIME_GET_MILLISEC(after));
346
else if (strcmp(cmd, "copyright") == 0)
350
else if (cmd[0] == 'd')
356
/* We don't do SQLID reduction on the pattern yet */
357
pattern = psql_scan_slash_option(scan_state,
358
OT_NORMAL, NULL, true);
360
show_verbose = strchr(cmd, '+') ? true : false;
361
show_system = strchr(cmd, 'S') ? true : false;
369
success = describeTableDetails(pattern, show_verbose, show_system);
371
/* standard listing of interesting things */
372
success = listTables("tvsE", NULL, show_verbose, show_system);
375
success = describeAggregates(pattern, show_verbose, show_system);
378
success = describeTablespaces(pattern, show_verbose);
381
success = listConversions(pattern, show_system);
384
success = listCasts(pattern);
387
if (strncmp(cmd, "ddp", 3) == 0)
388
success = listDefaultACLs(pattern);
390
success = objectDescription(pattern, show_system);
393
success = listDomains(pattern, show_system);
395
case 'f': /* function subsystem */
405
success = describeFunctions(&cmd[2], pattern, show_verbose, show_system);
408
status = PSQL_CMD_UNKNOWN;
413
/* no longer distinct from \du */
414
success = describeRoles(pattern, show_verbose);
417
success = do_lo_list();
420
success = listLanguages(pattern, show_verbose, show_system);
423
success = listSchemas(pattern, show_verbose, show_system);
426
success = describeOperators(pattern, show_system);
429
success = listCollations(pattern, show_verbose, show_system);
432
success = permissionsList(pattern);
435
success = describeTypes(pattern, show_verbose, show_system);
442
success = listTables(&cmd[1], pattern, show_verbose, show_system);
445
if (cmd[2] == 'd' && cmd[3] == 's')
447
char *pattern2 = NULL;
450
pattern2 = psql_scan_slash_option(scan_state,
451
OT_NORMAL, NULL, true);
452
success = listDbRoleSettings(pattern, pattern2);
455
success = PSQL_CMD_UNKNOWN;
458
success = describeRoles(pattern, show_verbose);
460
case 'F': /* text search subsystem */
465
success = listTSConfigs(pattern, show_verbose);
468
success = listTSParsers(pattern, show_verbose);
471
success = listTSDictionaries(pattern, show_verbose);
474
success = listTSTemplates(pattern, show_verbose);
477
status = PSQL_CMD_UNKNOWN;
481
case 'e': /* SQL/MED subsystem */
485
success = listForeignServers(pattern, show_verbose);
488
success = listUserMappings(pattern, show_verbose);
491
success = listForeignDataWrappers(pattern, show_verbose);
494
success = listForeignTables(pattern, show_verbose);
497
status = PSQL_CMD_UNKNOWN;
501
case 'x': /* Extensions */
503
success = listExtensionContents(pattern);
505
success = listExtensions(pattern);
508
status = PSQL_CMD_UNKNOWN;
517
* \e or \edit -- edit the current query buffer, or edit a file and make
518
* it the query buffer
520
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
524
psql_error("no query buffer\n");
525
status = PSQL_CMD_ERROR;
533
fname = psql_scan_slash_option(scan_state,
534
OT_NORMAL, NULL, true);
537
/* try to get separate lineno arg */
538
ln = psql_scan_slash_option(scan_state,
539
OT_NORMAL, NULL, true);
542
/* only one arg; maybe it is lineno not fname */
544
strspn(fname, "0123456789") == strlen(fname))
546
/* all digits, so assume it is lineno */
557
psql_error("invalid line number: %s\n", ln);
558
status = PSQL_CMD_ERROR;
561
if (status != PSQL_CMD_ERROR)
563
expand_tilde(&fname);
565
canonicalize_path(fname);
566
if (do_edit(fname, query_buf, lineno, NULL))
567
status = PSQL_CMD_NEWEDIT;
569
status = PSQL_CMD_ERROR;
579
* \ef -- edit the named function, or present a blank CREATE FUNCTION
580
* template if no argument is given
582
else if (strcmp(cmd, "ef") == 0)
588
psql_error("no query buffer\n");
589
status = PSQL_CMD_ERROR;
594
Oid foid = InvalidOid;
596
func = psql_scan_slash_option(scan_state,
597
OT_WHOLE_LINE, NULL, true);
598
lineno = strip_lineno_from_funcdesc(func);
601
/* error already reported */
602
status = PSQL_CMD_ERROR;
606
/* set up an empty command to fill in */
607
printfPQExpBuffer(query_buf,
608
"CREATE FUNCTION ( )\n"
611
" -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n"
615
else if (!lookup_function_oid(pset.db, func, &foid))
617
/* error already reported */
618
status = PSQL_CMD_ERROR;
620
else if (!get_create_function_cmd(pset.db, foid, query_buf))
622
/* error already reported */
623
status = PSQL_CMD_ERROR;
628
* lineno "1" should correspond to the first line of the
629
* function body. We expect that pg_get_functiondef() will
630
* emit that on a line beginning with "AS ", and that there
631
* can be no such line before the real start of the function
632
* body. Increment lineno by the number of lines before that
633
* line, so that it becomes relative to the first line of the
634
* function definition.
636
const char *lines = query_buf->data;
638
while (*lines != '\0')
640
if (strncmp(lines, "AS ", 3) == 0)
643
/* find start of next line */
644
lines = strchr(lines, '\n');
655
if (status != PSQL_CMD_ERROR)
659
if (!do_edit(NULL, query_buf, lineno, &edited))
660
status = PSQL_CMD_ERROR;
662
puts(_("No changes"));
664
status = PSQL_CMD_NEWEDIT;
668
/* \echo and \qecho */
669
else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
673
bool no_newline = false;
677
if (strcmp(cmd, "qecho") == 0)
678
fout = pset.queryFout;
682
while ((value = psql_scan_slash_option(scan_state,
683
OT_NORMAL, "ed, false)))
685
if (!quoted && strcmp(value, "-n") == 0)
701
/* \encoding -- set/show client side encoding */
702
else if (strcmp(cmd, "encoding") == 0)
704
char *encoding = psql_scan_slash_option(scan_state,
705
OT_NORMAL, NULL, false);
710
puts(pg_encoding_to_char(pset.encoding));
715
if (PQsetClientEncoding(pset.db, encoding) == -1)
716
psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
719
/* save encoding info into psql internal data */
720
pset.encoding = PQclientEncoding(pset.db);
721
pset.popt.topt.encoding = pset.encoding;
722
SetVariable(pset.vars, "ENCODING",
723
pg_encoding_to_char(pset.encoding));
729
/* \f -- change field separator */
730
else if (strcmp(cmd, "f") == 0)
732
char *fname = psql_scan_slash_option(scan_state,
733
OT_NORMAL, NULL, false);
735
success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
739
/* \g means send query */
740
else if (strcmp(cmd, "g") == 0)
742
char *fname = psql_scan_slash_option(scan_state,
743
OT_FILEPIPE, NULL, false);
749
expand_tilde(&fname);
750
pset.gfname = pg_strdup(fname);
753
status = PSQL_CMD_SEND;
757
else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
759
char *opt = psql_scan_slash_option(scan_state,
760
OT_WHOLE_LINE, NULL, false);
763
/* strip any trailing spaces and semicolons */
768
(isspace((unsigned char) opt[len - 1])
769
|| opt[len - 1] == ';'))
773
helpSQL(opt, pset.popt.topt.pager);
778
else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
780
if (pset.popt.topt.format != PRINT_HTML)
781
success = do_pset("format", "html", &pset.popt, pset.quiet);
783
success = do_pset("format", "aligned", &pset.popt, pset.quiet);
787
/* \i is include file */
788
else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
790
char *fname = psql_scan_slash_option(scan_state,
791
OT_NORMAL, NULL, true);
795
psql_error("\\%s: missing required argument\n", cmd);
800
expand_tilde(&fname);
801
success = (process_file(fname, false) == EXIT_SUCCESS);
806
/* \l is list databases */
807
else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
808
success = listAllDbs(false);
809
else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
810
success = listAllDbs(true);
813
* large object things
815
else if (strncmp(cmd, "lo_", 3) == 0)
820
opt1 = psql_scan_slash_option(scan_state,
821
OT_NORMAL, NULL, true);
822
opt2 = psql_scan_slash_option(scan_state,
823
OT_NORMAL, NULL, true);
825
if (strcmp(cmd + 3, "export") == 0)
829
psql_error("\\%s: missing required argument\n", cmd);
835
success = do_lo_export(opt1, opt2);
839
else if (strcmp(cmd + 3, "import") == 0)
843
psql_error("\\%s: missing required argument\n", cmd);
849
success = do_lo_import(opt1, opt2);
853
else if (strcmp(cmd + 3, "list") == 0)
854
success = do_lo_list();
856
else if (strcmp(cmd + 3, "unlink") == 0)
860
psql_error("\\%s: missing required argument\n", cmd);
864
success = do_lo_unlink(opt1);
868
status = PSQL_CMD_UNKNOWN;
875
/* \o -- set query output */
876
else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
878
char *fname = psql_scan_slash_option(scan_state,
879
OT_FILEPIPE, NULL, true);
881
expand_tilde(&fname);
882
success = setQFout(fname);
886
/* \p prints the current query buffer */
887
else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
889
if (query_buf && query_buf->len > 0)
890
puts(query_buf->data);
891
else if (!pset.quiet)
892
puts(_("Query buffer is empty."));
896
/* \password -- set user password */
897
else if (strcmp(cmd, "password") == 0)
902
pw1 = simple_prompt("Enter new password: ", 100, false);
903
pw2 = simple_prompt("Enter it again: ", 100, false);
905
if (strcmp(pw1, pw2) != 0)
907
fprintf(stderr, _("Passwords didn't match.\n"));
912
char *opt0 = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true);
914
char *encrypted_password;
919
user = PQuser(pset.db);
921
encrypted_password = PQencryptPassword(pw1, user);
923
if (!encrypted_password)
925
fprintf(stderr, _("Password encryption failed.\n"));
933
initPQExpBuffer(&buf);
934
printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
936
appendStringLiteralConn(&buf, encrypted_password, pset.db);
937
res = PSQLexec(buf.data, false);
938
termPQExpBuffer(&buf);
943
PQfreemem(encrypted_password);
951
/* \prompt -- prompt and set variable */
952
else if (strcmp(cmd, "prompt") == 0)
959
arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
960
arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
964
psql_error("\\%s: missing required argument\n", cmd);
980
result = simple_prompt(prompt_text, 4096, true);
985
fputs(prompt_text, stdout);
988
result = gets_fromFile(stdin);
991
if (!SetVariable(pset.vars, opt, result))
993
psql_error("\\%s: error\n", cmd);
1004
/* \pset -- set printing parameters */
1005
else if (strcmp(cmd, "pset") == 0)
1007
char *opt0 = psql_scan_slash_option(scan_state,
1008
OT_NORMAL, NULL, false);
1009
char *opt1 = psql_scan_slash_option(scan_state,
1010
OT_NORMAL, NULL, false);
1014
psql_error("\\%s: missing required argument\n", cmd);
1018
success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
1025
else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
1026
status = PSQL_CMD_TERMINATE;
1028
/* reset(clear) the buffer */
1029
else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
1031
resetPQExpBuffer(query_buf);
1032
psql_scan_reset(scan_state);
1034
puts(_("Query buffer reset (cleared)."));
1037
/* \s save history in a file or show it on the screen */
1038
else if (strcmp(cmd, "s") == 0)
1040
char *fname = psql_scan_slash_option(scan_state,
1041
OT_NORMAL, NULL, true);
1043
expand_tilde(&fname);
1044
/* This scrolls off the screen when using /dev/tty */
1045
success = saveHistory(fname ? fname : DEVTTY, -1, false, false);
1046
if (success && !pset.quiet && fname)
1047
printf(gettext("Wrote history to file \"%s/%s\".\n"),
1048
pset.dirname ? pset.dirname : ".", fname);
1054
/* \set -- generalized set variable/option command */
1055
else if (strcmp(cmd, "set") == 0)
1057
char *opt0 = psql_scan_slash_option(scan_state,
1058
OT_NORMAL, NULL, false);
1062
/* list all variables */
1063
PrintVariables(pset.vars);
1069
* Set variable to the concatenation of the arguments.
1074
opt = psql_scan_slash_option(scan_state,
1075
OT_NORMAL, NULL, false);
1076
newval = pg_strdup(opt ? opt : "");
1079
while ((opt = psql_scan_slash_option(scan_state,
1080
OT_NORMAL, NULL, false)))
1082
newval = realloc(newval, strlen(newval) + strlen(opt) + 1);
1085
psql_error("out of memory\n");
1088
strcat(newval, opt);
1092
if (!SetVariable(pset.vars, opt0, newval))
1094
psql_error("\\%s: error\n", cmd);
1102
/* \sf -- show a function's source code */
1103
else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
1105
bool show_linenumbers = (strcmp(cmd, "sf+") == 0);
1106
PQExpBuffer func_buf;
1108
Oid foid = InvalidOid;
1110
func_buf = createPQExpBuffer();
1111
func = psql_scan_slash_option(scan_state,
1112
OT_WHOLE_LINE, NULL, true);
1115
psql_error("function name is required\n");
1116
status = PSQL_CMD_ERROR;
1118
else if (!lookup_function_oid(pset.db, func, &foid))
1120
/* error already reported */
1121
status = PSQL_CMD_ERROR;
1123
else if (!get_create_function_cmd(pset.db, foid, func_buf))
1125
/* error already reported */
1126
status = PSQL_CMD_ERROR;
1133
/* Select output stream: stdout, pager, or file */
1134
if (pset.queryFout == stdout)
1136
/* count lines in function to see if pager is needed */
1138
const char *lines = func_buf->data;
1140
while (*lines != '\0')
1143
/* find start of next line */
1144
lines = strchr(lines, '\n');
1150
output = PageOutput(lineno, pset.popt.topt.pager);
1155
/* use previously set output file, without pager */
1156
output = pset.queryFout;
1160
if (show_linenumbers)
1162
bool in_header = true;
1164
char *lines = func_buf->data;
1167
* lineno "1" should correspond to the first line of the
1168
* function body. We expect that pg_get_functiondef() will
1169
* emit that on a line beginning with "AS ", and that there
1170
* can be no such line before the real start of the function
1173
* Note that this loop scribbles on func_buf.
1175
while (*lines != '\0')
1179
if (in_header && strncmp(lines, "AS ", 3) == 0)
1181
/* increment lineno only for body's lines */
1185
/* find and mark end of current line */
1186
eol = strchr(lines, '\n');
1190
/* show current line as appropriate */
1192
fprintf(output, " %s\n", lines);
1194
fprintf(output, "%-7d %s\n", lineno, lines);
1196
/* advance to next line, if any */
1204
/* just send the function definition to output */
1205
fputs(func_buf->data, output);
1214
destroyPQExpBuffer(func_buf);
1217
/* \t -- turn off headers and row count */
1218
else if (strcmp(cmd, "t") == 0)
1220
char *opt = psql_scan_slash_option(scan_state,
1221
OT_NORMAL, NULL, true);
1223
success = do_pset("tuples_only", opt, &pset.popt, pset.quiet);
1227
/* \T -- define html <table ...> attributes */
1228
else if (strcmp(cmd, "T") == 0)
1230
char *value = psql_scan_slash_option(scan_state,
1231
OT_NORMAL, NULL, false);
1233
success = do_pset("tableattr", value, &pset.popt, pset.quiet);
1237
/* \timing -- toggle timing of queries */
1238
else if (strcmp(cmd, "timing") == 0)
1240
char *opt = psql_scan_slash_option(scan_state,
1241
OT_NORMAL, NULL, false);
1244
pset.timing = ParseVariableBool(opt);
1246
pset.timing = !pset.timing;
1250
puts(_("Timing is on."));
1252
puts(_("Timing is off."));
1258
else if (strcmp(cmd, "unset") == 0)
1260
char *opt = psql_scan_slash_option(scan_state,
1261
OT_NORMAL, NULL, false);
1265
psql_error("\\%s: missing required argument\n", cmd);
1268
else if (!SetVariable(pset.vars, opt, NULL))
1270
psql_error("\\%s: error\n", cmd);
1276
/* \w -- write query buffer to file */
1277
else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
1280
bool is_pipe = false;
1285
psql_error("no query buffer\n");
1286
status = PSQL_CMD_ERROR;
1290
fname = psql_scan_slash_option(scan_state,
1291
OT_FILEPIPE, NULL, true);
1292
expand_tilde(&fname);
1296
psql_error("\\%s: missing required argument\n", cmd);
1301
if (fname[0] == '|')
1304
fd = popen(&fname[1], "w");
1308
canonicalize_path(fname);
1309
fd = fopen(fname, "w");
1313
psql_error("%s: %s\n", fname, strerror(errno));
1323
if (query_buf && query_buf->len > 0)
1324
fprintf(fd, "%s\n", query_buf->data);
1327
result = pclose(fd);
1329
result = fclose(fd);
1333
psql_error("%s: %s\n", fname, strerror(errno));
1341
/* \x -- toggle expanded table representation */
1342
else if (strcmp(cmd, "x") == 0)
1344
char *opt = psql_scan_slash_option(scan_state,
1345
OT_NORMAL, NULL, true);
1347
success = do_pset("expanded", opt, &pset.popt, pset.quiet);
1351
/* \z -- list table rights (equivalent to \dp) */
1352
else if (strcmp(cmd, "z") == 0)
1354
char *pattern = psql_scan_slash_option(scan_state,
1355
OT_NORMAL, NULL, true);
1357
success = permissionsList(pattern);
1362
/* \! -- shell escape */
1363
else if (strcmp(cmd, "!") == 0)
1365
char *opt = psql_scan_slash_option(scan_state,
1366
OT_WHOLE_LINE, NULL, false);
1368
success = do_shell(opt);
1372
/* \? -- slash command help */
1373
else if (strcmp(cmd, "?") == 0)
1374
slashUsage(pset.popt.topt.pager);
1379
* These commands don't do anything. I just use them to test the parser.
1381
else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
1386
while ((value = psql_scan_slash_option(scan_state,
1387
OT_NORMAL, NULL, true)))
1389
fprintf(stderr, "+ opt(%d) = |%s|\n", i++, value);
1396
status = PSQL_CMD_UNKNOWN;
1399
status = PSQL_CMD_ERROR;
1405
* Ask the user for a password; 'username' is the username the
1406
* password is for, if one has been explicitly specified. Returns a
1410
prompt_for_password(const char *username)
1414
if (username == NULL)
1415
result = simple_prompt("Password: ", 100, false);
1420
prompt_text = malloc(strlen(username) + 100);
1421
snprintf(prompt_text, strlen(username) + 100,
1422
_("Password for user %s: "), username);
1423
result = simple_prompt(prompt_text, 100, false);
1431
param_is_newly_set(const char *old_val, const char *new_val)
1433
if (new_val == NULL)
1436
if (old_val == NULL || strcmp(old_val, new_val) != 0)
1443
* do_connect -- handler for \connect
1445
* Connects to a database with given parameters. If there exists an
1446
* established connection, NULL values will be replaced with the ones
1447
* in the current connection. Otherwise NULL will be passed for that
1448
* parameter to PQconnectdbParams(), so the libpq defaults will be used.
1450
* In interactive mode, if connection fails with the given parameters,
1451
* the old connection will be kept.
1454
do_connect(char *dbname, char *user, char *host, char *port)
1456
PGconn *o_conn = pset.db,
1458
char *password = NULL;
1461
dbname = PQdb(o_conn);
1463
user = PQuser(o_conn);
1465
host = PQhost(o_conn);
1467
port = PQport(o_conn);
1470
* If the user asked to be prompted for a password, ask for one now. If
1471
* not, use the password from the old connection, provided the username
1472
* has not changed. Otherwise, try to connect without a password first,
1473
* and then ask for a password if needed.
1475
* XXX: this behavior leads to spurious connection attempts recorded in
1476
* the postmaster's log. But libpq offers no API that would let us obtain
1477
* a password and then continue with the first connection attempt.
1479
if (pset.getPassword == TRI_YES)
1481
password = prompt_for_password(user);
1483
else if (o_conn && user && strcmp(PQuser(o_conn), user) == 0)
1485
password = strdup(PQpass(o_conn));
1490
#define PARAMS_ARRAY_SIZE 8
1491
const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
1492
const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
1494
keywords[0] = "host";
1496
keywords[1] = "port";
1498
keywords[2] = "user";
1500
keywords[3] = "password";
1501
values[3] = password;
1502
keywords[4] = "dbname";
1504
keywords[5] = "fallback_application_name";
1505
values[5] = pset.progname;
1506
keywords[6] = "client_encoding";
1507
values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
1511
n_conn = PQconnectdbParams(keywords, values, true);
1516
/* We can immediately discard the password -- no longer needed */
1520
if (PQstatus(n_conn) == CONNECTION_OK)
1524
* Connection attempt failed; either retry the connection attempt with
1525
* a new password, or give up.
1527
if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
1530
password = prompt_for_password(user);
1535
* Failed to connect to the database. In interactive mode, keep the
1536
* previous connection to the DB; in scripting mode, close our
1537
* previous connection as well.
1539
if (pset.cur_cmd_interactive)
1541
psql_error("%s", PQerrorMessage(n_conn));
1543
/* pset.db is left unmodified */
1545
fputs(_("Previous connection kept\n"), stderr);
1549
psql_error("\\connect: %s", PQerrorMessage(n_conn));
1562
* Replace the old connection with the new one, and update
1563
* connection-dependent variables.
1565
PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
1568
connection_warnings(false); /* Must be after SyncVariables */
1570
/* Tell the user about the new connection */
1573
if (param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
1574
param_is_newly_set(PQport(o_conn), PQport(pset.db)))
1576
char *host = PQhost(pset.db);
1579
host = DEFAULT_PGSOCKET_DIR;
1580
/* If the host is an absolute path, the connection is via socket */
1581
if (is_absolute_path(host))
1582
printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
1583
PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
1585
printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
1586
PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
1589
printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
1590
PQdb(pset.db), PQuser(pset.db));
1600
connection_warnings(bool in_startup)
1602
if (!pset.quiet && !pset.notty)
1604
int client_ver = parse_version(PG_VERSION);
1606
if (pset.sversion != client_ver)
1608
const char *server_version;
1609
char server_ver_str[16];
1611
/* Try to get full text form, might include "devel" etc */
1612
server_version = PQparameterStatus(pset.db, "server_version");
1613
if (!server_version)
1615
snprintf(server_ver_str, sizeof(server_ver_str),
1617
pset.sversion / 10000,
1618
(pset.sversion / 100) % 100,
1619
pset.sversion % 100);
1620
server_version = server_ver_str;
1623
printf(_("%s (%s, server %s)\n"),
1624
pset.progname, PG_VERSION, server_version);
1626
/* For version match, only print psql banner on startup. */
1627
else if (in_startup)
1628
printf("%s (%s)\n", pset.progname, PG_VERSION);
1630
if (pset.sversion / 100 != client_ver / 100)
1631
printf(_("WARNING: %s version %d.%d, server version %d.%d.\n"
1632
" Some psql features might not work.\n"),
1633
pset.progname, client_ver / 10000, (client_ver / 100) % 100,
1634
pset.sversion / 10000, (pset.sversion / 100) % 100);
1637
checkWin32Codepage();
1647
* Prints information about the current SSL connection, if SSL is in use
1656
ssl = PQgetssl(pset.db);
1658
return; /* no SSL */
1660
SSL_get_cipher_bits(ssl, &sslbits);
1661
printf(_("SSL connection (cipher: %s, bits: %i)\n"),
1662
SSL_get_cipher(ssl), sslbits);
1666
* If psql is compiled without SSL but is using a libpq with SSL, we
1667
* cannot figure out the specifics about the connection. But we know it's
1670
if (PQgetssl(pset.db))
1671
printf(_("SSL connection (unknown cipher)\n"));
1677
* checkWin32Codepage
1679
* Prints a warning when win32 console codepage differs from Windows codepage
1683
checkWin32Codepage(void)
1689
concp = GetConsoleCP();
1692
printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n"
1693
" 8-bit characters might not work correctly. See psql reference\n"
1694
" page \"Notes for Windows users\" for details.\n"),
1704
* Make psql's internal variables agree with connection state upon
1705
* establishing a new connection.
1710
/* get stuff from connection */
1711
pset.encoding = PQclientEncoding(pset.db);
1712
pset.popt.topt.encoding = pset.encoding;
1713
pset.sversion = PQserverVersion(pset.db);
1715
SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
1716
SetVariable(pset.vars, "USER", PQuser(pset.db));
1717
SetVariable(pset.vars, "HOST", PQhost(pset.db));
1718
SetVariable(pset.vars, "PORT", PQport(pset.db));
1719
SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
1721
/* send stuff to it, too */
1722
PQsetErrorVerbosity(pset.db, pset.verbosity);
1728
* Clear variables that should be not be set when there is no connection.
1731
UnsyncVariables(void)
1733
SetVariable(pset.vars, "DBNAME", NULL);
1734
SetVariable(pset.vars, "USER", NULL);
1735
SetVariable(pset.vars, "HOST", NULL);
1736
SetVariable(pset.vars, "PORT", NULL);
1737
SetVariable(pset.vars, "ENCODING", NULL);
1742
* do_edit -- handler for \e
1744
* If you do not specify a filename, the current query buffer will be copied
1745
* into a temporary one.
1748
editFile(const char *fname, int lineno)
1750
const char *editorName;
1751
const char *editor_lineno_switch = NULL;
1757
/* Find an editor to use */
1758
editorName = getenv("PSQL_EDITOR");
1760
editorName = getenv("EDITOR");
1762
editorName = getenv("VISUAL");
1764
editorName = DEFAULT_EDITOR;
1766
/* Get line number switch, if we need it. */
1769
editor_lineno_switch = GetVariable(pset.vars,
1770
"EDITOR_LINENUMBER_SWITCH");
1771
if (editor_lineno_switch == NULL)
1773
psql_error("EDITOR_LINENUMBER_SWITCH variable must be set to specify a line number\n");
1778
/* Allocate sufficient memory for command line. */
1780
sys = pg_malloc(strlen(editorName)
1781
+ strlen(editor_lineno_switch) + 10 /* for integer */
1782
+ 1 + strlen(fname) + 10 + 1);
1784
sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);
1787
* On Unix the EDITOR value should *not* be quoted, since it might include
1788
* switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
1789
* if necessary. But this policy is not very workable on Windows, due to
1790
* severe brain damage in their command shell plus the fact that standard
1791
* program paths include spaces.
1795
sprintf(sys, "exec %s %s%d '%s'",
1796
editorName, editor_lineno_switch, lineno, fname);
1798
sprintf(sys, "exec %s '%s'",
1802
sprintf(sys, SYSTEMQUOTE "\"%s\" %s%d \"%s\"" SYSTEMQUOTE,
1803
editorName, editor_lineno_switch, lineno, fname);
1805
sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE,
1808
result = system(sys);
1810
psql_error("could not start editor \"%s\"\n", editorName);
1811
else if (result == 127)
1812
psql_error("could not start /bin/sh\n");
1821
do_edit(const char *filename_arg, PQExpBuffer query_buf,
1822
int lineno, bool *edited)
1824
char fnametmp[MAXPGPATH];
1825
FILE *stream = NULL;
1834
fname = filename_arg;
1837
/* make a temp file to edit */
1839
const char *tmpdir = getenv("TMPDIR");
1844
char tmpdir[MAXPGPATH];
1847
ret = GetTempPath(MAXPGPATH, tmpdir);
1848
if (ret == 0 || ret > MAXPGPATH)
1850
psql_error("cannot locate temporary directory: %s",
1851
!ret ? strerror(errno) : "");
1856
* No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
1857
* current directory to the supplied path unless we use only
1858
* backslashes, so we do that.
1862
snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
1863
"/", (int) getpid());
1865
snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
1866
"" /* trailing separator already present */ , (int) getpid());
1869
fname = (const char *) fnametmp;
1871
fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
1873
stream = fdopen(fd, "w");
1875
if (fd == -1 || !stream)
1877
psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno));
1882
unsigned int ql = query_buf->len;
1884
if (ql == 0 || query_buf->data[ql - 1] != '\n')
1886
appendPQExpBufferChar(query_buf, '\n');
1890
if (fwrite(query_buf->data, 1, ql, stream) != ql)
1892
psql_error("%s: %s\n", fname, strerror(errno));
1897
else if (fclose(stream) != 0)
1899
psql_error("%s: %s\n", fname, strerror(errno));
1906
if (!error && stat(fname, &before) != 0)
1908
psql_error("%s: %s\n", fname, strerror(errno));
1914
error = !editFile(fname, lineno);
1916
if (!error && stat(fname, &after) != 0)
1918
psql_error("%s: %s\n", fname, strerror(errno));
1922
if (!error && before.st_mtime != after.st_mtime)
1924
stream = fopen(fname, PG_BINARY_R);
1927
psql_error("%s: %s\n", fname, strerror(errno));
1932
/* read file back into query_buf */
1935
resetPQExpBuffer(query_buf);
1936
while (fgets(line, sizeof(line), stream) != NULL)
1937
appendPQExpBufferStr(query_buf, line);
1941
psql_error("%s: %s\n", fname, strerror(errno));
1953
/* remove temp file */
1956
if (remove(fname) == -1)
1958
psql_error("%s: %s\n", fname, strerror(errno));
1971
* Read commands from filename and then them to the main processing loop
1972
* Handler for \i, but can be used for other things as well. Returns
1973
* MainLoop() error code.
1976
process_file(char *filename, bool single_txn)
1984
return EXIT_FAILURE;
1986
if (strcmp(filename, "-") != 0)
1988
canonicalize_path(filename);
1989
fd = fopen(filename, PG_BINARY_R);
1996
psql_error("%s: %s\n", filename, strerror(errno));
1997
return EXIT_FAILURE;
2000
oldfilename = pset.inputfile;
2001
pset.inputfile = filename;
2005
if ((res = PSQLexec("BEGIN", false)) == NULL)
2007
if (pset.on_error_stop)
2017
result = MainLoop(fd);
2021
if ((res = PSQLexec("COMMIT", false)) == NULL)
2023
if (pset.on_error_stop)
2037
pset.inputfile = oldfilename;
2048
_align2string(enum printFormat in)
2055
case PRINT_UNALIGNED:
2070
case PRINT_TROFF_MS:
2079
do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
2086
vallen = strlen(value);
2089
if (strcmp(param, "format") == 0)
2093
else if (pg_strncasecmp("unaligned", value, vallen) == 0)
2094
popt->topt.format = PRINT_UNALIGNED;
2095
else if (pg_strncasecmp("aligned", value, vallen) == 0)
2096
popt->topt.format = PRINT_ALIGNED;
2097
else if (pg_strncasecmp("wrapped", value, vallen) == 0)
2098
popt->topt.format = PRINT_WRAPPED;
2099
else if (pg_strncasecmp("html", value, vallen) == 0)
2100
popt->topt.format = PRINT_HTML;
2101
else if (pg_strncasecmp("latex", value, vallen) == 0)
2102
popt->topt.format = PRINT_LATEX;
2103
else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
2104
popt->topt.format = PRINT_TROFF_MS;
2107
psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
2112
printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
2115
/* set table line style */
2116
else if (strcmp(param, "linestyle") == 0)
2120
else if (pg_strncasecmp("ascii", value, vallen) == 0)
2121
popt->topt.line_style = &pg_asciiformat;
2122
else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
2123
popt->topt.line_style = &pg_asciiformat_old;
2124
else if (pg_strncasecmp("unicode", value, vallen) == 0)
2125
popt->topt.line_style = &pg_utf8format;
2128
psql_error("\\pset: allowed line styles are ascii, old-ascii, unicode\n");
2133
printf(_("Line style is %s.\n"),
2134
get_line_style(&popt->topt)->name);
2137
/* set border style/width */
2138
else if (strcmp(param, "border") == 0)
2141
popt->topt.border = atoi(value);
2144
printf(_("Border style is %d.\n"), popt->topt.border);
2147
/* set expanded/vertical mode */
2148
else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
2151
popt->topt.expanded = ParseVariableBool(value);
2153
popt->topt.expanded = !popt->topt.expanded;
2155
printf(popt->topt.expanded
2156
? _("Expanded display is on.\n")
2157
: _("Expanded display is off.\n"));
2160
/* locale-aware numeric output */
2161
else if (strcmp(param, "numericlocale") == 0)
2164
popt->topt.numericLocale = ParseVariableBool(value);
2166
popt->topt.numericLocale = !popt->topt.numericLocale;
2169
if (popt->topt.numericLocale)
2170
puts(_("Showing locale-adjusted numeric output."));
2172
puts(_("Locale-adjusted numeric output is off."));
2177
else if (strcmp(param, "null") == 0)
2181
free(popt->nullPrint);
2182
popt->nullPrint = pg_strdup(value);
2185
printf(_("Null display is \"%s\".\n"), popt->nullPrint ? popt->nullPrint : "");
2188
/* field separator for unaligned text */
2189
else if (strcmp(param, "fieldsep") == 0)
2193
free(popt->topt.fieldSep);
2194
popt->topt.fieldSep = pg_strdup(value);
2197
printf(_("Field separator is \"%s\".\n"), popt->topt.fieldSep);
2200
/* record separator for unaligned text */
2201
else if (strcmp(param, "recordsep") == 0)
2205
free(popt->topt.recordSep);
2206
popt->topt.recordSep = pg_strdup(value);
2210
if (strcmp(popt->topt.recordSep, "\n") == 0)
2211
printf(_("Record separator is <newline>."));
2213
printf(_("Record separator is \"%s\".\n"), popt->topt.recordSep);
2217
/* toggle between full and tuples-only format */
2218
else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
2221
popt->topt.tuples_only = ParseVariableBool(value);
2223
popt->topt.tuples_only = !popt->topt.tuples_only;
2226
if (popt->topt.tuples_only)
2227
puts(_("Showing only tuples."));
2229
puts(_("Tuples only is off."));
2233
/* set title override */
2234
else if (strcmp(param, "title") == 0)
2240
popt->title = pg_strdup(value);
2245
printf(_("Title is \"%s\".\n"), popt->title);
2247
printf(_("Title is unset.\n"));
2251
/* set HTML table tag options */
2252
else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
2254
free(popt->topt.tableAttr);
2256
popt->topt.tableAttr = NULL;
2258
popt->topt.tableAttr = pg_strdup(value);
2262
if (popt->topt.tableAttr)
2263
printf(_("Table attribute is \"%s\".\n"), popt->topt.tableAttr);
2265
printf(_("Table attributes unset.\n"));
2269
/* toggle use of pager */
2270
else if (strcmp(param, "pager") == 0)
2272
if (value && pg_strcasecmp(value, "always") == 0)
2273
popt->topt.pager = 2;
2275
if (ParseVariableBool(value))
2276
popt->topt.pager = 1;
2278
popt->topt.pager = 0;
2279
else if (popt->topt.pager == 1)
2280
popt->topt.pager = 0;
2282
popt->topt.pager = 1;
2285
if (popt->topt.pager == 1)
2286
puts(_("Pager is used for long output."));
2287
else if (popt->topt.pager == 2)
2288
puts(_("Pager is always used."));
2290
puts(_("Pager usage is off."));
2294
/* disable "(x rows)" footer */
2295
else if (strcmp(param, "footer") == 0)
2298
popt->default_footer = ParseVariableBool(value);
2300
popt->default_footer = !popt->default_footer;
2303
if (popt->default_footer)
2304
puts(_("Default footer is on."));
2306
puts(_("Default footer is off."));
2310
/* set border style/width */
2311
else if (strcmp(param, "columns") == 0)
2314
popt->topt.columns = atoi(value);
2317
printf(_("Target width for \"wrapped\" format is %d.\n"), popt->topt.columns);
2322
psql_error("\\pset: unknown option: %s\n", param);
2332
#define DEFAULT_SHELL "/bin/sh"
2335
* CMD.EXE is in different places in different Win32 releases so we
2336
* have to rely on the path to find it.
2338
#define DEFAULT_SHELL "cmd.exe"
2342
do_shell(const char *command)
2349
const char *shellName;
2351
shellName = getenv("SHELL");
2353
if (shellName == NULL)
2354
shellName = getenv("COMSPEC");
2356
if (shellName == NULL)
2357
shellName = DEFAULT_SHELL;
2359
sys = pg_malloc(strlen(shellName) + 16);
2362
/* See EDITOR handling comment for an explaination */
2363
"exec %s", shellName);
2365
/* See EDITOR handling comment for an explaination */
2366
sprintf(sys, SYSTEMQUOTE "\"%s\"" SYSTEMQUOTE, shellName);
2368
result = system(sys);
2372
result = system(command);
2374
if (result == 127 || result == -1)
2376
psql_error("\\!: failed\n");
2383
* This function takes a function description, e.g. "x" or "x(int)", and
2384
* issues a query on the given connection to retrieve the function's OID
2385
* using a cast to regproc or regprocedure (as appropriate). The result,
2386
* if there is one, is returned at *foid. Note that we'll fail if the
2387
* function doesn't exist OR if there are multiple matching candidates
2388
* OR if there's something syntactically wrong with the function description;
2389
* unfortunately it can be hard to tell the difference.
2392
lookup_function_oid(PGconn *conn, const char *desc, Oid *foid)
2398
query = createPQExpBuffer();
2399
printfPQExpBuffer(query, "SELECT ");
2400
appendStringLiteralConn(query, desc, conn);
2401
appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
2402
strchr(desc, '(') ? "regprocedure" : "regproc");
2404
res = PQexec(conn, query->data);
2405
if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
2406
*foid = atooid(PQgetvalue(res, 0, 0));
2409
minimal_error_message(res);
2414
destroyPQExpBuffer(query);
2420
* Fetches the "CREATE OR REPLACE FUNCTION ..." command that describes the
2421
* function with the given OID. If successful, the result is stored in buf.
2424
get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf)
2430
query = createPQExpBuffer();
2431
printfPQExpBuffer(query, "SELECT pg_catalog.pg_get_functiondef(%u)", oid);
2433
res = PQexec(conn, query->data);
2434
if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
2436
resetPQExpBuffer(buf);
2437
appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
2441
minimal_error_message(res);
2446
destroyPQExpBuffer(query);
2452
* If the given argument of \ef ends with a line number, delete the line
2453
* number from the argument string and return it as an integer. (We need
2454
* this kluge because we're too lazy to parse \ef's function name argument
2455
* carefully --- we just slop it up in OT_WHOLE_LINE mode.)
2457
* Returns -1 if no line number is present, 0 on error, or a positive value
2461
strip_lineno_from_funcdesc(char *func)
2466
if (!func || func[0] == '\0')
2469
c = func + strlen(func) - 1;
2472
* This business of parsing backwards is dangerous as can be in a
2473
* multibyte environment: there is no reason to believe that we are
2474
* looking at the first byte of a character, nor are we necessarily
2475
* working in a "safe" encoding. Fortunately the bitpatterns we are
2476
* looking for are unlikely to occur as non-first bytes, but beware of
2477
* trying to expand the set of cases that can be recognized. We must
2478
* guard the <ctype.h> macros by using isascii() first, too.
2481
/* skip trailing whitespace */
2482
while (c > func && isascii((unsigned char) *c) && isspace((unsigned char) *c))
2485
/* must have a digit as last non-space char */
2486
if (c == func || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c))
2489
/* find start of digit string */
2490
while (c > func && isascii((unsigned char) *c) && isdigit((unsigned char) *c))
2493
/* digits must be separated from func name by space or closing paren */
2494
/* notice also that we are not allowing an empty func name ... */
2495
if (c == func || !isascii((unsigned char) *c) ||
2496
!(isspace((unsigned char) *c) || *c == ')'))
2499
/* parse digit string */
2504
psql_error("invalid line number: %s\n", c);
2508
/* strip digit string from func */
2515
* Report just the primary error; this is to avoid cluttering the output
2516
* with, for instance, a redisplay of the internally generated query
2519
minimal_error_message(PGresult *res)
2524
msg = createPQExpBuffer();
2526
fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
2528
printfPQExpBuffer(msg, "%s: ", fld);
2530
printfPQExpBuffer(msg, "ERROR: ");
2531
fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
2533
appendPQExpBufferStr(msg, fld);
2535
appendPQExpBufferStr(msg, "(not available)");
2536
appendPQExpBufferStr(msg, "\n");
2538
psql_error("%s", msg->data);
2540
destroyPQExpBuffer(msg);