summaryrefslogtreecommitdiff
path: root/src/bin/psql
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1999-11-04 23:14:30 +0000
committerBruce Momjian <bruce@momjian.us>1999-11-04 23:14:30 +0000
commit0e6652e67357354e01f2466184343d0bc0ee2cab (patch)
tree0c06450508417e033f8a2b90241a7126cd54c4fe /src/bin/psql
parent2323b63631080b7d4c287872a83b0ea30bd7874a (diff)
downloadpostgresql-0e6652e67357354e01f2466184343d0bc0ee2cab.tar.gz
psql cleanup
Diffstat (limited to 'src/bin/psql')
-rw-r--r--src/bin/psql/command.c1953
-rw-r--r--src/bin/psql/command.h63
-rw-r--r--src/bin/psql/common.c675
-rw-r--r--src/bin/psql/common.h16
-rw-r--r--src/bin/psql/copy.c526
-rw-r--r--src/bin/psql/copy.h6
-rw-r--r--src/bin/psql/describe.c1320
-rw-r--r--src/bin/psql/describe.h20
-rw-r--r--src/bin/psql/help.c422
-rw-r--r--src/bin/psql/help.h9
-rw-r--r--src/bin/psql/input.c156
-rw-r--r--src/bin/psql/input.h10
-rw-r--r--src/bin/psql/large_obj.c427
-rw-r--r--src/bin/psql/large_obj.h10
-rw-r--r--src/bin/psql/mainloop.c615
-rw-r--r--src/bin/psql/mainloop.h4
-rw-r--r--src/bin/psql/print.c1604
-rw-r--r--src/bin/psql/print.h70
-rw-r--r--src/bin/psql/prompt.c385
-rw-r--r--src/bin/psql/prompt.h21
-rw-r--r--src/bin/psql/psql.c3297
-rw-r--r--src/bin/psql/psqlHelp.h5
-rw-r--r--src/bin/psql/settings.h39
-rw-r--r--src/bin/psql/sql_help.h364
-rw-r--r--src/bin/psql/startup.c787
-rw-r--r--src/bin/psql/stringutils.c249
-rw-r--r--src/bin/psql/stringutils.h13
-rw-r--r--src/bin/psql/variables.c168
-rw-r--r--src/bin/psql/variables.h23
29 files changed, 5236 insertions, 8021 deletions
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 6bcf96c9cd..29df279262 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -7,9 +7,9 @@
#include <stdlib.h>
#include <ctype.h>
#ifndef WIN32
-#include <sys/types.h> /* for umask() */
-#include <sys/stat.h> /* for umask(), stat() */
-#include <unistd.h> /* for geteuid(), getpid(), stat() */
+#include <sys/types.h> /* for umask() */
+#include <sys/stat.h> /* for umask(), stat() */
+#include <unistd.h> /* for geteuid(), getpid(), stat() */
#endif
#include <assert.h>
@@ -35,21 +35,20 @@
/* functions for use in this file only */
-static backslashResult
-exec_command(const char * cmd,
- char * const * options,
- const char * options_string,
- PQExpBuffer query_buf,
- PsqlSettings * pset);
+static backslashResult exec_command(const char *cmd,
+ char *const * options,
+ const char *options_string,
+ PQExpBuffer query_buf,
+ PsqlSettings *pset);
static bool
-do_edit(const char *filename_arg, PQExpBuffer query_buf);
+ do_edit(const char *filename_arg, PQExpBuffer query_buf);
static char *
-unescape(const char * source, PsqlSettings * pset);
+ unescape(const char *source, PsqlSettings *pset);
static bool
-do_shell(const char *command);
+ do_shell(const char *command);
@@ -72,538 +71,616 @@ do_shell(const char *command);
backslashResult
HandleSlashCmds(PsqlSettings *pset,
- const char *line,
- PQExpBuffer query_buf,
- const char ** end_of_cmd)
+ const char *line,
+ PQExpBuffer query_buf,
+ const char **end_of_cmd)
{
- backslashResult status = CMD_SKIP_LINE;
- char * my_line;
- char * options[17] ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- char * token;
- const char * options_string = NULL;
- const char * cmd;
- size_t blank_loc;
- int i;
- const char * continue_parse = NULL; /* tell the mainloop where the backslash command ended */
-
- my_line = xstrdup(line);
-
- /* Find the first whitespace (or backslash)
- line[blank_loc] will now be the whitespace character
- or the \0 at the end */
- blank_loc = strcspn(my_line, " \t");
-
- /* do we have an option string? */
- if (my_line[blank_loc] != '\0') {
- options_string = &my_line[blank_loc+1];
-
- my_line[blank_loc] = '\0';
- }
-
- if (options_string) {
- char quote;
- unsigned int pos;
- options_string = &options_string[strspn(options_string, " \t")]; /* skip leading whitespace */
-
- i = 0;
- token = strtokx(options_string, " \t", "\"'`", '\\', &quote, &pos);
-
- for (i = 0; token && i<16; i++) {
- switch(quote) {
- case '"':
- options[i] = unescape(token, pset);
- break;
- case '\'':
- options[i] = xstrdup(token);
- break;
- case '`':
- {
- bool error = false;
- FILE * fd = NULL;
- char * file = unescape(token, pset);
- PQExpBufferData output;
- char buf[512];
- size_t result;
-
- fd = popen(file, "r");
- if (!fd) {
- perror(file);
- error = true;
- }
+ backslashResult status = CMD_SKIP_LINE;
+ char *my_line;
+ char *options[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ char *token;
+ const char *options_string = NULL;
+ const char *cmd;
+ size_t blank_loc;
+ int i;
+ const char *continue_parse = NULL; /* tell the mainloop where the
+ * backslash command ended */
+
+ my_line = xstrdup(line);
+
+ /*
+ * Find the first whitespace (or backslash) line[blank_loc] will now
+ * be the whitespace character or the \0 at the end
+ */
+ blank_loc = strcspn(my_line, " \t");
+
+ /* do we have an option string? */
+ if (my_line[blank_loc] != '\0')
+ {
+ options_string = &my_line[blank_loc + 1];
- if (!error) {
- initPQExpBuffer(&output);
+ my_line[blank_loc] = '\0';
+ }
- do {
- result = fread(buf, 1, 512, fd);
- if (ferror(fd)) {
- perror(file);
- error = true;
- break;
+ if (options_string)
+ {
+ char quote;
+ unsigned int pos;
+
+ options_string = &options_string[strspn(options_string, " \t")]; /* skip leading
+ * whitespace */
+
+ i = 0;
+ token = strtokx(options_string, " \t", "\"'`", '\\', &quote, &pos);
+
+ for (i = 0; token && i < 16; i++)
+ {
+ switch (quote)
+ {
+ case '"':
+ options[i] = unescape(token, pset);
+ break;
+ case '\'':
+ options[i] = xstrdup(token);
+ break;
+ case '`':
+ {
+ bool error = false;
+ FILE *fd = NULL;
+ char *file = unescape(token, pset);
+ PQExpBufferData output;
+ char buf[512];
+ size_t result;
+
+ fd = popen(file, "r");
+ if (!fd)
+ {
+ perror(file);
+ error = true;
+ }
+
+ if (!error)
+ {
+ initPQExpBuffer(&output);
+
+ do
+ {
+ result = fread(buf, 1, 512, fd);
+ if (ferror(fd))
+ {
+ perror(file);
+ error = true;
+ break;
+ }
+ appendBinaryPQExpBuffer(&output, buf, result);
+ } while (!feof(fd));
+ appendPQExpBufferChar(&output, '\0');
+
+ if (pclose(fd) == -1)
+ {
+ perror(file);
+ error = true;
+ }
+ }
+
+ if (!error)
+ {
+ if (output.data[strlen(output.data) - 1] == '\n')
+ output.data[strlen(output.data) - 1] = '\0';
+ }
+
+ free(file);
+ if (!error)
+ options[i] = output.data;
+ else
+ {
+ options[i] = xstrdup("");
+ termPQExpBuffer(&output);
+ }
+ break;
+ }
+ case 0:
+ default:
+ if (token[0] == '\\')
+ continue_parse = options_string + pos;
+ else if (token[0] == '$')
+ options[i] = xstrdup(interpolate_var(token + 1, pset));
+ else
+ options[i] = xstrdup(token);
+ break;
}
- appendBinaryPQExpBuffer(&output, buf, result);
- } while (!feof(fd));
- appendPQExpBufferChar(&output, '\0');
-
- if (pclose(fd) == -1) {
- perror(file);
- error = true;
- }
- }
- if (!error) {
- if (output.data[strlen(output.data)-1] == '\n')
- output.data[strlen(output.data)-1] = '\0';
- }
+ if (continue_parse)
+ break;
- free(file);
- if (!error)
- options[i] = output.data;
- else {
- options[i] = xstrdup("");
- termPQExpBuffer(&output);
+ token = strtokx(NULL, " \t", "\"'`", '\\', &quote, &pos);
}
- break;
- }
- case 0:
- default:
- if (token[0] == '\\')
- continue_parse = options_string + pos;
- else if (token[0] == '$')
- options[i] = xstrdup(interpolate_var(token+1, pset));
- else
- options[i] = xstrdup(token);
- break;
- }
-
- if (continue_parse)
- break;
-
- token = strtokx(NULL, " \t", "\"'`", '\\', &quote, &pos);
}
- }
- cmd = my_line;
+ cmd = my_line;
- status = exec_command(cmd, options, options_string, query_buf, pset);
+ status = exec_command(cmd, options, options_string, query_buf, pset);
- if (status == CMD_UNKNOWN) {
- /* If the command was not recognized, try inserting a space after
- the first letter and call again. The one letter commands
- allow arguments to start immediately after the command,
- but that is no longer encouraged. */
- const char * new_options[17];
- char new_cmd[2];
- int i;
+ if (status == CMD_UNKNOWN)
+ {
- for (i=1; i<17; i++)
- new_options[i] = options[i-1];
- new_options[0] = cmd+1;
+ /*
+ * If the command was not recognized, try inserting a space after
+ * the first letter and call again. The one letter commands allow
+ * arguments to start immediately after the command, but that is
+ * no longer encouraged.
+ */
+ const char *new_options[17];
+ char new_cmd[2];
+ int i;
- new_cmd[0] = cmd[0];
- new_cmd[1] = '\0';
+ for (i = 1; i < 17; i++)
+ new_options[i] = options[i - 1];
+ new_options[0] = cmd + 1;
+
+ new_cmd[0] = cmd[0];
+ new_cmd[1] = '\0';
+
+ status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf, pset);
+ }
- status = exec_command(new_cmd, (char * const *)new_options, my_line+2, query_buf, pset);
- }
+ if (status == CMD_UNKNOWN)
+ {
+ fprintf(stderr, "Unrecognized command: \\%s. Try \\? for help.\n", cmd);
+ status = CMD_ERROR;
+ }
- if (status == CMD_UNKNOWN) {
- fprintf(stderr, "Unrecognized command: \\%s. Try \\? for help.\n", cmd);
- status = CMD_ERROR;
- }
-
- if (continue_parse && *(continue_parse+1) == '\\')
- continue_parse+=2;
+ if (continue_parse && *(continue_parse + 1) == '\\')
+ continue_parse += 2;
- if (end_of_cmd) {
- if (continue_parse)
- *end_of_cmd = line + (continue_parse - my_line);
- else
- *end_of_cmd = NULL;
- }
+ if (end_of_cmd)
+ {
+ if (continue_parse)
+ *end_of_cmd = line + (continue_parse - my_line);
+ else
+ *end_of_cmd = NULL;
+ }
- /* clean up */
- for (i = 0; i<16 && options[i]; i++)
- free(options[i]);
+ /* clean up */
+ for (i = 0; i < 16 && options[i]; i++)
+ free(options[i]);
- free(my_line);
+ free(my_line);
- return status;
+ return status;
}
static backslashResult
-exec_command(const char * cmd,
- char * const * options,
- const char * options_string,
- PQExpBuffer query_buf,
- PsqlSettings * pset)
+exec_command(const char *cmd,
+ char *const * options,
+ const char *options_string,
+ PQExpBuffer query_buf,
+ PsqlSettings *pset)
{
- bool success = true; /* indicate here if the command ran ok or failed */
- bool quiet = GetVariableBool(pset->vars, "quiet");
+ bool success = true; /* indicate here if the command ran ok or
+ * failed */
+ bool quiet = GetVariableBool(pset->vars, "quiet");
- backslashResult status = CMD_SKIP_LINE;
+ backslashResult status = CMD_SKIP_LINE;
- /* \a -- toggle field alignment
- This is deprecated and makes no sense, but we keep it around. */
- if (strcmp(cmd, "a") == 0) {
- if (pset->popt.topt.format != PRINT_ALIGNED)
- success = do_pset("format", "aligned", &pset->popt, quiet);
- else
- success = do_pset("format", "unaligned", &pset->popt, quiet);
- }
-
-
- /* \C -- override table title
- (formerly change HTML caption) This is deprecated. */
- else if (strcmp(cmd, "C") == 0)
- success = do_pset("title", options[0], &pset->popt, quiet);
-
-
-
- /* \c or \connect -- connect to new database or as different user
- *
- * \c foo bar : connect to db "foo" as user "bar"
- * \c foo [-] : connect to db "foo" as current user
- * \c - bar : connect to current db as user "bar"
- * \c : connect to default db as default user
- */
- else if (strcmp(cmd, "c")==0 || strcmp(cmd, "connect")==0)
- {
- if (options[1])
- /* gave username */
- success = do_connect(options[0], options[1], pset);
- else {
- if (options[0])
- /* gave database name */
- success = do_connect(options[0], "", pset); /* empty string is same username as before,
- NULL would mean libpq default */
- else
- /* connect to default db as default user */
- success = do_connect(NULL, NULL, pset);
+ /*
+ * \a -- toggle field alignment This is deprecated and makes no sense,
+ * but we keep it around.
+ */
+ if (strcmp(cmd, "a") == 0)
+ {
+ if (pset->popt.topt.format != PRINT_ALIGNED)
+ success = do_pset("format", "aligned", &pset->popt, quiet);
+ else
+ success = do_pset("format", "unaligned", &pset->popt, quiet);
}
- }
-
-
- /* \copy */
- else if (strcmp(cmd, "copy") == 0)
- success = do_copy(options_string, pset);
-
- /* \copyright */
- else if (strcmp(cmd, "copyright") == 0)
- print_copyright();
-
- /* \d* commands */
- else if (cmd[0] == 'd') {
- switch(cmd[1]) {
- case '\0':
- if (options[0])
- success = describeTableDetails(options[0], pset);
- else
- success = listTables("tvs", NULL, pset); /* standard listing of interesting things */
- break;
- case 'a':
- success = describeAggregates(options[0], pset);
- break;
- case 'd':
- success = objectDescription(options[0], pset);
- break;
- case 'f':
- success = describeFunctions(options[0], pset);
- break;
- case 'l':
- success = do_lo_list(pset);
- break;
- case 'o':
- success = describeOperators(options[0], pset);
- break;
- case 'p':
- success = permissionsList(options[0], pset);
- break;
- case 'T':
- success = describeTypes(options[0], pset);
- break;
- case 't': case 'v': case 'i': case 's': case 'S':
- if (cmd[1] == 'S' && cmd[2] == '\0')
- success = listTables("Stvs", NULL, pset);
- else
- success = listTables(&cmd[1], options[0], pset);
- break;
- default:
- status = CMD_UNKNOWN;
+
+
+ /*
+ * \C -- override table title (formerly change HTML caption) This is
+ * deprecated.
+ */
+ else if (strcmp(cmd, "C") == 0)
+ success = do_pset("title", options[0], &pset->popt, quiet);
+
+
+
+ /*
+ * \c or \connect -- connect to new database or as different user
+ *
+ * \c foo bar : connect to db "foo" as user "bar" \c foo [-] :
+ * connect to db "foo" as current user \c - bar : connect to
+ * current db as user "bar" \c : connect to default db as
+ * default user
+ */
+ else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
+ {
+ if (options[1])
+ /* gave username */
+ success = do_connect(options[0], options[1], pset);
+ else
+ {
+ if (options[0])
+ /* gave database name */
+ success = do_connect(options[0], "", pset); /* empty string is same
+ * username as before,
+ * NULL would mean libpq
+ * default */
+ else
+ /* connect to default db as default user */
+ success = do_connect(NULL, NULL, pset);
+ }
}
- }
- /* \e or \edit -- edit the current query buffer (or a file and make it the
- query buffer */
- else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
- status = do_edit(options[0], query_buf) ? CMD_NEWEDIT : CMD_ERROR;
+ /* \copy */
+ else if (strcmp(cmd, "copy") == 0)
+ success = do_copy(options_string, pset);
+ /* \copyright */
+ else if (strcmp(cmd, "copyright") == 0)
+ print_copyright();
- /* \echo */
- else if (strcmp(cmd, "echo") == 0) {
- int i;
- for (i=0; i<16 && options[i]; i++)
- fputs(options[i], stdout);
- fputs("\n", stdout);
- }
+ /* \d* commands */
+ else if (cmd[0] == 'd')
+ {
+ switch (cmd[1])
+ {
+ case '\0':
+ if (options[0])
+ success = describeTableDetails(options[0], pset);
+ else
+ success = listTables("tvs", NULL, pset); /* standard listing of
+ * interesting things */
+ break;
+ case 'a':
+ success = describeAggregates(options[0], pset);
+ break;
+ case 'd':
+ success = objectDescription(options[0], pset);
+ break;
+ case 'f':
+ success = describeFunctions(options[0], pset);
+ break;
+ case 'l':
+ success = do_lo_list(pset);
+ break;
+ case 'o':
+ success = describeOperators(options[0], pset);
+ break;
+ case 'p':
+ success = permissionsList(options[0], pset);
+ break;
+ case 'T':
+ success = describeTypes(options[0], pset);
+ break;
+ case 't':
+ case 'v':
+ case 'i':
+ case 's':
+ case 'S':
+ if (cmd[1] == 'S' && cmd[2] == '\0')
+ success = listTables("Stvs", NULL, pset);
+ else
+ success = listTables(&cmd[1], options[0], pset);
+ break;
+ default:
+ status = CMD_UNKNOWN;
+ }
+ }
- /* \f -- change field separator
- (This is deprecated in favour of \pset.) */
- else if (strcmp(cmd, "f") == 0)
- success = do_pset("fieldsep", options[0], &pset->popt, quiet);
+ /*
+ * \e or \edit -- edit the current query buffer (or a file and make it
+ * the query buffer
+ */
+ else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
+ status = do_edit(options[0], query_buf) ? CMD_NEWEDIT : CMD_ERROR;
- /* \g means send query */
- else if (strcmp(cmd, "g") == 0) {
- if (!options[0])
- pset->gfname = NULL;
- else
- pset->gfname = xstrdup(options[0]);
- status = CMD_SEND;
- }
- /* help */
- else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
- helpSQL(options_string);
+ /* \echo */
+ else if (strcmp(cmd, "echo") == 0)
+ {
+ int i;
+ for (i = 0; i < 16 && options[i]; i++)
+ fputs(options[i], stdout);
+ fputs("\n", stdout);
+ }
- /* HTML mode */
- else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
- success = do_pset("format", "html", &pset->popt, quiet);
+ /*
+ * \f -- change field separator (This is deprecated in favour of
+ * \pset.)
+ */
+ else if (strcmp(cmd, "f") == 0)
+ success = do_pset("fieldsep", options[0], &pset->popt, quiet);
- /* \i is include file */
- else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
- {
- if (!options[0]) {
- fputs("Usage: \\i <filename>\n", stderr);
- success = false;
+ /* \g means send query */
+ else if (strcmp(cmd, "g") == 0)
+ {
+ if (!options[0])
+ pset->gfname = NULL;
+ else
+ pset->gfname = xstrdup(options[0]);
+ status = CMD_SEND;
}
- else
- success = process_file(options[0], pset);
- }
-
- /* \l is list databases */
- else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
- success = listAllDbs(pset);
-
-
- /* large object things */
- else if (strncmp(cmd, "lo_", 3)==0) {
- if (strcmp(cmd+3, "export") == 0) {
- if (!options[1]) {
- fputs("Usage: \\lo_export <loid> <filename>\n", stderr);
- success = false;
- }
- else
- success = do_lo_export(pset, options[0], options[1]);
+
+ /* help */
+ else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
+ helpSQL(options_string);
+
+
+ /* HTML mode */
+ else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
+ success = do_pset("format", "html", &pset->popt, quiet);
+
+
+ /* \i is include file */
+ else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
+ {
+ if (!options[0])
+ {
+ fputs("Usage: \\i <filename>\n", stderr);
+ success = false;
+ }
+ else
+ success = process_file(options[0], pset);
}
- else if (strcmp(cmd+3, "import") == 0) {
- if (!options[0]) {
- fputs("Usage: \\lo_import <filename> [<description>]\n", stderr);
- success = false;
- }
- else
- success = do_lo_import(pset, options[0], options[1]);
+ /* \l is list databases */
+ else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
+ success = listAllDbs(pset);
+
+
+ /* large object things */
+ else if (strncmp(cmd, "lo_", 3) == 0)
+ {
+ if (strcmp(cmd + 3, "export") == 0)
+ {
+ if (!options[1])
+ {
+ fputs("Usage: \\lo_export <loid> <filename>\n", stderr);
+ success = false;
+ }
+ else
+ success = do_lo_export(pset, options[0], options[1]);
+ }
+
+ else if (strcmp(cmd + 3, "import") == 0)
+ {
+ if (!options[0])
+ {
+ fputs("Usage: \\lo_import <filename> [<description>]\n", stderr);
+ success = false;
+ }
+ else
+ success = do_lo_import(pset, options[0], options[1]);
+ }
+
+ else if (strcmp(cmd + 3, "list") == 0)
+ success = do_lo_list(pset);
+
+ else if (strcmp(cmd + 3, "unlink") == 0)
+ {
+ if (!options[0])
+ {
+ fputs("Usage: \\lo_unlink <loid>\n", stderr);
+ success = false;
+ }
+ else
+ success = do_lo_unlink(pset, options[0]);
+ }
+
+ else
+ status = CMD_UNKNOWN;
}
- else if (strcmp(cmd+3, "list") == 0)
- success = do_lo_list(pset);
+ /* \o -- set query output */
+ else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
+ success = setQFout(options[0], pset);
- else if (strcmp(cmd+3, "unlink") == 0) {
- if (!options[0]) {
- fputs("Usage: \\lo_unlink <loid>\n", stderr);
- success = false;
- }
- else
- success = do_lo_unlink(pset, options[0]);
+
+ /* \p prints the current query buffer */
+ else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
+ {
+ if (query_buf && query_buf->len > 0)
+ puts(query_buf->data);
+ else if (!GetVariableBool(pset->vars, "quiet"))
+ puts("Query buffer is empty.");
}
- else
- status = CMD_UNKNOWN;
- }
-
- /* \o -- set query output */
- else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
- success = setQFout(options[0], pset);
-
-
- /* \p prints the current query buffer */
- else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0 )
- {
- if (query_buf && query_buf->len > 0)
- puts(query_buf->data);
- else if (!GetVariableBool(pset->vars, "quiet"))
- puts("Query buffer is empty.");
- }
-
- /* \pset -- set printing parameters */
- else if (strcmp(cmd, "pset")==0) {
- if (!options[0]) {
- fputs("Usage: \\pset <parameter> [<value>]\n", stderr);
- success = false;
+ /* \pset -- set printing parameters */
+ else if (strcmp(cmd, "pset") == 0)
+ {
+ if (!options[0])
+ {
+ fputs("Usage: \\pset <parameter> [<value>]\n", stderr);
+ success = false;
+ }
+ else
+ success = do_pset(options[0], options[1], &pset->popt, quiet);
}
- else
- success = do_pset(options[0], options[1], &pset->popt, quiet);
- }
-
- /* \q or \quit */
- else if (strcmp(cmd, "q")==0 || strcmp(cmd, "quit")==0)
- status = CMD_TERMINATE;
-
- /* \qecho */
- else if (strcmp(cmd, "qecho") == 0) {
- int i;
- for (i=0; i<16 && options[i]; i++)
- fputs(options[i], pset->queryFout);
- fputs("\n", pset->queryFout);
- }
-
- /* reset(clear) the buffer */
- else if (strcmp(cmd, "r")==0 || strcmp(cmd, "reset")==0)
- {
- resetPQExpBuffer(query_buf);
- if (!quiet) puts("Query buffer reset (cleared).");
- }
-
-
- /* \s save history in a file or show it on the screen */
- else if (strcmp(cmd, "s")==0)
- {
- const char * fname;
- if (!options[0])
- fname = "/dev/tty";
- else
- fname = options[0];
-
- success = saveHistory(fname);
-
- if (success && !quiet && options[0])
- printf("Wrote history to %s.\n", fname);
- }
-
-
- /* \set -- generalized set option command */
- else if (strcmp(cmd, "set")==0)
- {
- if (!options[0]) {
- /* list all variables */
- /* (This is in utter violation of the GetVariable abstraction, but
- I have not dreamt up a better way.) */
- struct _variable * ptr;
- for (ptr = pset->vars; ptr->next; ptr = ptr->next)
- fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
- success = true;
+
+ /* \q or \quit */
+ else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
+ status = CMD_TERMINATE;
+
+ /* \qecho */
+ else if (strcmp(cmd, "qecho") == 0)
+ {
+ int i;
+
+ for (i = 0; i < 16 && options[i]; i++)
+ fputs(options[i], pset->queryFout);
+ fputs("\n", pset->queryFout);
}
- else {
- if (!SetVariable(pset->vars, options[0], options[1])) {
- fprintf(stderr, "Set variable failed.\n");
- success = false;
- }
+
+ /* reset(clear) the buffer */
+ else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
+ {
+ resetPQExpBuffer(query_buf);
+ if (!quiet)
+ puts("Query buffer reset (cleared).");
}
- }
- /* \t -- turn off headers and row count */
- else if (strcmp(cmd, "t")==0)
- success = do_pset("tuples_only", NULL, &pset->popt, quiet);
+ /* \s save history in a file or show it on the screen */
+ else if (strcmp(cmd, "s") == 0)
+ {
+ const char *fname;
+
+ if (!options[0])
+ fname = "/dev/tty";
+ else
+ fname = options[0];
- /* \T -- define html <table ...> attributes */
- else if (strcmp(cmd, "T")==0)
- success = do_pset("tableattr", options[0], &pset->popt, quiet);
+ success = saveHistory(fname);
+ if (success && !quiet && options[0])
+ printf("Wrote history to %s.\n", fname);
+ }
- /* \w -- write query buffer to file */
- else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0 )
- {
- FILE *fd = NULL;
- bool pipe = false;
- if (!options[0]) {
- fprintf(stderr, "Usage \\%s <filename>\n", cmd);
- success = false;
+ /* \set -- generalized set option command */
+ else if (strcmp(cmd, "set") == 0)
+ {
+ if (!options[0])
+ {
+ /* list all variables */
+
+ /*
+ * (This is in utter violation of the GetVariable abstraction,
+ * but I have not dreamt up a better way.)
+ */
+ struct _variable *ptr;
+
+ for (ptr = pset->vars; ptr->next; ptr = ptr->next)
+ fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
+ success = true;
+ }
+ else
+ {
+ if (!SetVariable(pset->vars, options[0], options[1]))
+ {
+ fprintf(stderr, "Set variable failed.\n");
+ success = false;
+ }
+ }
}
- else {
- if (options[0][0] == '|') {
- pipe = true;
+
+ /* \t -- turn off headers and row count */
+ else if (strcmp(cmd, "t") == 0)
+ success = do_pset("tuples_only", NULL, &pset->popt, quiet);
+
+
+ /* \T -- define html <table ...> attributes */
+ else if (strcmp(cmd, "T") == 0)
+ success = do_pset("tableattr", options[0], &pset->popt, quiet);
+
+
+ /* \w -- write query buffer to file */
+ else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
+ {
+ FILE *fd = NULL;
+ bool pipe = false;
+
+ if (!options[0])
+ {
+ fprintf(stderr, "Usage \\%s <filename>\n", cmd);
+ success = false;
+ }
+ else
+ {
+ if (options[0][0] == '|')
+ {
+ pipe = true;
#ifndef __CYGWIN32__
- fd = popen(&options[0][1], "w");
+ fd = popen(&options[0][1], "w");
#else
- fd = popen(&options[0][1], "wb");
+ fd = popen(&options[0][1], "wb");
#endif
- }
- else {
+ }
+ else
+ {
#ifndef __CYGWIN32__
- fd = fopen(options[0], "w");
+ fd = fopen(options[0], "w");
#else
- fd = fopen(options[0], "wb");
+ fd = fopen(options[0], "wb");
#endif
- }
+ }
- if (!fd) {
- perror(options[0]);
- success = false;
- }
- }
+ if (!fd)
+ {
+ perror(options[0]);
+ success = false;
+ }
+ }
- if (fd) {
- int result;
+ if (fd)
+ {
+ int result;
- if (query_buf && query_buf->len > 0)
- fprintf(fd, "%s\n", query_buf->data);
+ if (query_buf && query_buf->len > 0)
+ fprintf(fd, "%s\n", query_buf->data);
- if (pipe)
- result = pclose(fd);
- else
- result = fclose(fd);
+ if (pipe)
+ result = pclose(fd);
+ else
+ result = fclose(fd);
- if (result == EOF) {
- perror("close");
- success = false;
- }
+ if (result == EOF)
+ {
+ perror("close");
+ success = false;
+ }
+ }
}
- }
- /* \x -- toggle expanded table representation */
- else if (strcmp(cmd, "x")==0)
- success = do_pset("expanded", NULL, &pset->popt, quiet);
+ /* \x -- toggle expanded table representation */
+ else if (strcmp(cmd, "x") == 0)
+ success = do_pset("expanded", NULL, &pset->popt, quiet);
- /* list table rights (grant/revoke) */
- else if (strcmp(cmd, "z")==0)
- success = permissionsList(options[0], pset);
-
+ /* list table rights (grant/revoke) */
+ else if (strcmp(cmd, "z") == 0)
+ success = permissionsList(options[0], pset);
- else if (strcmp(cmd, "!")==0)
- success = do_shell(options_string);
- else if (strcmp(cmd, "?")==0)
- slashUsage(pset);
+ else if (strcmp(cmd, "!") == 0)
+ success = do_shell(options_string);
+
+ else if (strcmp(cmd, "?") == 0)
+ slashUsage(pset);
#ifdef NOT_USED
- /* These commands don't do anything. I just use them to test the parser. */
- else if (strcmp(cmd, "void")==0 || strcmp(cmd, "#")==0)
- {
- int i;
- fprintf(stderr, "+ optline = |%s|\n", options_string);
- for(i=0; options[i]; i++)
- fprintf(stderr, "+ opt%d = |%s|\n", i, options[i]);
- }
+
+ /*
+ * These commands don't do anything. I just use them to test the
+ * parser.
+ */
+ else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
+ {
+ int i;
+
+ fprintf(stderr, "+ optline = |%s|\n", options_string);
+ for (i = 0; options[i]; i++)
+ fprintf(stderr, "+ opt%d = |%s|\n", i, options[i]);
+ }
#endif
- else {
- status = CMD_UNKNOWN;
- }
+ else
+ status = CMD_UNKNOWN;
- if (!success) status = CMD_ERROR;
- return status;
+ if (!success)
+ status = CMD_ERROR;
+ return status;
}
@@ -617,104 +694,119 @@ exec_command(const char * cmd,
* The return value is malloc()'ed.
*/
static char *
-unescape(const char * source, PsqlSettings * pset)
+unescape(const char *source, PsqlSettings *pset)
{
- unsigned char *p;
- bool esc = false; /* Last character we saw was the
- escape character */
- char *destination, *tmp;
- size_t length;
+ unsigned char *p;
+ bool esc = false; /* Last character we saw was the escape
+ * character */
+ char *destination,
+ *tmp;
+ size_t length;
#ifdef USE_ASSERT_CHECKING
- assert(source);
+ assert(source);
#endif
- length = strlen(source)+1;
-
- tmp = destination = (char *) malloc(length);
- if (!tmp) {
- perror("malloc");
- exit(EXIT_FAILURE);
- }
-
- for (p = (char *) source; *p; p += PQmblen(p)) {
- if (esc) {
- char c;
-
- switch (*p)
- {
- case 'n':
- c = '\n';
- break;
- case 'r':
- c = '\r';
- break;
- case 't':
- c = '\t';
- break;
- case 'f':
- c = '\f';
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- long int l;
- char * end;
- l = strtol(p, &end, 0);
- c = l;
- p = end-1;
- break;
- }
- default:
- c = *p;
- }
- *tmp++ = c;
- esc = false;
- }
+ length = strlen(source) + 1;
- else if (*p == '\\') {
- esc = true;
+ tmp = destination = (char *) malloc(length);
+ if (!tmp)
+ {
+ perror("malloc");
+ exit(EXIT_FAILURE);
}
- else if (*p == '$')
+ for (p = (char *) source; *p; p += PQmblen(p))
{
- if (*(p+1) == '{') {
- unsigned int len;
- char *copy;
- const char *value;
- void * new;
- len = strcspn(p+2, "}");
- copy = xstrdup(p+2);
- copy[len] = '\0';
- value = interpolate_var(copy, pset);
-
- length += strlen(value) - (len+3);
- new = realloc(destination, length);
- if (!new) {
- perror("realloc");
- exit(EXIT_FAILURE);
+ if (esc)
+ {
+ char c;
+
+ switch (*p)
+ {
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'f':
+ c = '\f';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ long int l;
+ char *end;
+
+ l = strtol(p, &end, 0);
+ c = l;
+ p = end - 1;
+ break;
+ }
+ default:
+ c = *p;
+ }
+ *tmp++ = c;
+ esc = false;
+ }
+
+ else if (*p == '\\')
+ esc = true;
+
+ else if (*p == '$')
+ {
+ if (*(p + 1) == '{')
+ {
+ unsigned int len;
+ char *copy;
+ const char *value;
+ void *new;
+
+ len = strcspn(p + 2, "}");
+ copy = xstrdup(p + 2);
+ copy[len] = '\0';
+ value = interpolate_var(copy, pset);
+
+ length += strlen(value) - (len + 3);
+ new = realloc(destination, length);
+ if (!new)
+ {
+ perror("realloc");
+ exit(EXIT_FAILURE);
+ }
+ tmp = new + (tmp - destination);
+ destination = new;
+
+ strcpy(tmp, value);
+ tmp += strlen(value);
+ p += len + 2;
+ free(copy);
+ }
+ else
+ *tmp++ = '$';
}
- tmp = new + (tmp - destination);
- destination = new;
-
- strcpy(tmp, value);
- tmp += strlen(value);
- p += len + 2;
- free(copy);
- }
- else {
- *tmp++ = '$';
- }
- }
- else {
- *tmp++ = *p;
- esc = false;
+ else
+ {
+ *tmp++ = *p;
+ esc = false;
+ }
}
- }
- *tmp = '\0';
- return destination;
+ *tmp = '\0';
+ return destination;
}
@@ -731,109 +823,120 @@ unescape(const char * source, PsqlSettings * pset)
* but the old one was set back. Otherwise it terminates the program.
*/
bool
-do_connect(const char *new_dbname, const char *new_user, PsqlSettings * pset)
+do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
{
- PGconn *oldconn = pset->db;
- const char *dbparam = NULL;
- const char *userparam = NULL;
- char *pwparam = NULL;
- char * prompted_password = NULL;
- char * prompted_user = NULL;
- bool need_pass;
- bool success = false;
-
- /* If dbname is "-" then use old name, else new one (even if NULL) */
- if (new_dbname && PQdb(oldconn) && (strcmp(new_dbname, "-") == 0 || strcmp(new_dbname, PQdb(oldconn))==0))
- dbparam = PQdb(oldconn);
- else
- dbparam = new_dbname;
-
- /* If user is "" or "-" then use the old one */
- if ( new_user && PQuser(oldconn) && ( strcmp(new_user, "")==0 || strcmp(new_user, "-")==0 || strcmp(new_user, PQuser(oldconn))==0 )) {
- userparam = PQuser(oldconn);
- }
- /* If username is "?" then prompt */
- else if (new_user && strcmp(new_user, "?")==0)
- userparam = prompted_user = simple_prompt("Username: ", 100, true); /* save for free() */
- else
- userparam = new_user;
-
- /* need to prompt for password? */
- if (pset->getPassword)
- pwparam = prompted_password = simple_prompt("Password: ", 100, false); /* need to save for free() */
-
- /* Use old password if no new one given (if you didn't have an old one, fine) */
- if (!pwparam)
- pwparam = PQpass(oldconn);
+ PGconn *oldconn = pset->db;
+ const char *dbparam = NULL;
+ const char *userparam = NULL;
+ char *pwparam = NULL;
+ char *prompted_password = NULL;
+ char *prompted_user = NULL;
+ bool need_pass;
+ bool success = false;
+
+ /* If dbname is "-" then use old name, else new one (even if NULL) */
+ if (new_dbname && PQdb(oldconn) && (strcmp(new_dbname, "-") == 0 || strcmp(new_dbname, PQdb(oldconn)) == 0))
+ dbparam = PQdb(oldconn);
+ else
+ dbparam = new_dbname;
+
+ /* If user is "" or "-" then use the old one */
+ if (new_user && PQuser(oldconn) && (strcmp(new_user, "") == 0 || strcmp(new_user, "-") == 0 || strcmp(new_user, PQuser(oldconn)) == 0))
+ userparam = PQuser(oldconn);
+ /* If username is "?" then prompt */
+ else if (new_user && strcmp(new_user, "?") == 0)
+ userparam = prompted_user = simple_prompt("Username: ", 100, true); /* save for free() */
+ else
+ userparam = new_user;
+
+ /* need to prompt for password? */
+ if (pset->getPassword)
+ pwparam = prompted_password = simple_prompt("Password: ", 100, false); /* need to save for
+ * free() */
+
+ /*
+ * Use old password if no new one given (if you didn't have an old
+ * one, fine)
+ */
+ if (!pwparam)
+ pwparam = PQpass(oldconn);
#ifdef MULTIBYTE
- /*
- * PGCLIENTENCODING may be set by the previous connection. if a
- * user does not explicitly set PGCLIENTENCODING, we should
- * discard PGCLIENTENCODING so that libpq could get the backend
- * encoding as the default PGCLIENTENCODING value. -- 1998/12/12
- * Tatsuo Ishii
- */
-
- if (!pset->has_client_encoding)
- putenv("PGCLIENTENCODING=");
+
+ /*
+ * PGCLIENTENCODING may be set by the previous connection. if a user
+ * does not explicitly set PGCLIENTENCODING, we should discard
+ * PGCLIENTENCODING so that libpq could get the backend encoding as
+ * the default PGCLIENTENCODING value. -- 1998/12/12 Tatsuo Ishii
+ */
+
+ if (!pset->has_client_encoding)
+ putenv("PGCLIENTENCODING=");
#endif
- do {
- need_pass = false;
- pset->db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
- NULL, NULL, dbparam, userparam, pwparam);
-
- if (PQstatus(pset->db)==CONNECTION_BAD &&
- strcmp(PQerrorMessage(pset->db), "fe_sendauth: no password supplied\n")==0) {
- need_pass = true;
- free(prompted_password);
- prompted_password = NULL;
- pwparam = prompted_password = simple_prompt("Password: ", 100, false);
- }
- } while (need_pass);
-
- free(prompted_password);
- free(prompted_user);
-
- /* If connection failed, try at least keep the old one.
- That's probably more convenient than just kicking you out of the
- program. */
- if (!pset->db || PQstatus(pset->db) == CONNECTION_BAD)
- {
- fprintf(stderr, "Could not establish database connection.\n%s", PQerrorMessage(pset->db));
- PQfinish(pset->db);
- if (!oldconn || !pset->cur_cmd_interactive) { /* we don't want unpredictable things to happen
- in scripting mode */
- fputs("Terminating.\n", stderr);
- if (oldconn)
- PQfinish(oldconn);
- pset->db = NULL;
- }
- else {
- fputs("Keeping old connection.\n", stderr);
- pset->db = oldconn;
- }
- }
- else {
- if (!GetVariable(pset->vars, "quiet")) {
- if (userparam != new_user) /* no new user */
- printf("You are now connected to database %s.\n", dbparam);
- else if (dbparam != new_dbname) /* no new db */
- printf("You are now connected as new user %s.\n", new_user);
- else /* both new */
- printf("You are now connected to database %s as user %s.\n",
- PQdb(pset->db), PQuser(pset->db));
+ do
+ {
+ need_pass = false;
+ pset->db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
+ NULL, NULL, dbparam, userparam, pwparam);
+
+ if (PQstatus(pset->db) == CONNECTION_BAD &&
+ strcmp(PQerrorMessage(pset->db), "fe_sendauth: no password supplied\n") == 0)
+ {
+ need_pass = true;
+ free(prompted_password);
+ prompted_password = NULL;
+ pwparam = prompted_password = simple_prompt("Password: ", 100, false);
+ }
+ } while (need_pass);
+
+ free(prompted_password);
+ free(prompted_user);
+
+ /*
+ * If connection failed, try at least keep the old one. That's
+ * probably more convenient than just kicking you out of the program.
+ */
+ if (!pset->db || PQstatus(pset->db) == CONNECTION_BAD)
+ {
+ fprintf(stderr, "Could not establish database connection.\n%s", PQerrorMessage(pset->db));
+ PQfinish(pset->db);
+ if (!oldconn || !pset->cur_cmd_interactive)
+ { /* we don't want unpredictable things to
+ * happen in scripting mode */
+ fputs("Terminating.\n", stderr);
+ if (oldconn)
+ PQfinish(oldconn);
+ pset->db = NULL;
+ }
+ else
+ {
+ fputs("Keeping old connection.\n", stderr);
+ pset->db = oldconn;
+ }
}
+ else
+ {
+ if (!GetVariable(pset->vars, "quiet"))
+ {
+ if (userparam != new_user) /* no new user */
+ printf("You are now connected to database %s.\n", dbparam);
+ else if (dbparam != new_dbname) /* no new db */
+ printf("You are now connected as new user %s.\n", new_user);
+ else
+/* both new */
+ printf("You are now connected to database %s as user %s.\n",
+ PQdb(pset->db), PQuser(pset->db));
+ }
- if (oldconn)
- PQfinish(oldconn);
+ if (oldconn)
+ PQfinish(oldconn);
- success = true;
- }
+ success = true;
+ }
- return success;
+ return success;
}
@@ -848,35 +951,36 @@ do_connect(const char *new_dbname, const char *new_user, PsqlSettings * pset)
static bool
editFile(const char *fname)
{
- char *editorName;
- char *sys;
- int result;
+ char *editorName;
+ char *sys;
+ int result;
#ifdef USE_ASSERT_CHECKING
- assert(fname);
+ assert(fname);
#else
- if (!fname) return false;
+ if (!fname)
+ return false;
#endif
- /* Find an editor to use */
- editorName = getenv("PSQL_EDITOR");
- if (!editorName)
- editorName = getenv("EDITOR");
- if (!editorName)
- editorName = getenv("VISUAL");
- if (!editorName)
- editorName = DEFAULT_EDITOR;
-
- sys = malloc(strlen(editorName) + strlen(fname) + 32 + 1);
- if (!sys)
- return false;
- sprintf(sys, "exec %s %s", editorName, fname);
- result = system(sys);
- if (result == -1 || result == 127)
- perror(sys);
- free(sys);
-
- return result==0;
+ /* Find an editor to use */
+ editorName = getenv("PSQL_EDITOR");
+ if (!editorName)
+ editorName = getenv("EDITOR");
+ if (!editorName)
+ editorName = getenv("VISUAL");
+ if (!editorName)
+ editorName = DEFAULT_EDITOR;
+
+ sys = malloc(strlen(editorName) + strlen(fname) + 32 + 1);
+ if (!sys)
+ return false;
+ sprintf(sys, "exec %s %s", editorName, fname);
+ result = system(sys);
+ if (result == -1 || result == 127)
+ perror(sys);
+ free(sys);
+
+ return result == 0;
}
@@ -884,117 +988,135 @@ editFile(const char *fname)
static bool
do_edit(const char *filename_arg, PQExpBuffer query_buf)
{
- char fnametmp[64];
- FILE * stream;
- const char *fname;
- bool error = false;
+ char fnametmp[64];
+ FILE *stream;
+ const char *fname;
+ bool error = false;
+
#ifndef WIN32
- struct stat before, after;
+ struct stat before,
+ after;
+
#endif
#ifdef USE_ASSERT_CHECKING
- assert(query_buf);
+ assert(query_buf);
#else
- if (!query_buf) return false;
+ if (!query_buf)
+ return false;
#endif
- if (filename_arg)
- fname = filename_arg;
+ if (filename_arg)
+ fname = filename_arg;
- else {
- /* make a temp file to edit */
+ else
+ {
+ /* make a temp file to edit */
#ifndef WIN32
- mode_t oldumask;
+ mode_t oldumask;
- sprintf(fnametmp, "/tmp/psql.edit.%ld.%ld", (long) geteuid(), (long) getpid());
+ sprintf(fnametmp, "/tmp/psql.edit.%ld.%ld", (long) geteuid(), (long) getpid());
#else
- GetTempFileName(".", "psql", 0, fnametmp);
+ GetTempFileName(".", "psql", 0, fnametmp);
#endif
- fname = (const char *)fnametmp;
+ fname = (const char *) fnametmp;
#ifndef WIN32
- oldumask = umask(0177);
+ oldumask = umask(0177);
#endif
- stream = fopen(fname, "w");
+ stream = fopen(fname, "w");
#ifndef WIN32
- umask(oldumask);
+ umask(oldumask);
#endif
- if (!stream) {
- perror(fname);
- error = true;
+ if (!stream)
+ {
+ perror(fname);
+ error = true;
+ }
+ else
+ {
+ unsigned int ql = query_buf->len;
+
+ if (ql == 0 || query_buf->data[ql - 1] != '\n')
+ {
+ appendPQExpBufferChar(query_buf, '\n');
+ ql++;
+ }
+
+ if (fwrite(query_buf->data, 1, ql, stream) != ql)
+ {
+ perror(fname);
+ fclose(stream);
+ remove(fname);
+ error = true;
+ }
+ else
+ fclose(stream);
+ }
}
- else {
- unsigned int ql = query_buf->len;
- if (ql == 0 || query_buf->data[ql - 1] != '\n') {
- appendPQExpBufferChar(query_buf, '\n');
- ql++;
- }
-
- if (fwrite(query_buf->data, 1, ql, stream) != ql) {
+
+#ifndef WIN32
+ if (!error && stat(fname, &before) != 0)
+ {
perror(fname);
- fclose(stream);
- remove(fname);
error = true;
- }
- else
- fclose(stream);
}
- }
-
-#ifndef WIN32
- if (!error && stat(fname, &before) != 0) {
- perror(fname);
- error = true;
- }
#endif
- /* call editor */
- if (!error)
- error = !editFile(fname);
+ /* call editor */
+ if (!error)
+ error = !editFile(fname);
#ifndef WIN32
- if (!error && stat(fname, &after) !=0) {
- perror(fname);
- error = true;
- }
+ if (!error && stat(fname, &after) != 0)
+ {
+ perror(fname);
+ error = true;
+ }
- if (!error && before.st_mtime != after.st_mtime) {
+ if (!error && before.st_mtime != after.st_mtime)
+ {
#else
- if (!error) {
+ if (!error)
+ {
#endif
- stream = fopen(fname, "r");
- if (!stream) {
- perror(fname);
- error = true;
- }
- else {
- /* read file back in */
- char line[1024];
- size_t result;
-
- resetPQExpBuffer(query_buf);
- do {
- result = fread(line, 1, 1024, stream);
- if (ferror(stream)) {
- perror(fname);
- error = true;
- break;
+ stream = fopen(fname, "r");
+ if (!stream)
+ {
+ perror(fname);
+ error = true;
+ }
+ else
+ {
+ /* read file back in */
+ char line[1024];
+ size_t result;
+
+ resetPQExpBuffer(query_buf);
+ do
+ {
+ result = fread(line, 1, 1024, stream);
+ if (ferror(stream))
+ {
+ perror(fname);
+ error = true;
+ break;
+ }
+ appendBinaryPQExpBuffer(query_buf, line, result);
+ } while (!feof(stream));
+ appendPQExpBufferChar(query_buf, '\0');
+
+ fclose(stream);
}
- appendBinaryPQExpBuffer(query_buf, line, result);
- } while (!feof(stream));
- appendPQExpBufferChar(query_buf, '\0');
- fclose(stream);
+ /* remove temp file */
+ if (!filename_arg)
+ remove(fname);
}
- /* remove temp file */
- if (!filename_arg)
- remove(fname);
- }
-
- return !error;
+ return !error;
}
@@ -1008,26 +1130,27 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
bool
process_file(const char *filename, PsqlSettings *pset)
{
- FILE *fd;
- int result;
+ FILE *fd;
+ int result;
- if (!filename)
- return false;
+ if (!filename)
+ return false;
#ifdef __CYGWIN32__
- fd = fopen(filename, "rb");
+ fd = fopen(filename, "rb");
#else
- fd = fopen(filename, "r");
+ fd = fopen(filename, "r");
#endif
- if (!fd) {
- perror(filename);
- return false;
- }
+ if (!fd)
+ {
+ perror(filename);
+ return false;
+ }
- result = MainLoop(pset, fd);
- fclose(fd);
- return (result == EXIT_SUCCESS);
+ result = MainLoop(pset, fd);
+ fclose(fd);
+ return (result == EXIT_SUCCESS);
}
@@ -1039,158 +1162,178 @@ process_file(const char *filename, PsqlSettings *pset)
static const char *
_align2string(enum printFormat in)
{
- switch (in) {
- case PRINT_NOTHING:
- return "nothing";
- break;
- case PRINT_UNALIGNED:
- return "unaligned";
- break;
- case PRINT_ALIGNED:
- return "aligned";
- break;
- case PRINT_HTML:
- return "html";
- break;
- case PRINT_LATEX:
- return "latex";
- break;
- }
- return "unknown";
+ switch (in)
+ {
+ case PRINT_NOTHING:
+ return "nothing";
+ break;
+ case PRINT_UNALIGNED:
+ return "unaligned";
+ break;
+ case PRINT_ALIGNED:
+ return "aligned";
+ break;
+ case PRINT_HTML:
+ return "html";
+ break;
+ case PRINT_LATEX:
+ return "latex";
+ break;
+ }
+ return "unknown";
}
bool
-do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet)
+do_pset(const char *param, const char *value, printQueryOpt * popt, bool quiet)
{
- size_t vallen = 0;
+ size_t vallen = 0;
+
#ifdef USE_ASSERT_CHECKING
- assert(param);
+ assert(param);
#else
- if (!param) return false;
+ if (!param)
+ return false;
#endif
- if (value)
- vallen = strlen(value);
-
- /* set format */
- if (strcmp(param, "format")==0) {
- if (!value)
- ;
- else if (strncasecmp("unaligned", value, vallen)==0)
- popt->topt.format = PRINT_UNALIGNED;
- else if (strncasecmp("aligned", value, vallen)==0)
- popt->topt.format = PRINT_ALIGNED;
- else if (strncasecmp("html", value, vallen)==0)
- popt->topt.format = PRINT_HTML;
- else if (strncasecmp("latex", value, vallen)==0)
- popt->topt.format = PRINT_LATEX;
- else {
- fprintf(stderr, "Allowed formats are unaligned, aligned, html, latex.\n");
- return false;
+ if (value)
+ vallen = strlen(value);
+
+ /* set format */
+ if (strcmp(param, "format") == 0)
+ {
+ if (!value)
+ ;
+ else if (strncasecmp("unaligned", value, vallen) == 0)
+ popt->topt.format = PRINT_UNALIGNED;
+ else if (strncasecmp("aligned", value, vallen) == 0)
+ popt->topt.format = PRINT_ALIGNED;
+ else if (strncasecmp("html", value, vallen) == 0)
+ popt->topt.format = PRINT_HTML;
+ else if (strncasecmp("latex", value, vallen) == 0)
+ popt->topt.format = PRINT_LATEX;
+ else
+ {
+ fprintf(stderr, "Allowed formats are unaligned, aligned, html, latex.\n");
+ return false;
+ }
+
+ if (!quiet)
+ printf("Output format is %s.\n", _align2string(popt->topt.format));
}
- if (!quiet)
- printf("Output format is %s.\n", _align2string(popt->topt.format));
- }
+ /* set border style/width */
+ else if (strcmp(param, "border") == 0)
+ {
+ if (value)
+ popt->topt.border = atoi(value);
- /* set border style/width */
- else if (strcmp(param, "border")==0) {
- if (value)
- popt->topt.border = atoi(value);
-
- if (!quiet)
- printf("Border style is %d.\n", popt->topt.border);
- }
-
- /* set expanded/vertical mode */
- else if (strcmp(param, "x")==0 || strcmp(param, "expanded")==0 || strcmp(param, "vertical")==0) {
- popt->topt.expanded = !popt->topt.expanded;
- if (!quiet)
- printf("Expanded display is %s.\n", popt->topt.expanded ? "on" : "off");
- }
-
- /* null display */
- else if (strcmp(param, "null")==0) {
- if (value) {
- free(popt->nullPrint);
- popt->nullPrint = xstrdup(value);
- }
- if (!quiet)
- printf("Null display is \"%s\".\n", popt->nullPrint ? popt->nullPrint : "");
- }
-
- /* field separator for unaligned text */
- else if (strcmp(param, "fieldsep")==0) {
- if (value) {
- free(popt->topt.fieldSep);
- popt->topt.fieldSep = xstrdup(value);
+ if (!quiet)
+ printf("Border style is %d.\n", popt->topt.border);
}
- if (!quiet)
- printf("Field separator is \"%s\".\n", popt->topt.fieldSep);
- }
-
- /* toggle between full and barebones format */
- else if (strcmp(param, "t")==0 || strcmp(param, "tuples_only")==0) {
- popt->topt.tuples_only = !popt->topt.tuples_only;
- if (!quiet) {
- if (popt->topt.tuples_only)
- puts("Showing only tuples.");
- else
- puts("Tuples only is off.");
+
+ /* set expanded/vertical mode */
+ else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
+ {
+ popt->topt.expanded = !popt->topt.expanded;
+ if (!quiet)
+ printf("Expanded display is %s.\n", popt->topt.expanded ? "on" : "off");
}
- }
- /* set title override */
- else if (strcmp(param, "title")==0) {
- free(popt->title);
- if (!value)
- popt->title = NULL;
- else
- popt->title = xstrdup(value);
-
- if (!quiet) {
- if (popt->title)
- printf("Title is \"%s\".\n", popt->title);
- else
- printf("Title is unset.\n");
+ /* null display */
+ else if (strcmp(param, "null") == 0)
+ {
+ if (value)
+ {
+ free(popt->nullPrint);
+ popt->nullPrint = xstrdup(value);
+ }
+ if (!quiet)
+ printf("Null display is \"%s\".\n", popt->nullPrint ? popt->nullPrint : "");
}
- }
- /* set HTML table tag options */
- else if (strcmp(param, "T")==0 || strcmp(param, "tableattr")==0) {
- free(popt->topt.tableAttr);
- if (!value)
- popt->topt.tableAttr = NULL;
- else
- popt->topt.tableAttr = xstrdup(value);
+ /* field separator for unaligned text */
+ else if (strcmp(param, "fieldsep") == 0)
+ {
+ if (value)
+ {
+ free(popt->topt.fieldSep);
+ popt->topt.fieldSep = xstrdup(value);
+ }
+ if (!quiet)
+ printf("Field separator is \"%s\".\n", popt->topt.fieldSep);
+ }
- if (!quiet) {
- if (popt->topt.tableAttr)
- printf("Table attribute is \"%s\".\n", popt->topt.tableAttr);
- else
- printf("Table attributes unset.\n");
+ /* toggle between full and barebones format */
+ else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
+ {
+ popt->topt.tuples_only = !popt->topt.tuples_only;
+ if (!quiet)
+ {
+ if (popt->topt.tuples_only)
+ puts("Showing only tuples.");
+ else
+ puts("Tuples only is off.");
+ }
+ }
+
+ /* set title override */
+ else if (strcmp(param, "title") == 0)
+ {
+ free(popt->title);
+ if (!value)
+ popt->title = NULL;
+ else
+ popt->title = xstrdup(value);
+
+ if (!quiet)
+ {
+ if (popt->title)
+ printf("Title is \"%s\".\n", popt->title);
+ else
+ printf("Title is unset.\n");
+ }
}
- }
-
- /* toggle use of pager */
- else if (strcmp(param, "pager")==0) {
- popt->topt.pager = !popt->topt.pager;
- if (!quiet) {
- if (popt->topt.pager)
- puts("Using pager is on.");
- else
- puts("Using pager is off.");
+
+ /* set HTML table tag options */
+ else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
+ {
+ free(popt->topt.tableAttr);
+ if (!value)
+ popt->topt.tableAttr = NULL;
+ else
+ popt->topt.tableAttr = xstrdup(value);
+
+ if (!quiet)
+ {
+ if (popt->topt.tableAttr)
+ printf("Table attribute is \"%s\".\n", popt->topt.tableAttr);
+ else
+ printf("Table attributes unset.\n");
+ }
}
- }
-
- else {
- fprintf(stderr, "Unknown option: %s\n", param);
- return false;
- }
+ /* toggle use of pager */
+ else if (strcmp(param, "pager") == 0)
+ {
+ popt->topt.pager = !popt->topt.pager;
+ if (!quiet)
+ {
+ if (popt->topt.pager)
+ puts("Using pager is on.");
+ else
+ puts("Using pager is off.");
+ }
+ }
- return true;
+
+ else
+ {
+ fprintf(stderr, "Unknown option: %s\n", param);
+ return false;
+ }
+
+ return true;
}
@@ -1200,29 +1343,31 @@ do_pset(const char * param, const char * value, printQueryOpt * popt, bool quiet
static bool
do_shell(const char *command)
{
- int result;
+ int result;
- if (!command) {
- char *sys;
- char *shellName;
+ if (!command)
+ {
+ char *sys;
+ char *shellName;
+
+ shellName = getenv("SHELL");
+ if (shellName == NULL)
+ shellName = DEFAULT_SHELL;
+
+ sys = malloc(strlen(shellName) + 16);
+ if (!sys)
+ return false;
+ sprintf(sys, "exec %s", shellName);
+ result = system(sys);
+ free(sys);
+ }
+ else
+ result = system(command);
- shellName = getenv("SHELL");
- if (shellName == NULL)
- shellName = DEFAULT_SHELL;
-
- sys = malloc(strlen(shellName) + 16);
- if (!sys)
- return false;
- sprintf(sys, "exec %s", shellName);
- result = system(sys);
- free(sys);
- }
- else
- result = system(command);
-
- if (result==127 || result==-1) {
- perror("system");
- return false;
- }
- return true;
+ if (result == 127 || result == -1)
+ {
+ perror("system");
+ return false;
+ }
+ return true;
}
diff --git a/src/bin/psql/command.h b/src/bin/psql/command.h
index eeaf0859ba..a7850263c3 100644
--- a/src/bin/psql/command.h
+++ b/src/bin/psql/command.h
@@ -11,39 +11,36 @@
-typedef enum _backslashResult {
- CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */
- CMD_SEND, /* query complete; send off */
- CMD_SKIP_LINE, /* keep building query */
- CMD_TERMINATE, /* quit program */
- CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
- CMD_ERROR /* the execution of the backslash command resulted
- in an error */
-} backslashResult;
-
-
-
-backslashResult
-HandleSlashCmds(PsqlSettings *pset,
- const char *line,
- PQExpBuffer query_buf,
- const char ** end_of_cmd);
-
-bool
-do_connect(const char *new_dbname,
- const char *new_user,
- PsqlSettings *pset);
-
-bool
-process_file(const char *filename,
- PsqlSettings *pset);
-
-
-bool
-do_pset(const char * param,
- const char * value,
- printQueryOpt * popt,
- bool quiet);
+typedef enum _backslashResult
+{
+ CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */
+ CMD_SEND, /* query complete; send off */
+ CMD_SKIP_LINE, /* keep building query */
+ CMD_TERMINATE, /* quit program */
+ CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
+ CMD_ERROR /* the execution of the backslash command
+ * resulted in an error */
+} backslashResult;
+
+
+
+backslashResult HandleSlashCmds(PsqlSettings *pset,
+ const char *line,
+ PQExpBuffer query_buf,
+ const char **end_of_cmd);
+
+bool do_connect(const char *new_dbname,
+ const char *new_user,
+ PsqlSettings *pset);
+
+bool process_file(const char *filename,
+ PsqlSettings *pset);
+
+
+bool do_pset(const char *param,
+ const char *value,
+ printQueryOpt * popt,
+ bool quiet);
#endif
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 71df7bd098..82c5d12a13 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -14,7 +14,7 @@
#include <signal.h>
#include <assert.h>
#ifndef WIN32
-#include <unistd.h> /* for write() */
+#include <unistd.h> /* for write() */
#endif
#include <libpq-fe.h>
@@ -39,19 +39,23 @@
* "Safe" wrapper around strdup()
* (Using this also avoids writing #ifdef HAVE_STRDUP in every file :)
*/
-char * xstrdup(const char * string)
+char *
+xstrdup(const char *string)
{
- char * tmp;
- if (!string) {
- fprintf(stderr, "xstrdup: Cannot duplicate null pointer.\n");
- exit(EXIT_FAILURE);
- }
- tmp = strdup(string);
- if (!tmp) {
- perror("strdup");
- exit(EXIT_FAILURE);
- }
- return tmp;
+ char *tmp;
+
+ if (!string)
+ {
+ fprintf(stderr, "xstrdup: Cannot duplicate null pointer.\n");
+ exit(EXIT_FAILURE);
+ }
+ tmp = strdup(string);
+ if (!tmp)
+ {
+ perror("strdup");
+ exit(EXIT_FAILURE);
+ }
+ return tmp;
}
@@ -67,66 +71,67 @@ char * xstrdup(const char * string)
bool
setQFout(const char *fname, PsqlSettings *pset)
{
- bool status = true;
+ bool status = true;
#ifdef USE_ASSERT_CHECKING
- assert(pset);
+ assert(pset);
#else
- if (!pset) return false;
+ if (!pset)
+ return false;
#endif
- /* Close old file/pipe */
- if (pset->queryFout && pset->queryFout != stdout && pset->queryFout != stderr)
- {
- if (pset->queryFoutPipe)
- pclose(pset->queryFout);
- else
- fclose(pset->queryFout);
- }
+ /* Close old file/pipe */
+ if (pset->queryFout && pset->queryFout != stdout && pset->queryFout != stderr)
+ {
+ if (pset->queryFoutPipe)
+ pclose(pset->queryFout);
+ else
+ fclose(pset->queryFout);
+ }
- /* If no filename, set stdout */
- if (!fname || fname[0]=='\0')
- {
- pset->queryFout = stdout;
- pset->queryFoutPipe = false;
- }
- else if (*fname == '|')
- {
- const char * pipename = fname+1;
+ /* If no filename, set stdout */
+ if (!fname || fname[0] == '\0')
+ {
+ pset->queryFout = stdout;
+ pset->queryFoutPipe = false;
+ }
+ else if (*fname == '|')
+ {
+ const char *pipename = fname + 1;
#ifndef __CYGWIN32__
- pset->queryFout = popen(pipename, "w");
+ pset->queryFout = popen(pipename, "w");
#else
- pset->queryFout = popen(pipename, "wb");
+ pset->queryFout = popen(pipename, "wb");
#endif
- pset->queryFoutPipe = true;
- }
- else
- {
+ pset->queryFoutPipe = true;
+ }
+ else
+ {
#ifndef __CYGWIN32__
- pset->queryFout = fopen(fname, "w");
+ pset->queryFout = fopen(fname, "w");
#else
- pset->queryFout = fopen(fname, "wb");
+ pset->queryFout = fopen(fname, "wb");
#endif
- pset->queryFoutPipe = false;
- }
-
- if (!pset->queryFout)
- {
- perror(fname);
- pset->queryFout = stdout;
- pset->queryFoutPipe = false;
- status = false;
- }
-
- /* Direct signals */
- if (pset->queryFoutPipe)
- pqsignal(SIGPIPE, SIG_IGN);
- else
- pqsignal(SIGPIPE, SIG_DFL);
-
- return status;
+ pset->queryFoutPipe = false;
+ }
+
+ if (!pset->queryFout)
+ {
+ perror(fname);
+ pset->queryFout = stdout;
+ pset->queryFoutPipe = false;
+ status = false;
+ }
+
+ /* Direct signals */
+ if (pset->queryFoutPipe)
+ pqsignal(SIGPIPE, SIG_IGN);
+ else
+ pqsignal(SIGPIPE, SIG_DFL);
+
+ return status;
}
@@ -137,60 +142,67 @@ setQFout(const char *fname, PsqlSettings *pset)
* Generalized function especially intended for reading in usernames and
* password interactively. Reads from stdin.
*
- * prompt: The prompt to print
- * maxlen: How many characters to accept
- * echo: Set to false if you want to hide what is entered (for passwords)
+ * prompt: The prompt to print
+ * maxlen: How many characters to accept
+ * echo: Set to false if you want to hide what is entered (for passwords)
*
* Returns a malloc()'ed string with the input (w/o trailing newline).
*/
char *
simple_prompt(const char *prompt, int maxlen, bool echo)
{
- int length;
- char * destination;
+ int length;
+ char *destination;
#ifdef HAVE_TERMIOS_H
- struct termios t_orig, t;
+ struct termios t_orig,
+ t;
+
#endif
- destination = (char *) malloc(maxlen+2);
- if (!destination)
- return NULL;
- if (prompt) fputs(prompt, stdout);
+ destination = (char *) malloc(maxlen + 2);
+ if (!destination)
+ return NULL;
+ if (prompt)
+ fputs(prompt, stdout);
#ifdef HAVE_TERMIOS_H
- if (!echo)
- {
- tcgetattr(0, &t);
- t_orig = t;
- t.c_lflag &= ~ECHO;
- tcsetattr(0, TCSADRAIN, &t);
- }
+ if (!echo)
+ {
+ tcgetattr(0, &t);
+ t_orig = t;
+ t.c_lflag &= ~ECHO;
+ tcsetattr(0, TCSADRAIN, &t);
+ }
#endif
- fgets(destination, maxlen, stdin);
+ fgets(destination, maxlen, stdin);
#ifdef HAVE_TERMIOS_H
- if (!echo) {
- tcsetattr(0, TCSADRAIN, &t_orig);
- puts("");
- }
+ if (!echo)
+ {
+ tcsetattr(0, TCSADRAIN, &t_orig);
+ puts("");
+ }
#endif
- length = strlen(destination);
- if (length > 0 && destination[length - 1] != '\n') {
- /* eat rest of the line */
- char buf[512];
- do {
- fgets(buf, 512, stdin);
- } while (buf[strlen(buf) - 1] != '\n');
- }
+ length = strlen(destination);
+ if (length > 0 && destination[length - 1] != '\n')
+ {
+ /* eat rest of the line */
+ char buf[512];
+
+ do
+ {
+ fgets(buf, 512, stdin);
+ } while (buf[strlen(buf) - 1] != '\n');
+ }
- if (length > 0 && destination[length - 1] == '\n')
- /* remove trailing newline */
- destination[length - 1] = '\0';
+ if (length > 0 && destination[length - 1] == '\n')
+ /* remove trailing newline */
+ destination[length - 1] = '\0';
- return destination;
+ return destination;
}
@@ -205,68 +217,79 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
* immediate consumption.
*/
const char *
-interpolate_var(const char * name, PsqlSettings * pset)
+interpolate_var(const char *name, PsqlSettings *pset)
{
- const char * var;
+ const char *var;
#ifdef USE_ASSERT_CHECKING
- assert(name);
- assert(pset);
+ assert(name);
+ assert(pset);
#else
- if (!name || !pset) return NULL;
+ if (!name || !pset)
+ return NULL;
#endif
- if (strspn(name, VALID_VARIABLE_CHARS) == strlen(name)) {
- var = GetVariable(pset->vars, name);
- if (var)
- return var;
- else
- return "";
- }
-
- /* otherwise return magic variable */
- /* (by convention these should be capitalized (but not all caps), to not be
- shadowed by regular vars or to shadow env vars) */
- if (strcmp(name, "Version")==0)
- return PG_VERSION_STR;
-
- if (strcmp(name, "Database")==0) {
- if (PQdb(pset->db))
- return PQdb(pset->db);
- else
- return "";
- }
+ if (strspn(name, VALID_VARIABLE_CHARS) == strlen(name))
+ {
+ var = GetVariable(pset->vars, name);
+ if (var)
+ return var;
+ else
+ return "";
+ }
- if (strcmp(name, "User")==0) {
- if (PQuser(pset->db))
- return PQuser(pset->db);
- else
- return "";
- }
+ /* otherwise return magic variable */
- if (strcmp(name, "Host")==0) {
- if (PQhost(pset->db))
- return PQhost(pset->db);
- else
- return "";
- }
+ /*
+ * (by convention these should be capitalized (but not all caps), to
+ * not be shadowed by regular vars or to shadow env vars)
+ */
+ if (strcmp(name, "Version") == 0)
+ return PG_VERSION_STR;
- if (strcmp(name, "Port")==0) {
- if (PQport(pset->db))
- return PQport(pset->db);
- else
- return "";
- }
+ if (strcmp(name, "Database") == 0)
+ {
+ if (PQdb(pset->db))
+ return PQdb(pset->db);
+ else
+ return "";
+ }
+
+ if (strcmp(name, "User") == 0)
+ {
+ if (PQuser(pset->db))
+ return PQuser(pset->db);
+ else
+ return "";
+ }
- /* env vars (if env vars are all caps there should be no prob, otherwise
- you're on your own */
+ if (strcmp(name, "Host") == 0)
+ {
+ if (PQhost(pset->db))
+ return PQhost(pset->db);
+ else
+ return "";
+ }
+
+ if (strcmp(name, "Port") == 0)
+ {
+ if (PQport(pset->db))
+ return PQport(pset->db);
+ else
+ return "";
+ }
+
+ /*
+ * env vars (if env vars are all caps there should be no prob,
+ * otherwise you're on your own
+ */
- if ((var = getenv(name)))
- return var;
+ if ((var = getenv(name)))
+ return var;
- return "";
+ return "";
}
-
+
/*
@@ -284,7 +307,7 @@ interpolate_var(const char * name, PsqlSettings * pset)
* at least avoid trusting printf by using the more primitive fputs().
*/
-PGconn * cancelConn;
+PGconn *cancelConn;
#ifdef WIN32
#define safe_write_stderr(String) fputs(s, stderr)
@@ -296,79 +319,84 @@ PGconn * cancelConn;
static void
handle_sigint(SIGNAL_ARGS)
{
- /* accept signal if no connection */
- if (cancelConn == NULL)
- exit(1);
- /* Try to send cancel request */
- if (PQrequestCancel(cancelConn))
- safe_write_stderr("\nCANCEL request sent\n");
- else {
- safe_write_stderr("\nCould not send cancel request: ");
- safe_write_stderr(PQerrorMessage(cancelConn));
- }
+ /* accept signal if no connection */
+ if (cancelConn == NULL)
+ exit(1);
+ /* Try to send cancel request */
+ if (PQrequestCancel(cancelConn))
+ safe_write_stderr("\nCANCEL request sent\n");
+ else
+ {
+ safe_write_stderr("\nCould not send cancel request: ");
+ safe_write_stderr(PQerrorMessage(cancelConn));
+ }
}
-/*
- * PSQLexec
+/*
+ * PSQLexec
*
* This is the way to send "backdoor" queries (those not directly entered
* by the user). It is subject to -E (echo_secret) but not -e (echo).
*/
-PGresult *
+PGresult *
PSQLexec(PsqlSettings *pset, const char *query)
{
- PGresult *res;
- const char * var;
-
- if (!pset->db) {
- fputs("You are not currently connected to a database.\n", stderr);
- return NULL;
- }
-
- var = GetVariable(pset->vars, "echo_secret");
- if (var) {
- printf("********* QUERY *********\n%s\n*************************\n\n", query);
- fflush(stdout);
- }
-
- if (var && strcmp(var, "noexec")==0)
- return NULL;
-
- cancelConn = pset->db;
- pqsignal(SIGINT, handle_sigint); /* control-C => cancel */
-
- res = PQexec(pset->db, query);
-
- pqsignal(SIGINT, SIG_DFL); /* no control-C is back to normal */
-
- if (PQstatus(pset->db) == CONNECTION_BAD)
- {
- fputs("The connection to the server was lost. Attempting reset: ", stderr);
- PQreset(pset->db);
- if (PQstatus(pset->db) == CONNECTION_BAD) {
- fputs("Failed.\n", stderr);
- PQfinish(pset->db);
- PQclear(res);
- pset->db = NULL;
- return NULL;
+ PGresult *res;
+ const char *var;
+
+ if (!pset->db)
+ {
+ fputs("You are not currently connected to a database.\n", stderr);
+ return NULL;
+ }
+
+ var = GetVariable(pset->vars, "echo_secret");
+ if (var)
+ {
+ printf("********* QUERY *********\n%s\n*************************\n\n", query);
+ fflush(stdout);
+ }
+
+ if (var && strcmp(var, "noexec") == 0)
+ return NULL;
+
+ cancelConn = pset->db;
+ pqsignal(SIGINT, handle_sigint); /* control-C => cancel */
+
+ res = PQexec(pset->db, query);
+
+ pqsignal(SIGINT, SIG_DFL); /* no control-C is back to normal */
+
+ if (PQstatus(pset->db) == CONNECTION_BAD)
+ {
+ fputs("The connection to the server was lost. Attempting reset: ", stderr);
+ PQreset(pset->db);
+ if (PQstatus(pset->db) == CONNECTION_BAD)
+ {
+ fputs("Failed.\n", stderr);
+ PQfinish(pset->db);
+ PQclear(res);
+ pset->db = NULL;
+ return NULL;
+ }
+ else
+ fputs("Succeeded.\n", stderr);
}
+
+ if (res && (PQresultStatus(res) == PGRES_COMMAND_OK ||
+ PQresultStatus(res) == PGRES_TUPLES_OK ||
+ PQresultStatus(res) == PGRES_COPY_IN ||
+ PQresultStatus(res) == PGRES_COPY_OUT)
+ )
+ return res;
else
- fputs("Succeeded.\n", stderr);
- }
-
- if (res && (PQresultStatus(res) == PGRES_COMMAND_OK ||
- PQresultStatus(res) == PGRES_TUPLES_OK ||
- PQresultStatus(res) == PGRES_COPY_IN ||
- PQresultStatus(res) == PGRES_COPY_OUT)
- )
- return res;
- else {
- fprintf(stderr, "%s", PQerrorMessage(pset->db));
- PQclear(res);
- return NULL;
- }
+ {
+ fprintf(stderr, "%s", PQerrorMessage(pset->db));
+ PQclear(res);
+ return NULL;
+ }
}
@@ -388,131 +416,136 @@ PSQLexec(PsqlSettings *pset, const char *query)
bool
SendQuery(PsqlSettings *pset, const char *query)
{
- bool success = false;
- PGresult *results;
- PGnotify *notify;
-
- if (!pset->db) {
- fputs("You are not currently connected to a database.\n", stderr);
- return false;
- }
-
- if (GetVariableBool(pset->vars, "singlestep")) {
- char buf[3];
- fprintf(stdout, "***(Single step mode: Verify query)*********************************************\n"
- "QUERY: %s\n"
- "***(press return to proceed or enter x and return to cancel)********************\n",
- query);
- fflush(stdout);
- fgets(buf, 3, stdin);
- if (buf[0]=='x')
- return false;
- fflush(stdin);
- }
-
- cancelConn = pset->db;
- pqsignal(SIGINT, handle_sigint);
-
- results = PQexec(pset->db, query);
-
- pqsignal(SIGINT, SIG_DFL);
-
- if (results == NULL)
- {
- fputs(PQerrorMessage(pset->db), pset->queryFout);
- success = false;
- }
- else
- {
- switch (PQresultStatus(results))
- {
- case PGRES_TUPLES_OK:
- if (pset->gfname)
- {
- PsqlSettings settings_copy = *pset;
-
- settings_copy.queryFout = stdout;
- if (!setQFout(pset->gfname, &settings_copy)) {
- success = false;
- break;
- }
+ bool success = false;
+ PGresult *results;
+ PGnotify *notify;
- printQuery(results, &settings_copy.popt, settings_copy.queryFout);
-
- /* close file/pipe */
- setQFout(NULL, &settings_copy);
-
- free(pset->gfname);
- pset->gfname = NULL;
-
- success = true;
- break;
- }
- else
- {
- success = true;
- printQuery(results, &pset->popt, pset->queryFout);
- fflush(pset->queryFout);
- }
- break;
- case PGRES_EMPTY_QUERY:
- success = true;
- break;
- case PGRES_COMMAND_OK:
- success = true;
- fprintf(pset->queryFout, "%s\n", PQcmdStatus(results));
- break;
-
- case PGRES_COPY_OUT:
- if (pset->cur_cmd_interactive && !GetVariable(pset->vars, "quiet"))
- puts("Copy command returns:");
-
- success = handleCopyOut(pset->db, pset->queryFout);
- break;
-
- case PGRES_COPY_IN:
- if (pset->cur_cmd_interactive && !GetVariable(pset->vars, "quiet"))
- puts("Enter data to be copied followed by a newline.\n"
- "End with a backslash and a period on a line by itself.");
-
- success = handleCopyIn(pset->db, pset->cur_cmd_source,
- pset->cur_cmd_interactive ? get_prompt(pset, PROMPT_COPY) : NULL);
- break;
-
- case PGRES_NONFATAL_ERROR:
- case PGRES_FATAL_ERROR:
- case PGRES_BAD_RESPONSE:
- success = false;
- fputs(PQerrorMessage(pset->db), pset->queryFout);
- break;
+ if (!pset->db)
+ {
+ fputs("You are not currently connected to a database.\n", stderr);
+ return false;
}
- if (PQstatus(pset->db) == CONNECTION_BAD)
+ if (GetVariableBool(pset->vars, "singlestep"))
{
- fputs("The connection to the server was lost. Attempting reset: ", stderr);
- PQreset(pset->db);
- if (PQstatus(pset->db) == CONNECTION_BAD) {
- fputs("Failed.\n", stderr);
- PQfinish(pset->db);
- PQclear(results);
- pset->db = NULL;
- return false;
- }
- else
- fputs("Succeeded.\n", stderr);
+ char buf[3];
+
+ fprintf(stdout, "***(Single step mode: Verify query)*********************************************\n"
+ "QUERY: %s\n"
+ "***(press return to proceed or enter x and return to cancel)********************\n",
+ query);
+ fflush(stdout);
+ fgets(buf, 3, stdin);
+ if (buf[0] == 'x')
+ return false;
+ fflush(stdin);
}
- /* check for asynchronous notification returns */
- while ((notify = PQnotifies(pset->db)) != NULL)
+ cancelConn = pset->db;
+ pqsignal(SIGINT, handle_sigint);
+
+ results = PQexec(pset->db, query);
+
+ pqsignal(SIGINT, SIG_DFL);
+
+ if (results == NULL)
{
- fprintf(pset->queryFout, "Asynchronous NOTIFY '%s' from backend with pid '%d' received.\n",
- notify->relname, notify->be_pid);
- free(notify);
+ fputs(PQerrorMessage(pset->db), pset->queryFout);
+ success = false;
}
+ else
+ {
+ switch (PQresultStatus(results))
+ {
+ case PGRES_TUPLES_OK:
+ if (pset->gfname)
+ {
+ PsqlSettings settings_copy = *pset;
+
+ settings_copy.queryFout = stdout;
+ if (!setQFout(pset->gfname, &settings_copy))
+ {
+ success = false;
+ break;
+ }
+
+ printQuery(results, &settings_copy.popt, settings_copy.queryFout);
+
+ /* close file/pipe */
+ setQFout(NULL, &settings_copy);
+
+ free(pset->gfname);
+ pset->gfname = NULL;
+
+ success = true;
+ break;
+ }
+ else
+ {
+ success = true;
+ printQuery(results, &pset->popt, pset->queryFout);
+ fflush(pset->queryFout);
+ }
+ break;
+ case PGRES_EMPTY_QUERY:
+ success = true;
+ break;
+ case PGRES_COMMAND_OK:
+ success = true;
+ fprintf(pset->queryFout, "%s\n", PQcmdStatus(results));
+ break;
+
+ case PGRES_COPY_OUT:
+ if (pset->cur_cmd_interactive && !GetVariable(pset->vars, "quiet"))
+ puts("Copy command returns:");
+
+ success = handleCopyOut(pset->db, pset->queryFout);
+ break;
+
+ case PGRES_COPY_IN:
+ if (pset->cur_cmd_interactive && !GetVariable(pset->vars, "quiet"))
+ puts("Enter data to be copied followed by a newline.\n"
+ "End with a backslash and a period on a line by itself.");
+
+ success = handleCopyIn(pset->db, pset->cur_cmd_source,
+ pset->cur_cmd_interactive ? get_prompt(pset, PROMPT_COPY) : NULL);
+ break;
+
+ case PGRES_NONFATAL_ERROR:
+ case PGRES_FATAL_ERROR:
+ case PGRES_BAD_RESPONSE:
+ success = false;
+ fputs(PQerrorMessage(pset->db), pset->queryFout);
+ break;
+ }
- if (results)
- PQclear(results);
- }
+ if (PQstatus(pset->db) == CONNECTION_BAD)
+ {
+ fputs("The connection to the server was lost. Attempting reset: ", stderr);
+ PQreset(pset->db);
+ if (PQstatus(pset->db) == CONNECTION_BAD)
+ {
+ fputs("Failed.\n", stderr);
+ PQfinish(pset->db);
+ PQclear(results);
+ pset->db = NULL;
+ return false;
+ }
+ else
+ fputs("Succeeded.\n", stderr);
+ }
+
+ /* check for asynchronous notification returns */
+ while ((notify = PQnotifies(pset->db)) != NULL)
+ {
+ fprintf(pset->queryFout, "Asynchronous NOTIFY '%s' from backend with pid '%d' received.\n",
+ notify->relname, notify->be_pid);
+ free(notify);
+ }
+
+ if (results)
+ PQclear(results);
+ }
- return success;
+ return success;
}
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h
index 25bda2c0f8..e3924e9d92 100644
--- a/src/bin/psql/common.h
+++ b/src/bin/psql/common.h
@@ -5,21 +5,21 @@
#include "settings.h"
char *
-xstrdup(const char * string);
+ xstrdup(const char *string);
bool
-setQFout(const char *fname, PsqlSettings *pset);
+ setQFout(const char *fname, PsqlSettings *pset);
char *
-simple_prompt(const char *prompt, int maxlen, bool echo);
+ simple_prompt(const char *prompt, int maxlen, bool echo);
const char *
-interpolate_var(const char * name, PsqlSettings * pset);
+ interpolate_var(const char *name, PsqlSettings *pset);
-PGresult *
-PSQLexec(PsqlSettings *pset, const char *query);
+PGresult *
+ PSQLexec(PsqlSettings *pset, const char *query);
bool
-SendQuery(PsqlSettings *pset, const char *query);
+ SendQuery(PsqlSettings *pset, const char *query);
-#endif /* COMMON_H */
+#endif /* COMMON_H */
diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c
index d8d11e3267..1d2a24c39f 100644
--- a/src/bin/psql/copy.c
+++ b/src/bin/psql/copy.c
@@ -8,9 +8,9 @@
#include <errno.h>
#include <assert.h>
#ifndef WIN32
-#include <unistd.h> /* for isatty */
+#include <unistd.h> /* for isatty */
#else
-#include <io.h> /* I think */
+#include <io.h> /* I think */
#endif
#include <libpq-fe.h>
@@ -33,137 +33,151 @@
* returns a malloc'ed structure with the options, or NULL on parsing error
*/
-struct copy_options {
- char * table;
- char * file;
- bool from;
- bool binary;
- bool oids;
- char * delim;
+struct copy_options
+{
+ char *table;
+ char *file;
+ bool from;
+ bool binary;
+ bool oids;
+ char *delim;
};
static void
free_copy_options(struct copy_options * ptr)
{
- if (!ptr)
- return;
- free(ptr->table);
- free(ptr->file);
- free(ptr->delim);
- free(ptr);
+ if (!ptr)
+ return;
+ free(ptr->table);
+ free(ptr->file);
+ free(ptr->delim);
+ free(ptr);
}
static struct copy_options *
parse_slash_copy(const char *args)
{
- struct copy_options * result;
- char * line;
- char * token;
- bool error = false;
- char quote;
-
- line = xstrdup(args);
-
- if (!(result = calloc(1, sizeof (struct copy_options)))) {
- perror("calloc");
- exit(EXIT_FAILURE);
- }
-
- token = strtokx(line, " \t", "\"", '\\', &quote, NULL);
- if (!token)
- error = true;
- else {
- if (!quote && strcasecmp(token, "binary")==0) {
- result->binary = true;
- token = strtokx(NULL, " \t", "\"", '\\', &quote, NULL);
- if (!token)
+ struct copy_options *result;
+ char *line;
+ char *token;
+ bool error = false;
+ char quote;
+
+ line = xstrdup(args);
+
+ if (!(result = calloc(1, sizeof(struct copy_options))))
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+
+ token = strtokx(line, " \t", "\"", '\\', &quote, NULL);
+ if (!token)
error = true;
+ else
+ {
+ if (!quote && strcasecmp(token, "binary") == 0)
+ {
+ result->binary = true;
+ token = strtokx(NULL, " \t", "\"", '\\', &quote, NULL);
+ if (!token)
+ error = true;
+ }
+ if (token)
+ result->table = xstrdup(token);
}
- if (token)
- result->table = xstrdup(token);
- }
#ifdef USE_ASSERT_CHECKING
- assert(error || result->table);
+ assert(error || result->table);
#endif
- if (!error) {
- token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
- if (!token)
- error = true;
- else {
- if (strcasecmp(token, "with")==0) {
+ if (!error)
+ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
- if (!token || strcasecmp(token, "oids")!=0)
- error = true;
- else
- result->oids = true;
-
- if (!error) {
- token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
- if (!token)
+ if (!token)
error = true;
+ else
+ {
+ if (strcasecmp(token, "with") == 0)
+ {
+ token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
+ if (!token || strcasecmp(token, "oids") != 0)
+ error = true;
+ else
+ result->oids = true;
+
+ if (!error)
+ {
+ token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
+ if (!token)
+ error = true;
+ }
+ }
+
+ if (!error && strcasecmp(token, "from") == 0)
+ result->from = true;
+ else if (!error && strcasecmp(token, "to") == 0)
+ result->from = false;
+ else
+ error = true;
}
- }
-
- if (!error && strcasecmp(token, "from")==0)
- result->from = true;
- else if (!error && strcasecmp(token, "to")==0)
- result->from = false;
- else
- error = true;
}
- }
- if (!error) {
- token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
- if (!token)
- error = true;
- else
- result->file=xstrdup(token);
- }
+ if (!error)
+ {
+ token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
+ if (!token)
+ error = true;
+ else
+ result->file = xstrdup(token);
+ }
#ifdef USE_ASSERT_CHECKING
- assert(error || result->file);
+ assert(error || result->file);
#endif
- if (!error) {
- token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
- if (token) {
- if (strcasecmp(token, "using")!=0)
- error = true;
- else {
+ if (!error)
+ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
- if (!token || strcasecmp(token, "delimiters")!=0)
- error = true;
- else {
- token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
- if (token)
- result->delim = xstrdup(token);
- else
- error = true;
+ if (token)
+ {
+ if (strcasecmp(token, "using") != 0)
+ error = true;
+ else
+ {
+ token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL);
+ if (!token || strcasecmp(token, "delimiters") != 0)
+ error = true;
+ else
+ {
+ token = strtokx(NULL, " \t", "'", '\\', NULL, NULL);
+ if (token)
+ result->delim = xstrdup(token);
+ else
+ error = true;
+ }
+ }
}
- }
}
- }
- free(line);
+ free(line);
- if (error) {
- fputs("Parse error at ", stderr);
- if (!token)
- fputs("end of line.", stderr);
+ if (error)
+ {
+ fputs("Parse error at ", stderr);
+ if (!token)
+ fputs("end of line.", stderr);
+ else
+ fprintf(stderr, "'%s'.", token);
+ fputs("\n", stderr);
+ free(result);
+ return NULL;
+ }
else
- fprintf(stderr, "'%s'.", token);
- fputs("\n", stderr);
- free(result);
- return NULL;
- }
- else
- return result;
-}
+ return result;
+}
@@ -171,103 +185,109 @@ parse_slash_copy(const char *args)
* Execute a \copy command (frontend copy). We have to open a file, then
* submit a COPY query to the backend and either feed it data from the
* file or route its response into the file.
- */
+ */
bool
-do_copy(const char * args, PsqlSettings *pset)
+do_copy(const char *args, PsqlSettings *pset)
{
- char query[128 + NAMEDATALEN];
- FILE *copystream;
- struct copy_options *options;
- PGresult *result;
- bool success;
+ char query[128 + NAMEDATALEN];
+ FILE *copystream;
+ struct copy_options *options;
+ PGresult *result;
+ bool success;
- /* parse options */
- options = parse_slash_copy(args);
+ /* parse options */
+ options = parse_slash_copy(args);
- if (!options)
- return false;
+ if (!options)
+ return false;
- strcpy(query, "COPY ");
- if (options->binary)
- fputs("Warning: \\copy binary is not implemented. Resorting to text output.\n", stderr);
+ strcpy(query, "COPY ");
+ if (options->binary)
+ fputs("Warning: \\copy binary is not implemented. Resorting to text output.\n", stderr);
/* strcat(query, "BINARY "); */
- strcat(query, "\"");
- strncat(query, options->table, NAMEDATALEN);
- strcat(query, "\" ");
- if (options->oids)
- strcat(query, "WITH OIDS ");
+ strcat(query, "\"");
+ strncat(query, options->table, NAMEDATALEN);
+ strcat(query, "\" ");
+ if (options->oids)
+ strcat(query, "WITH OIDS ");
- if (options->from)
- strcat(query, "FROM stdin");
- else
- strcat(query, "TO stdout");
+ if (options->from)
+ strcat(query, "FROM stdin");
+ else
+ strcat(query, "TO stdout");
- if (options->delim) {
- /* backend copy only uses the first character here,
- but that might be the escape backslash
- (makes me wonder though why it's called delimiterS) */
- strncat(query, " USING DELIMITERS '", 2);
- strcat(query, options->delim);
- strcat(query, "'");
- }
+ if (options->delim)
+ {
+
+ /*
+ * backend copy only uses the first character here, but that might
+ * be the escape backslash (makes me wonder though why it's called
+ * delimiterS)
+ */
+ strncat(query, " USING DELIMITERS '", 2);
+ strcat(query, options->delim);
+ strcat(query, "'");
+ }
- if (options->from)
+ if (options->from)
#ifndef __CYGWIN32__
- copystream = fopen(options->file, "r");
+ copystream = fopen(options->file, "r");
#else
- copystream = fopen(options->file, "rb");
+ copystream = fopen(options->file, "rb");
#endif
- else
+ else
#ifndef __CYGWIN32__
- copystream = fopen(options->file, "w");
+ copystream = fopen(options->file, "w");
#else
- copystream = fopen(options->file, "wb");
+ copystream = fopen(options->file, "wb");
#endif
- if (!copystream) {
- fprintf(stderr,
- "Unable to open file %s which to copy: %s\n",
- options->from ? "from" : "to", strerror(errno));
- free_copy_options(options);
- return false;
- }
-
- result = PSQLexec(pset, query);
-
- switch (PQresultStatus(result))
- {
- case PGRES_COPY_OUT:
- success = handleCopyOut(pset->db, copystream);
- break;
- case PGRES_COPY_IN:
- success = handleCopyIn(pset->db, copystream, NULL);
- break;
- case PGRES_NONFATAL_ERROR:
- case PGRES_FATAL_ERROR:
- case PGRES_BAD_RESPONSE:
- success = false;
- fputs(PQerrorMessage(pset->db), stderr);
- break;
- default:
- success = false;
- fprintf(stderr, "Unexpected response (%d)\n", PQresultStatus(result));
- }
-
- PQclear(result);
-
- if (!GetVariable(pset->vars, "quiet")) {
- if (success)
- puts("Successfully copied.");
- else
- puts("Copy failed.");
- }
+ if (!copystream)
+ {
+ fprintf(stderr,
+ "Unable to open file %s which to copy: %s\n",
+ options->from ? "from" : "to", strerror(errno));
+ free_copy_options(options);
+ return false;
+ }
+
+ result = PSQLexec(pset, query);
+
+ switch (PQresultStatus(result))
+ {
+ case PGRES_COPY_OUT:
+ success = handleCopyOut(pset->db, copystream);
+ break;
+ case PGRES_COPY_IN:
+ success = handleCopyIn(pset->db, copystream, NULL);
+ break;
+ case PGRES_NONFATAL_ERROR:
+ case PGRES_FATAL_ERROR:
+ case PGRES_BAD_RESPONSE:
+ success = false;
+ fputs(PQerrorMessage(pset->db), stderr);
+ break;
+ default:
+ success = false;
+ fprintf(stderr, "Unexpected response (%d)\n", PQresultStatus(result));
+ }
+
+ PQclear(result);
- fclose(copystream);
- free_copy_options(options);
- return success;
+ if (!GetVariable(pset->vars, "quiet"))
+ {
+ if (success)
+ puts("Successfully copied.");
+ else
+ puts("Copy failed.");
+ }
+
+ fclose(copystream);
+ free_copy_options(options);
+ return success;
}
@@ -287,38 +307,38 @@ do_copy(const char * args, PsqlSettings *pset)
bool
handleCopyOut(PGconn *conn, FILE *copystream)
{
- bool copydone = false; /* haven't started yet */
- char copybuf[COPYBUFSIZ];
- int ret;
-
- while (!copydone)
- {
- ret = PQgetline(conn, copybuf, COPYBUFSIZ);
+ bool copydone = false; /* haven't started yet */
+ char copybuf[COPYBUFSIZ];
+ int ret;
- if (copybuf[0] == '\\' &&
- copybuf[1] == '.' &&
- copybuf[2] == '\0')
+ while (!copydone)
{
- copydone = true; /* we're at the end */
- }
- else
- {
- fputs(copybuf, copystream);
- switch (ret)
- {
- case EOF:
- copydone = true;
- /* FALLTHROUGH */
- case 0:
- fputc('\n', copystream);
- break;
- case 1:
- break;
- }
+ ret = PQgetline(conn, copybuf, COPYBUFSIZ);
+
+ if (copybuf[0] == '\\' &&
+ copybuf[1] == '.' &&
+ copybuf[2] == '\0')
+ {
+ copydone = true; /* we're at the end */
+ }
+ else
+ {
+ fputs(copybuf, copystream);
+ switch (ret)
+ {
+ case EOF:
+ copydone = true;
+ /* FALLTHROUGH */
+ case 0:
+ fputc('\n', copystream);
+ break;
+ case 1:
+ break;
+ }
+ }
}
- }
- fflush(copystream);
- return !PQendcopy(conn);
+ fflush(copystream);
+ return !PQendcopy(conn);
}
@@ -333,58 +353,58 @@ handleCopyOut(PGconn *conn, FILE *copystream)
* (and which gave you PGRES_COPY_IN back);
* copystream is the file stream you want the input to come from
* prompt is something to display to request user input (only makes sense
- * if stdin is an interactive tty)
+ * if stdin is an interactive tty)
*/
bool
-handleCopyIn(PGconn *conn, FILE *copystream, const char * prompt)
+handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
{
- bool copydone = false;
- bool firstload;
- bool linedone;
- char copybuf[COPYBUFSIZ];
- char *s;
- int buflen;
- int c = 0;
-
- while (!copydone)
- { /* for each input line ... */
- if (prompt && isatty(fileno(stdin)))
- {
- fputs(prompt, stdout);
- fflush(stdout);
- }
- firstload = true;
- linedone = false;
- while (!linedone)
- { /* for each buffer ... */
- s = copybuf;
- for (buflen = COPYBUFSIZ; buflen > 1; buflen--)
- {
- c = getc(copystream);
- if (c == '\n' || c == EOF)
+ bool copydone = false;
+ bool firstload;
+ bool linedone;
+ char copybuf[COPYBUFSIZ];
+ char *s;
+ int buflen;
+ int c = 0;
+
+ while (!copydone)
+ { /* for each input line ... */
+ if (prompt && isatty(fileno(stdin)))
{
- linedone = true;
- break;
+ fputs(prompt, stdout);
+ fflush(stdout);
+ }
+ firstload = true;
+ linedone = false;
+ while (!linedone)
+ { /* for each buffer ... */
+ s = copybuf;
+ for (buflen = COPYBUFSIZ; buflen > 1; buflen--)
+ {
+ c = getc(copystream);
+ if (c == '\n' || c == EOF)
+ {
+ linedone = true;
+ break;
+ }
+ *s++ = c;
+ }
+ *s = '\0';
+ if (c == EOF)
+ {
+ PQputline(conn, "\\.");
+ copydone = true;
+ break;
+ }
+ PQputline(conn, copybuf);
+ if (firstload)
+ {
+ if (!strcmp(copybuf, "\\."))
+ copydone = true;
+ firstload = false;
+ }
}
- *s++ = c;
- }
- *s = '\0';
- if (c == EOF)
- {
- PQputline(conn, "\\.");
- copydone = true;
- break;
- }
- PQputline(conn, copybuf);
- if (firstload)
- {
- if (!strcmp(copybuf, "\\."))
- copydone = true;
- firstload = false;
- }
+ PQputline(conn, "\n");
}
- PQputline(conn, "\n");
- }
- return !PQendcopy(conn);
+ return !PQendcopy(conn);
}
diff --git a/src/bin/psql/copy.h b/src/bin/psql/copy.h
index 50fe0afcf5..6e01c5457d 100644
--- a/src/bin/psql/copy.h
+++ b/src/bin/psql/copy.h
@@ -8,15 +8,15 @@
/* handler for \copy */
bool
-do_copy(const char *args, PsqlSettings *pset);
+ do_copy(const char *args, PsqlSettings *pset);
/* lower level processors for copy in/out streams */
bool
-handleCopyOut(PGconn *conn, FILE *copystream);
+ handleCopyOut(PGconn *conn, FILE *copystream);
bool
-handleCopyIn(PGconn *conn, FILE *copystream, const char * prompt);
+ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt);
#endif
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 6304bc14ee..58534e2575 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -4,7 +4,7 @@
#include <string.h>
-#include <postgres.h> /* for VARHDRSZ, int4 type */
+#include <postgres.h> /* for VARHDRSZ, int4 type */
#include <postgres_ext.h>
#include <libpq-fe.h>
@@ -20,7 +20,7 @@
*
* If you add something here, consider this:
* - If (and only if) the variable "description" is set, the description/
- * comment for the object should be displayed.
+ * comment for the object should be displayed.
* - Try to format the query to look nice in -E output.
*----------------
*/
@@ -34,61 +34,66 @@
* takes an optional regexp to match specific aggregates by name
*/
bool
-describeAggregates(const char * name, PsqlSettings * pset)
+describeAggregates(const char *name, PsqlSettings *pset)
{
- char descbuf[384 + 2*REGEXP_CUTOFF]; /* observe/adjust this if you change the query */
- PGresult * res;
- bool description = GetVariableBool(pset->vars, "description");
- printQueryOpt myopt = pset->popt;
-
- descbuf[0] = '\0';
-
- /* There are two kinds of aggregates: ones that work on particular types
- ones that work on all */
- strcat(descbuf,
- "SELECT a.aggname AS \"Name\", t.typname AS \"Type\"");
- if (description)
- strcat(descbuf,
- ",\n obj_description(a.oid) as \"Description\"");
- strcat(descbuf,
- "\nFROM pg_aggregate a, pg_type t\n"
- "WHERE a.aggbasetype = t.oid\n");
- if (name) {
- strcat(descbuf, " AND a.aggname ~* '^");
- strncat(descbuf, name, REGEXP_CUTOFF);
- strcat(descbuf, "'\n");
- }
-
- strcat(descbuf,
- "UNION\n"
- "SELECT a.aggname AS \"Name\", '(all types)' as \"Type\"");
- if (description)
- strcat(descbuf,
- ",\n obj_description(a.oid) as \"Description\"");
- strcat(descbuf,
- "\nFROM pg_aggregate a\n"
- "WHERE a.aggbasetype = 0\n");
- if (name)
- {
- strcat(descbuf, " AND a.aggname ~* '^");
- strncat(descbuf, name, REGEXP_CUTOFF);
- strcat(descbuf, "'\n");
- }
-
- strcat(descbuf, "ORDER BY \"Name\", \"Type\"");
-
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
-
- myopt.topt.tuples_only = false;
- myopt.nullPrint = NULL;
- myopt.title = "List of aggregates";
-
- printQuery(res, &myopt, pset->queryFout);
-
- PQclear(res);
- return true;
+ char descbuf[384 + 2 * REGEXP_CUTOFF]; /* observe/adjust this
+ * if you change the
+ * query */
+ PGresult *res;
+ bool description = GetVariableBool(pset->vars, "description");
+ printQueryOpt myopt = pset->popt;
+
+ descbuf[0] = '\0';
+
+ /*
+ * There are two kinds of aggregates: ones that work on particular
+ * types ones that work on all
+ */
+ strcat(descbuf,
+ "SELECT a.aggname AS \"Name\", t.typname AS \"Type\"");
+ if (description)
+ strcat(descbuf,
+ ",\n obj_description(a.oid) as \"Description\"");
+ strcat(descbuf,
+ "\nFROM pg_aggregate a, pg_type t\n"
+ "WHERE a.aggbasetype = t.oid\n");
+ if (name)
+ {
+ strcat(descbuf, " AND a.aggname ~* '^");
+ strncat(descbuf, name, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+
+ strcat(descbuf,
+ "UNION\n"
+ "SELECT a.aggname AS \"Name\", '(all types)' as \"Type\"");
+ if (description)
+ strcat(descbuf,
+ ",\n obj_description(a.oid) as \"Description\"");
+ strcat(descbuf,
+ "\nFROM pg_aggregate a\n"
+ "WHERE a.aggbasetype = 0\n");
+ if (name)
+ {
+ strcat(descbuf, " AND a.aggname ~* '^");
+ strncat(descbuf, name, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+
+ strcat(descbuf, "ORDER BY \"Name\", \"Type\"");
+
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
+
+ myopt.topt.tuples_only = false;
+ myopt.nullPrint = NULL;
+ myopt.title = "List of aggregates";
+
+ printQuery(res, &myopt, pset->queryFout);
+
+ PQclear(res);
+ return true;
}
@@ -96,45 +101,44 @@ describeAggregates(const char * name, PsqlSettings * pset)
* takes an optional regexp to narrow down the function name
*/
bool
-describeFunctions(const char * name, PsqlSettings * pset)
+describeFunctions(const char *name, PsqlSettings *pset)
{
- char descbuf[384 + REGEXP_CUTOFF];
- PGresult * res;
- printQueryOpt myopt = pset->popt;
-
- /*
- * we skip in/out funcs by excluding functions that take
- * some arguments, but have no types defined for those
- * arguments
- */
- descbuf[0] = '\0';
-
- strcat(descbuf, "SELECT t.typname as \"Result\", p.proname as \"Function\",\n"
- " oid8types(p.proargtypes) as \"Arguments\"");
- if (GetVariableBool(pset->vars, "description"))
- strcat(descbuf, "\n, obj_description(p.oid) as \"Description\"");
- strcat(descbuf, "\nFROM pg_proc p, pg_type t\n"
- "WHERE p.prorettype = t.oid and (pronargs = 0 or oid8types(p.proargtypes) != '')\n");
- if (name)
- {
- strcat(descbuf, " AND p.proname ~* '^");
- strncat(descbuf, name, REGEXP_CUTOFF);
- strcat(descbuf, "'\n");
- }
- strcat(descbuf, "ORDER BY \"Function\", \"Result\", \"Arguments\"");
-
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
-
- myopt.topt.tuples_only = false;
- myopt.nullPrint = NULL;
- myopt.title = "List of functions";
-
- printQuery(res, &myopt, pset->queryFout);
-
- PQclear(res);
- return true;
+ char descbuf[384 + REGEXP_CUTOFF];
+ PGresult *res;
+ printQueryOpt myopt = pset->popt;
+
+ /*
+ * we skip in/out funcs by excluding functions that take some
+ * arguments, but have no types defined for those arguments
+ */
+ descbuf[0] = '\0';
+
+ strcat(descbuf, "SELECT t.typname as \"Result\", p.proname as \"Function\",\n"
+ " oid8types(p.proargtypes) as \"Arguments\"");
+ if (GetVariableBool(pset->vars, "description"))
+ strcat(descbuf, "\n, obj_description(p.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_proc p, pg_type t\n"
+ "WHERE p.prorettype = t.oid and (pronargs = 0 or oid8types(p.proargtypes) != '')\n");
+ if (name)
+ {
+ strcat(descbuf, " AND p.proname ~* '^");
+ strncat(descbuf, name, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+ strcat(descbuf, "ORDER BY \"Function\", \"Result\", \"Arguments\"");
+
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
+
+ myopt.topt.tuples_only = false;
+ myopt.nullPrint = NULL;
+ myopt.title = "List of functions";
+
+ printQuery(res, &myopt, pset->queryFout);
+
+ PQclear(res);
+ return true;
}
@@ -145,38 +149,39 @@ describeFunctions(const char * name, PsqlSettings * pset)
* for \dT
*/
bool
-describeTypes(const char * name, PsqlSettings * pset)
+describeTypes(const char *name, PsqlSettings *pset)
{
- char descbuf[256 + REGEXP_CUTOFF];
- PGresult * res;
- printQueryOpt myopt = pset->popt;
-
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT typname AS \"Type\"");
- if (GetVariableBool(pset->vars, "description"))
- strcat(descbuf, ", obj_description(p.oid) as \"Description\"");
- strcat(descbuf, "\nFROM pg_type\n"
- "WHERE typrelid = 0 AND typname !~ '^_.*'\n");
-
- if (name) {
- strcat(descbuf, " AND typname ~* '^");
- strncat(descbuf, name, REGEXP_CUTOFF);
- strcat(descbuf, "' ");
- }
- strcat(descbuf, "ORDER BY typname;");
-
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
-
- myopt.topt.tuples_only = false;
- myopt.nullPrint = NULL;
- myopt.title = "List of types";
-
- printQuery(res, &myopt, pset->queryFout);
-
- PQclear(res);
- return true;
+ char descbuf[256 + REGEXP_CUTOFF];
+ PGresult *res;
+ printQueryOpt myopt = pset->popt;
+
+ descbuf[0] = '\0';
+ strcat(descbuf, "SELECT typname AS \"Type\"");
+ if (GetVariableBool(pset->vars, "description"))
+ strcat(descbuf, ", obj_description(p.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_type\n"
+ "WHERE typrelid = 0 AND typname !~ '^_.*'\n");
+
+ if (name)
+ {
+ strcat(descbuf, " AND typname ~* '^");
+ strncat(descbuf, name, REGEXP_CUTOFF);
+ strcat(descbuf, "' ");
+ }
+ strcat(descbuf, "ORDER BY typname;");
+
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
+
+ myopt.topt.tuples_only = false;
+ myopt.nullPrint = NULL;
+ myopt.title = "List of types";
+
+ printQuery(res, &myopt, pset->queryFout);
+
+ PQclear(res);
+ return true;
}
@@ -187,87 +192,88 @@ describeTypes(const char * name, PsqlSettings * pset)
* exact match string.
*/
bool
-describeOperators(const char * name, PsqlSettings * pset)
+describeOperators(const char *name, PsqlSettings *pset)
{
- char descbuf[1536 + 3 * 32]; /* 32 is max length for operator name */
- PGresult * res;
- bool description = GetVariableBool(pset->vars, "description");
- printQueryOpt myopt = pset->popt;
-
- descbuf[0] = '\0';
-
- strcat(descbuf, "SELECT o.oprname AS \"Op\",\n"
- " t1.typname AS \"Left arg\",\n"
- " t2.typname AS \"Right arg\",\n"
- " t0.typname AS \"Result\"");
- if (description)
- strcat(descbuf, ",\n obj_description(p.oid) as \"Description\"");
- strcat(descbuf, "\nFROM pg_proc p, pg_type t0,\n"
- " pg_type t1, pg_type t2,\n"
- " pg_operator o\n"
- "WHERE p.prorettype = t0.oid AND\n"
- " RegprocToOid(o.oprcode) = p.oid AND\n"
- " p.pronargs = 2 AND\n"
- " o.oprleft = t1.oid AND\n"
- " o.oprright = t2.oid\n");
- if (name)
- {
- strcat(descbuf, " AND o.oprname = '");
- strncat(descbuf, name, 32);
- strcat(descbuf, "'\n");
- }
-
- strcat(descbuf, "\nUNION\n\n"
- "SELECT o.oprname as \"Op\",\n"
- " ''::name AS \"Left arg\",\n"
- " t1.typname AS \"Right arg\",\n"
- " t0.typname AS \"Result\"");
- if (description)
- strcat(descbuf, ",\n obj_description(p.oid) as \"Description\"");
- strcat(descbuf, "\nFROM pg_operator o, pg_proc p, pg_type t0, pg_type t1\n"
- "WHERE RegprocToOid(o.oprcode) = p.oid AND\n"
- " o.oprresult = t0.oid AND\n"
- " o.oprkind = 'l' AND\n"
- " o.oprright = t1.oid\n");
- if (name)
- {
- strcat(descbuf, "AND o.oprname = '");
- strncat(descbuf, name, 32);
- strcat(descbuf, "'\n");
- }
-
- strcat(descbuf, "\nUNION\n\n"
- "SELECT o.oprname as \"Op\",\n"
- " t1.typname AS \"Left arg\",\n"
- " ''::name AS \"Right arg\",\n"
- " t0.typname AS \"Result\"");
- if (description)
- strcat(descbuf, ",\n obj_description(p.oid) as \"Description\"");
- strcat(descbuf, "\nFROM pg_operator o, pg_proc p, pg_type t0, pg_type t1\n"
- "WHERE RegprocToOid(o.oprcode) = p.oid AND\n"
- " o.oprresult = t0.oid AND\n"
- " o.oprkind = 'r' AND\n"
- " o.oprleft = t1.oid\n");
- if (name)
- {
- strcat(descbuf, "AND o.oprname = '");
- strncat(descbuf, name, 32);
- strcat(descbuf, "'\n");
- }
- strcat(descbuf, "\nORDER BY \"Op\", \"Left arg\", \"Right arg\", \"Result\"");
-
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
-
- myopt.topt.tuples_only = false;
- myopt.nullPrint = NULL;
- myopt.title = "List of operators";
-
- printQuery(res, &myopt, pset->queryFout);
-
- PQclear(res);
- return true;
+ char descbuf[1536 + 3 * 32]; /* 32 is max length for operator
+ * name */
+ PGresult *res;
+ bool description = GetVariableBool(pset->vars, "description");
+ printQueryOpt myopt = pset->popt;
+
+ descbuf[0] = '\0';
+
+ strcat(descbuf, "SELECT o.oprname AS \"Op\",\n"
+ " t1.typname AS \"Left arg\",\n"
+ " t2.typname AS \"Right arg\",\n"
+ " t0.typname AS \"Result\"");
+ if (description)
+ strcat(descbuf, ",\n obj_description(p.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_proc p, pg_type t0,\n"
+ " pg_type t1, pg_type t2,\n"
+ " pg_operator o\n"
+ "WHERE p.prorettype = t0.oid AND\n"
+ " RegprocToOid(o.oprcode) = p.oid AND\n"
+ " p.pronargs = 2 AND\n"
+ " o.oprleft = t1.oid AND\n"
+ " o.oprright = t2.oid\n");
+ if (name)
+ {
+ strcat(descbuf, " AND o.oprname = '");
+ strncat(descbuf, name, 32);
+ strcat(descbuf, "'\n");
+ }
+
+ strcat(descbuf, "\nUNION\n\n"
+ "SELECT o.oprname as \"Op\",\n"
+ " ''::name AS \"Left arg\",\n"
+ " t1.typname AS \"Right arg\",\n"
+ " t0.typname AS \"Result\"");
+ if (description)
+ strcat(descbuf, ",\n obj_description(p.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_operator o, pg_proc p, pg_type t0, pg_type t1\n"
+ "WHERE RegprocToOid(o.oprcode) = p.oid AND\n"
+ " o.oprresult = t0.oid AND\n"
+ " o.oprkind = 'l' AND\n"
+ " o.oprright = t1.oid\n");
+ if (name)
+ {
+ strcat(descbuf, "AND o.oprname = '");
+ strncat(descbuf, name, 32);
+ strcat(descbuf, "'\n");
+ }
+
+ strcat(descbuf, "\nUNION\n\n"
+ "SELECT o.oprname as \"Op\",\n"
+ " t1.typname AS \"Left arg\",\n"
+ " ''::name AS \"Right arg\",\n"
+ " t0.typname AS \"Result\"");
+ if (description)
+ strcat(descbuf, ",\n obj_description(p.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_operator o, pg_proc p, pg_type t0, pg_type t1\n"
+ "WHERE RegprocToOid(o.oprcode) = p.oid AND\n"
+ " o.oprresult = t0.oid AND\n"
+ " o.oprkind = 'r' AND\n"
+ " o.oprleft = t1.oid\n");
+ if (name)
+ {
+ strcat(descbuf, "AND o.oprname = '");
+ strncat(descbuf, name, 32);
+ strcat(descbuf, "'\n");
+ }
+ strcat(descbuf, "\nORDER BY \"Op\", \"Left arg\", \"Right arg\", \"Result\"");
+
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
+
+ myopt.topt.tuples_only = false;
+ myopt.nullPrint = NULL;
+ myopt.title = "List of operators";
+
+ printQuery(res, &myopt, pset->queryFout);
+
+ PQclear(res);
+ return true;
}
@@ -279,81 +285,82 @@ describeOperators(const char * name, PsqlSettings * pset)
bool
listAllDbs(PsqlSettings *pset)
{
- PGresult *res;
- char descbuf[256];
- printQueryOpt myopt = pset->popt;
+ PGresult *res;
+ char descbuf[256];
+ printQueryOpt myopt = pset->popt;
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT pg_database.datname as \"Database\",\n"
- " pg_user.usename as \"Owner\""
+ descbuf[0] = '\0';
+ strcat(descbuf, "SELECT pg_database.datname as \"Database\",\n"
+ " pg_user.usename as \"Owner\""
#ifdef MULTIBYTE
- ",\n pg_database.encoding as \"Encoding\""
+ ",\n pg_database.encoding as \"Encoding\""
#endif
- );
- if (GetVariableBool(pset->vars, "description"))
- strcat(descbuf, ",\n obj_description(pg_database.oid) as \"Description\"\n");
- strcat(descbuf, "FROM pg_database, pg_user\n"
- "WHERE pg_database.datdba = pg_user.usesysid\n"
- "ORDER BY \"Database\"");
+ );
+ if (GetVariableBool(pset->vars, "description"))
+ strcat(descbuf, ",\n obj_description(pg_database.oid) as \"Description\"\n");
+ strcat(descbuf, "FROM pg_database, pg_user\n"
+ "WHERE pg_database.datdba = pg_user.usesysid\n"
+ "ORDER BY \"Database\"");
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
- myopt.topt.tuples_only = false;
- myopt.nullPrint = NULL;
- myopt.title = "List of databases";
+ myopt.topt.tuples_only = false;
+ myopt.nullPrint = NULL;
+ myopt.title = "List of databases";
- printQuery(res, &myopt, pset->queryFout);
+ printQuery(res, &myopt, pset->queryFout);
- PQclear(res);
- return true;
+ PQclear(res);
+ return true;
}
/* List Tables Grant/Revoke Permissions
* \z (now also \dp -- perhaps more mnemonic)
- *
+ *
*/
bool
-permissionsList(const char * name, PsqlSettings *pset)
+permissionsList(const char *name, PsqlSettings *pset)
{
- char descbuf[256 + REGEXP_CUTOFF];
- PGresult *res;
- printQueryOpt myopt = pset->popt;
-
- descbuf[0] = '\0';
- /* Currently, we ignore indexes since they have no meaningful rights */
- strcat(descbuf, "SELECT relname as \"Relation\",\n"
- " relacl as \"Access permissions\"\n"
- "FROM pg_class\n"
- "WHERE ( relkind = 'r' OR relkind = 'S') AND\n"
- " relname !~ '^pg_'\n");
- if (name) {
- strcat(descbuf, " AND rename ~ '^");
- strncat(descbuf, name, REGEXP_CUTOFF);
- strcat(descbuf, "'\n");
- }
- strcat (descbuf, "ORDER BY relname");
-
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
-
- if (PQntuples(res) == 0) {
- fputs("Couldn't find any tables.\n", pset->queryFout);
- }
- else {
- myopt.topt.tuples_only = false;
- myopt.nullPrint = NULL;
- sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset->db));
- myopt.title = descbuf;
+ char descbuf[256 + REGEXP_CUTOFF];
+ PGresult *res;
+ printQueryOpt myopt = pset->popt;
+
+ descbuf[0] = '\0';
+ /* Currently, we ignore indexes since they have no meaningful rights */
+ strcat(descbuf, "SELECT relname as \"Relation\",\n"
+ " relacl as \"Access permissions\"\n"
+ "FROM pg_class\n"
+ "WHERE ( relkind = 'r' OR relkind = 'S') AND\n"
+ " relname !~ '^pg_'\n");
+ if (name)
+ {
+ strcat(descbuf, " AND rename ~ '^");
+ strncat(descbuf, name, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+ strcat(descbuf, "ORDER BY relname");
- printQuery(res, &myopt, pset->queryFout);
- }
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
+
+ if (PQntuples(res) == 0)
+ fputs("Couldn't find any tables.\n", pset->queryFout);
+ else
+ {
+ myopt.topt.tuples_only = false;
+ myopt.nullPrint = NULL;
+ sprintf(descbuf, "Access permissions for database \"%s\"", PQdb(pset->db));
+ myopt.title = descbuf;
- PQclear(res);
- return true;
+ printQuery(res, &myopt, pset->queryFout);
+ }
+
+ PQclear(res);
+ return true;
}
@@ -368,106 +375,113 @@ permissionsList(const char * name, PsqlSettings *pset)
* lists of things, there are other \d? commands.
*/
bool
-objectDescription(const char * object, PsqlSettings *pset)
+objectDescription(const char *object, PsqlSettings *pset)
{
- char descbuf[2048 + 7*REGEXP_CUTOFF];
- PGresult *res;
- printQueryOpt myopt = pset->popt;
-
- descbuf[0] = '\0';
-
- /* Aggregate descriptions */
- strcat(descbuf, "SELECT DISTINCT a.aggname as \"Name\", 'aggregate'::text as \"What\", d.description as \"Description\"\n"
- "FROM pg_aggregate a, pg_description d\n"
- "WHERE a.oid = d.objoid\n");
- if (object) {
- strcat(descbuf," AND a.aggname ~* '^");
- strncat(descbuf, object, REGEXP_CUTOFF);
- strcat(descbuf,"'\n");
- }
-
- /* Function descriptions (except in/outs for datatypes) */
- strcat(descbuf, "\nUNION ALL\n\n");
- strcat(descbuf, "SELECT DISTINCT p.proname as \"Name\", 'function'::text as \"What\", d.description as \"Description\"\n"
- "FROM pg_proc p, pg_description d\n"
- "WHERE p.oid = d.objoid AND (p.pronargs = 0 or oid8types(p.proargtypes) != '')\n");
- if (object) {
- strcat(descbuf," AND p.proname ~* '^");
- strncat(descbuf, object, REGEXP_CUTOFF);
- strcat(descbuf,"'\n");
- }
-
- /* Operator descriptions */
- strcat(descbuf, "\nUNION ALL\n\n");
- strcat(descbuf, "SELECT DISTINCT o.oprname as \"Name\", 'operator'::text as \"What\", d.description as \"Description\"\n"
- "FROM pg_operator o, pg_description d\n"
- // must get comment via associated function
- "WHERE RegprocToOid(o.oprcode) = d.objoid\n");
- if (object) {
- strcat(descbuf," AND o.oprname = '");
- strncat(descbuf, object, REGEXP_CUTOFF);
- strcat(descbuf,"'\n");
- }
-
- /* Type description */
- strcat(descbuf, "\nUNION ALL\n\n");
- strcat(descbuf, "SELECT DISTINCT t.typname as \"Name\", 'type'::text as \"What\", d.description as \"Description\"\n"
- "FROM pg_type t, pg_description d\n"
- "WHERE t.oid = d.objoid\n");
- if (object) {
- strcat(descbuf," AND t.typname ~* '^");
- strncat(descbuf, object, REGEXP_CUTOFF);
- strcat(descbuf,"'\n");
- }
-
- /* Relation (tables, views, indices, sequences) descriptions */
- strcat(descbuf, "\nUNION ALL\n\n");
- strcat(descbuf, "SELECT DISTINCT c.relname as \"Name\", 'relation'::text||'('||c.relkind||')' as \"What\", d.description as \"Description\"\n"
- "FROM pg_class c, pg_description d\n"
- "WHERE c.oid = d.objoid\n");
- if (object) {
- strcat(descbuf," AND c.relname ~* '^");
- strncat(descbuf, object, REGEXP_CUTOFF);
- strcat(descbuf,"'\n");
- }
-
- /* Rule description (ignore rules for views) */
- strcat(descbuf, "\nUNION ALL\n\n");
- strcat(descbuf, "SELECT DISTINCT r.rulename as \"Name\", 'rule'::text as \"What\", d.description as \"Description\"\n"
- "FROM pg_rewrite r, pg_description d\n"
- "WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n");
- if (object) {
- strcat(descbuf," AND r.rulename ~* '^");
- strncat(descbuf, object, REGEXP_CUTOFF);
- strcat(descbuf,"'\n");
- }
-
- /* Trigger description */
- strcat(descbuf, "\nUNION ALL\n\n");
- strcat(descbuf, "SELECT DISTINCT t.tgname as \"Name\", 'trigger'::text as \"What\", d.description as \"Description\"\n"
- "FROM pg_trigger t, pg_description d\n"
- "WHERE t.oid = d.objoid\n");
- if (object) {
- strcat(descbuf," AND t.tgname ~* '^");
- strncat(descbuf, object, REGEXP_CUTOFF);
- strcat(descbuf,"'\n");
- }
-
- strcat(descbuf, "\nORDER BY \"Name\"");
-
-
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
-
- myopt.topt.tuples_only = false;
- myopt.nullPrint = NULL;
- myopt.title = "Object descriptions";
-
- printQuery(res, &myopt, pset->queryFout);
-
- PQclear(res);
- return true;
+ char descbuf[2048 + 7 * REGEXP_CUTOFF];
+ PGresult *res;
+ printQueryOpt myopt = pset->popt;
+
+ descbuf[0] = '\0';
+
+ /* Aggregate descriptions */
+ strcat(descbuf, "SELECT DISTINCT a.aggname as \"Name\", 'aggregate'::text as \"What\", d.description as \"Description\"\n"
+ "FROM pg_aggregate a, pg_description d\n"
+ "WHERE a.oid = d.objoid\n");
+ if (object)
+ {
+ strcat(descbuf, " AND a.aggname ~* '^");
+ strncat(descbuf, object, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+
+ /* Function descriptions (except in/outs for datatypes) */
+ strcat(descbuf, "\nUNION ALL\n\n");
+ strcat(descbuf, "SELECT DISTINCT p.proname as \"Name\", 'function'::text as \"What\", d.description as \"Description\"\n"
+ "FROM pg_proc p, pg_description d\n"
+ "WHERE p.oid = d.objoid AND (p.pronargs = 0 or oid8types(p.proargtypes) != '')\n");
+ if (object)
+ {
+ strcat(descbuf, " AND p.proname ~* '^");
+ strncat(descbuf, object, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+
+ /* Operator descriptions */
+ strcat(descbuf, "\nUNION ALL\n\n");
+ strcat(descbuf, "SELECT DISTINCT o.oprname as \"Name\", 'operator'::text as \"What\", d.description as \"Description\"\n"
+ "FROM pg_operator o, pg_description d\n"
+ // must get comment via associated function
+ "WHERE RegprocToOid(o.oprcode) = d.objoid\n");
+ if (object)
+ {
+ strcat(descbuf, " AND o.oprname = '");
+ strncat(descbuf, object, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+
+ /* Type description */
+ strcat(descbuf, "\nUNION ALL\n\n");
+ strcat(descbuf, "SELECT DISTINCT t.typname as \"Name\", 'type'::text as \"What\", d.description as \"Description\"\n"
+ "FROM pg_type t, pg_description d\n"
+ "WHERE t.oid = d.objoid\n");
+ if (object)
+ {
+ strcat(descbuf, " AND t.typname ~* '^");
+ strncat(descbuf, object, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+
+ /* Relation (tables, views, indices, sequences) descriptions */
+ strcat(descbuf, "\nUNION ALL\n\n");
+ strcat(descbuf, "SELECT DISTINCT c.relname as \"Name\", 'relation'::text||'('||c.relkind||')' as \"What\", d.description as \"Description\"\n"
+ "FROM pg_class c, pg_description d\n"
+ "WHERE c.oid = d.objoid\n");
+ if (object)
+ {
+ strcat(descbuf, " AND c.relname ~* '^");
+ strncat(descbuf, object, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+
+ /* Rule description (ignore rules for views) */
+ strcat(descbuf, "\nUNION ALL\n\n");
+ strcat(descbuf, "SELECT DISTINCT r.rulename as \"Name\", 'rule'::text as \"What\", d.description as \"Description\"\n"
+ "FROM pg_rewrite r, pg_description d\n"
+ "WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n");
+ if (object)
+ {
+ strcat(descbuf, " AND r.rulename ~* '^");
+ strncat(descbuf, object, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+
+ /* Trigger description */
+ strcat(descbuf, "\nUNION ALL\n\n");
+ strcat(descbuf, "SELECT DISTINCT t.tgname as \"Name\", 'trigger'::text as \"What\", d.description as \"Description\"\n"
+ "FROM pg_trigger t, pg_description d\n"
+ "WHERE t.oid = d.objoid\n");
+ if (object)
+ {
+ strcat(descbuf, " AND t.tgname ~* '^");
+ strncat(descbuf, object, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
+
+ strcat(descbuf, "\nORDER BY \"Name\"");
+
+
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
+
+ myopt.topt.tuples_only = false;
+ myopt.nullPrint = NULL;
+ myopt.title = "Object descriptions";
+
+ printQuery(res, &myopt, pset->queryFout);
+
+ PQclear(res);
+ return true;
}
@@ -480,199 +494,218 @@ objectDescription(const char * object, PsqlSettings *pset)
* and pass it to the underlying printTable() function.
*
*/
-static void * xmalloc(size_t size)
+static void *
+xmalloc(size_t size)
{
- void * tmp;
- tmp = malloc(size);
- if (!tmp) {
- perror("malloc");
- exit(EXIT_FAILURE);
- }
- return tmp;
+ void *tmp;
+
+ tmp = malloc(size);
+ if (!tmp)
+ {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+ return tmp;
}
bool
-describeTableDetails(const char * name, PsqlSettings * pset)
+describeTableDetails(const char *name, PsqlSettings *pset)
{
- char descbuf[512 + NAMEDATALEN];
- PGresult *res = NULL, *res2 = NULL, *res3 = NULL;
- printTableOpt myopt = pset->popt.topt;
- bool description = GetVariableBool(pset->vars, "description");
- int i;
- char * view_def = NULL;
- char * headers[5];
- char ** cells = NULL;
- char * title = NULL;
- char ** footers = NULL;
- char ** ptr;
- unsigned int cols;
-
- cols = 3 + (description ? 1 : 0);
-
- headers[0] = "Attribute";
- headers[1] = "Type";
- headers[2] = "Info";
- if (description) {
- headers[3] = "Description";
- headers[4] = NULL;
- }
- else
- headers[3] = NULL;
-
- /* Get general table info */
- strcpy(descbuf, "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum");
- if (description)
- strcat(descbuf, ", obj_description(a.oid)");
- strcat(descbuf, "\nFROM pg_class c, pg_attribute a, pg_type t\n"
- "WHERE c.relname = '");
- strncat(descbuf, name, NAMEDATALEN);
- strcat(descbuf, "'\n AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid\n"
- "ORDER BY a.attnum");
-
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
-
- /* Did we get anything? */
- if (PQntuples(res)==0) {
- if (!GetVariableBool(pset->vars, "quiet"))
- fprintf(stdout, "Did not find any class named \"%s\".\n", name);
- PQclear(res);
- return false;
- }
-
- /* Check if table is a view */
- strcpy(descbuf, "SELECT definition FROM pg_views WHERE viewname = '");
- strncat(descbuf, name, NAMEDATALEN);
- strcat(descbuf, "'");
- res2 = PSQLexec(pset, descbuf);
- if (!res2)
- return false;
-
- if (PQntuples(res2) > 0)
- view_def = PQgetvalue(res2,0,0);
-
-
-
- /* Generate table cells to be printed */
- cells = calloc(PQntuples(res) * cols + 1, sizeof(*cells));
- if (!cells) {
- perror("calloc");
- exit(EXIT_FAILURE);
- }
-
- for (i = 0; i < PQntuples(res); i++) {
- int4 attypmod = atoi(PQgetvalue(res, i, 3));
- char * attype = PQgetvalue(res, i, 1);
-
- /* Name */
- cells[i*cols + 0] = PQgetvalue(res, i, 0); /* don't free this afterwards */
-
- /* Type */
- cells[i*cols + 1] = xmalloc(NAMEDATALEN + 16);
- if (strcmp(attype, "bpchar")==0)
- sprintf(cells[i*cols + 1], "char(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0);
- else if (strcmp(attype, "varchar")==0)
- sprintf(cells[i*cols + 1], "varchar(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0);
- else if (strcmp(attype, "numeric")==0)
- sprintf(cells[i*cols + 1], "numeric(%d,%d)", ((attypmod - VARHDRSZ) >> 16) & 0xffff,
- (attypmod - VARHDRSZ) & 0xffff );
- else if (attype[0] == '_')
- sprintf(cells[i*cols + 1], "%s[]", attype+1);
- else
- strcpy(cells[i*cols + 1], attype);
-
- /* Info */
- cells[i*cols + 2] = xmalloc(128 + 128); /* I'm cutting off the default string at 128 */
- cells[i*cols + 2][0] = '\0';
- if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
- strcat(cells[i*cols + 2], "not null");
- if (strcmp(PQgetvalue(res, i, 5), "t") == 0) {
- /* handle "default" here */
- strcpy(descbuf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
- "WHERE c.relname = '");
- strncat(descbuf, name, NAMEDATALEN);
- strcat(descbuf, "' AND c.oid = d.adrelid AND d.adnum = ");
- strcat(descbuf, PQgetvalue(res, i, 6));
-
- res3 = PSQLexec(pset, descbuf);
- if (!res) return false;
- if (cells[i*cols+2][0]) strcat(cells[i*cols+2], " ");
- strcat(cells[i*cols + 2], "default ");
- strcat(cells[i*cols + 2], PQgetvalue(res3, 0, 0));
+ char descbuf[512 + NAMEDATALEN];
+ PGresult *res = NULL,
+ *res2 = NULL,
+ *res3 = NULL;
+ printTableOpt myopt = pset->popt.topt;
+ bool description = GetVariableBool(pset->vars, "description");
+ int i;
+ char *view_def = NULL;
+ char *headers[5];
+ char **cells = NULL;
+ char *title = NULL;
+ char **footers = NULL;
+ char **ptr;
+ unsigned int cols;
+
+ cols = 3 + (description ? 1 : 0);
+
+ headers[0] = "Attribute";
+ headers[1] = "Type";
+ headers[2] = "Info";
+ if (description)
+ {
+ headers[3] = "Description";
+ headers[4] = NULL;
}
+ else
+ headers[3] = NULL;
- /* Description */
+ /* Get general table info */
+ strcpy(descbuf, "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum");
if (description)
- cells[i*cols + 3] = PQgetvalue(res, i, 7);
- }
-
- /* Make title */
- title = xmalloc(10 + strlen(name));
- if (view_def)
- sprintf(title, "View \"%s\"", name);
- else
- sprintf(title, "Table \"%s\"", name);
-
- /* Make footers */
- if (view_def) {
- footers = xmalloc(2 * sizeof(*footers));
- footers[0] = xmalloc(20 + strlen(view_def));
- sprintf(footers[0], "View definition: %s", view_def);
- footers[1] = NULL;
- }
- else {
- /* display indices */
- strcpy(descbuf, "SELECT c2.relname\n"
- "FROM pg_class c, pg_class c2, pg_index i\n"
- "WHERE c.relname = '");
+ strcat(descbuf, ", obj_description(a.oid)");
+ strcat(descbuf, "\nFROM pg_class c, pg_attribute a, pg_type t\n"
+ "WHERE c.relname = '");
+ strncat(descbuf, name, NAMEDATALEN);
+ strcat(descbuf, "'\n AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid\n"
+ "ORDER BY a.attnum");
+
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
+
+ /* Did we get anything? */
+ if (PQntuples(res) == 0)
+ {
+ if (!GetVariableBool(pset->vars, "quiet"))
+ fprintf(stdout, "Did not find any class named \"%s\".\n", name);
+ PQclear(res);
+ return false;
+ }
+
+ /* Check if table is a view */
+ strcpy(descbuf, "SELECT definition FROM pg_views WHERE viewname = '");
strncat(descbuf, name, NAMEDATALEN);
- strcat(descbuf, "' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
- "ORDER BY c2.relname");
- res3 = PSQLexec(pset, descbuf);
- if (!res3)
- return false;
-
- if (PQntuples(res3) > 0) {
- footers = xmalloc((PQntuples(res3) + 1) * sizeof(*footers));
-
- for (i=0; i<PQntuples(res3); i++) {
- footers[i] = xmalloc(10 + NAMEDATALEN);
- if (PQntuples(res3)==1)
- sprintf(footers[i], "Index: %s", PQgetvalue(res3, i, 0));
- else if (i==0)
- sprintf(footers[i], "Indices: %s", PQgetvalue(res3, i, 0));
+ strcat(descbuf, "'");
+ res2 = PSQLexec(pset, descbuf);
+ if (!res2)
+ return false;
+
+ if (PQntuples(res2) > 0)
+ view_def = PQgetvalue(res2, 0, 0);
+
+
+
+ /* Generate table cells to be printed */
+ cells = calloc(PQntuples(res) * cols + 1, sizeof(*cells));
+ if (!cells)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < PQntuples(res); i++)
+ {
+ int4 attypmod = atoi(PQgetvalue(res, i, 3));
+ char *attype = PQgetvalue(res, i, 1);
+
+ /* Name */
+ cells[i * cols + 0] = PQgetvalue(res, i, 0); /* don't free this
+ * afterwards */
+
+ /* Type */
+ cells[i * cols + 1] = xmalloc(NAMEDATALEN + 16);
+ if (strcmp(attype, "bpchar") == 0)
+ sprintf(cells[i * cols + 1], "char(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0);
+ else if (strcmp(attype, "varchar") == 0)
+ sprintf(cells[i * cols + 1], "varchar(%d)", attypmod != -1 ? attypmod - VARHDRSZ : 0);
+ else if (strcmp(attype, "numeric") == 0)
+ sprintf(cells[i * cols + 1], "numeric(%d,%d)", ((attypmod - VARHDRSZ) >> 16) & 0xffff,
+ (attypmod - VARHDRSZ) & 0xffff);
+ else if (attype[0] == '_')
+ sprintf(cells[i * cols + 1], "%s[]", attype + 1);
else
- sprintf(footers[i], " %s", PQgetvalue(res3, i, 0));
- }
+ strcpy(cells[i * cols + 1], attype);
+
+ /* Info */
+ cells[i * cols + 2] = xmalloc(128 + 128); /* I'm cutting off the
+ * default string at 128 */
+ cells[i * cols + 2][0] = '\0';
+ if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
+ strcat(cells[i * cols + 2], "not null");
+ if (strcmp(PQgetvalue(res, i, 5), "t") == 0)
+ {
+ /* handle "default" here */
+ strcpy(descbuf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
+ "WHERE c.relname = '");
+ strncat(descbuf, name, NAMEDATALEN);
+ strcat(descbuf, "' AND c.oid = d.adrelid AND d.adnum = ");
+ strcat(descbuf, PQgetvalue(res, i, 6));
+
+ res3 = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
+ if (cells[i * cols + 2][0])
+ strcat(cells[i * cols + 2], " ");
+ strcat(cells[i * cols + 2], "default ");
+ strcat(cells[i * cols + 2], PQgetvalue(res3, 0, 0));
+ }
+
+ /* Description */
+ if (description)
+ cells[i * cols + 3] = PQgetvalue(res, i, 7);
+ }
- footers[i] = NULL;
+ /* Make title */
+ title = xmalloc(10 + strlen(name));
+ if (view_def)
+ sprintf(title, "View \"%s\"", name);
+ else
+ sprintf(title, "Table \"%s\"", name);
+
+ /* Make footers */
+ if (view_def)
+ {
+ footers = xmalloc(2 * sizeof(*footers));
+ footers[0] = xmalloc(20 + strlen(view_def));
+ sprintf(footers[0], "View definition: %s", view_def);
+ footers[1] = NULL;
+ }
+ else
+ {
+ /* display indices */
+ strcpy(descbuf, "SELECT c2.relname\n"
+ "FROM pg_class c, pg_class c2, pg_index i\n"
+ "WHERE c.relname = '");
+ strncat(descbuf, name, NAMEDATALEN);
+ strcat(descbuf, "' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
+ "ORDER BY c2.relname");
+ res3 = PSQLexec(pset, descbuf);
+ if (!res3)
+ return false;
+
+ if (PQntuples(res3) > 0)
+ {
+ footers = xmalloc((PQntuples(res3) + 1) * sizeof(*footers));
+
+ for (i = 0; i < PQntuples(res3); i++)
+ {
+ footers[i] = xmalloc(10 + NAMEDATALEN);
+ if (PQntuples(res3) == 1)
+ sprintf(footers[i], "Index: %s", PQgetvalue(res3, i, 0));
+ else if (i == 0)
+ sprintf(footers[i], "Indices: %s", PQgetvalue(res3, i, 0));
+ else
+ sprintf(footers[i], " %s", PQgetvalue(res3, i, 0));
+ }
+
+ footers[i] = NULL;
+ }
}
- }
- myopt.tuples_only = false;
- printTable(title, headers, cells, footers, "llll", &myopt, pset->queryFout);
+ myopt.tuples_only = false;
+ printTable(title, headers, cells, footers, "llll", &myopt, pset->queryFout);
- /* clean up */
- free(title);
+ /* clean up */
+ free(title);
- for (i = 0; i<PQntuples(res); i++) {
- free(cells[i*cols + 1]);
- free(cells[i*cols + 2]);
- }
- free(cells);
+ for (i = 0; i < PQntuples(res); i++)
+ {
+ free(cells[i * cols + 1]);
+ free(cells[i * cols + 2]);
+ }
+ free(cells);
- for (ptr = footers; footers && *ptr; ptr++)
- free(*ptr);
- free(footers);
+ for (ptr = footers; footers && *ptr; ptr++)
+ free(*ptr);
+ free(footers);
- PQclear(res);
- PQclear(res2);
- PQclear(res3);
+ PQclear(res);
+ PQclear(res2);
+ PQclear(res3);
- return true;
+ return true;
}
@@ -691,125 +724,134 @@ describeTableDetails(const char * name, PsqlSettings * pset)
* (any order of the above is fine)
*/
bool
-listTables(const char * infotype, const char * name, PsqlSettings * pset)
+listTables(const char *infotype, const char *name, PsqlSettings *pset)
{
- bool showTables = strchr(infotype, 't') != NULL;
- bool showIndices= strchr(infotype, 'i') != NULL;
- bool showViews = strchr(infotype, 'v') != NULL;
- bool showSeq = strchr(infotype, 's') != NULL;
- bool showSystem = strchr(infotype, 'S') != NULL;
-
- bool description = GetVariableBool(pset->vars, "description");
-
- char descbuf[1536 + 4 * REGEXP_CUTOFF];
- PGresult *res;
- printQueryOpt myopt = pset->popt;
-
- descbuf[0] = '\0';
-
- /* tables */
- if (showTables) {
- strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'table'::text as \"Type\"");
- if (description)
- strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
- strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
- "WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n"
- " AND not exists (select 1 from pg_views where viewname = c.relname)\n");
- strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
- if (name) {
- strcat(descbuf, " AND c.relname ~ '^");
- strncat(descbuf, name, REGEXP_CUTOFF);
- strcat(descbuf, "'\n");
+ bool showTables = strchr(infotype, 't') != NULL;
+ bool showIndices = strchr(infotype, 'i') != NULL;
+ bool showViews = strchr(infotype, 'v') != NULL;
+ bool showSeq = strchr(infotype, 's') != NULL;
+ bool showSystem = strchr(infotype, 'S') != NULL;
+
+ bool description = GetVariableBool(pset->vars, "description");
+
+ char descbuf[1536 + 4 * REGEXP_CUTOFF];
+ PGresult *res;
+ printQueryOpt myopt = pset->popt;
+
+ descbuf[0] = '\0';
+
+ /* tables */
+ if (showTables)
+ {
+ strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'table'::text as \"Type\"");
+ if (description)
+ strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
+ "WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n"
+ " AND not exists (select 1 from pg_views where viewname = c.relname)\n");
+ strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
+ if (name)
+ {
+ strcat(descbuf, " AND c.relname ~ '^");
+ strncat(descbuf, name, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
}
- }
-
- /* views */
- if (showViews) {
- if (descbuf[0])
- strcat(descbuf, "\nUNION\n\n");
- strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'view'::text as \"Type\"");
- if (description)
- strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
- strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
- "WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n"
- " AND exists (select 1 from pg_views where viewname = c.relname)\n");
- strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
- if (name) {
- strcat(descbuf, " AND c.relname ~ '^");
- strncat(descbuf, name, REGEXP_CUTOFF);
- strcat(descbuf, "'\n");
+ /* views */
+ if (showViews)
+ {
+ if (descbuf[0])
+ strcat(descbuf, "\nUNION\n\n");
+
+ strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'view'::text as \"Type\"");
+ if (description)
+ strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
+ "WHERE c.relowner = u.usesysid AND c.relkind = 'r'\n"
+ " AND exists (select 1 from pg_views where viewname = c.relname)\n");
+ strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
+ if (name)
+ {
+ strcat(descbuf, " AND c.relname ~ '^");
+ strncat(descbuf, name, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
}
- }
-
- /* indices, sequences */
- if (showIndices || showSeq) {
- if (descbuf[0])
- strcat(descbuf, "\nUNION\n\n");
- strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\",\n"
- " (CASE WHEN relkind = 'S' THEN 'sequence'::text ELSE 'index'::text END) as \"Type\"");
- if (description)
- strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
- strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
- "WHERE c.relowner = u.usesysid AND relkind in (");
- if (showIndices && showSeq)
- strcat(descbuf, "'i', 'S'");
- else if (showIndices)
- strcat(descbuf, "'i'");
- else
- strcat(descbuf, "'S'");
- strcat(descbuf, ")\n");
-
- /* ignore large-obj indices */
- if (showIndices)
- strcat(descbuf, " AND (c.relkind != 'i' OR c.relname !~ '^xinx')\n");
-
- strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
- if (name) {
- strcat(descbuf, " AND c.relname ~ '^");
- strncat(descbuf, name, REGEXP_CUTOFF);
- strcat(descbuf, "'\n");
+ /* indices, sequences */
+ if (showIndices || showSeq)
+ {
+ if (descbuf[0])
+ strcat(descbuf, "\nUNION\n\n");
+
+ strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\",\n"
+ " (CASE WHEN relkind = 'S' THEN 'sequence'::text ELSE 'index'::text END) as \"Type\"");
+ if (description)
+ strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
+ "WHERE c.relowner = u.usesysid AND relkind in (");
+ if (showIndices && showSeq)
+ strcat(descbuf, "'i', 'S'");
+ else if (showIndices)
+ strcat(descbuf, "'i'");
+ else
+ strcat(descbuf, "'S'");
+ strcat(descbuf, ")\n");
+
+ /* ignore large-obj indices */
+ if (showIndices)
+ strcat(descbuf, " AND (c.relkind != 'i' OR c.relname !~ '^xinx')\n");
+
+ strcat(descbuf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
+ if (name)
+ {
+ strcat(descbuf, " AND c.relname ~ '^");
+ strncat(descbuf, name, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
}
- }
-
- /* real system catalogue tables */
- if (showSystem && showTables) {
- if (descbuf[0])
- strcat(descbuf, "\nUNION\n\n");
- strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'system'::text as \"Type\"");
- if (description)
- strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
- strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
- "WHERE c.relowner = u.usesysid AND c.relkind = 's'\n");
- if (name) {
- strcat(descbuf, " AND c.relname ~ '^");
- strncat(descbuf, name, REGEXP_CUTOFF);
- strcat(descbuf, "'\n");
+ /* real system catalogue tables */
+ if (showSystem && showTables)
+ {
+ if (descbuf[0])
+ strcat(descbuf, "\nUNION\n\n");
+
+ strcat(descbuf, "SELECT u.usename as \"Owner\", c.relname as \"Name\", 'system'::text as \"Type\"");
+ if (description)
+ strcat(descbuf, ", obj_description(c.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_class c, pg_user u\n"
+ "WHERE c.relowner = u.usesysid AND c.relkind = 's'\n");
+ if (name)
+ {
+ strcat(descbuf, " AND c.relname ~ '^");
+ strncat(descbuf, name, REGEXP_CUTOFF);
+ strcat(descbuf, "'\n");
+ }
}
- }
- strcat(descbuf, "\nORDER BY \"Name\"");
+ strcat(descbuf, "\nORDER BY \"Name\"");
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
- if (PQntuples(res) == 0)
- fprintf(pset->queryFout, "No matching classes found.\n");
+ if (PQntuples(res) == 0)
+ fprintf(pset->queryFout, "No matching classes found.\n");
- else {
- myopt.topt.tuples_only = false;
- myopt.nullPrint = NULL;
- myopt.title = "List of classes";
+ else
+ {
+ myopt.topt.tuples_only = false;
+ myopt.nullPrint = NULL;
+ myopt.title = "List of classes";
- printQuery(res, &myopt, pset->queryFout);
- }
+ printQuery(res, &myopt, pset->queryFout);
+ }
- PQclear(res);
- return true;
+ PQclear(res);
+ return true;
}
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 8f165b4f80..3ab6367c8d 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -5,38 +5,38 @@
/* \da */
bool
-describeAggregates(const char * name, PsqlSettings * pset);
+ describeAggregates(const char *name, PsqlSettings *pset);
/* \df */
bool
-describeFunctions(const char * name, PsqlSettings * pset);
+ describeFunctions(const char *name, PsqlSettings *pset);
/* \dT */
bool
-describeTypes(const char * name, PsqlSettings * pset);
+ describeTypes(const char *name, PsqlSettings *pset);
/* \do */
bool
-describeOperators(const char * name, PsqlSettings * pset);
+ describeOperators(const char *name, PsqlSettings *pset);
/* \dp (formerly \z) */
bool
-permissionsList(const char * name, PsqlSettings *pset);
+ permissionsList(const char *name, PsqlSettings *pset);
/* \dd */
bool
-objectDescription(const char * object, PsqlSettings *pset);
+ objectDescription(const char *object, PsqlSettings *pset);
/* \d foo */
bool
-describeTableDetails(const char * name, PsqlSettings * pset);
+ describeTableDetails(const char *name, PsqlSettings *pset);
/* \l */
bool
-listAllDbs(PsqlSettings *pset);
+ listAllDbs(PsqlSettings *pset);
/* \dt, \di, \dS, etc. */
bool
-listTables(const char * infotype, const char * name, PsqlSettings * pset);
+ listTables(const char *infotype, const char *name, PsqlSettings *pset);
-#endif /* DESCRIBE_H */
+#endif /* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 0caab0f0d0..0c8943944d 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -7,12 +7,12 @@
#include <signal.h>
#ifndef WIN32
-#include <sys/ioctl.h> /* for ioctl() */
+#include <sys/ioctl.h> /* for ioctl() */
#ifdef HAVE_PWD_H
-#include <pwd.h> /* for getpwuid() */
+#include <pwd.h> /* for getpwuid() */
#endif
-#include <sys/types.h> /* (ditto) */
-#include <unistd.h> /* for getuid() */
+#include <sys/types.h> /* (ditto) */
+#include <unistd.h> /* for getuid() */
#else
#define strcasecmp(x,y) stricmp(x,y)
#define popen(x,y) _popen(x,y)
@@ -34,85 +34,94 @@
*/
#define ON(var) (var ? "on" : "off")
-void usage(void)
+void
+usage(void)
{
- const char *env;
- const char *user;
+ const char *env;
+ const char *user;
+
#ifndef WIN32
- struct passwd *pw = NULL;
+ struct passwd *pw = NULL;
+
#endif
- /* Find default user, in case we need it. */
- user = getenv("USER");
- if (!user) {
+ /* Find default user, in case we need it. */
+ user = getenv("USER");
+ if (!user)
+ {
#ifndef WIN32
- pw = getpwuid(getuid());
- if (pw) user = pw->pw_name;
- else {
- perror("getpwuid()");
- exit(EXIT_FAILURE);
- }
+ pw = getpwuid(getuid());
+ if (pw)
+ user = pw->pw_name;
+ else
+ {
+ perror("getpwuid()");
+ exit(EXIT_FAILURE);
+ }
#else
- user = "?";
+ user = "?";
#endif
- }
+ }
/* If string begins " here, then it ought to end there to fit on an 80 column terminal> > > > > > > " */
- fprintf(stderr, "Usage: psql [options] [dbname [username]] \n");
- fprintf(stderr, " -A Unaligned table output mode (-P format=unaligned)\n");
- fprintf(stderr, " -c query Run single query (slash commands, too) and exit\n");
-
- /* Display default database */
- env = getenv("PGDATABASE");
- if (!env) env=user;
- fprintf(stderr, " -d dbname Specify database name to connect to (default: %s)\n", env);
-
- fprintf(stderr, " -e Echo all input in non-interactive mode\n");
- fprintf(stderr, " -E Display queries that internal commands generate\n");
- fprintf(stderr, " -f filename Execute queries from file, then exit\n");
- fprintf(stderr, " -F sep Set field separator (default: '" DEFAULT_FIELD_SEP "') (-P fieldsep=)\n");
-
- /* Display default host */
- env = getenv("PGHOST");
- fprintf(stderr, " -h host Specify database server host (default: ");
- if (env)
- fprintf(stderr, env);
- else
- fprintf(stderr, "domain socket");
- fprintf(stderr, ")\n");
-
- fprintf(stderr, " -H HTML table output mode (-P format=html)\n");
- fprintf(stderr, " -l List available databases, then exit\n");
- fprintf(stderr, " -n Do not use readline and history\n");
- fprintf(stderr, " -o filename Send query output to filename (or |pipe)\n");
-
- /* Display default port */
- env = getenv("PGPORT");
- fprintf(stderr, " -p port Specify database server port (default: %s)\n",
- env ? env : "hardwired");
-
- fprintf(stderr, " -P var[=arg] Set printing option 'var' to 'arg'. (see \\pset command)\n");
- fprintf(stderr, " -q Run quietly (no messages, no prompts)\n");
- fprintf(stderr, " -s Single step mode (confirm each query)\n");
- fprintf(stderr, " -S Single line mode (newline sends query)\n");
- fprintf(stderr, " -t Don't print headings and row count (-P tuples_only)\n");
- fprintf(stderr, " -T text Set HTML table tag options (e.g., width, border)\n");
- fprintf(stderr, " -u Prompt for username and password (same as \"-U ? -W\")\n");
-
- /* Display default user */
- env = getenv("PGUSER");
- if (!env) env=user;
- fprintf(stderr, " -U [username] Specifiy username, \"?\"=prompt (default user: %s)\n", env);
-
- fprintf(stderr, " -x Turn on expanded table output (-P expanded)\n");
- fprintf(stderr, " -v name=val Set psql variable 'name' to 'value'\n");
- fprintf(stderr, " -V Show version information and exit\n");
- fprintf(stderr, " -W Prompt for password (should happen automatically)\n");
-
- fprintf(stderr, "Consult the documentation for the complete details.\n");
+ fprintf(stderr, "Usage: psql [options] [dbname [username]] \n");
+ fprintf(stderr, " -A Unaligned table output mode (-P format=unaligned)\n");
+ fprintf(stderr, " -c query Run single query (slash commands, too) and exit\n");
+
+ /* Display default database */
+ env = getenv("PGDATABASE");
+ if (!env)
+ env = user;
+ fprintf(stderr, " -d dbname Specify database name to connect to (default: %s)\n", env);
+
+ fprintf(stderr, " -e Echo all input in non-interactive mode\n");
+ fprintf(stderr, " -E Display queries that internal commands generate\n");
+ fprintf(stderr, " -f filename Execute queries from file, then exit\n");
+ fprintf(stderr, " -F sep Set field separator (default: '" DEFAULT_FIELD_SEP "') (-P fieldsep=)\n");
+
+ /* Display default host */
+ env = getenv("PGHOST");
+ fprintf(stderr, " -h host Specify database server host (default: ");
+ if (env)
+ fprintf(stderr, env);
+ else
+ fprintf(stderr, "domain socket");
+ fprintf(stderr, ")\n");
+
+ fprintf(stderr, " -H HTML table output mode (-P format=html)\n");
+ fprintf(stderr, " -l List available databases, then exit\n");
+ fprintf(stderr, " -n Do not use readline and history\n");
+ fprintf(stderr, " -o filename Send query output to filename (or |pipe)\n");
+
+ /* Display default port */
+ env = getenv("PGPORT");
+ fprintf(stderr, " -p port Specify database server port (default: %s)\n",
+ env ? env : "hardwired");
+
+ fprintf(stderr, " -P var[=arg] Set printing option 'var' to 'arg'. (see \\pset command)\n");
+ fprintf(stderr, " -q Run quietly (no messages, no prompts)\n");
+ fprintf(stderr, " -s Single step mode (confirm each query)\n");
+ fprintf(stderr, " -S Single line mode (newline sends query)\n");
+ fprintf(stderr, " -t Don't print headings and row count (-P tuples_only)\n");
+ fprintf(stderr, " -T text Set HTML table tag options (e.g., width, border)\n");
+ fprintf(stderr, " -u Prompt for username and password (same as \"-U ? -W\")\n");
+
+ /* Display default user */
+ env = getenv("PGUSER");
+ if (!env)
+ env = user;
+ fprintf(stderr, " -U [username] Specifiy username, \"?\"=prompt (default user: %s)\n", env);
+
+ fprintf(stderr, " -x Turn on expanded table output (-P expanded)\n");
+ fprintf(stderr, " -v name=val Set psql variable 'name' to 'value'\n");
+ fprintf(stderr, " -V Show version information and exit\n");
+ fprintf(stderr, " -W Prompt for password (should happen automatically)\n");
+
+ fprintf(stderr, "Consult the documentation for the complete details.\n");
#ifndef WIN32
- if (pw) free(pw);
+ if (pw)
+ free(pw);
#endif
}
@@ -125,82 +134,85 @@ void usage(void)
*/
#ifndef TIOCGWINSZ
-struct winsize {
- int ws_row;
- int ws_col;
+struct winsize
+{
+ int ws_row;
+ int ws_col;
};
+
#endif
void
slashUsage(PsqlSettings *pset)
{
- bool usePipe = false;
- const char *pagerenv;
- FILE *fout;
- struct winsize screen_size;
+ bool usePipe = false;
+ const char *pagerenv;
+ FILE *fout;
+ struct winsize screen_size;
#ifdef TIOCGWINSZ
- if (pset->notty == 0 &&
- (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
- screen_size.ws_col == 0 ||
- screen_size.ws_row == 0))
- {
+ if (pset->notty == 0 &&
+ (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
+ screen_size.ws_col == 0 ||
+ screen_size.ws_row == 0))
+ {
#endif
- screen_size.ws_row = 24;
- screen_size.ws_col = 80;
+ screen_size.ws_row = 24;
+ screen_size.ws_col = 80;
#ifdef TIOCGWINSZ
- }
+ }
#endif
- if (pset->notty == 0 &&
- (pagerenv = getenv("PAGER")) &&
- (pagerenv[0] != '\0') &&
- screen_size.ws_row <= 36 &&
- (fout = popen(pagerenv, "w")))
- {
- usePipe = true;
- pqsignal(SIGPIPE, SIG_IGN);
- }
- else
- fout = stdout;
-
- /* if you add/remove a line here, change the row test above */
- fprintf(fout, " \\? -- help\n");
- fprintf(fout, " \\c[onnect] [<dbname>|- [<user>|?]] -- connect to new database (currently '%s')\n", PQdb(pset->db));
- fprintf(fout, " \\copy [binary] <table> [with oids] {from|to} <fname> [with delimiters '<char>']\n");
- fprintf(fout, " \\copyright -- show PostgreSQL copyright\n");
- fprintf(fout, " \\d -- list tables, views, and sequences\n");
- fprintf(fout, " \\distvS -- list only indices/sequences/tables/views/system tables\n");
- fprintf(fout, " \\da -- list aggregates\n");
- fprintf(fout, " \\dd [<object>]- list comment for table, type, function, or operator\n");
- fprintf(fout, " \\df -- list functions\n");
- fprintf(fout, " \\do -- list operators\n");
- fprintf(fout, " \\dT -- list data types\n");
- fprintf(fout, " \\e [<fname>] -- edit the current query buffer or <fname> with external editor\n");
- fprintf(fout, " \\echo <text> -- write text to stdout\n");
- fprintf(fout, " \\g [<fname>] -- send query to backend (and results in <fname> or |pipe)\n");
- fprintf(fout, " \\h [<cmd>] -- help on syntax of sql commands, * for all commands\n");
- fprintf(fout, " \\i <fname> -- read and execute queries from filename\n");
- fprintf(fout, " \\l -- list all databases\n");
- fprintf(fout, " \\lo_export, \\lo_import, \\lo_list, \\lo_unlink -- large object operations\n");
- fprintf(fout, " \\o [<fname>] -- send all query results to <fname>, or |pipe\n");
- fprintf(fout, " \\p -- print the content of the current query buffer\n");
- fprintf(fout, " \\pset -- set table output options\n");
- fprintf(fout, " \\q -- quit\n");
- fprintf(fout, " \\qecho <text>-- write text to query output stream (see \\o)\n");
- fprintf(fout, " \\r -- reset (clear) the query buffer\n");
- fprintf(fout, " \\s [<fname>] -- print history or save it in <fname>\n");
- fprintf(fout, " \\set <var> [<value>] -- set/unset internal variable\n");
- fprintf(fout, " \\t -- don't show table headers or footers (currently %s)\n", ON(pset->popt.topt.tuples_only));
- fprintf(fout, " \\x -- toggle expanded output (currently %s)\n", ON(pset->popt.topt.expanded));
- fprintf(fout, " \\w <fname> -- write current query buffer to a file\n");
- fprintf(fout, " \\z -- list table access permissions\n");
- fprintf(fout, " \\! [<cmd>] -- shell escape or command\n");
-
- if (usePipe) {
- pclose(fout);
- pqsignal(SIGPIPE, SIG_DFL);
- }
+ if (pset->notty == 0 &&
+ (pagerenv = getenv("PAGER")) &&
+ (pagerenv[0] != '\0') &&
+ screen_size.ws_row <= 36 &&
+ (fout = popen(pagerenv, "w")))
+ {
+ usePipe = true;
+ pqsignal(SIGPIPE, SIG_IGN);
+ }
+ else
+ fout = stdout;
+
+ /* if you add/remove a line here, change the row test above */
+ fprintf(fout, " \\? -- help\n");
+ fprintf(fout, " \\c[onnect] [<dbname>|- [<user>|?]] -- connect to new database (currently '%s')\n", PQdb(pset->db));
+ fprintf(fout, " \\copy [binary] <table> [with oids] {from|to} <fname> [with delimiters '<char>']\n");
+ fprintf(fout, " \\copyright -- show PostgreSQL copyright\n");
+ fprintf(fout, " \\d -- list tables, views, and sequences\n");
+ fprintf(fout, " \\distvS -- list only indices/sequences/tables/views/system tables\n");
+ fprintf(fout, " \\da -- list aggregates\n");
+ fprintf(fout, " \\dd [<object>]- list comment for table, type, function, or operator\n");
+ fprintf(fout, " \\df -- list functions\n");
+ fprintf(fout, " \\do -- list operators\n");
+ fprintf(fout, " \\dT -- list data types\n");
+ fprintf(fout, " \\e [<fname>] -- edit the current query buffer or <fname> with external editor\n");
+ fprintf(fout, " \\echo <text> -- write text to stdout\n");
+ fprintf(fout, " \\g [<fname>] -- send query to backend (and results in <fname> or |pipe)\n");
+ fprintf(fout, " \\h [<cmd>] -- help on syntax of sql commands, * for all commands\n");
+ fprintf(fout, " \\i <fname> -- read and execute queries from filename\n");
+ fprintf(fout, " \\l -- list all databases\n");
+ fprintf(fout, " \\lo_export, \\lo_import, \\lo_list, \\lo_unlink -- large object operations\n");
+ fprintf(fout, " \\o [<fname>] -- send all query results to <fname>, or |pipe\n");
+ fprintf(fout, " \\p -- print the content of the current query buffer\n");
+ fprintf(fout, " \\pset -- set table output options\n");
+ fprintf(fout, " \\q -- quit\n");
+ fprintf(fout, " \\qecho <text>-- write text to query output stream (see \\o)\n");
+ fprintf(fout, " \\r -- reset (clear) the query buffer\n");
+ fprintf(fout, " \\s [<fname>] -- print history or save it in <fname>\n");
+ fprintf(fout, " \\set <var> [<value>] -- set/unset internal variable\n");
+ fprintf(fout, " \\t -- don't show table headers or footers (currently %s)\n", ON(pset->popt.topt.tuples_only));
+ fprintf(fout, " \\x -- toggle expanded output (currently %s)\n", ON(pset->popt.topt.expanded));
+ fprintf(fout, " \\w <fname> -- write current query buffer to a file\n");
+ fprintf(fout, " \\z -- list table access permissions\n");
+ fprintf(fout, " \\! [<cmd>] -- shell escape or command\n");
+
+ if (usePipe)
+ {
+ pclose(fout);
+ pqsignal(SIGPIPE, SIG_DFL);
+ }
}
@@ -212,59 +224,59 @@ slashUsage(PsqlSettings *pset)
void
helpSQL(const char *topic)
{
- if (!topic || strlen(topic)==0)
- {
- char left_center_right; /* Which column we're displaying */
- int i; /* Index into QL_HELP[] */
-
- puts("Syntax: \\h <cmd> or \\help <cmd>, where <cmd> is one of the following:");
-
- left_center_right = 'L';/* Start with left column */
- i = 0;
- while (QL_HELP[i].cmd != NULL)
+ if (!topic || strlen(topic) == 0)
{
- switch (left_center_right)
- {
- case 'L':
- printf(" %-25s", QL_HELP[i].cmd);
- left_center_right = 'C';
- break;
- case 'C':
- printf("%-25s", QL_HELP[i].cmd);
- left_center_right = 'R';
- break;
- case 'R':
- printf("%-25s\n", QL_HELP[i].cmd);
- left_center_right = 'L';
- break;
- }
- i++;
+ char left_center_right; /* Which column we're displaying */
+ int i; /* Index into QL_HELP[] */
+
+ puts("Syntax: \\h <cmd> or \\help <cmd>, where <cmd> is one of the following:");
+
+ left_center_right = 'L';/* Start with left column */
+ i = 0;
+ while (QL_HELP[i].cmd != NULL)
+ {
+ switch (left_center_right)
+ {
+ case 'L':
+ printf(" %-25s", QL_HELP[i].cmd);
+ left_center_right = 'C';
+ break;
+ case 'C':
+ printf("%-25s", QL_HELP[i].cmd);
+ left_center_right = 'R';
+ break;
+ case 'R':
+ printf("%-25s\n", QL_HELP[i].cmd);
+ left_center_right = 'L';
+ break;
+ }
+ i++;
+ }
+ if (left_center_right != 'L')
+ puts("\n");
+ puts("Or type \\h * for a complete description of all commands.");
}
- if (left_center_right != 'L')
- puts("\n");
- puts("Or type \\h * for a complete description of all commands.");
- }
- else
- {
- int i;
- bool help_found = false;
-
- for (i = 0; QL_HELP[i].cmd; i++)
+ else
{
- if (strcasecmp(QL_HELP[i].cmd, topic) == 0 ||
- strcmp(topic, "*") == 0)
- {
- help_found = true;
- printf("Command: %s\nDescription: %s\nSyntax:\n%s\n\n",
- QL_HELP[i].cmd, QL_HELP[i].help, QL_HELP[i].syntax);
- }
+ int i;
+ bool help_found = false;
+
+ for (i = 0; QL_HELP[i].cmd; i++)
+ {
+ if (strcasecmp(QL_HELP[i].cmd, topic) == 0 ||
+ strcmp(topic, "*") == 0)
+ {
+ help_found = true;
+ printf("Command: %s\nDescription: %s\nSyntax:\n%s\n\n",
+ QL_HELP[i].cmd, QL_HELP[i].help, QL_HELP[i].syntax);
+ }
+ }
+
+ if (!help_found)
+ printf("No help available for '%s'.\nTry \\h with no arguments to see available help.\n", topic);
}
-
- if (!help_found)
- printf("No help available for '%s'.\nTry \\h with no arguments to see available help.\n", topic);
- }
}
@@ -273,34 +285,34 @@ helpSQL(const char *topic)
void
print_copyright(void)
{
- puts(
-"
-PostgreSQL Data Base Management System
+ puts(
+ "
+ PostgreSQL Data Base Management System
-Copyright (c) 1996-9 PostgreSQL Global Development Group
+ Copyright(c) 1996 - 9 PostgreSQL Global Development Group
-This software is based on Postgres95, formerly known as Postgres, which
-contains the following notice:
+ This software is based on Postgres95, formerly known as Postgres, which
+ contains the following notice:
-Copyright (c) 1994-7 Regents of the University of California
+ Copyright(c) 1994 - 7 Regents of the University of California
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose, without fee, and without a written agreement
-is hereby granted, provided that the above copyright notice and this paragraph
-and the following two paragraphs appear in all copies.
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose, without fee, and without a written agreement
+ is hereby granted, provided that the above copyright notice and this paragraph
+ and the following two paragraphs appear in all copies.
-IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
-DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
-PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
-THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
+ IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
+ PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
-THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN \"AS IS\" BASIS,
-AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
-SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE.THE SOFTWARE PROVIDED HEREUNDER IS ON AN \ "AS IS\" BASIS,
+ AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
+ SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-(end of terms)"
+ (end of terms) "
);
}
diff --git a/src/bin/psql/help.h b/src/bin/psql/help.h
index 34bb267764..791e0313ca 100644
--- a/src/bin/psql/help.h
+++ b/src/bin/psql/help.h
@@ -3,14 +3,13 @@
#include "settings.h"
-void usage(void);
+void usage(void);
-void slashUsage(PsqlSettings *pset);
+void slashUsage(PsqlSettings *pset);
-void helpSQL(const char *topic);
+void helpSQL(const char *topic);
-void print_copyright(void);
+void print_copyright(void);
#endif
-
diff --git a/src/bin/psql/input.c b/src/bin/psql/input.c
index 3bb418be48..d8ceebab93 100644
--- a/src/bin/psql/input.c
+++ b/src/bin/psql/input.c
@@ -10,9 +10,11 @@
/* (of course there is no runtime command for doing that :) */
#ifdef USE_READLINE
static bool useReadline;
+
#endif
#ifdef USE_HISTORY
static bool useHistory;
+
#endif
@@ -25,29 +27,31 @@ static bool useHistory;
char *
gets_interactive(const char *prompt)
{
- char * s;
+ char *s;
#ifdef USE_READLINE
- if (useReadline) {
- s = readline(prompt);
- fputc('\r', stdout);
- fflush(stdout);
- }
- else {
+ if (useReadline)
+ {
+ s = readline(prompt);
+ fputc('\r', stdout);
+ fflush(stdout);
+ }
+ else
+ {
#endif
- fputs(prompt, stdout);
- fflush(stdout);
- s = gets_fromFile(stdin);
+ fputs(prompt, stdout);
+ fflush(stdout);
+ s = gets_fromFile(stdin);
#ifdef USE_READLINE
- }
+ }
#endif
#ifdef USE_HISTORY
- if (useHistory && s && s[0] != '\0')
- add_history(s);
+ if (useHistory && s && s[0] != '\0')
+ add_history(s);
#endif
- return s;
+ return s;
}
@@ -60,25 +64,27 @@ gets_interactive(const char *prompt)
char *
gets_fromFile(FILE *source)
{
- PQExpBufferData buffer;
- char line[1024];
-
- initPQExpBuffer(&buffer);
-
- while (fgets(line, 1024, source) != NULL) {
- appendPQExpBufferStr(&buffer, line);
- if (buffer.data[buffer.len-1] == '\n') {
- buffer.data[buffer.len-1] = '\0';
- return buffer.data;
+ PQExpBufferData buffer;
+ char line[1024];
+
+ initPQExpBuffer(&buffer);
+
+ while (fgets(line, 1024, source) != NULL)
+ {
+ appendPQExpBufferStr(&buffer, line);
+ if (buffer.data[buffer.len - 1] == '\n')
+ {
+ buffer.data[buffer.len - 1] = '\0';
+ return buffer.data;
+ }
}
- }
- if (buffer.len > 0)
- return buffer.data; /* EOF after reading some bufferload(s) */
+ if (buffer.len > 0)
+ return buffer.data; /* EOF after reading some bufferload(s) */
- /* EOF, so return null */
- termPQExpBuffer(&buffer);
- return NULL;
+ /* EOF, so return null */
+ termPQExpBuffer(&buffer);
+ return NULL;
}
@@ -93,28 +99,33 @@ void
initializeInput(int flags)
{
#ifdef USE_READLINE
- if (flags == 1) {
- useReadline = true;
- rl_readline_name = "psql";
- }
+ if (flags == 1)
+ {
+ useReadline = true;
+ rl_readline_name = "psql";
+ }
#endif
#ifdef USE_HISTORY
- if (flags == 1) {
- const char * home;
-
- useHistory = true;
- using_history();
- home = getenv("HOME");
- if (home) {
- char * psql_history = (char *) malloc(strlen(home) + 20);
- if (psql_history) {
- sprintf(psql_history, "%s/.psql_history", home);
- read_history(psql_history);
- free(psql_history);
- }
+ if (flags == 1)
+ {
+ const char *home;
+
+ useHistory = true;
+ using_history();
+ home = getenv("HOME");
+ if (home)
+ {
+ char *psql_history = (char *) malloc(strlen(home) + 20);
+
+ if (psql_history)
+ {
+ sprintf(psql_history, "%s/.psql_history", home);
+ read_history(psql_history);
+ free(psql_history);
+ }
+ }
}
- }
#endif
}
@@ -124,17 +135,19 @@ bool
saveHistory(const char *fname)
{
#ifdef USE_HISTORY
- if (useHistory) {
- if (write_history(fname) != 0) {
- perror(fname);
- return false;
+ if (useHistory)
+ {
+ if (write_history(fname) != 0)
+ {
+ perror(fname);
+ return false;
+ }
+ return true;
}
- return true;
- }
- else
- return false;
+ else
+ return false;
#else
- return false;
+ return false;
#endif
}
@@ -144,19 +157,22 @@ void
finishInput(void)
{
#ifdef USE_HISTORY
- if (useHistory) {
- char * home;
- char * psql_history;
-
- home = getenv("HOME");
- if (home) {
- psql_history = (char *) malloc(strlen(home) + 20);
- if (psql_history) {
- sprintf(psql_history, "%s/.psql_history", home);
- write_history(psql_history);
- free(psql_history);
- }
+ if (useHistory)
+ {
+ char *home;
+ char *psql_history;
+
+ home = getenv("HOME");
+ if (home)
+ {
+ psql_history = (char *) malloc(strlen(home) + 20);
+ if (psql_history)
+ {
+ sprintf(psql_history, "%s/.psql_history", home);
+ write_history(psql_history);
+ free(psql_history);
+ }
+ }
}
- }
#endif
}
diff --git a/src/bin/psql/input.h b/src/bin/psql/input.h
index 272b0574f1..c91e9ca7b1 100644
--- a/src/bin/psql/input.h
+++ b/src/bin/psql/input.h
@@ -38,19 +38,19 @@
char *
-gets_interactive(const char *prompt);
+ gets_interactive(const char *prompt);
char *
-gets_fromFile(FILE *source);
+ gets_fromFile(FILE *source);
void
-initializeInput(int flags);
+ initializeInput(int flags);
bool
-saveHistory(const char *fname);
+ saveHistory(const char *fname);
void
-finishInput(void);
+ finishInput(void);
#endif
diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c
index dfc39435ab..885a18cd4c 100644
--- a/src/bin/psql/large_obj.c
+++ b/src/bin/psql/large_obj.c
@@ -14,7 +14,7 @@
#include "print.h"
-/*
+/*
* Since all large object ops must be in a transaction, we must do some magic
* here. You can set the variable lo_transaction to one of commit|rollback|
* nothing to get your favourite behaviour regarding any transaction in
@@ -24,47 +24,50 @@
static char notice[80];
static void
-_my_notice_handler(void * arg, const char * message) {
- (void)arg;
- strncpy(notice, message, 79);
- notice[79] = '\0';
+_my_notice_handler(void *arg, const char *message)
+{
+ (void) arg;
+ strncpy(notice, message, 79);
+ notice[79] = '\0';
}
static bool
-handle_transaction(PsqlSettings * pset)
+handle_transaction(PsqlSettings *pset)
{
- const char * var = GetVariable(pset->vars, "lo_transaction");
- PGresult * res;
- bool commit;
- PQnoticeProcessor old_notice_hook;
+ const char *var = GetVariable(pset->vars, "lo_transaction");
+ PGresult *res;
+ bool commit;
+ PQnoticeProcessor old_notice_hook;
- if (var && strcmp(var, "nothing")==0)
- return true;
+ if (var && strcmp(var, "nothing") == 0)
+ return true;
+
+ commit = (var && strcmp(var, "commit") == 0);
+
+ notice[0] = '\0';
+ old_notice_hook = PQsetNoticeProcessor(pset->db, _my_notice_handler, NULL);
+
+ res = PSQLexec(pset, commit ? "COMMIT" : "ROLLBACK");
+ if (!res)
+ return false;
- commit = (var && strcmp(var, "commit")==0);
-
- notice[0] = '\0';
- old_notice_hook = PQsetNoticeProcessor(pset->db, _my_notice_handler, NULL);
-
- res = PSQLexec(pset, commit ? "COMMIT" : "ROLLBACK");
- if (!res)
- return false;
-
- if (notice[0]) {
- if ( (!commit && strcmp(notice, "NOTICE: UserAbortTransactionBlock and not in in-progress state\n")!=0) ||
- (commit && strcmp(notice, "NOTICE: EndTransactionBlock and not inprogress/abort state\n")!=0) )
- fputs(notice, stderr);
- }
- else if (!GetVariableBool(pset->vars, "quiet")) {
- if (commit)
- puts("Warning: Your transaction in progress has been committed.");
- else
- puts("Warning: Your transaction in progress has been rolled back.");
- }
-
- PQsetNoticeProcessor(pset->db, old_notice_hook, NULL);
- return true;
+ if (notice[0])
+ {
+ if ((!commit && strcmp(notice, "NOTICE: UserAbortTransactionBlock and not in in-progress state\n") != 0) ||
+ (commit && strcmp(notice, "NOTICE: EndTransactionBlock and not inprogress/abort state\n") != 0))
+ fputs(notice, stderr);
+ }
+ else if (!GetVariableBool(pset->vars, "quiet"))
+ {
+ if (commit)
+ puts("Warning: Your transaction in progress has been committed.");
+ else
+ puts("Warning: Your transaction in progress has been rolled back.");
+ }
+
+ PQsetNoticeProcessor(pset->db, old_notice_hook, NULL);
+ return true;
}
@@ -75,54 +78,61 @@ handle_transaction(PsqlSettings * pset)
* Write a large object to a file
*/
bool
-do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_arg)
+do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg)
{
- PGresult * res;
- int status;
- bool own_transaction = true;
- const char * var = GetVariable(pset->vars, "lo_transaction");
-
- if (var && strcmp(var, "nothing")==0)
- own_transaction = false;
+ PGresult *res;
+ int status;
+ bool own_transaction = true;
+ const char *var = GetVariable(pset->vars, "lo_transaction");
+
+ if (var && strcmp(var, "nothing") == 0)
+ own_transaction = false;
+
+ if (!pset->db)
+ {
+ fputs("You are not connected to a database.\n", stderr);
+ return false;
+ }
- if (!pset->db) {
- fputs("You are not connected to a database.\n", stderr);
- return false;
- }
+ if (own_transaction)
+ {
+ if (!handle_transaction(pset))
+ return false;
- if (own_transaction) {
- if (!handle_transaction(pset))
- return false;
+ if (!(res = PSQLexec(pset, "BEGIN")))
+ return false;
- if (!(res = PSQLexec(pset, "BEGIN")))
- return false;
+ PQclear(res);
+ }
- PQclear(res);
- }
-
- status = lo_export(pset->db, atol(loid_arg), (char *)filename_arg);
- if (status != 1) { /* of course this status is documented nowhere :( */
- fputs(PQerrorMessage(pset->db), stderr);
- if (own_transaction) {
- res = PQexec(pset->db, "ROLLBACK");
- PQclear(res);
+ status = lo_export(pset->db, atol(loid_arg), (char *) filename_arg);
+ if (status != 1)
+ { /* of course this status is documented
+ * nowhere :( */
+ fputs(PQerrorMessage(pset->db), stderr);
+ if (own_transaction)
+ {
+ res = PQexec(pset->db, "ROLLBACK");
+ PQclear(res);
+ }
+ return false;
}
- return false;
- }
-
- if (own_transaction) {
- if (!(res = PSQLexec(pset, "COMMIT"))) {
- res = PQexec(pset->db, "ROLLBACK");
- PQclear(res);
- return false;
+
+ if (own_transaction)
+ {
+ if (!(res = PSQLexec(pset, "COMMIT")))
+ {
+ res = PQexec(pset->db, "ROLLBACK");
+ PQclear(res);
+ return false;
+ }
+
+ PQclear(res);
}
- PQclear(res);
- }
+ fprintf(pset->queryFout, "lo_export\n");
- fprintf(pset->queryFout, "lo_export\n");
-
- return true;
+ return true;
}
@@ -133,76 +143,85 @@ do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_a
* Copy large object from file to database
*/
bool
-do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * comment_arg)
+do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_arg)
{
- PGresult * res;
- Oid loid;
- char buf[1024];
- unsigned int i;
- bool own_transaction = true;
- const char * var = GetVariable(pset->vars, "lo_transaction");
-
- if (var && strcmp(var, "nothing")==0)
- own_transaction = false;
-
- if (!pset->db) {
- fputs("You are not connected to a database.\n", stderr);
- return false;
- }
+ PGresult *res;
+ Oid loid;
+ char buf[1024];
+ unsigned int i;
+ bool own_transaction = true;
+ const char *var = GetVariable(pset->vars, "lo_transaction");
+
+ if (var && strcmp(var, "nothing") == 0)
+ own_transaction = false;
+
+ if (!pset->db)
+ {
+ fputs("You are not connected to a database.\n", stderr);
+ return false;
+ }
- if (own_transaction) {
- if (!handle_transaction(pset))
- return false;
+ if (own_transaction)
+ {
+ if (!handle_transaction(pset))
+ return false;
- if (!(res = PSQLexec(pset, "BEGIN")))
- return false;
+ if (!(res = PSQLexec(pset, "BEGIN")))
+ return false;
- PQclear(res);
- }
-
- loid = lo_import(pset->db, (char *)filename_arg);
- if (loid == InvalidOid) {
- fputs(PQerrorMessage(pset->db), stderr);
- if (own_transaction) {
- res = PQexec(pset->db, "ROLLBACK");
- PQclear(res);
- }
- return false;
- }
-
- /* insert description if given */
- if (comment_arg) {
- sprintf(buf, "INSERT INTO pg_description VALUES (%d, '", loid);
- for (i=0; i<strlen(comment_arg); i++)
- if (comment_arg[i]=='\'')
- strcat(buf, "\\'");
- else
- strncat(buf, &comment_arg[i], 1);
- strcat(buf, "')");
-
- if (!(res = PSQLexec(pset, buf))) {
- if (own_transaction) {
- res = PQexec(pset->db, "ROLLBACK");
PQclear(res);
- }
- return false;
}
- }
- if (own_transaction) {
- if (!(res = PSQLexec(pset, "COMMIT"))) {
- res = PQexec(pset->db, "ROLLBACK");
- PQclear(res);
- return false;
+ loid = lo_import(pset->db, (char *) filename_arg);
+ if (loid == InvalidOid)
+ {
+ fputs(PQerrorMessage(pset->db), stderr);
+ if (own_transaction)
+ {
+ res = PQexec(pset->db, "ROLLBACK");
+ PQclear(res);
+ }
+ return false;
}
- PQclear(res);
- }
+ /* insert description if given */
+ if (comment_arg)
+ {
+ sprintf(buf, "INSERT INTO pg_description VALUES (%d, '", loid);
+ for (i = 0; i < strlen(comment_arg); i++)
+ if (comment_arg[i] == '\'')
+ strcat(buf, "\\'");
+ else
+ strncat(buf, &comment_arg[i], 1);
+ strcat(buf, "')");
+
+ if (!(res = PSQLexec(pset, buf)))
+ {
+ if (own_transaction)
+ {
+ res = PQexec(pset->db, "ROLLBACK");
+ PQclear(res);
+ }
+ return false;
+ }
+ }
+ if (own_transaction)
+ {
+ if (!(res = PSQLexec(pset, "COMMIT")))
+ {
+ res = PQexec(pset->db, "ROLLBACK");
+ PQclear(res);
+ return false;
+ }
- fprintf(pset->queryFout, "lo_import %d\n", loid);
+ PQclear(res);
+ }
- return true;
+
+ fprintf(pset->queryFout, "lo_import %d\n", loid);
+
+ return true;
}
@@ -212,67 +231,76 @@ do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * commen
*
* removes a large object out of the database
*/
-bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
+bool
+do_lo_unlink(PsqlSettings *pset, const char *loid_arg)
{
- PGresult * res;
- int status;
- Oid loid = (Oid)atol(loid_arg);
- char buf[256];
- bool own_transaction = true;
- const char * var = GetVariable(pset->vars, "lo_transaction");
-
- if (var && strcmp(var, "nothing")==0)
- own_transaction = false;
+ PGresult *res;
+ int status;
+ Oid loid = (Oid) atol(loid_arg);
+ char buf[256];
+ bool own_transaction = true;
+ const char *var = GetVariable(pset->vars, "lo_transaction");
+
+ if (var && strcmp(var, "nothing") == 0)
+ own_transaction = false;
+
+ if (!pset->db)
+ {
+ fputs("You are not connected to a database.\n", stderr);
+ return false;
+ }
- if (!pset->db) {
- fputs("You are not connected to a database.\n", stderr);
- return false;
- }
+ if (own_transaction)
+ {
+ if (!handle_transaction(pset))
+ return false;
- if (own_transaction) {
- if (!handle_transaction(pset))
- return false;
+ if (!(res = PSQLexec(pset, "BEGIN")))
+ return false;
- if (!(res = PSQLexec(pset, "BEGIN")))
- return false;
+ PQclear(res);
+ }
- PQclear(res);
- }
-
- status = lo_unlink(pset->db, loid);
- if (status == -1) {
- fputs(PQerrorMessage(pset->db), stderr);
- if (own_transaction) {
- res = PQexec(pset->db, "ROLLBACK");
- PQclear(res);
+ status = lo_unlink(pset->db, loid);
+ if (status == -1)
+ {
+ fputs(PQerrorMessage(pset->db), stderr);
+ if (own_transaction)
+ {
+ res = PQexec(pset->db, "ROLLBACK");
+ PQclear(res);
+ }
+ return false;
}
- return false;
- }
-
- /* remove the comment as well */
- sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid);
- if (!(res = PSQLexec(pset, buf))) {
- if (own_transaction) {
- res = PQexec(pset->db, "ROLLBACK");
- PQclear(res);
+
+ /* remove the comment as well */
+ sprintf(buf, "DELETE FROM pg_description WHERE objoid = %d", loid);
+ if (!(res = PSQLexec(pset, buf)))
+ {
+ if (own_transaction)
+ {
+ res = PQexec(pset->db, "ROLLBACK");
+ PQclear(res);
+ }
+ return false;
}
- return false;
- }
- if (own_transaction) {
- if (!(res = PSQLexec(pset, "COMMIT"))) {
- res = PQexec(pset->db, "ROLLBACK");
- PQclear(res);
- return false;
+ if (own_transaction)
+ {
+ if (!(res = PSQLexec(pset, "COMMIT")))
+ {
+ res = PQexec(pset->db, "ROLLBACK");
+ PQclear(res);
+ return false;
+ }
+ PQclear(res);
}
- PQclear(res);
- }
- fprintf(pset->queryFout, "lo_unlink %d\n", loid);
+ fprintf(pset->queryFout, "lo_unlink %d\n", loid);
- return true;
+ return true;
}
@@ -282,30 +310,31 @@ bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg)
*
* Show all large objects in database, with comments if desired
*/
-bool do_lo_list(PsqlSettings * pset)
+bool
+do_lo_list(PsqlSettings *pset)
{
- PGresult * res;
- char descbuf[512];
- printQueryOpt myopt = pset->popt;
-
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT usename as \"Owner\", substring(relname from 5) as \"ID\"");
- if (GetVariableBool(pset->vars, "description"))
- strcat(descbuf, ",\n obj_description(pg_class.oid) as \"Description\"");
- strcat(descbuf,"\nFROM pg_class, pg_user\n"
+ PGresult *res;
+ char descbuf[512];
+ printQueryOpt myopt = pset->popt;
+
+ descbuf[0] = '\0';
+ strcat(descbuf, "SELECT usename as \"Owner\", substring(relname from 5) as \"ID\"");
+ if (GetVariableBool(pset->vars, "description"))
+ strcat(descbuf, ",\n obj_description(pg_class.oid) as \"Description\"");
+ strcat(descbuf, "\nFROM pg_class, pg_user\n"
"WHERE usesysid = relowner AND relkind = 'l'\n"
"ORDER BY \"ID\"");
- res = PSQLexec(pset, descbuf);
- if (!res)
- return false;
+ res = PSQLexec(pset, descbuf);
+ if (!res)
+ return false;
- myopt.topt.tuples_only = false;
- myopt.nullPrint = NULL;
- myopt.title = "Large objects";
+ myopt.topt.tuples_only = false;
+ myopt.nullPrint = NULL;
+ myopt.title = "Large objects";
- printQuery(res, &myopt, pset->queryFout);
+ printQuery(res, &myopt, pset->queryFout);
- PQclear(res);
- return true;
+ PQclear(res);
+ return true;
}
diff --git a/src/bin/psql/large_obj.h b/src/bin/psql/large_obj.h
index 22228e7b11..4f3f2fc428 100644
--- a/src/bin/psql/large_obj.h
+++ b/src/bin/psql/large_obj.h
@@ -3,9 +3,9 @@
#include "settings.h"
-bool do_lo_export(PsqlSettings * pset, const char * loid_arg, const char * filename_arg);
-bool do_lo_import(PsqlSettings * pset, const char * filename_arg, const char * comment_arg);
-bool do_lo_unlink(PsqlSettings * pset, const char * loid_arg);
-bool do_lo_list(PsqlSettings * pset);
+bool do_lo_export(PsqlSettings *pset, const char *loid_arg, const char *filename_arg);
+bool do_lo_import(PsqlSettings *pset, const char *filename_arg, const char *comment_arg);
+bool do_lo_unlink(PsqlSettings *pset, const char *loid_arg);
+bool do_lo_list(PsqlSettings *pset);
-#endif /* LARGE_OBJ_H */
+#endif /* LARGE_OBJ_H */
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index 2f38ffbcff..560488fff4 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -26,343 +26,380 @@
int
MainLoop(PsqlSettings *pset, FILE *source)
{
- PQExpBuffer query_buf; /* buffer for query being accumulated */
- char *line; /* current line of input */
- char *xcomment; /* start of extended comment */
- int len; /* length of the line */
- int successResult = EXIT_SUCCESS;
- backslashResult slashCmdStatus;
+ PQExpBuffer query_buf; /* buffer for query being accumulated */
+ char *line; /* current line of input */
+ char *xcomment; /* start of extended comment */
+ int len; /* length of the line */
+ int successResult = EXIT_SUCCESS;
+ backslashResult slashCmdStatus;
- bool eof = false; /* end of our command input? */
- bool success;
- char in_quote; /* == 0 for no in_quote */
- bool was_bslash; /* backslash */
- int paren_level;
- unsigned int query_start;
+ bool eof = false; /* end of our command input? */
+ bool success;
+ char in_quote; /* == 0 for no in_quote */
+ bool was_bslash; /* backslash */
+ int paren_level;
+ unsigned int query_start;
- int i, prevlen, thislen;
+ int i,
+ prevlen,
+ thislen;
- /* Save the prior command source */
- FILE *prev_cmd_source;
- bool prev_cmd_interactive;
+ /* Save the prior command source */
+ FILE *prev_cmd_source;
+ bool prev_cmd_interactive;
- bool die_on_error;
- const char *interpol_char;
+ bool die_on_error;
+ const char *interpol_char;
- /* Save old settings */
- prev_cmd_source = pset->cur_cmd_source;
- prev_cmd_interactive = pset->cur_cmd_interactive;
+ /* Save old settings */
+ prev_cmd_source = pset->cur_cmd_source;
+ prev_cmd_interactive = pset->cur_cmd_interactive;
- /* Establish new source */
- pset->cur_cmd_source = source;
- pset->cur_cmd_interactive = ((source == stdin) && !pset->notty);
+ /* Establish new source */
+ pset->cur_cmd_source = source;
+ pset->cur_cmd_interactive = ((source == stdin) && !pset->notty);
- query_buf = createPQExpBuffer();
- if (!query_buf) {
- perror("createPQExpBuffer");
- exit(EXIT_FAILURE);
- }
+ query_buf = createPQExpBuffer();
+ if (!query_buf)
+ {
+ perror("createPQExpBuffer");
+ exit(EXIT_FAILURE);
+ }
- xcomment = NULL;
- in_quote = 0;
- paren_level = 0;
- slashCmdStatus = CMD_UNKNOWN; /* set default */
+ xcomment = NULL;
+ in_quote = 0;
+ paren_level = 0;
+ slashCmdStatus = CMD_UNKNOWN; /* set default */
- /* main loop to get queries and execute them */
- while (!eof)
- {
- if (slashCmdStatus == CMD_NEWEDIT)
+ /* main loop to get queries and execute them */
+ while (!eof)
{
- /*
- * just returned from editing the line? then just copy to the
- * input buffer
- */
- line = strdup(query_buf->data);
- resetPQExpBuffer(query_buf);
- /* reset parsing state since we are rescanning whole query */
- xcomment = NULL;
- in_quote = 0;
- paren_level = 0;
- }
- else
- {
- /*
- * otherwise, set interactive prompt if necessary
- * and get another line
- */
- if (pset->cur_cmd_interactive)
- {
- int prompt_status;
-
- if (in_quote && in_quote == '\'')
- prompt_status = PROMPT_SINGLEQUOTE;
- else if (in_quote && in_quote == '"')
- prompt_status= PROMPT_DOUBLEQUOTE;
- else if (xcomment != NULL)
- prompt_status = PROMPT_COMMENT;
- else if (query_buf->len > 0)
- prompt_status = PROMPT_CONTINUE;
+ if (slashCmdStatus == CMD_NEWEDIT)
+ {
+
+ /*
+ * just returned from editing the line? then just copy to the
+ * input buffer
+ */
+ line = strdup(query_buf->data);
+ resetPQExpBuffer(query_buf);
+ /* reset parsing state since we are rescanning whole query */
+ xcomment = NULL;
+ in_quote = 0;
+ paren_level = 0;
+ }
else
- prompt_status = PROMPT_READY;
-
- line = gets_interactive(get_prompt(pset, prompt_status));
- }
- else
- line = gets_fromFile(source);
- }
+ {
+
+ /*
+ * otherwise, set interactive prompt if necessary and get
+ * another line
+ */
+ if (pset->cur_cmd_interactive)
+ {
+ int prompt_status;
+
+ if (in_quote && in_quote == '\'')
+ prompt_status = PROMPT_SINGLEQUOTE;
+ else if (in_quote && in_quote == '"')
+ prompt_status = PROMPT_DOUBLEQUOTE;
+ else if (xcomment != NULL)
+ prompt_status = PROMPT_COMMENT;
+ else if (query_buf->len > 0)
+ prompt_status = PROMPT_CONTINUE;
+ else
+ prompt_status = PROMPT_READY;
+
+ line = gets_interactive(get_prompt(pset, prompt_status));
+ }
+ else
+ line = gets_fromFile(source);
+ }
- /* Setting these will not have effect until next line */
- die_on_error = GetVariableBool(pset->vars, "die_on_error");
- interpol_char = GetVariable(pset->vars, "sql_interpol");;
+ /* Setting these will not have effect until next line */
+ die_on_error = GetVariableBool(pset->vars, "die_on_error");
+ interpol_char = GetVariable(pset->vars, "sql_interpol");;
- /*
- * query_buf holds query already accumulated. line is the malloc'd
- * new line of input (note it must be freed before looping around!)
- * query_start is the next command start location within the line.
- */
+ /*
+ * query_buf holds query already accumulated. line is the
+ * malloc'd new line of input (note it must be freed before
+ * looping around!) query_start is the next command start location
+ * within the line.
+ */
- /* No more input. Time to quit, or \i done */
- if (line == NULL || (!pset->cur_cmd_interactive && *line == '\0'))
- {
- if (GetVariableBool(pset->vars, "echo") && !GetVariableBool(pset->vars, "quiet"))
- puts("EOF");
- eof = true;
- continue;
- }
+ /* No more input. Time to quit, or \i done */
+ if (line == NULL || (!pset->cur_cmd_interactive && *line == '\0'))
+ {
+ if (GetVariableBool(pset->vars, "echo") && !GetVariableBool(pset->vars, "quiet"))
+ puts("EOF");
+ eof = true;
+ continue;
+ }
- /* not currently inside an extended comment? */
- if (xcomment)
- xcomment = line;
+ /* not currently inside an extended comment? */
+ if (xcomment)
+ xcomment = line;
- /* strip trailing backslashes, they don't have a clear meaning */
- while (1) {
- char * cp = strrchr(line, '\\');
- if (cp && (*(cp + 1) == '\0'))
- *cp = '\0';
- else
- break;
- }
+ /* strip trailing backslashes, they don't have a clear meaning */
+ while (1)
+ {
+ char *cp = strrchr(line, '\\');
-
- /* echo back if input is from file and flag is set */
- if (!pset->cur_cmd_interactive && GetVariableBool(pset->vars, "echo"))
- fprintf(stderr, "%s\n", line);
-
-
- /* interpolate variables into SQL */
- len = strlen(line);
- thislen = PQmblen(line);
-
- for (i = 0; line[i]; i += (thislen = PQmblen(&line[i])) ) {
- if (interpol_char && interpol_char[0] != '\0' && interpol_char[0] == line[i]) {
- size_t in_length, out_length;
- const char * value;
- char * new;
- bool closer; /* did we have a closing delimiter or just an end of line? */
-
- in_length = strcspn(&line[i+thislen], interpol_char);
- closer = line[i + thislen + in_length] == line[i];
- line[i + thislen + in_length] = '\0';
- value = interpolate_var(&line[i + thislen], pset);
- out_length = strlen(value);
-
- new = malloc(len + out_length - (in_length + (closer ? 2 : 1)) + 1);
- if (!new) {
- perror("malloc");
- exit(EXIT_FAILURE);
+ if (cp && (*(cp + 1) == '\0'))
+ *cp = '\0';
+ else
+ break;
}
- new[0] = '\0';
- strncat(new, line, i);
- strcat(new, value);
- if (closer)
- strcat(new, line + i + 2 + in_length);
- free(line);
- line = new;
- i += out_length;
- }
- }
+ /* echo back if input is from file and flag is set */
+ if (!pset->cur_cmd_interactive && GetVariableBool(pset->vars, "echo"))
+ fprintf(stderr, "%s\n", line);
+
+
+ /* interpolate variables into SQL */
+ len = strlen(line);
+ thislen = PQmblen(line);
+
+ for (i = 0; line[i]; i += (thislen = PQmblen(&line[i])))
+ {
+ if (interpol_char && interpol_char[0] != '\0' && interpol_char[0] == line[i])
+ {
+ size_t in_length,
+ out_length;
+ const char *value;
+ char *new;
+ bool closer; /* did we have a closing delimiter
+ * or just an end of line? */
+
+ in_length = strcspn(&line[i + thislen], interpol_char);
+ closer = line[i + thislen + in_length] == line[i];
+ line[i + thislen + in_length] = '\0';
+ value = interpolate_var(&line[i + thislen], pset);
+ out_length = strlen(value);
+
+ new = malloc(len + out_length - (in_length + (closer ? 2 : 1)) + 1);
+ if (!new)
+ {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
+ new[0] = '\0';
+ strncat(new, line, i);
+ strcat(new, value);
+ if (closer)
+ strcat(new, line + i + 2 + in_length);
+
+ free(line);
+ line = new;
+ i += out_length;
+ }
+ }
- /* nothing left on line? then ignore */
- if (line[0] == '\0') {
- free(line);
- continue;
- }
+ /* nothing left on line? then ignore */
+ if (line[0] == '\0')
+ {
+ free(line);
+ continue;
+ }
- slashCmdStatus = CMD_UNKNOWN;
+ slashCmdStatus = CMD_UNKNOWN;
- len = strlen(line);
- query_start = 0;
+ len = strlen(line);
+ query_start = 0;
- /*
- * Parse line, looking for command separators.
- *
- * The current character is at line[i], the prior character at
- * line[i - prevlen], the next character at line[i + thislen].
- */
- prevlen = 0;
- thislen = (len > 0) ? PQmblen(line) : 0;
+ /*
+ * Parse line, looking for command separators.
+ *
+ * The current character is at line[i], the prior character at line[i
+ * - prevlen], the next character at line[i + thislen].
+ */
+ prevlen = 0;
+ thislen = (len > 0) ? PQmblen(line) : 0;
#define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i))
- success = true;
- for (i = 0; i < len; ADVANCE_1) {
- if (!success && die_on_error)
- break;
-
-
- /* was the previous character a backslash? */
- if (i > 0 && line[i - prevlen] == '\\')
- was_bslash = true;
- else
- was_bslash = false;
-
-
- /* in quote? */
- if (in_quote) {
- /* end of quote */
- if (line[i] == in_quote && !was_bslash)
- in_quote = '\0';
- }
-
- /* start of quote */
- else if (line[i] == '\'' || line[i] == '"')
- in_quote = line[i];
-
- /* in extended comment? */
- else if (xcomment != NULL) {
- if (line[i] == '*' && line[i + thislen] == '/') {
- xcomment = NULL;
- ADVANCE_1;
- }
- }
-
- /* start of extended comment? */
- else if (line[i] == '/' && line[i + thislen] == '*') {
- xcomment = &line[i];
- ADVANCE_1;
- }
-
- /* single-line comment? truncate line */
- else if ((line[i] == '-' && line[i + thislen] == '-') ||
- (line[i] == '/' && line[i + thislen] == '/'))
- {
- line[i] = '\0'; /* remove comment */
- break;
- }
-
- /* count nested parentheses */
- else if (line[i] == '(')
- paren_level++;
-
- else if (line[i] == ')' && paren_level > 0)
- paren_level--;
-
- /* semicolon? then send query */
- else if (line[i] == ';' && !was_bslash && paren_level==0) {
- line[i] = '\0';
- /* is there anything else on the line? */
- if (line[query_start + strspn(line + query_start, " \t")]!='\0') {
- /* insert a cosmetic newline, if this is not the first line in the buffer */
- if (query_buf->len > 0)
- appendPQExpBufferChar(query_buf, '\n');
- /* append the line to the query buffer */
- appendPQExpBufferStr(query_buf, line + query_start);
+ success = true;
+ for (i = 0; i < len; ADVANCE_1)
+ {
+ if (!success && die_on_error)
+ break;
+
+
+ /* was the previous character a backslash? */
+ if (i > 0 && line[i - prevlen] == '\\')
+ was_bslash = true;
+ else
+ was_bslash = false;
+
+
+ /* in quote? */
+ if (in_quote)
+ {
+ /* end of quote */
+ if (line[i] == in_quote && !was_bslash)
+ in_quote = '\0';
+ }
+
+ /* start of quote */
+ else if (line[i] == '\'' || line[i] == '"')
+ in_quote = line[i];
+
+ /* in extended comment? */
+ else if (xcomment != NULL)
+ {
+ if (line[i] == '*' && line[i + thislen] == '/')
+ {
+ xcomment = NULL;
+ ADVANCE_1;
+ }
+ }
+
+ /* start of extended comment? */
+ else if (line[i] == '/' && line[i + thislen] == '*')
+ {
+ xcomment = &line[i];
+ ADVANCE_1;
+ }
+
+ /* single-line comment? truncate line */
+ else if ((line[i] == '-' && line[i + thislen] == '-') ||
+ (line[i] == '/' && line[i + thislen] == '/'))
+ {
+ line[i] = '\0'; /* remove comment */
+ break;
+ }
+
+ /* count nested parentheses */
+ else if (line[i] == '(')
+ paren_level++;
+
+ else if (line[i] == ')' && paren_level > 0)
+ paren_level--;
+
+ /* semicolon? then send query */
+ else if (line[i] == ';' && !was_bslash && paren_level == 0)
+ {
+ line[i] = '\0';
+ /* is there anything else on the line? */
+ if (line[query_start + strspn(line + query_start, " \t")] != '\0')
+ {
+
+ /*
+ * insert a cosmetic newline, if this is not the first
+ * line in the buffer
+ */
+ if (query_buf->len > 0)
+ appendPQExpBufferChar(query_buf, '\n');
+ /* append the line to the query buffer */
+ appendPQExpBufferStr(query_buf, line + query_start);
+ }
+
+ /* execute query */
+ success = SendQuery(pset, query_buf->data);
+
+ resetPQExpBuffer(query_buf);
+ query_start = i + thislen;
+ }
+
+ /* backslash command */
+ else if (was_bslash)
+ {
+ const char *end_of_cmd = NULL;
+
+ line[i - prevlen] = '\0'; /* overwrites backslash */
+
+ /* is there anything else on the line? */
+ if (line[query_start + strspn(line + query_start, " \t")] != '\0')
+ {
+
+ /*
+ * insert a cosmetic newline, if this is not the first
+ * line in the buffer
+ */
+ if (query_buf->len > 0)
+ appendPQExpBufferChar(query_buf, '\n');
+ /* append the line to the query buffer */
+ appendPQExpBufferStr(query_buf, line + query_start);
+ }
+
+ /* handle backslash command */
+
+ slashCmdStatus = HandleSlashCmds(pset, &line[i], query_buf, &end_of_cmd);
+
+ success = slashCmdStatus != CMD_ERROR;
+
+ if (slashCmdStatus == CMD_SEND)
+ {
+ success = SendQuery(pset, query_buf->data);
+ resetPQExpBuffer(query_buf);
+ query_start = i + thislen;
+ }
+
+ /* is there anything left after the backslash command? */
+ if (end_of_cmd)
+ {
+ i += end_of_cmd - &line[i];
+ query_start = i;
+ }
+ else
+ break;
+ }
}
- /* execute query */
- success = SendQuery(pset, query_buf->data);
-
- resetPQExpBuffer(query_buf);
- query_start = i + thislen;
- }
-
- /* backslash command */
- else if (was_bslash) {
- const char * end_of_cmd = NULL;
-
- line[i - prevlen] = '\0'; /* overwrites backslash */
- /* is there anything else on the line? */
- if (line[query_start + strspn(line + query_start, " \t")]!='\0') {
- /* insert a cosmetic newline, if this is not the first line in the buffer */
- if (query_buf->len > 0)
- appendPQExpBufferChar(query_buf, '\n');
- /* append the line to the query buffer */
- appendPQExpBufferStr(query_buf, line + query_start);
+ if (!success && die_on_error && !pset->cur_cmd_interactive)
+ {
+ successResult = EXIT_USER;
+ break;
}
- /* handle backslash command */
- slashCmdStatus = HandleSlashCmds(pset, &line[i], query_buf, &end_of_cmd);
-
- success = slashCmdStatus != CMD_ERROR;
-
- if (slashCmdStatus == CMD_SEND) {
- success = SendQuery(pset, query_buf->data);
- resetPQExpBuffer(query_buf);
- query_start = i + thislen;
+ if (slashCmdStatus == CMD_TERMINATE)
+ {
+ successResult = EXIT_SUCCESS;
+ break;
}
- /* is there anything left after the backslash command? */
- if (end_of_cmd) {
- i += end_of_cmd - &line[i];
- query_start = i;
- }
- else
- break;
- }
- }
-
-
- if (!success && die_on_error && !pset->cur_cmd_interactive) {
- successResult = EXIT_USER;
- break;
- }
+ /* Put the rest of the line in the query buffer. */
+ if (line[query_start + strspn(line + query_start, " \t")] != '\0')
+ {
+ if (query_buf->len > 0)
+ appendPQExpBufferChar(query_buf, '\n');
+ appendPQExpBufferStr(query_buf, line + query_start);
+ }
- if (slashCmdStatus == CMD_TERMINATE) {
- successResult = EXIT_SUCCESS;
- break;
- }
-
+ free(line);
- /* Put the rest of the line in the query buffer. */
- if (line[query_start + strspn(line + query_start, " \t")]!='\0') {
- if (query_buf->len > 0)
- appendPQExpBufferChar(query_buf, '\n');
- appendPQExpBufferStr(query_buf, line + query_start);
- }
- free(line);
+ /* In single line mode, send off the query if any */
+ if (query_buf->data[0] != '\0' && GetVariableBool(pset->vars, "singleline"))
+ {
+ success = SendQuery(pset, query_buf->data);
+ resetPQExpBuffer(query_buf);
+ }
- /* In single line mode, send off the query if any */
- if (query_buf->data[0] != '\0' && GetVariableBool(pset->vars, "singleline")) {
- success = SendQuery(pset, query_buf->data);
- resetPQExpBuffer(query_buf);
- }
-
-
- /* Have we lost the db connection? */
- if (pset->db == NULL && !pset->cur_cmd_interactive) {
- successResult = EXIT_BADCONN;
- break;
- }
- } /* while */
+ /* Have we lost the db connection? */
+ if (pset->db == NULL && !pset->cur_cmd_interactive)
+ {
+ successResult = EXIT_BADCONN;
+ break;
+ }
+ } /* while */
- destroyPQExpBuffer(query_buf);
+ destroyPQExpBuffer(query_buf);
- pset->cur_cmd_source = prev_cmd_source;
- pset->cur_cmd_interactive = prev_cmd_interactive;
+ pset->cur_cmd_source = prev_cmd_source;
+ pset->cur_cmd_interactive = prev_cmd_interactive;
- return successResult;
+ return successResult;
} /* MainLoop() */
-
diff --git a/src/bin/psql/mainloop.h b/src/bin/psql/mainloop.h
index 0e2e5dd06e..b2b05d7d11 100644
--- a/src/bin/psql/mainloop.h
+++ b/src/bin/psql/mainloop.h
@@ -5,6 +5,6 @@
#include "settings.h"
int
-MainLoop(PsqlSettings *pset, FILE *source);
+ MainLoop(PsqlSettings *pset, FILE *source);
-#endif MAINLOOP_H
+#endif /* MAINLOOP_H */
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index c710f02f28..5c6525b6f3 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -7,8 +7,8 @@
#include <math.h>
#include <signal.h>
#ifndef WIN32
-#include <unistd.h> /* for isatty() */
-#include <sys/ioctl.h> /* for ioctl() */
+#include <unistd.h> /* for isatty() */
+#include <sys/ioctl.h> /* for ioctl() */
#else
#define popen(x,y) _popen(x,y)
#define pclose(x) _pclose(x)
@@ -16,386 +16,422 @@
#include <pqsignal.h>
#include <libpq-fe.h>
-#include <postgres_ext.h> /* for Oid type */
+#include <postgres_ext.h> /* for Oid type */
#define DEFAULT_PAGER "/bin/more"
/*************************/
-/* Unaligned text */
+/* Unaligned text */
/*************************/
static void
-print_unaligned_text(const char * title, char ** headers, char ** cells, char ** footers,
- const char * opt_fieldsep, bool opt_barebones,
- FILE * fout)
+print_unaligned_text(const char *title, char **headers, char **cells, char **footers,
+ const char *opt_fieldsep, bool opt_barebones,
+ FILE *fout)
{
- unsigned int col_count = 0;
- unsigned int i;
- char ** ptr;
-
- if (!opt_fieldsep)
- opt_fieldsep = "";
-
- /* print title */
- if (!opt_barebones && title)
- fprintf(fout, "%s\n", title);
-
- /* print headers and count columns */
- for (ptr = headers; *ptr; ptr++) {
- col_count++;
- if (!opt_barebones) {
- if (col_count>1)
- fputs(opt_fieldsep, fout);
- fputs(*ptr, fout);
- }
- }
- if (!opt_barebones)
- fputs("\n", fout);
-
- /* print cells */
- i = 0;
- for (ptr = cells; *ptr; ptr++) {
- fputs(*ptr, fout);
- if ((i+1) % col_count)
- fputs(opt_fieldsep, fout);
- else
- fputs("\n", fout);
- i++;
- }
+ unsigned int col_count = 0;
+ unsigned int i;
+ char **ptr;
+
+ if (!opt_fieldsep)
+ opt_fieldsep = "";
+
+ /* print title */
+ if (!opt_barebones && title)
+ fprintf(fout, "%s\n", title);
+
+ /* print headers and count columns */
+ for (ptr = headers; *ptr; ptr++)
+ {
+ col_count++;
+ if (!opt_barebones)
+ {
+ if (col_count > 1)
+ fputs(opt_fieldsep, fout);
+ fputs(*ptr, fout);
+ }
+ }
+ if (!opt_barebones)
+ fputs("\n", fout);
+
+ /* print cells */
+ i = 0;
+ for (ptr = cells; *ptr; ptr++)
+ {
+ fputs(*ptr, fout);
+ if ((i + 1) % col_count)
+ fputs(opt_fieldsep, fout);
+ else
+ fputs("\n", fout);
+ i++;
+ }
- /* print footers */
+ /* print footers */
- if (!opt_barebones && footers)
- for (ptr = footers; *ptr; ptr++)
- fprintf(fout, "%s\n", *ptr);
+ if (!opt_barebones && footers)
+ for (ptr = footers; *ptr; ptr++)
+ fprintf(fout, "%s\n", *ptr);
}
static void
-print_unaligned_vertical(const char * title, char ** headers, char ** cells, char ** footers,
- const char * opt_fieldsep, bool opt_barebones,
- FILE * fout)
+print_unaligned_vertical(const char *title, char **headers, char **cells, char **footers,
+ const char *opt_fieldsep, bool opt_barebones,
+ FILE *fout)
{
- unsigned int col_count = 0;
- unsigned int i;
- unsigned int record = 1;
- char ** ptr;
-
- if (!opt_fieldsep)
- opt_fieldsep = "";
-
- /* print title */
- if (!opt_barebones && title)
- fprintf(fout, "%s\n", title);
-
- /* count columns */
- for (ptr = headers; *ptr; ptr++) {
- col_count++;
- }
-
- /* print records */
- for (i=0, ptr = cells; *ptr; i++, ptr++) {
- if (i % col_count == 0) {
- if (!opt_barebones)
- fprintf(fout, "-- RECORD %d\n", record++);
- else
- fputc('\n', fout);
+ unsigned int col_count = 0;
+ unsigned int i;
+ unsigned int record = 1;
+ char **ptr;
+
+ if (!opt_fieldsep)
+ opt_fieldsep = "";
+
+ /* print title */
+ if (!opt_barebones && title)
+ fprintf(fout, "%s\n", title);
+
+ /* count columns */
+ for (ptr = headers; *ptr; ptr++)
+ col_count++;
+
+ /* print records */
+ for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ {
+ if (i % col_count == 0)
+ {
+ if (!opt_barebones)
+ fprintf(fout, "-- RECORD %d\n", record++);
+ else
+ fputc('\n', fout);
+ }
+ fprintf(fout, "%s%s%s\n", headers[i % col_count], opt_fieldsep, *ptr);
}
- fprintf(fout, "%s%s%s\n", headers[i%col_count], opt_fieldsep, *ptr);
- }
- /* print footers */
+ /* print footers */
- if (!opt_barebones && footers) {
- fputs("--- END ---\n", fout);
- for (ptr = footers; *ptr; ptr++)
- fprintf(fout, "%s\n", *ptr);
- }
+ if (!opt_barebones && footers)
+ {
+ fputs("--- END ---\n", fout);
+ for (ptr = footers; *ptr; ptr++)
+ fprintf(fout, "%s\n", *ptr);
+ }
}
/********************/
-/* Aligned text */
+/* Aligned text */
/********************/
/* draw "line" */
static void
-_print_horizontal_line(const unsigned int col_count, const unsigned int * widths, unsigned short border, FILE * fout)
+_print_horizontal_line(const unsigned int col_count, const unsigned int *widths, unsigned short border, FILE *fout)
{
- unsigned int i, j;
- if (border == 1)
- fputc('-', fout);
- else if (border == 2)
- fputs("+-", fout);
-
- for (i=0; i<col_count; i++) {
- for (j=0; j<widths[i]; j++)
- fputc('-', fout);
-
- if (i<col_count-1) {
- if (border == 0)
- fputc(' ', fout);
- else
- fputs("-+-", fout);
- }
- }
-
- if (border == 2)
- fputs("-+", fout);
- else if (border == 1)
- fputc('-', fout);
-
- fputc('\n', fout);
+ unsigned int i,
+ j;
+
+ if (border == 1)
+ fputc('-', fout);
+ else if (border == 2)
+ fputs("+-", fout);
+
+ for (i = 0; i < col_count; i++)
+ {
+ for (j = 0; j < widths[i]; j++)
+ fputc('-', fout);
+
+ if (i < col_count - 1)
+ {
+ if (border == 0)
+ fputc(' ', fout);
+ else
+ fputs("-+-", fout);
+ }
+ }
+
+ if (border == 2)
+ fputs("-+", fout);
+ else if (border == 1)
+ fputc('-', fout);
+
+ fputc('\n', fout);
}
static void
-print_aligned_text(const char * title, char ** headers, char ** cells, char ** footers,
- const char * opt_align, bool opt_barebones, unsigned short int opt_border,
- FILE * fout)
+print_aligned_text(const char *title, char **headers, char **cells, char **footers,
+const char *opt_align, bool opt_barebones, unsigned short int opt_border,
+ FILE *fout)
{
- unsigned int col_count = 0;
- unsigned int i, tmp;
- unsigned int * widths, total_w;
- char ** ptr;
-
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- widths = calloc(col_count, sizeof (*widths));
- if (!widths) {
- perror("calloc");
- exit(EXIT_FAILURE);
- }
-
- /* calc column widths */
- for (i=0; i<col_count; i++)
- if ((tmp = strlen(headers[i])) > widths[i])
- widths[i] = tmp; /* don't wanna call strlen twice */
-
- for (i=0, ptr = cells; *ptr; ptr++, i++)
- if ((tmp = strlen(*ptr)) > widths[i % col_count])
- widths[i % col_count] = tmp;
-
- if (opt_border==0)
- total_w = col_count - 1;
- else if (opt_border==1)
- total_w = col_count*3 - 2;
- else
- total_w = col_count*3 + 1;
-
- for (i=0; i<col_count; i++)
- total_w += widths[i];
-
- /* print title */
- if (title && !opt_barebones) {
- if (strlen(title)>=total_w)
- fprintf(fout, "%s\n", title);
+ unsigned int col_count = 0;
+ unsigned int i,
+ tmp;
+ unsigned int *widths,
+ total_w;
+ char **ptr;
+
+ /* count columns */
+ for (ptr = headers; *ptr; ptr++)
+ col_count++;
+
+ widths = calloc(col_count, sizeof(*widths));
+ if (!widths)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+
+ /* calc column widths */
+ for (i = 0; i < col_count; i++)
+ if ((tmp = strlen(headers[i])) > widths[i])
+ widths[i] = tmp; /* don't wanna call strlen twice */
+
+ for (i = 0, ptr = cells; *ptr; ptr++, i++)
+ if ((tmp = strlen(*ptr)) > widths[i % col_count])
+ widths[i % col_count] = tmp;
+
+ if (opt_border == 0)
+ total_w = col_count - 1;
+ else if (opt_border == 1)
+ total_w = col_count * 3 - 2;
else
- fprintf(fout, "%-*s%s\n", (total_w-strlen(title))/2, "", title);
- }
-
- /* print headers */
- if (!opt_barebones) {
- if (opt_border==2)
- _print_horizontal_line(col_count, widths, opt_border, fout);
-
- if (opt_border==2)
- fputs("| ", fout);
- else if (opt_border==1)
- fputc(' ', fout);
-
- for (i=0; i<col_count; i++) {
- /* centered */
- fprintf(fout, "%-*s%s%-*s", (int)floor((widths[i]-strlen(headers[i]))/2.0), "", headers[i], (int)ceil((widths[i]-strlen(headers[i]))/2.0) , "");
-
- if (i<col_count-1) {
- if (opt_border==0)
- fputc(' ', fout);
+ total_w = col_count * 3 + 1;
+
+ for (i = 0; i < col_count; i++)
+ total_w += widths[i];
+
+ /* print title */
+ if (title && !opt_barebones)
+ {
+ if (strlen(title) >= total_w)
+ fprintf(fout, "%s\n", title);
else
- fputs(" | ", fout);
- }
+ fprintf(fout, "%-*s%s\n", (total_w - strlen(title)) / 2, "", title);
}
- if (opt_border==2)
- fputs(" |", fout);
- else if (opt_border==1)
- fputc(' ', fout);;
- fputc('\n', fout);
+ /* print headers */
+ if (!opt_barebones)
+ {
+ if (opt_border == 2)
+ _print_horizontal_line(col_count, widths, opt_border, fout);
- _print_horizontal_line(col_count, widths, opt_border, fout);
- }
+ if (opt_border == 2)
+ fputs("| ", fout);
+ else if (opt_border == 1)
+ fputc(' ', fout);
+
+ for (i = 0; i < col_count; i++)
+ {
+ /* centered */
+ fprintf(fout, "%-*s%s%-*s", (int) floor((widths[i] - strlen(headers[i])) / 2.0), "", headers[i], (int) ceil((widths[i] - strlen(headers[i])) / 2.0), "");
+
+ if (i < col_count - 1)
+ {
+ if (opt_border == 0)
+ fputc(' ', fout);
+ else
+ fputs(" | ", fout);
+ }
+ }
- /* print cells */
- for (i=0, ptr = cells; *ptr; i++, ptr++) {
- /* beginning of line */
- if (i % col_count == 0) {
- if (opt_border==2)
- fputs("| ", fout);
- else if (opt_border==1)
- fputc(' ', fout);
- }
+ if (opt_border == 2)
+ fputs(" |", fout);
+ else if (opt_border == 1)
+ fputc(' ', fout);;
+ fputc('\n', fout);
- /* content */
- if (opt_align[(i) % col_count ] == 'r')
- fprintf(fout, "%*s", widths[i%col_count], cells[i]);
- else {
- if ((i+1) % col_count == 0 && opt_border != 2)
- fputs(cells[i], fout);
- else
- fprintf(fout, "%-*s", widths[i%col_count], cells[i]);
+ _print_horizontal_line(col_count, widths, opt_border, fout);
}
- /* divider */
- if ((i+1) % col_count) {
- if (opt_border==0)
- fputc(' ', fout);
- else
- fputs(" | ", fout);
- }
- /* end of line */
- else {
- if (opt_border==2)
- fputs(" |", fout);
- fputc('\n', fout);
+ /* print cells */
+ for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ {
+ /* beginning of line */
+ if (i % col_count == 0)
+ {
+ if (opt_border == 2)
+ fputs("| ", fout);
+ else if (opt_border == 1)
+ fputc(' ', fout);
+ }
+
+ /* content */
+ if (opt_align[(i) % col_count] == 'r')
+ fprintf(fout, "%*s", widths[i % col_count], cells[i]);
+ else
+ {
+ if ((i + 1) % col_count == 0 && opt_border != 2)
+ fputs(cells[i], fout);
+ else
+ fprintf(fout, "%-*s", widths[i % col_count], cells[i]);
+ }
+
+ /* divider */
+ if ((i + 1) % col_count)
+ {
+ if (opt_border == 0)
+ fputc(' ', fout);
+ else
+ fputs(" | ", fout);
+ }
+ /* end of line */
+ else
+ {
+ if (opt_border == 2)
+ fputs(" |", fout);
+ fputc('\n', fout);
+ }
}
- }
- if (opt_border==2)
- _print_horizontal_line(col_count, widths, opt_border, fout);
+ if (opt_border == 2)
+ _print_horizontal_line(col_count, widths, opt_border, fout);
- /* print footers */
- if (footers && !opt_barebones)
- for (ptr = footers; *ptr; ptr++)
- fprintf(fout, "%s\n", *ptr);
+ /* print footers */
+ if (footers && !opt_barebones)
+ for (ptr = footers; *ptr; ptr++)
+ fprintf(fout, "%s\n", *ptr);
- fputc('\n', fout);
+ fputc('\n', fout);
- /* clean up */
- free(widths);
+ /* clean up */
+ free(widths);
}
static void
-print_aligned_vertical(const char * title, char ** headers, char ** cells, char ** footers,
- bool opt_barebones, unsigned short int opt_border,
- FILE * fout)
+print_aligned_vertical(const char *title, char **headers, char **cells, char **footers,
+ bool opt_barebones, unsigned short int opt_border,
+ FILE *fout)
{
- unsigned int col_count = 0;
- unsigned int record = 1;
- char ** ptr;
- unsigned int i, tmp, hwidth=0, dwidth=0;
- char * divider;
-
- /* count columns and find longest header */
- for (ptr = headers; *ptr; ptr++) {
- col_count++;
- if ((tmp = strlen(*ptr)) > hwidth)
- hwidth = tmp; /* don't wanna call strlen twice */
- }
-
- /* find longest data cell */
- for (ptr = cells; *ptr; ptr++)
- if ((tmp = strlen(*ptr)) > dwidth)
- dwidth = tmp;
-
- /* print title */
- if (!opt_barebones && title)
- fprintf(fout, "%s\n", title);
-
- /* make horizontal border */
- divider = malloc(hwidth + dwidth + 10);
- if (!divider) {
- perror("malloc");
- exit(EXIT_FAILURE);
- }
- divider[0] = '\0';
- if (opt_border == 2)
- strcat(divider, "+-");
- for (i=0; i<hwidth; i++) strcat(divider, opt_border > 0 ? "-" : " ");
- if (opt_border > 0)
- strcat(divider, "-+-");
- else
- strcat(divider, " ");
- for (i=0; i<dwidth; i++) strcat(divider, opt_border > 0 ? "-" : " ");
- if (opt_border == 2)
- strcat(divider, "-+");
-
-
- /* print records */
- for (i=0, ptr = cells; *ptr; i++, ptr++) {
- if (i % col_count == 0) {
- if (!opt_barebones) {
- char * div_copy = strdup(divider);
- char * record_str = malloc(32);
- size_t record_str_len;
-
- if (!div_copy || !record_str) {
- perror("malloc");
- exit(EXIT_FAILURE);
- }
+ unsigned int col_count = 0;
+ unsigned int record = 1;
+ char **ptr;
+ unsigned int i,
+ tmp,
+ hwidth = 0,
+ dwidth = 0;
+ char *divider;
+
+ /* count columns and find longest header */
+ for (ptr = headers; *ptr; ptr++)
+ {
+ col_count++;
+ if ((tmp = strlen(*ptr)) > hwidth)
+ hwidth = tmp; /* don't wanna call strlen twice */
+ }
- if (opt_border==0)
- sprintf(record_str, "* Record %d", record++);
- else
- sprintf(record_str, "[ RECORD %d ]", record++);
- record_str_len = strlen(record_str);
- if (record_str_len + opt_border > strlen(div_copy)) {
- void * new;
- new = realloc(div_copy, record_str_len + opt_border);
- if (!new) {
- perror("realloc");
- exit(EXIT_FAILURE);
- }
- div_copy = new;
- }
- strncpy(div_copy + opt_border, record_str, record_str_len);
- fprintf(fout, "%s\n", div_copy);
- free(record_str);
- free(div_copy);
- }
- else if (i != 0 && opt_border < 2)
- fprintf(fout, "%s\n", divider);
+ /* find longest data cell */
+ for (ptr = cells; *ptr; ptr++)
+ if ((tmp = strlen(*ptr)) > dwidth)
+ dwidth = tmp;
+
+ /* print title */
+ if (!opt_barebones && title)
+ fprintf(fout, "%s\n", title);
+
+ /* make horizontal border */
+ divider = malloc(hwidth + dwidth + 10);
+ if (!divider)
+ {
+ perror("malloc");
+ exit(EXIT_FAILURE);
}
+ divider[0] = '\0';
if (opt_border == 2)
- fputs("| ", fout);
- fprintf(fout, "%-*s", hwidth, headers[i%col_count]);
+ strcat(divider, "+-");
+ for (i = 0; i < hwidth; i++)
+ strcat(divider, opt_border > 0 ? "-" : " ");
if (opt_border > 0)
- fputs(" | ", fout);
+ strcat(divider, "-+-");
else
- fputs(" ", fout);
+ strcat(divider, " ");
+ for (i = 0; i < dwidth; i++)
+ strcat(divider, opt_border > 0 ? "-" : " ");
+ if (opt_border == 2)
+ strcat(divider, "-+");
+
+
+ /* print records */
+ for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ {
+ if (i % col_count == 0)
+ {
+ if (!opt_barebones)
+ {
+ char *div_copy = strdup(divider);
+ char *record_str = malloc(32);
+ size_t record_str_len;
+
+ if (!div_copy || !record_str)
+ {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
+ if (opt_border == 0)
+ sprintf(record_str, "* Record %d", record++);
+ else
+ sprintf(record_str, "[ RECORD %d ]", record++);
+ record_str_len = strlen(record_str);
+ if (record_str_len + opt_border > strlen(div_copy))
+ {
+ void *new;
+
+ new = realloc(div_copy, record_str_len + opt_border);
+ if (!new)
+ {
+ perror("realloc");
+ exit(EXIT_FAILURE);
+ }
+ div_copy = new;
+ }
+ strncpy(div_copy + opt_border, record_str, record_str_len);
+ fprintf(fout, "%s\n", div_copy);
+ free(record_str);
+ free(div_copy);
+ }
+ else if (i != 0 && opt_border < 2)
+ fprintf(fout, "%s\n", divider);
+ }
+ if (opt_border == 2)
+ fputs("| ", fout);
+ fprintf(fout, "%-*s", hwidth, headers[i % col_count]);
+ if (opt_border > 0)
+ fputs(" | ", fout);
+ else
+ fputs(" ", fout);
- if (opt_border < 2)
- fprintf(fout, "%s\n", *ptr);
- else
- fprintf(fout, "%-*s |\n", dwidth, *ptr);
- }
+ if (opt_border < 2)
+ fprintf(fout, "%s\n", *ptr);
+ else
+ fprintf(fout, "%-*s |\n", dwidth, *ptr);
+ }
- if (opt_border == 2)
- fprintf(fout, "%s\n", divider);
+ if (opt_border == 2)
+ fprintf(fout, "%s\n", divider);
- /* print footers */
+ /* print footers */
- if (!opt_barebones && footers && *footers) {
- if (opt_border < 2)
- fputc('\n', fout);
- for (ptr = footers; *ptr; ptr++)
- fprintf(fout, "%s\n", *ptr);
- }
+ if (!opt_barebones && footers && *footers)
+ {
+ if (opt_border < 2)
+ fputc('\n', fout);
+ for (ptr = footers; *ptr; ptr++)
+ fprintf(fout, "%s\n", *ptr);
+ }
- fputc('\n', fout);
- free(divider);
+ fputc('\n', fout);
+ free(divider);
}
@@ -408,351 +444,382 @@ print_aligned_vertical(const char * title, char ** headers, char ** cells, char
static void
-html_escaped_print(const char * in, FILE * fout)
+html_escaped_print(const char *in, FILE *fout)
{
- const char * p;
- for (p=in; *p; p++)
- switch (*p) {
- case '&':
- fputs("&amp;", fout);
- break;
- case '<':
- fputs("&lt;", fout);
- break;
- case '>':
- fputs("&gt;", fout);
- break;
- case '\n':
- fputs("<br>", fout);
- break;
- default:
- fputc(*p, fout);
- }
+ const char *p;
+
+ for (p = in; *p; p++)
+ switch (*p)
+ {
+ case '&':
+ fputs("&amp;", fout);
+ break;
+ case '<':
+ fputs("&lt;", fout);
+ break;
+ case '>':
+ fputs("&gt;", fout);
+ break;
+ case '\n':
+ fputs("<br>", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
}
static void
-print_html_text(const char * title, char ** headers, char ** cells, char ** footers,
- const char * opt_align, bool opt_barebones, unsigned short int opt_border,
- char * opt_table_attr,
- FILE * fout)
+print_html_text(const char *title, char **headers, char **cells, char **footers,
+const char *opt_align, bool opt_barebones, unsigned short int opt_border,
+ char *opt_table_attr,
+ FILE *fout)
{
- unsigned int col_count = 0;
- unsigned int i;
- char ** ptr;
-
- fprintf(fout, "<table border=%d", opt_border);
- if (opt_table_attr)
- fprintf(fout, " %s", opt_table_attr);
- fputs(">\n", fout);
-
- /* print title */
- if (!opt_barebones && title) {
- fputs(" <caption>", fout);
- html_escaped_print(title, fout);
- fputs("</caption>\n", fout);
- }
-
- /* print headers and count columns */
- if (!opt_barebones)
- fputs(" <tr>\n", fout);
- for (i=0, ptr = headers; *ptr; i++, ptr++) {
- col_count++;
- if (!opt_barebones) {
- fputs(" <th align=center>", fout);
- html_escaped_print(*ptr, fout);
- fputs("</th>\n", fout);
- }
- }
- if (!opt_barebones)
- fputs(" </tr>\n", fout);
-
- /* print cells */
- for (i=0, ptr = cells; *ptr; i++, ptr++) {
- if ( i % col_count == 0 )
- fputs(" <tr valign=top>\n", fout);
-
- fprintf(fout, " <td align=%s>", opt_align[(i)%col_count] == 'r' ? "right" : "left");
- if ( (*ptr)[strspn(*ptr, " \t")] == '\0' ) /* is string only whitespace? */
- fputs("&nbsp;", fout);
- else
- html_escaped_print(*ptr, fout);
- fputs("</td>\n", fout);
+ unsigned int col_count = 0;
+ unsigned int i;
+ char **ptr;
+
+ fprintf(fout, "<table border=%d", opt_border);
+ if (opt_table_attr)
+ fprintf(fout, " %s", opt_table_attr);
+ fputs(">\n", fout);
+
+ /* print title */
+ if (!opt_barebones && title)
+ {
+ fputs(" <caption>", fout);
+ html_escaped_print(title, fout);
+ fputs("</caption>\n", fout);
+ }
- if ( (i+1) % col_count == 0 )
- fputs(" </tr>\n", fout);
- }
+ /* print headers and count columns */
+ if (!opt_barebones)
+ fputs(" <tr>\n", fout);
+ for (i = 0, ptr = headers; *ptr; i++, ptr++)
+ {
+ col_count++;
+ if (!opt_barebones)
+ {
+ fputs(" <th align=center>", fout);
+ html_escaped_print(*ptr, fout);
+ fputs("</th>\n", fout);
+ }
+ }
+ if (!opt_barebones)
+ fputs(" </tr>\n", fout);
+
+ /* print cells */
+ for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ {
+ if (i % col_count == 0)
+ fputs(" <tr valign=top>\n", fout);
+
+ fprintf(fout, " <td align=%s>", opt_align[(i) % col_count] == 'r' ? "right" : "left");
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0') /* is string only
+ * whitespace? */
+ fputs("&nbsp;", fout);
+ else
+ html_escaped_print(*ptr, fout);
+ fputs("</td>\n", fout);
- fputs("</table>\n", fout);
+ if ((i + 1) % col_count == 0)
+ fputs(" </tr>\n", fout);
+ }
- /* print footers */
+ fputs("</table>\n", fout);
- if (footers && !opt_barebones)
- for (ptr = footers; *ptr; ptr++) {
- html_escaped_print(*ptr, fout);
- fputs("<br>\n", fout);
- }
+ /* print footers */
+
+ if (footers && !opt_barebones)
+ for (ptr = footers; *ptr; ptr++)
+ {
+ html_escaped_print(*ptr, fout);
+ fputs("<br>\n", fout);
+ }
- fputc('\n', fout);
+ fputc('\n', fout);
}
static void
-print_html_vertical(const char * title, char ** headers, char ** cells, char ** footers,
- const char * opt_align, bool opt_barebones, unsigned short int opt_border,
- char * opt_table_attr,
- FILE * fout)
+print_html_vertical(const char *title, char **headers, char **cells, char **footers,
+const char *opt_align, bool opt_barebones, unsigned short int opt_border,
+ char *opt_table_attr,
+ FILE *fout)
{
- unsigned int col_count = 0;
- unsigned int i;
- unsigned int record = 1;
- char ** ptr;
-
- fprintf(fout, "<table border=%d", opt_border);
- if (opt_table_attr)
- fprintf(fout, " %s", opt_table_attr);
- fputs(">\n", fout);
-
- /* print title */
- if (!opt_barebones && title) {
- fputs(" <caption>", fout);
- html_escaped_print(title, fout);
- fputs("</caption>\n", fout);
- }
-
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
- /* print records */
- for (i=0, ptr = cells; *ptr; i++, ptr++) {
- if (i % col_count == 0) {
- if (!opt_barebones)
- fprintf(fout, "\n <tr><td colspan=2 align=center>Record %d</td></tr>\n", record++);
- else
- fputs("\n <tr><td colspan=2>&nbsp;</td></tr>\n", fout);
- }
- fputs(" <tr valign=top>\n"
- " <th>", fout);
- html_escaped_print(headers[i%col_count], fout);
- fputs("</th>\n", fout);
-
- fprintf(fout, " <td align=%s>", opt_align[i%col_count] == 'r' ? "right" : "left");
- if ( (*ptr)[strspn(*ptr, " \t")] == '\0' ) /* is string only whitespace? */
- fputs("&nbsp;", fout);
- else
- html_escaped_print(*ptr, fout);
- fputs("</td>\n </tr>\n", fout);
- }
+ unsigned int col_count = 0;
+ unsigned int i;
+ unsigned int record = 1;
+ char **ptr;
+
+ fprintf(fout, "<table border=%d", opt_border);
+ if (opt_table_attr)
+ fprintf(fout, " %s", opt_table_attr);
+ fputs(">\n", fout);
+
+ /* print title */
+ if (!opt_barebones && title)
+ {
+ fputs(" <caption>", fout);
+ html_escaped_print(title, fout);
+ fputs("</caption>\n", fout);
+ }
- fputs("</table>\n", fout);
+ /* count columns */
+ for (ptr = headers; *ptr; ptr++)
+ col_count++;
- /* print footers */
- if (footers && !opt_barebones)
- for (ptr = footers; *ptr; ptr++) {
- html_escaped_print(*ptr, fout);
- fputs("<br>\n", fout);
+ /* print records */
+ for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ {
+ if (i % col_count == 0)
+ {
+ if (!opt_barebones)
+ fprintf(fout, "\n <tr><td colspan=2 align=center>Record %d</td></tr>\n", record++);
+ else
+ fputs("\n <tr><td colspan=2>&nbsp;</td></tr>\n", fout);
+ }
+ fputs(" <tr valign=top>\n"
+ " <th>", fout);
+ html_escaped_print(headers[i % col_count], fout);
+ fputs("</th>\n", fout);
+
+ fprintf(fout, " <td align=%s>", opt_align[i % col_count] == 'r' ? "right" : "left");
+ if ((*ptr)[strspn(*ptr, " \t")] == '\0') /* is string only
+ * whitespace? */
+ fputs("&nbsp;", fout);
+ else
+ html_escaped_print(*ptr, fout);
+ fputs("</td>\n </tr>\n", fout);
}
- fputc('\n', fout);
+ fputs("</table>\n", fout);
+
+ /* print footers */
+ if (footers && !opt_barebones)
+ for (ptr = footers; *ptr; ptr++)
+ {
+ html_escaped_print(*ptr, fout);
+ fputs("<br>\n", fout);
+ }
+
+ fputc('\n', fout);
}
/*************************/
-/* LaTeX */
+/* LaTeX */
/*************************/
static void
-latex_escaped_print(const char * in, FILE * fout)
+latex_escaped_print(const char *in, FILE *fout)
{
- const char * p;
- for (p=in; *p; p++)
- switch (*p) {
- case '&':
- fputs("\\&", fout);
- break;
- case '%':
- fputs("\\%", fout);
- break;
- case '$':
- fputs("\\$", fout);
- break;
- case '{':
- fputs("\\{", fout);
- break;
- case '}':
- fputs("\\}", fout);
- break;
- case '\\':
- fputs("\\backslash", fout);
- break;
- case '\n':
- fputs("\\\\", fout);
- break;
- default:
- fputc(*p, fout);
- }
+ const char *p;
+
+ for (p = in; *p; p++)
+ switch (*p)
+ {
+ case '&':
+ fputs("\\&", fout);
+ break;
+ case '%':
+ fputs("\\%", fout);
+ break;
+ case '$':
+ fputs("\\$", fout);
+ break;
+ case '{':
+ fputs("\\{", fout);
+ break;
+ case '}':
+ fputs("\\}", fout);
+ break;
+ case '\\':
+ fputs("\\backslash", fout);
+ break;
+ case '\n':
+ fputs("\\\\", fout);
+ break;
+ default:
+ fputc(*p, fout);
+ }
}
static void
-print_latex_text(const char * title, char ** headers, char ** cells, char ** footers,
- const char * opt_align, bool opt_barebones, unsigned short int opt_border,
- FILE * fout)
+print_latex_text(const char *title, char **headers, char **cells, char **footers,
+const char *opt_align, bool opt_barebones, unsigned short int opt_border,
+ FILE *fout)
{
- unsigned int col_count = 0;
- unsigned int i;
- const char * cp;
- char ** ptr;
-
-
- /* print title */
- if (!opt_barebones && title) {
- fputs("\begin{center}\n", fout);
- latex_escaped_print(title, fout);
- fputs("\n\end{center}\n\n", fout);
- }
-
- /* begin environment and set alignments and borders */
- fputs("\\begin{tabular}{", fout);
- if (opt_border==0)
- fputs(opt_align, fout);
- else if (opt_border==1) {
- for (cp = opt_align; *cp; cp++) {
- if (cp != opt_align) fputc('|', fout);
- fputc(*cp, fout);
- }
- }
- else if (opt_border==2) {
- for (cp = opt_align; *cp; cp++) {
- fputc('|', fout);
- fputc(*cp, fout);
- }
- fputc('|', fout);
- }
- fputs("}\n", fout);
-
- if (!opt_barebones && opt_border==2)
- fputs("\\hline\n", fout);
-
- /* print headers and count columns */
- for (i=0, ptr = headers; *ptr; i++, ptr++) {
- col_count++;
- if (!opt_barebones) {
- if (i!=0)
- fputs(" & ", fout);
- latex_escaped_print(*ptr, fout);
+ unsigned int col_count = 0;
+ unsigned int i;
+ const char *cp;
+ char **ptr;
+
+
+ /* print title */
+ if (!opt_barebones && title)
+ {
+ fputs("\begin{center}\n", fout);
+ latex_escaped_print(title, fout);
+ fputs("\n\end{center}\n\n", fout);
}
- }
- if (!opt_barebones) {
- fputs(" \\\\\n", fout);
- fputs("\\hline\n", fout);
- }
+ /* begin environment and set alignments and borders */
+ fputs("\\begin{tabular}{", fout);
+ if (opt_border == 0)
+ fputs(opt_align, fout);
+ else if (opt_border == 1)
+ {
+ for (cp = opt_align; *cp; cp++)
+ {
+ if (cp != opt_align)
+ fputc('|', fout);
+ fputc(*cp, fout);
+ }
+ }
+ else if (opt_border == 2)
+ {
+ for (cp = opt_align; *cp; cp++)
+ {
+ fputc('|', fout);
+ fputc(*cp, fout);
+ }
+ fputc('|', fout);
+ }
+ fputs("}\n", fout);
- /* print cells */
- for (i=0, ptr = cells; *ptr; i++, ptr++) {
- latex_escaped_print(*ptr, fout);
+ if (!opt_barebones && opt_border == 2)
+ fputs("\\hline\n", fout);
- if ( (i+1) % col_count == 0 )
- fputs(" \\\\\n", fout);
- else
- fputs(" & ", fout);
- }
+ /* print headers and count columns */
+ for (i = 0, ptr = headers; *ptr; i++, ptr++)
+ {
+ col_count++;
+ if (!opt_barebones)
+ {
+ if (i != 0)
+ fputs(" & ", fout);
+ latex_escaped_print(*ptr, fout);
+ }
+ }
+
+ if (!opt_barebones)
+ {
+ fputs(" \\\\\n", fout);
+ fputs("\\hline\n", fout);
+ }
+
+ /* print cells */
+ for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ {
+ latex_escaped_print(*ptr, fout);
- if (opt_border==2)
- fputs("\\hline\n", fout);
+ if ((i + 1) % col_count == 0)
+ fputs(" \\\\\n", fout);
+ else
+ fputs(" & ", fout);
+ }
- fputs("\\end{tabular}\n\n", fout);
+ if (opt_border == 2)
+ fputs("\\hline\n", fout);
+ fputs("\\end{tabular}\n\n", fout);
- /* print footers */
- if (footers && !opt_barebones)
- for (ptr = footers; *ptr; ptr++) {
- latex_escaped_print(*ptr, fout);
- fputs(" \\\\\n", fout);
- }
+ /* print footers */
- fputc('\n', fout);
+ if (footers && !opt_barebones)
+ for (ptr = footers; *ptr; ptr++)
+ {
+ latex_escaped_print(*ptr, fout);
+ fputs(" \\\\\n", fout);
+ }
+
+ fputc('\n', fout);
}
static void
-print_latex_vertical(const char * title, char ** headers, char ** cells, char ** footers,
- const char * opt_align, bool opt_barebones, unsigned short int opt_border,
- FILE * fout)
+print_latex_vertical(const char *title, char **headers, char **cells, char **footers,
+const char *opt_align, bool opt_barebones, unsigned short int opt_border,
+ FILE *fout)
{
- unsigned int col_count = 0;
- unsigned int i;
- char ** ptr;
- unsigned int record = 1;
-
- (void)opt_align; /* currently unused parameter */
-
- /* print title */
- if (!opt_barebones && title) {
- fputs("\begin{center}\n", fout);
- latex_escaped_print(title, fout);
- fputs("\n\end{center}\n\n", fout);
- }
-
- /* begin environment and set alignments and borders */
- fputs("\\begin{tabular}{", fout);
- if (opt_border==0)
- fputs("cl", fout);
- else if (opt_border==1)
- fputs("c|l", fout);
- else if (opt_border==2)
- fputs("|c|l|", fout);
- fputs("}\n", fout);
-
-
- /* count columns */
- for (ptr = headers; *ptr; ptr++)
- col_count++;
-
-
- /* print records */
- for (i=0, ptr = cells; *ptr; i++, ptr++) {
- /* new record */
- if (i % col_count == 0) {
- if (!opt_barebones) {
- if (opt_border == 2)
- fputs("\\hline\n", fout);
- fprintf(fout, "\\multicolumn{2}{c}{Record %d} \\\\\n", record++);
- }
- if (opt_border >= 1)
- fputs("\\hline\n", fout);
+ unsigned int col_count = 0;
+ unsigned int i;
+ char **ptr;
+ unsigned int record = 1;
+
+ (void) opt_align; /* currently unused parameter */
+
+ /* print title */
+ if (!opt_barebones && title)
+ {
+ fputs("\begin{center}\n", fout);
+ latex_escaped_print(title, fout);
+ fputs("\n\end{center}\n\n", fout);
}
- latex_escaped_print(headers[i%col_count], fout);
- fputs(" & ", fout);
- latex_escaped_print(*ptr, fout);
- fputs(" \\\\\n", fout);
- }
+ /* begin environment and set alignments and borders */
+ fputs("\\begin{tabular}{", fout);
+ if (opt_border == 0)
+ fputs("cl", fout);
+ else if (opt_border == 1)
+ fputs("c|l", fout);
+ else if (opt_border == 2)
+ fputs("|c|l|", fout);
+ fputs("}\n", fout);
- if (opt_border==2)
- fputs("\\hline\n", fout);
- fputs("\\end{tabular}\n\n", fout);
+ /* count columns */
+ for (ptr = headers; *ptr; ptr++)
+ col_count++;
- /* print footers */
+ /* print records */
+ for (i = 0, ptr = cells; *ptr; i++, ptr++)
+ {
+ /* new record */
+ if (i % col_count == 0)
+ {
+ if (!opt_barebones)
+ {
+ if (opt_border == 2)
+ fputs("\\hline\n", fout);
+ fprintf(fout, "\\multicolumn{2}{c}{Record %d} \\\\\n", record++);
+ }
+ if (opt_border >= 1)
+ fputs("\\hline\n", fout);
+ }
- if (footers && !opt_barebones)
- for (ptr = footers; *ptr; ptr++) {
- latex_escaped_print(*ptr, fout);
- fputs(" \\\\\n", fout);
+ latex_escaped_print(headers[i % col_count], fout);
+ fputs(" & ", fout);
+ latex_escaped_print(*ptr, fout);
+ fputs(" \\\\\n", fout);
}
- fputc('\n', fout);
+ if (opt_border == 2)
+ fputs("\\hline\n", fout);
+
+ fputs("\\end{tabular}\n\n", fout);
+
+
+ /* print footers */
+
+ if (footers && !opt_barebones)
+ for (ptr = footers; *ptr; ptr++)
+ {
+ latex_escaped_print(*ptr, fout);
+ fputs(" \\\\\n", fout);
+ }
+
+ fputc('\n', fout);
}
@@ -761,214 +828,231 @@ print_latex_vertical(const char * title, char ** headers, char ** cells, char **
/********************************/
-/* Public functions */
+/* Public functions */
/********************************/
void
-printTable(const char * title, char ** headers, char ** cells, char ** footers,
- const char * align,
- const printTableOpt * opt, FILE * fout)
+printTable(const char *title, char **headers, char **cells, char **footers,
+ const char *align,
+ const printTableOpt * opt, FILE *fout)
{
- char * default_footer[] = { NULL };
- unsigned short int border = opt->border;
- FILE * pager = NULL,
- * output;
+ char *default_footer[] = {NULL};
+ unsigned short int border = opt->border;
+ FILE *pager = NULL,
+ *output;
- if (opt->format == PRINT_NOTHING)
- return;
+ if (opt->format == PRINT_NOTHING)
+ return;
- if (!footers)
- footers = default_footer;
+ if (!footers)
+ footers = default_footer;
- if (opt->format != PRINT_HTML && border > 2)
- border = 2;
+ if (opt->format != PRINT_HTML && border > 2)
+ border = 2;
- /* check whether we need / can / are supposed to use pager */
- if (fout == stdout && opt->pager
+ /* check whether we need / can / are supposed to use pager */
+ if (fout == stdout && opt->pager
#ifndef WIN32
- &&
- isatty(fileno(stdin)) &&
- isatty(fileno(stdout))
+ &&
+ isatty(fileno(stdin)) &&
+ isatty(fileno(stdout))
#endif
- )
- {
- const char * pagerprog;
-#ifdef TIOCGWINSZ
- unsigned int col_count=0, row_count=0, lines;
- char ** ptr;
- int result;
- struct winsize screen_size;
-
- /* rough estimate of columns and rows */
- if (headers)
- for (ptr=headers; *ptr; ptr++)
- col_count++;
- if (cells)
- for (ptr=cells; *ptr; ptr++)
- row_count++;
- row_count /= col_count;
+ )
+ {
+ const char *pagerprog;
- if (opt->expanded)
- lines = (col_count+1) * row_count;
- else
- lines = row_count+1;
- if (!opt->tuples_only)
- lines += 5;
+#ifdef TIOCGWINSZ
+ unsigned int col_count = 0,
+ row_count = 0,
+ lines;
+ char **ptr;
+ int result;
+ struct winsize screen_size;
+
+ /* rough estimate of columns and rows */
+ if (headers)
+ for (ptr = headers; *ptr; ptr++)
+ col_count++;
+ if (cells)
+ for (ptr = cells; *ptr; ptr++)
+ row_count++;
+ row_count /= col_count;
+
+ if (opt->expanded)
+ lines = (col_count + 1) * row_count;
+ else
+ lines = row_count + 1;
+ if (!opt->tuples_only)
+ lines += 5;
- result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
- if (result==-1 || lines > screen_size.ws_row) {
+ result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
+ if (result == -1 || lines > screen_size.ws_row)
+ {
#endif
- pagerprog = getenv("PAGER");
- if (!pagerprog) pagerprog = DEFAULT_PAGER;
- pager = popen(pagerprog, "w");
+ pagerprog = getenv("PAGER");
+ if (!pagerprog)
+ pagerprog = DEFAULT_PAGER;
+ pager = popen(pagerprog, "w");
#ifdef TIOCGWINSZ
- }
+ }
#endif
- }
-
- if (pager) {
- output = pager;
- pqsignal(SIGPIPE, SIG_IGN);
- }
- else
- output = fout;
-
-
- /* print the stuff */
+ }
- switch (opt->format) {
- case PRINT_UNALIGNED:
- if (opt->expanded)
- print_unaligned_vertical(title, headers, cells, footers, opt->fieldSep, opt->tuples_only, output);
- else
- print_unaligned_text(title, headers, cells, footers, opt->fieldSep, opt->tuples_only, output);
- break;
- case PRINT_ALIGNED:
- if (opt->expanded)
- print_aligned_vertical(title, headers, cells, footers, opt->tuples_only, border, output);
- else
- print_aligned_text(title, headers, cells, footers, align, opt->tuples_only, border, output);
- break;
- case PRINT_HTML:
- if (opt->expanded)
- print_html_vertical(title, headers, cells, footers, align, opt->tuples_only, border, opt->tableAttr, output);
- else
- print_html_text(title, headers, cells, footers, align, opt->tuples_only, border, opt->tableAttr, output);
- break;
- case PRINT_LATEX:
- if (opt->expanded)
- print_latex_vertical(title, headers, cells, footers, align, opt->tuples_only, border, output);
+ if (pager)
+ {
+ output = pager;
+ pqsignal(SIGPIPE, SIG_IGN);
+ }
else
- print_latex_text(title, headers, cells, footers, align, opt->tuples_only, border, output);
- break;
- default:
- fprintf(stderr, "+ Oops, you shouldn't see this!\n");
- }
-
- if (pager) {
- pclose(pager);
- pqsignal(SIGPIPE, SIG_DFL);
- }
+ output = fout;
+
+
+ /* print the stuff */
+
+ switch (opt->format)
+ {
+ case PRINT_UNALIGNED:
+ if (opt->expanded)
+ print_unaligned_vertical(title, headers, cells, footers, opt->fieldSep, opt->tuples_only, output);
+ else
+ print_unaligned_text(title, headers, cells, footers, opt->fieldSep, opt->tuples_only, output);
+ break;
+ case PRINT_ALIGNED:
+ if (opt->expanded)
+ print_aligned_vertical(title, headers, cells, footers, opt->tuples_only, border, output);
+ else
+ print_aligned_text(title, headers, cells, footers, align, opt->tuples_only, border, output);
+ break;
+ case PRINT_HTML:
+ if (opt->expanded)
+ print_html_vertical(title, headers, cells, footers, align, opt->tuples_only, border, opt->tableAttr, output);
+ else
+ print_html_text(title, headers, cells, footers, align, opt->tuples_only, border, opt->tableAttr, output);
+ break;
+ case PRINT_LATEX:
+ if (opt->expanded)
+ print_latex_vertical(title, headers, cells, footers, align, opt->tuples_only, border, output);
+ else
+ print_latex_text(title, headers, cells, footers, align, opt->tuples_only, border, output);
+ break;
+ default:
+ fprintf(stderr, "+ Oops, you shouldn't see this!\n");
+ }
+
+ if (pager)
+ {
+ pclose(pager);
+ pqsignal(SIGPIPE, SIG_DFL);
+ }
}
void
-printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout)
+printQuery(PGresult *result, const printQueryOpt * opt, FILE *fout)
{
- int nfields;
- char ** headers;
- char ** cells;
- char ** footers;
- char * align;
- int i;
+ int nfields;
+ char **headers;
+ char **cells;
+ char **footers;
+ char *align;
+ int i;
+
+ /* extract headers */
+
+ nfields = PQnfields(result);
+
+ headers = calloc(nfields + 1, sizeof(*headers));
+ if (!headers)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
- /* extract headers */
+ for (i = 0; i < nfields; i++)
+ headers[i] = PQfname(result, i);
- nfields = PQnfields(result);
+ /* set cells */
- headers = calloc(nfields+1, sizeof(*headers));
- if (!headers) {
- perror("calloc");
- exit(EXIT_FAILURE);
- }
+ cells = calloc(nfields * PQntuples(result) + 1, sizeof(*cells));
+ if (!cells)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
- for (i=0; i<nfields; i++)
- headers[i] = PQfname(result, i);
+ for (i = 0; i < nfields * PQntuples(result); i++)
+ {
+ if (PQgetisnull(result, i / nfields, i % nfields))
+ cells[i] = opt->nullPrint ? opt->nullPrint : "";
+ else
+ cells[i] = PQgetvalue(result, i / nfields, i % nfields);
+ }
- /* set cells */
+ /* set footers */
- cells = calloc(nfields * PQntuples(result) + 1, sizeof(*cells));
- if (!cells) {
- perror("calloc");
- exit(EXIT_FAILURE);
- }
+ if (opt->footers)
+ footers = opt->footers;
+ else if (!opt->topt.expanded)
+ {
+ footers = calloc(2, sizeof(*footers));
+ if (!footers)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
- for (i=0; i< nfields * PQntuples(result); i++) {
- if (PQgetisnull(result, i / nfields, i % nfields))
- cells[i] = opt->nullPrint ? opt->nullPrint : "";
+ footers[0] = malloc(100);
+ if (PQntuples(result) == 1)
+ strcpy(footers[0], "(1 row)");
+ else
+ sprintf(footers[0], "(%d rows)", PQntuples(result));
+ }
else
- cells[i] = PQgetvalue(result, i / nfields, i % nfields);
- }
+ footers = NULL;
- /* set footers */
+ /* set alignment */
- if (opt->footers)
- footers = opt->footers;
- else if (!opt->topt.expanded) {
- footers = calloc(2, sizeof(*footers));
- if (!footers) {
- perror("calloc");
- exit(EXIT_FAILURE);
+ align = calloc(nfields + 1, sizeof(*align));
+ if (!align)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
}
- footers[0] = malloc(100);
- if (PQntuples(result)==1)
- strcpy(footers[0], "(1 row)");
- else
- sprintf(footers[0], "(%d rows)", PQntuples(result));
- }
- else
- footers = NULL;
-
- /* set alignment */
-
- align = calloc(nfields+1, sizeof(*align));
- if (!align) {
- perror("calloc");
- exit(EXIT_FAILURE);
- }
-
- for (i=0; i<nfields; i++) {
- Oid ftype = PQftype(result, i);
- if ( ftype == 20 || /* int8 */
- ftype == 21 || /* int2 */
- ftype == 23 || /* int4 */
- (ftype >=26 && ftype <=30) || /* ?id */
- ftype == 700 || /* float4 */
- ftype == 701 || /* float8 */
- ftype == 790 || /* money */
- ftype == 1700 /* numeric */
- )
- align[i] = 'r';
- else
- align[i] = 'l';
- }
+ for (i = 0; i < nfields; i++)
+ {
+ Oid ftype = PQftype(result, i);
+
+ if (ftype == 20 || /* int8 */
+ ftype == 21 || /* int2 */
+ ftype == 23 || /* int4 */
+ (ftype >= 26 && ftype <= 30) || /* ?id */
+ ftype == 700 || /* float4 */
+ ftype == 701 || /* float8 */
+ ftype == 790 || /* money */
+ ftype == 1700 /* numeric */
+ )
+ align[i] = 'r';
+ else
+ align[i] = 'l';
+ }
- /* call table printer */
+ /* call table printer */
- printTable(opt->title, headers, cells, footers ? footers : opt->footers, align,
- &opt->topt, fout);
+ printTable(opt->title, headers, cells, footers ? footers : opt->footers, align,
+ &opt->topt, fout);
- free(headers);
- free(cells);
- if (footers) {
- free(footers[0]);
- free(footers);
- }
+ free(headers);
+ free(cells);
+ if (footers)
+ {
+ free(footers[0]);
+ free(footers);
+ }
}
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index d24e41e853..64d0271f50 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -7,52 +7,58 @@
#include <stdio.h>
#include <libpq-fe.h>
-enum printFormat {
- PRINT_NOTHING = 0, /* to make sure someone initializes this */
- PRINT_UNALIGNED,
- PRINT_ALIGNED,
- PRINT_HTML,
- PRINT_LATEX
- /* add your favourite output format here ... */
+enum printFormat
+{
+ PRINT_NOTHING = 0, /* to make sure someone initializes this */
+ PRINT_UNALIGNED,
+ PRINT_ALIGNED,
+ PRINT_HTML,
+ PRINT_LATEX
+ /* add your favourite output format here ... */
};
-typedef struct _printTableOpt {
- enum printFormat format; /* one of the above */
- bool expanded; /* expanded/vertical output (if supported by output format) */
- bool pager; /* use pager for output (if to stdout and stdout is a tty) */
- bool tuples_only; /* don't output headers, row counts, etc. */
- unsigned short int border; /* Print a border around the table. 0=none, 1=dividing lines, 2=full */
- char *fieldSep; /* field separator for unaligned text mode */
- char *tableAttr; /* attributes for HTML <table ...> */
-} printTableOpt;
+typedef struct _printTableOpt
+{
+ enum printFormat format; /* one of the above */
+ bool expanded; /* expanded/vertical output (if supported
+ * by output format) */
+ bool pager; /* use pager for output (if to stdout and
+ * stdout is a tty) */
+ bool tuples_only; /* don't output headers, row counts, etc. */
+ unsigned short int border; /* Print a border around the table.
+ * 0=none, 1=dividing lines, 2=full */
+ char *fieldSep; /* field separator for unaligned text mode */
+ char *tableAttr; /* attributes for HTML <table ...> */
+} printTableOpt;
/*
* Use this to print just any table in the supported formats.
* - title is just any string (NULL is fine)
* - headers is the column headings (NULL ptr terminated). It must be given and
- * complete since the column count is generated from this.
+ * complete since the column count is generated from this.
* - cells are the data cells to be printed. Now you know why the correct
- * column count is important
+ * column count is important
* - footers are lines to be printed below the table
* - align is an 'l' or an 'r' for every column, if the output format needs it.
- * (You must specify this long enough. Otherwise anything could happen.)
+ * (You must specify this long enough. Otherwise anything could happen.)
*/
-void
-printTable(const char * title, char ** headers, char ** cells, char ** footers,
- const char * align,
- const printTableOpt * opt, FILE * fout);
+void printTable(const char *title, char **headers, char **cells, char **footers,
+ const char *align,
+ const printTableOpt * opt, FILE *fout);
-typedef struct _printQueryOpt {
- printTableOpt topt; /* the options above */
- char * nullPrint; /* how to print null entities */
- bool quote; /* quote all values as much as possible */
- char * title; /* override title */
- char ** footers; /* override footer (default is "(xx rows)") */
-} printQueryOpt;
+typedef struct _printQueryOpt
+{
+ printTableOpt topt; /* the options above */
+ char *nullPrint; /* how to print null entities */
+ bool quote; /* quote all values as much as possible */
+ char *title; /* override title */
+ char **footers; /* override footer (default is "(xx
+ * rows)") */
+} printQueryOpt;
/*
* Use this to print query results
@@ -60,7 +66,7 @@ typedef struct _printQueryOpt {
* It calls the printTable above with all the things set straight.
*/
void
-printQuery(PGresult * result, const printQueryOpt * opt, FILE * fout);
+ printQuery(PGresult *result, const printQueryOpt * opt, FILE *fout);
-#endif /* PRINT_H */
+#endif /* PRINT_H */
diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c
index a0fa797595..2912bd16eb 100644
--- a/src/bin/psql/prompt.c
+++ b/src/bin/psql/prompt.c
@@ -34,20 +34,20 @@
* %~ - like %/ but "~" when database name equals user name
* %# - "#" if the username is postgres, ">" otherwise
* %R - in prompt1 normally =, or ^ if single line mode,
- * or a ! if session is not connected to a database;
- * in prompt2 -, *, ', or ";
- * in prompt3 nothing
+ * or a ! if session is not connected to a database;
+ * in prompt2 -, *, ', or ";
+ * in prompt3 nothing
* %? - the error code of the last query (not yet implemented)
* %% - a percent sign
*
- * %[0-9] - the character with the given decimal code
- * %0[0-7] - the character with the given octal code
+ * %[0-9] - the character with the given decimal code
+ * %0[0-7] - the character with the given octal code
* %0x[0-9A-Fa-f] - the character with the given hexadecimal code
*
- * %`command` - The result of executing command in /bin/sh with trailing
- * newline stripped.
- * %$name$ - The value of the psql/environment/magic varible 'name'
- * (same rules as for, e.g., \echo $foo)
+ * %`command` - The result of executing command in /bin/sh with trailing
+ * newline stripped.
+ * %$name$ - The value of the psql/environment/magic varible 'name'
+ * (same rules as for, e.g., \echo $foo)
* (those will not be rescanned for more escape sequences!)
*
*
@@ -60,197 +60,214 @@ const char *
get_prompt(PsqlSettings *pset, promptStatus_t status)
{
#define MAX_PROMPT_SIZE 256
- static char destination[MAX_PROMPT_SIZE+1];
- char buf[MAX_PROMPT_SIZE+1];
- bool esc = false;
- const char *p;
- const char * prompt_string;
+ static char destination[MAX_PROMPT_SIZE + 1];
+ char buf[MAX_PROMPT_SIZE + 1];
+ bool esc = false;
+ const char *p;
+ const char *prompt_string;
- if (GetVariable(pset->vars, "quiet"))
- return "";
+ if (GetVariable(pset->vars, "quiet"))
+ return "";
- if (status == PROMPT_READY)
- prompt_string = GetVariable(pset->vars, "prompt1");
- else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT)
- prompt_string = GetVariable(pset->vars, "prompt2");
- else if (status == PROMPT_COPY)
- prompt_string = GetVariable(pset->vars, "prompt3");
- else
- prompt_string = "? ";
+ if (status == PROMPT_READY)
+ prompt_string = GetVariable(pset->vars, "prompt1");
+ else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT)
+ prompt_string = GetVariable(pset->vars, "prompt2");
+ else if (status == PROMPT_COPY)
+ prompt_string = GetVariable(pset->vars, "prompt3");
+ else
+ prompt_string = "? ";
- destination[0] = '\0';
+ destination[0] = '\0';
- for (p = prompt_string;
- p && *p && strlen(destination)<MAX_PROMPT_SIZE;
- p++)
- {
- MemSet(buf, 0, MAX_PROMPT_SIZE+1);
- if (esc)
+ for (p = prompt_string;
+ p && *p && strlen(destination) < MAX_PROMPT_SIZE;
+ p++)
{
- switch (*p)
- {
- case '%':
- strcpy(buf, "%");
- break;
+ MemSet(buf, 0, MAX_PROMPT_SIZE + 1);
+ if (esc)
+ {
+ switch (*p)
+ {
+ case '%':
+ strcpy(buf, "%");
+ break;
- /* Current database */
- case '/':
- if (pset->db)
- strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
- break;
- case '~': {
- const char * var;
- if (pset->db) {
- if ( strcmp(PQdb(pset->db), PQuser(pset->db))==0 ||
- ( (var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db))==0) )
- strcpy(buf, "~");
- else
- strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
- }
- break;
- }
- /* DB server hostname (long/short) */
- case 'M':
- case 'm':
- if (pset->db) {
- if (PQhost(pset->db)) {
- strncpy(buf, PQhost(pset->db), MAX_PROMPT_SIZE);
- if (*p == 'm')
- buf[strcspn(buf,".")] = '\0';
- }
- else
- buf[0] = '.';
- }
- break;
- /* DB server port number */
- case '>':
- if (pset->db) {
- if (PQhost(pset->db))
- strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE);
- else
- buf[0] = '.';
- }
- break;
- /* DB server user name */
- case 'n':
- if (pset->db)
- strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE);
- break;
+ /* Current database */
+ case '/':
+ if (pset->db)
+ strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
+ break;
+ case '~':
+ {
+ const char *var;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- long int l;
- char * end;
- l = strtol(p, &end, 0);
- sprintf(buf, "%c", (unsigned char)l);
- p = end-1;
- break;
- }
+ if (pset->db)
+ {
+ if (strcmp(PQdb(pset->db), PQuser(pset->db)) == 0 ||
+ ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset->db)) == 0))
+ strcpy(buf, "~");
+ else
+ strncpy(buf, PQdb(pset->db), MAX_PROMPT_SIZE);
+ }
+ break;
+ }
+ /* DB server hostname (long/short) */
+ case 'M':
+ case 'm':
+ if (pset->db)
+ {
+ if (PQhost(pset->db))
+ {
+ strncpy(buf, PQhost(pset->db), MAX_PROMPT_SIZE);
+ if (*p == 'm')
+ buf[strcspn(buf, ".")] = '\0';
+ }
+ else
+ buf[0] = '.';
+ }
+ break;
+ /* DB server port number */
+ case '>':
+ if (pset->db)
+ {
+ if (PQhost(pset->db))
+ strncpy(buf, PQport(pset->db), MAX_PROMPT_SIZE);
+ else
+ buf[0] = '.';
+ }
+ break;
+ /* DB server user name */
+ case 'n':
+ if (pset->db)
+ strncpy(buf, PQuser(pset->db), MAX_PROMPT_SIZE);
+ break;
- case 'R':
- switch(status) {
- case PROMPT_READY:
- if (!pset->db)
- buf[0] = '!';
- else if (!GetVariableBool(pset->vars, "singleline"))
- buf[0] = '=';
- else
- buf[0] = '^';
- break;
- case PROMPT_CONTINUE:
- buf[0] = '-';
- break;
- case PROMPT_SINGLEQUOTE:
- buf[0] = '\'';
- break;
- case PROMPT_DOUBLEQUOTE:
- buf[0] = '"';
- break;
- case PROMPT_COMMENT:
- buf[0] = '*';
- break;
- default:
- buf[0] = '\0';
- break;
- }
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ long int l;
+ char *end;
- case '?':
- /* not here yet */
- break;
+ l = strtol(p, &end, 0);
+ sprintf(buf, "%c", (unsigned char) l);
+ p = end - 1;
+ break;
+ }
- case '#':
- {
- if (pset->db && strcmp(PQuser(pset->db), "postgres")==0)
- buf[0] = '#';
- else
- buf[0] = '>';
-
- break;
- }
+ case 'R':
+ switch (status)
+ {
+ case PROMPT_READY:
+ if (!pset->db)
+ buf[0] = '!';
+ else if (!GetVariableBool(pset->vars, "singleline"))
+ buf[0] = '=';
+ else
+ buf[0] = '^';
+ break;
+ case PROMPT_CONTINUE:
+ buf[0] = '-';
+ break;
+ case PROMPT_SINGLEQUOTE:
+ buf[0] = '\'';
+ break;
+ case PROMPT_DOUBLEQUOTE:
+ buf[0] = '"';
+ break;
+ case PROMPT_COMMENT:
+ buf[0] = '*';
+ break;
+ default:
+ buf[0] = '\0';
+ break;
+ }
- /* execute command */
- case '`':
- {
- FILE * fd = NULL;
- char * file = strdup(p+1);
- int cmdend;
- cmdend = strcspn(file, "`");
- file[cmdend] = '\0';
- if (file)
- fd = popen(file, "r");
- if (fd) {
- fgets(buf, MAX_PROMPT_SIZE-1, fd);
- pclose(fd);
- }
- if (buf[strlen(buf)-1] == '\n')
- buf[strlen(buf)-1] = '\0';
- free(file);
- p += cmdend+1;
- break;
- }
+ case '?':
+ /* not here yet */
+ break;
- /* interpolate variable */
- case '$':
- {
- char *name;
- const char *val;
- int nameend;
- name = strdup(p+1);
- nameend = strcspn(name, "$");
- name[nameend] = '\0';
- val = interpolate_var(name, pset);
- if (val)
- strncpy(buf, val, MAX_PROMPT_SIZE);
- free(name);
- p += nameend+1;
- break;
- }
-
+ case '#':
+ {
+ if (pset->db && strcmp(PQuser(pset->db), "postgres") == 0)
+ buf[0] = '#';
+ else
+ buf[0] = '>';
- default:
- buf[0] = *p;
- buf[1] = '\0';
+ break;
+ }
- }
- esc = false;
- }
- else if (*p == '%')
- esc = true;
- else
- {
- buf[0] = *p;
- buf[1] = '\0';
- esc = false;
- }
+ /* execute command */
+ case '`':
+ {
+ FILE *fd = NULL;
+ char *file = strdup(p + 1);
+ int cmdend;
- if (!esc) {
- strncat(destination, buf, MAX_PROMPT_SIZE-strlen(destination));
+ cmdend = strcspn(file, "`");
+ file[cmdend] = '\0';
+ if (file)
+ fd = popen(file, "r");
+ if (fd)
+ {
+ fgets(buf, MAX_PROMPT_SIZE - 1, fd);
+ pclose(fd);
+ }
+ if (buf[strlen(buf) - 1] == '\n')
+ buf[strlen(buf) - 1] = '\0';
+ free(file);
+ p += cmdend + 1;
+ break;
+ }
+
+ /* interpolate variable */
+ case '$':
+ {
+ char *name;
+ const char *val;
+ int nameend;
+
+ name = strdup(p + 1);
+ nameend = strcspn(name, "$");
+ name[nameend] = '\0';
+ val = interpolate_var(name, pset);
+ if (val)
+ strncpy(buf, val, MAX_PROMPT_SIZE);
+ free(name);
+ p += nameend + 1;
+ break;
+ }
+
+
+ default:
+ buf[0] = *p;
+ buf[1] = '\0';
+
+ }
+ esc = false;
+ }
+ else if (*p == '%')
+ esc = true;
+ else
+ {
+ buf[0] = *p;
+ buf[1] = '\0';
+ esc = false;
+ }
+
+ if (!esc)
+ strncat(destination, buf, MAX_PROMPT_SIZE - strlen(destination));
}
- }
- destination[MAX_PROMPT_SIZE] = '\0';
- return destination;
+ destination[MAX_PROMPT_SIZE] = '\0';
+ return destination;
}
-
diff --git a/src/bin/psql/prompt.h b/src/bin/psql/prompt.h
index f38a2d6f31..e4c1242deb 100644
--- a/src/bin/psql/prompt.h
+++ b/src/bin/psql/prompt.h
@@ -3,17 +3,18 @@
#include "settings.h"
-typedef enum _promptStatus {
- PROMPT_READY,
- PROMPT_CONTINUE,
- PROMPT_COMMENT,
- PROMPT_SINGLEQUOTE,
- PROMPT_DOUBLEQUOTE,
- PROMPT_COPY
-} promptStatus_t;
+typedef enum _promptStatus
+{
+ PROMPT_READY,
+ PROMPT_CONTINUE,
+ PROMPT_COMMENT,
+ PROMPT_SINGLEQUOTE,
+ PROMPT_DOUBLEQUOTE,
+ PROMPT_COPY
+} promptStatus_t;
const char *
-get_prompt(PsqlSettings *pset, promptStatus_t status);
+ get_prompt(PsqlSettings *pset, promptStatus_t status);
-#endif /* PROMPT_H */
+#endif /* PROMPT_H */
diff --git a/src/bin/psql/psql.c b/src/bin/psql/psql.c
deleted file mode 100644
index ca2fc6f27c..0000000000
--- a/src/bin/psql/psql.c
+++ /dev/null
@@ -1,3297 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * psql.c
- * an interactive front-end to postgreSQL
- *
- * Copyright (c) 1996, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.195 1999/10/26 04:40:58 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include <signal.h>
-#include <errno.h>
-#include <sys/types.h>
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <io.h>
-#else
-#include <sys/ioctl.h>
-#include <unistd.h>
-#endif
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <ctype.h>
-
-#include "postgres.h"
-#include "libpq-fe.h"
-#include "pqexpbuffer.h"
-#include "pqsignal.h"
-#include "stringutils.h"
-#include "psqlHelp.h"
-
-#ifndef HAVE_STRDUP
-#include "strdup.h"
-#endif
-
-#ifdef HAVE_TERMIOS_H
-#include <termios.h>
-#endif
-
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-
-#ifdef HAVE_LIBREADLINE
-#ifdef HAVE_READLINE_H
-#include <readline.h>
-#define USE_READLINE 1
-#if defined(HAVE_HISTORY_H)
-#include <history.h>
-#define USE_HISTORY 1
-#endif
-#else
-#if defined(HAVE_READLINE_READLINE_H)
-#include <readline/readline.h>
-#define USE_READLINE 1
-#if defined(HAVE_READLINE_HISTORY_H)
-#include <readline/history.h>
-#define USE_HISTORY 1
-#endif
-#endif
-#endif
-#if defined(HAVE_HISTORY) && !defined(USE_HISTORY)
-#define USE_HISTORY 1
-#endif
-#endif
-
-
-#ifdef WIN32
-#define popen(x,y) _popen(x,y)
-#define pclose(x) _pclose(x)
-#define open(x,y,z) _open(x,y,z)
-#define strcasecmp(x,y) stricmp(x,y)
-#define pqsignal(x,y)
-#define R_OK 0
-
-/* getopt is not in the standard includes on Win32 */
-extern char *optarg;
-extern int optind,
- opterr,
- optopt;
-int getopt(int, char *const[], const char *);
-char *__progname = "psql";
-
-#endif
-
-#ifdef MULTIBYTE
-/* flag to indicate if PGCLIENTENCODING has been set by a user */
-static char *has_client_encoding = 0;
-
-#endif
-
-/* This prompt string is assumed to have at least 3 characters by code in MainLoop().
- * A character two characters from the end is replaced each time by a mode character.
- */
-#define PROMPT "=> "
-
-#define PROMPT_READY '='
-#define PROMPT_CONTINUE '-'
-#define PROMPT_COMMENT '*'
-#define PROMPT_SINGLEQUOTE '\''
-#define PROMPT_DOUBLEQUOTE '"'
-
-/* Backslash command handling:
- * 0 - send currently constructed query to backend (i.e. we got a \g)
- * 1 - skip processing of this line, continue building up query
- * 2 - terminate processing (i.e. we got a \q)
- * 3 - new query supplied by edit
- */
-#define CMD_UNKNOWN -1
-#define CMD_SEND 0
-#define CMD_SKIP_LINE 1
-#define CMD_TERMINATE 2
-#define CMD_NEWEDIT 3
-
-#define COPYBUFSIZ 8192
-
-#define DEFAULT_FIELD_SEP "|"
-#define DEFAULT_EDITOR "vi"
-#define DEFAULT_SHELL "/bin/sh"
-
-typedef struct _psqlSettings
-{
- PGconn *db; /* connection to backend */
- FILE *queryFout; /* where to send the query results */
- PQprintOpt opt; /* options to be passed to PQprint */
- char *prompt; /* prompt to display */
- char *gfname; /* one-shot file output argument for \g */
- bool notty; /* input or output is not a tty */
- bool pipe; /* queryFout is from a popen() */
- bool echoQuery; /* echo the query before sending it */
- bool echoAllQueries; /* echo all queries before sending it */
- bool quiet; /* run quietly, no messages, no promt */
- bool singleStep; /* prompt before for each query */
- bool singleLineMode; /* query terminated by newline */
- bool useReadline; /* use libreadline routines */
- bool getPassword; /* prompt the user for a username and
- * password */
-} PsqlSettings;
-
-/*
- * cur_cmd_source and cur_cmd_interactive are the top of a stack of
- * source files (one stack level per recursive invocation of MainLoop).
- * It's kinda grotty to make these global variables, but the alternative
- * of passing them around through many function parameter lists seems
- * worse.
- */
-static FILE *cur_cmd_source = NULL; /* current source of command input */
-static bool cur_cmd_interactive = false; /* is it an interactive
- * source? */
-
-
-#ifdef TIOCGWINSZ
-struct winsize screen_size;
-
-#else
-struct winsize
-{
- int ws_row;
- int ws_col;
-} screen_size;
-
-#endif
-
-/* declarations for functions in this file */
-static void usage(char *progname);
-static void slashUsage();
-static bool handleCopyOut(PGconn *conn, FILE *copystream);
-static bool handleCopyIn(PGconn *conn, const bool mustprompt,
- FILE *copystream);
-static int tableList(PsqlSettings *pset, bool deep_tablelist,
- char info_type, bool system_tables);
-static int tableDesc(PsqlSettings *pset, char *table, FILE *fout);
-static int objectDescription(PsqlSettings *pset, char *object);
-static int rightsList(PsqlSettings *pset);
-static void emitNtimes(FILE *fout, const char *str, int N);
-static void prompt_for_password(char *username, char *password);
-
-static char *gets_noreadline(char *prompt, FILE *source);
-static char *gets_readline(char *prompt, FILE *source);
-static char *gets_fromFile(char *prompt, FILE *source);
-static int listAllDbs(PsqlSettings *pset);
-static bool SendQuery(PsqlSettings *pset, const char *query,
- FILE *copy_in_stream, FILE *copy_out_stream);
-static int HandleSlashCmds(PsqlSettings *pset, char *line,
- PQExpBuffer query_buf);
-static int MainLoop(PsqlSettings *pset, FILE *source);
-static FILE *setFout(PsqlSettings *pset, char *fname);
-
-static char *selectVersion(PsqlSettings *pset);
-
-/*
- * usage print out usage for command line arguments
- */
-
-static void
-usage(char *progname)
-{
- fprintf(stderr, "Usage: %s [options] [dbname]\n", progname);
- fprintf(stderr, "\t -a authsvc set authentication service\n");
- fprintf(stderr, "\t -A turn off alignment when printing out attributes\n");
- fprintf(stderr, "\t -c query run single query (slash commands too)\n");
- fprintf(stderr, "\t -d dbName specify database name\n");
- fprintf(stderr, "\t -e echo the query sent to the backend\n");
- fprintf(stderr, "\t -E echo all queries sent to the backend\n");
- fprintf(stderr, "\t -f filename use file as a source of queries\n");
- fprintf(stderr, "\t -F sep set the field separator (default is '|')\n");
- fprintf(stderr, "\t -h host set database server host\n");
- fprintf(stderr, "\t -H turn on html3.0 table output\n");
- fprintf(stderr, "\t -l list available databases\n");
- fprintf(stderr, "\t -n don't use readline library\n");
- fprintf(stderr, "\t -o filename send output to filename or (|pipe)\n");
- fprintf(stderr, "\t -p port set port number\n");
- fprintf(stderr, "\t -q run quietly (no messages, no prompts)\n");
- fprintf(stderr, "\t -s single step mode (prompts for each query)\n");
- fprintf(stderr, "\t -S single line mode (i.e. query terminated by newline)\n");
- fprintf(stderr, "\t -t turn off printing of headings and row count\n");
- fprintf(stderr, "\t -T html set html3.0 table command options (cf. -H)\n");
- fprintf(stderr, "\t -u ask for a username and password for authentication\n");
- fprintf(stderr, "\t -x turn on expanded output (field names on left)\n");
- exit(1);
-}
-
-/*
- * slashUsage print out usage for the backslash commands
- */
-
-static char *
-on(bool f)
-{
- return f ? "on" : "off";
-}
-
-static void
-slashUsage(PsqlSettings *pset)
-{
- int usePipe = 0;
- char *pagerenv;
- FILE *fout;
-
-#ifdef TIOCGWINSZ
- if (pset->notty == 0 &&
- (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
- screen_size.ws_col == 0 ||
- screen_size.ws_row == 0))
- {
-#endif
- screen_size.ws_row = 24;
- screen_size.ws_col = 80;
-#ifdef TIOCGWINSZ
- }
-#endif
-
- if (pset->notty == 0 &&
- (pagerenv = getenv("PAGER")) &&
- (pagerenv[0] != '\0') &&
- screen_size.ws_row <= 35 &&
- (fout = popen(pagerenv, "w")))
- {
- usePipe = 1;
- pqsignal(SIGPIPE, SIG_IGN);
- }
- else
- fout = stdout;
-
- /* if you add/remove a line here, change the row test above */
- fprintf(fout, " \\? -- help\n");
- fprintf(fout, " \\a -- toggle field-alignment (currently %s)\n", on(pset->opt.align));
- fprintf(fout, " \\C [<captn>] -- set html3 caption (currently '%s')\n", pset->opt.caption ? pset->opt.caption : "");
- fprintf(fout, " \\connect <dbname|-> <user> -- connect to new database (currently '%s')\n", PQdb(pset->db));
- fprintf(fout, " \\copy table {from | to} <fname>\n");
- fprintf(fout, " \\d [<table>] -- list tables and indices, columns in <table>, or * for all\n");
- fprintf(fout, " \\da -- list aggregates\n");
- fprintf(fout, " \\dd [<object>]- list comment an object.\n");
- fprintf(fout, " \\df -- list functions\n");
- fprintf(fout, " \\di -- list only indices\n");
- fprintf(fout, " \\do -- list operators\n");
- fprintf(fout, " \\ds -- list only sequences\n");
- fprintf(fout, " \\dS -- list system tables and indexes\n");
- fprintf(fout, " \\dt -- list only tables\n");
- fprintf(fout, " \\dT -- list types\n");
- fprintf(fout, " \\e [<fname>] -- edit the current query buffer or <fname>\n");
- fprintf(fout, " \\E [<fname>] -- edit the current query buffer or <fname>, and execute\n");
- fprintf(fout, " \\f [<sep>] -- change field separater (currently '%s')\n", pset->opt.fieldSep);
- fprintf(fout, " \\g [<fname>] [|<cmd>] -- send query to backend [and results in <fname> or pipe]\n");
- fprintf(fout, " \\h [<cmd>] -- help on syntax of sql commands, * for all commands\n");
- fprintf(fout, " \\H -- toggle html3 output (currently %s)\n", on(pset->opt.html3));
- fprintf(fout, " \\i <fname> -- read and execute queries from filename\n");
- fprintf(fout, " \\l -- list all databases\n");
- fprintf(fout, " \\m -- toggle monitor-like table display (currently %s)\n", on(pset->opt.standard));
- fprintf(fout, " \\o [<fname>] [|<cmd>] -- send all query results to stdout, <fname>, or pipe\n");
- fprintf(fout, " \\p -- print the current query buffer\n");
- fprintf(fout, " \\q -- quit\n");
- fprintf(fout, " \\r -- reset(clear) the query buffer\n");
- fprintf(fout, " \\s [<fname>] -- print history or save it in <fname>\n");
- fprintf(fout, " \\t -- toggle table headings and row count (currently %s)\n", on(pset->opt.header));
- fprintf(fout, " \\T [<html>] -- set html3.0 <table ...> options (currently '%s')\n", pset->opt.tableOpt ? pset->opt.tableOpt : "");
- fprintf(fout, " \\x -- toggle expanded output (currently %s)\n", on(pset->opt.expanded));
- fprintf(fout, " \\w <fname> -- write current buffer to a file\n");
- fprintf(fout, " \\z -- list current grant/revoke permissions\n");
- fprintf(fout, " \\! [<cmd>] -- shell escape or command\n");
-
- if (usePipe)
- {
- pclose(fout);
- pqsignal(SIGPIPE, SIG_DFL);
- }
-}
-
-static PGresult *
-PSQLexec(PsqlSettings *pset, char *query)
-{
- PGresult *res;
-
- if (pset->echoAllQueries)
- {
- fprintf(stderr, "QUERY: %s\n", query);
- fprintf(stderr, "\n");
- fflush(stderr);
- }
-
- res = PQexec(pset->db, query);
- if (!res)
- fputs(PQerrorMessage(pset->db), stderr);
- else
- {
- if (PQresultStatus(res) == PGRES_COMMAND_OK ||
- PQresultStatus(res) == PGRES_TUPLES_OK)
- return res;
- if (!pset->quiet)
- fputs(PQerrorMessage(pset->db), stderr);
- PQclear(res);
- }
- return NULL;
-}
-
-/*
- * Code to support command cancellation.
- * If interactive, we enable a SIGINT signal catcher that sends
- * a cancel request to the backend.
- * Note that sending the cancel directly from the signal handler
- * is safe only because PQrequestCancel is carefully written to
- * make it so. We have to be very careful what else we do in the
- * signal handler.
- * Writing on stderr is potentially dangerous, if the signal interrupted
- * some stdio operation on stderr. On Unix we can avoid trouble by using
- * write() instead; on Windows that's probably not workable, but we can
- * at least avoid trusting printf by using the more primitive fputs.
- */
-
-static PGconn *cancelConn = NULL; /* connection to try cancel on */
-
-static void
-safe_write_stderr(const char *s)
-{
-#ifdef WIN32
- fputs(s, stderr);
-#else
- write(fileno(stderr), s, strlen(s));
-#endif
-}
-
-static void
-handle_sigint(SIGNAL_ARGS)
-{
- if (cancelConn == NULL)
- exit(1); /* accept signal if no connection */
- /* Try to send cancel request */
- if (PQrequestCancel(cancelConn))
- safe_write_stderr("\nCANCEL request sent\n");
- else
- {
- safe_write_stderr("\nCannot send cancel request:\n");
- safe_write_stderr(PQerrorMessage(cancelConn));
- }
-}
-
-
-/*
- * listAllDbs
- *
- * list all the databases in the system returns 0 if all went well
- *
- *
- */
-
-static int
-listAllDbs(PsqlSettings *pset)
-{
- PGresult *results;
- char *query = "select * from pg_database;";
-
- if (!(results = PSQLexec(pset, query)))
- return 1;
- else
- {
- PQprint(pset->queryFout,
- results,
- &pset->opt);
- PQclear(results);
- return 0;
- }
-}
-
-/*
- * List The Database Tables returns 0 if all went well
- *
- */
-static int
-tableList(PsqlSettings *pset, bool deep_tablelist, char info_type,
- bool system_tables)
-{
- char listbuf[512];
- int nColumns;
- int i;
- char *rk;
- char *rr;
- PGresult *res;
- int usePipe = 0;
- bool haveIndexes = false;
- char *pagerenv;
- FILE *fout;
-
-#ifdef TIOCGWINSZ
- if (pset->notty == 0 &&
- (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
- screen_size.ws_col == 0 ||
- screen_size.ws_row == 0))
- {
-#endif
- screen_size.ws_row = 24;
- screen_size.ws_col = 80;
-#ifdef TIOCGWINSZ
- }
-#endif
-
- listbuf[0] = '\0';
- strcat(listbuf, "SELECT usename, relname, relkind, relhasrules ");
- strcat(listbuf, "FROM pg_class, pg_user ");
- strcat(listbuf, "WHERE usesysid = relowner ");
- switch (info_type)
- {
- case 't':
- strcat(listbuf, "and ( relkind = 'r') ");
- break;
- case 'i':
- strcat(listbuf, "and ( relkind = 'i') ");
- haveIndexes = true;
- break;
- case 'S':
- strcat(listbuf, "and ( relkind = 'S') ");
- break;
- case 'b':
- default:
- strcat(listbuf, "and ( relkind = 'r' OR relkind = 'i' OR relkind = 'S') ");
- haveIndexes = true;
- break;
- }
- if (!system_tables)
- strcat(listbuf, "and relname !~ '^pg_' ");
- else
- strcat(listbuf, "and relname ~ '^pg_' ");
- /*
- * Large-object relations are automatically ignored because they have
- * relkind 'l'. However, we want to ignore their indexes as well.
- * The clean way to do that would be to do a join to find out which
- * table each index is for. The ugly but fast way is to know that
- * large object indexes have names starting with 'xinx'.
- */
- if (haveIndexes)
- strcat(listbuf, "and (relkind != 'i' OR relname !~ '^xinx') ");
-
- strcat(listbuf, " ORDER BY relname ");
- if (!(res = PSQLexec(pset, listbuf)))
- return -1;
- /* first, print out the attribute names */
- nColumns = PQntuples(res);
- if (nColumns > 0)
- {
- if (pset->notty == 0 &&
- (pagerenv = getenv("PAGER")) &&
- pagerenv[0] != '\0' &&
- (deep_tablelist ||
- screen_size.ws_row <= nColumns + 7) &&
- (fout = popen(pagerenv, "w")))
- {
- usePipe = 1;
- pqsignal(SIGPIPE, SIG_IGN);
- }
- else
- fout = stdout;
-
- if (deep_tablelist)
- {
- /* describe everything here */
- char **table;
-
- table = (char **) malloc(nColumns * sizeof(char *));
- if (table == NULL)
- perror("malloc");
-
- /* load table table */
-
- /*
- * Put double quotes around the table name to allow for
- * mixed-case and whitespaces in the table name. - BGA
- * 1998-11-14
- */
- for (i = 0; i < nColumns; i++)
- {
- table[i] = (char *) malloc(PQgetlength(res, i, 1) * sizeof(char) + 3);
- if (table[i] == NULL)
- perror("malloc");
- strcpy(table[i], "\"");
- strcat(table[i], PQgetvalue(res, i, 1));
- strcat(table[i], "\"");
- }
-
- PQclear(res);
- for (i = 0; i < nColumns; i++)
- tableDesc(pset, table[i], fout);
- free(table);
- }
- else
- {
- /* Display the information */
-
- fprintf(fout, "Database = %s\n", PQdb(pset->db));
- fprintf(fout, " +------------------+----------------------------------+----------+\n");
- fprintf(fout, " | Owner | Relation | Type |\n");
- fprintf(fout, " +------------------+----------------------------------+----------+\n");
-
- /* next, print out the instances */
- for (i = 0; i < PQntuples(res); i++)
- {
- fprintf(fout, " | %-16.16s", PQgetvalue(res, i, 0));
- fprintf(fout, " | %-32.32s | ", PQgetvalue(res, i, 1));
- rk = PQgetvalue(res, i, 2);
- rr = PQgetvalue(res, i, 3);
- if (strcmp(rk, "r") == 0)
- fprintf(fout, "%-8.8s |", (rr[0] == 't') ? "view?" : "table");
- else if (strcmp(rk, "i") == 0)
- fprintf(fout, "%-8.8s |", "index");
- else
- fprintf(fout, "%-8.8s |", "sequence");
- fprintf(fout, "\n");
- }
- fprintf(fout, " +------------------+----------------------------------+----------+\n");
- fprintf(fout, "\n");
- PQclear(res);
- }
- if (usePipe)
- {
- pclose(fout);
- pqsignal(SIGPIPE, SIG_DFL);
- }
- return 0;
-
- }
- else
- {
- PQclear(res);
- switch (info_type)
- {
- case 't':
- fprintf(stderr, "Couldn't find any tables!\n");
- break;
- case 'i':
- fprintf(stderr, "Couldn't find any indices!\n");
- break;
- case 'S':
- fprintf(stderr, "Couldn't find any sequences!\n");
- break;
- case 'b':
- default:
- fprintf(stderr, "Couldn't find any tables, sequences or indices!\n");
- break;
- }
- return -1;
- }
-}
-
-/*
- * List Tables Grant/Revoke Permissions returns 0 if all went well
- *
- */
-static int
-rightsList(PsqlSettings *pset)
-{
- char listbuf[512];
- int nColumns;
- int i;
- int maxCol1Len;
- int maxCol2Len;
- int usePipe = 0;
- char *pagerenv;
- FILE *fout;
- PGresult *res;
-
-#ifdef TIOCGWINSZ
- if (pset->notty == 0 &&
- (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
- screen_size.ws_col == 0 ||
- screen_size.ws_row == 0))
- {
-#endif
- screen_size.ws_row = 24;
- screen_size.ws_col = 80;
-#ifdef TIOCGWINSZ
- }
-#endif
-
- listbuf[0] = '\0';
- strcat(listbuf, "SELECT relname, relacl ");
- strcat(listbuf, "FROM pg_class ");
- /* Currently, we ignore indexes since they have no meaningful rights */
- strcat(listbuf, "WHERE ( relkind = 'r' OR relkind = 'S') ");
- strcat(listbuf, " and relname !~ '^pg_'");
- strcat(listbuf, " ORDER BY relname ");
- if (!(res = PSQLexec(pset, listbuf)))
- return -1;
- /* first, print out the attribute names */
- nColumns = PQntuples(res);
- if (nColumns > 0)
- {
- if (pset->notty == 0 &&
- (pagerenv = getenv("PAGER")) &&
- pagerenv[0] != '\0' &&
- screen_size.ws_row <= nColumns + 7 &&
- (fout = popen(pagerenv, "w")))
- {
- usePipe = 1;
- pqsignal(SIGPIPE, SIG_IGN);
- }
- else
- fout = stdout;
-
- /* choose column widths */
- maxCol1Len = strlen("Relation");
- maxCol2Len = strlen("Grant/Revoke Permissions");
- for (i = 0; i < PQntuples(res); i++)
- {
- int l = strlen(PQgetvalue(res, i, 0));
-
- if (l > maxCol1Len)
- maxCol1Len = l;
- l = strlen(PQgetvalue(res, i, 1));
- if (l > maxCol2Len)
- maxCol2Len = l;
- }
-
- /* Display the information */
-
- fprintf(fout, "Database = %s\n", PQdb(pset->db));
- fprintf(fout, " +");
- emitNtimes(fout, "-", maxCol1Len + 2);
- fprintf(fout, "+");
- emitNtimes(fout, "-", maxCol2Len + 2);
- fprintf(fout, "+\n");
- fprintf(fout, " | %-*s | %-*s |\n",
- maxCol1Len, "Relation",
- maxCol2Len, "Grant/Revoke Permissions");
- fprintf(fout, " +");
- emitNtimes(fout, "-", maxCol1Len + 2);
- fprintf(fout, "+");
- emitNtimes(fout, "-", maxCol2Len + 2);
- fprintf(fout, "+\n");
-
- /* next, print out the instances */
- for (i = 0; i < PQntuples(res); i++)
- {
- fprintf(fout, " | %-*s | %-*s |\n",
- maxCol1Len, PQgetvalue(res, i, 0),
- maxCol2Len, PQgetvalue(res, i, 1));
- }
-
- fprintf(fout, " +");
- emitNtimes(fout, "-", maxCol1Len + 2);
- fprintf(fout, "+");
- emitNtimes(fout, "-", maxCol2Len + 2);
- fprintf(fout, "+\n");
-
- PQclear(res);
- if (usePipe)
- {
- pclose(fout);
- pqsignal(SIGPIPE, SIG_DFL);
- }
- return 0;
- }
- else
- {
- PQclear(res);
- fprintf(stderr, "Couldn't find any tables!\n");
- return -1;
- }
-}
-
-static void
-emitNtimes(FILE *fout, const char *str, int N)
-{
- int i;
-
- for (i = 0; i < N; i++)
- fputs(str, fout);
-}
-
-/*
- * Describe a table
- *
- * Describe the columns in a database table. returns 0 if all went well
- *
- *
- */
-static int
-tableDesc(PsqlSettings *pset, char *table, FILE *fout)
-{
- char descbuf[512];
- int nColumns,
- nIndices;
- char *rtype;
- char *rnotnull;
- char *rhasdef;
- int i;
- int attlen,
- atttypmod;
- PGresult *res,
- *res2;
- int usePipe = 0;
- char *pagerenv;
-
-#ifdef TIOCGWINSZ
- if (pset->notty == 0 &&
- (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
- screen_size.ws_col == 0 ||
- screen_size.ws_row == 0))
- {
-#endif
- screen_size.ws_row = 24;
- screen_size.ws_col = 80;
-#ifdef TIOCGWINSZ
- }
-#endif
-
- /* Build the query */
-
- /*
- * if the table name is surrounded by double-quotes, then don't
- * convert case
- */
- if (*table == '"')
- {
- table++;
- if (*(table + strlen(table) - 1) == '"')
- *(table + strlen(table) - 1) = '\0';
- }
- else
- {
-#ifdef MULTIBYTE
- for (i = 0; table[i]; i += PQmblen(table + i))
-#else
- for (i = 0; table[i]; i++)
-#endif
- if (isascii((unsigned char) table[i]) &&
- isupper(table[i]))
- table[i] = tolower(table[i]);
- }
-
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT a.attnum, a.attname, t.typname, a.attlen, ");
- strcat(descbuf, "a.atttypmod, a.attnotnull, a.atthasdef ");
- strcat(descbuf, "FROM pg_class c, pg_attribute a, pg_type t ");
- strcat(descbuf, "WHERE c.relname = '");
- strcat(descbuf, table);
- strcat(descbuf, "'");
- strcat(descbuf, " and a.attnum > 0 ");
- strcat(descbuf, " and a.attrelid = c.oid ");
- strcat(descbuf, " and a.atttypid = t.oid ");
- strcat(descbuf, " ORDER BY attnum ");
- if (!(res = PSQLexec(pset, descbuf)))
- return -1;
- /* first, print out the attribute names */
- nColumns = PQntuples(res);
- if (nColumns > 0)
- {
- if (fout == NULL)
- {
- if (pset->notty == 0 &&
- (pagerenv = getenv("PAGER")) &&
- pagerenv[0] != '\0' &&
- screen_size.ws_row <= nColumns + 7 &&
- (fout = popen(pagerenv, "w")))
- {
- usePipe = 1;
- pqsignal(SIGPIPE, SIG_IGN);
- }
- else
- fout = stdout;
- }
-
- /*
- * Extract the veiw name and veiw definition from pg_views. -Ryan
- * 2/14/99
- */
-
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT viewname, definition ");
- strcat(descbuf, "FROM pg_views ");
- strcat(descbuf, "WHERE viewname like '");
- strcat(descbuf, table);
- strcat(descbuf, "' ");
- if (!(res2 = PSQLexec(pset, descbuf)))
- return -1;
-
- /*
- * Display the information
- */
- if (PQntuples(res2))
- {
-
- /*
- * display the query. o * -Ryan 2/14/99
- */
- fprintf(fout, "View = %s\n", table);
- fprintf(fout, "Query = %s\n", PQgetvalue(res2, 0, 1));
- }
- else
- fprintf(fout, "Table = %s\n", table);
- PQclear(res2);
-
- fprintf(fout, "+----------------------------------+----------------------------------+-------+\n");
- fprintf(fout, "| Field | Type | Length|\n");
- fprintf(fout, "+----------------------------------+----------------------------------+-------+\n");
-
- /* next, print out the instances */
- for (i = 0; i < PQntuples(res); i++)
- {
- char type_str[33];
-
- fprintf(fout, "| %-32.32s | ", PQgetvalue(res, i, 1));
- rtype = PQgetvalue(res, i, 2);
- attlen = atoi(PQgetvalue(res, i, 3));
- atttypmod = atoi(PQgetvalue(res, i, 4));
- rnotnull = PQgetvalue(res, i, 5);
- rhasdef = PQgetvalue(res, i, 6);
-
- strcpy(type_str, rtype);
- if (strcmp(rtype, "bpchar") == 0)
- strcpy(type_str, "char()");
- else if (strcmp(rtype, "varchar") == 0)
- strcpy(type_str, "varchar()");
- else if (rtype[0] == '_')
- {
- strcpy(type_str, rtype + 1);
- strncat(type_str, "[]", 32 - strlen(type_str));
- type_str[32] = '\0';
- }
-
- if (rnotnull[0] == 't')
- {
- strncat(type_str, " not null", 32 - strlen(type_str));
- type_str[32] = '\0';
- }
- if (rhasdef[0] == 't')
- {
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT d.adsrc ");
- strcat(descbuf, "FROM pg_attrdef d, pg_class c ");
- strcat(descbuf, "WHERE c.relname = '");
- strcat(descbuf, table);
- strcat(descbuf, "'");
- strcat(descbuf, " and c.oid = d.adrelid ");
- strcat(descbuf, " and d.adnum = ");
- strcat(descbuf, PQgetvalue(res, i, 0));
- if (!(res2 = PSQLexec(pset, descbuf)))
- return -1;
- strcat(type_str, " default ");
- strncat(type_str, PQgetvalue(res2, 0, 0), 32 - strlen(type_str));
- type_str[32] = '\0';
- }
- fprintf(fout, "%-32.32s |", type_str);
-
- if (strcmp(rtype, "text") == 0)
- fprintf(fout, "%6s |", "var");
- else if (strcmp(rtype, "bpchar") == 0 ||
- strcmp(rtype, "varchar") == 0)
- fprintf(fout, "%6i |", atttypmod != -1 ? atttypmod - VARHDRSZ : 0);
- else if (strcmp(rtype, "numeric") == 0)
- fprintf(fout, "%3i.%-2i |",
- ((atttypmod - VARHDRSZ) >> 16) & 0xffff,
- (atttypmod - VARHDRSZ) & 0xffff);
- else
- {
- if (attlen > 0)
- fprintf(fout, "%6i |", attlen);
- else
- fprintf(fout, "%6s |", "var");
- }
- fprintf(fout, "\n");
- }
- fprintf(fout, "+----------------------------------+----------------------------------+-------+\n");
- PQclear(res);
-
- /* display defined indexes for this table */
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT c2.relname ");
- strcat(descbuf, "FROM pg_class c, pg_class c2, pg_index i ");
- strcat(descbuf, "WHERE c.relname = '");
- strcat(descbuf, table);
- strcat(descbuf, "'");
- strcat(descbuf, " and c.oid = i.indrelid ");
- strcat(descbuf, " and i.indexrelid = c2.oid ");
- strcat(descbuf, " ORDER BY c2.relname ");
- if ((res = PSQLexec(pset, descbuf)))
- {
- nIndices = PQntuples(res);
- if (nIndices > 0)
- {
-
- /*
- * Display the information
- */
-
- if (nIndices == 1)
- fprintf(fout, "Index: ");
- else
- fprintf(fout, "Indices: ");
-
- /* next, print out the instances */
- for (i = 0; i < PQntuples(res); i++)
- if (i == 0)
- fprintf(fout, "%s\n", PQgetvalue(res, i, 0));
- else
- fprintf(fout, " %s\n", PQgetvalue(res, i, 0));
- fprintf(fout, "\n");
- }
- PQclear(res);
- }
- if (usePipe)
- {
- pclose(fout);
- pqsignal(SIGPIPE, SIG_DFL);
- }
- return 0;
- }
- else
- {
- PQclear(res);
- fprintf(stderr, "Couldn't find table %s!\n", table);
- return -1;
- }
-}
-
-/*
- * Get object comments
- *
- * Describe the columns in a database table. returns 0 if all went well
- *
- *
- */
-static int
-objectDescription(PsqlSettings *pset, char *object)
-{
- char descbuf[512];
- PGresult *res;
- int i;
- bool success;
-
- /* Build the query */
-
- while (isspace(*object))
- object++;
-
- /*
- * if the object name is surrounded by double-quotes, then don't
- * convert case
- */
- if (*object == '"')
- {
- object++;
- if (*(object + strlen(object) - 1) == '"')
- *(object + strlen(object) - 1) = '\0';
- }
- else
- {
-#ifdef MULTIBYTE
- for (i = 0; object[i]; i += PQmblen(object + i))
-#else
- for (i = 0; object[i]; i++)
-#endif
- if (isupper(object[i]))
- object[i] = tolower(object[i]);
- }
-
- descbuf[0] = '\0';
- if (strchr(object, '.') != NULL)
- {
- char table[NAMEDATALEN],
- column[NAMEDATALEN];
-
- StrNCpy(table, object,
- ((strchr(object, '.') - object + 1) < NAMEDATALEN) ?
- (strchr(object, '.') - object + 1) : NAMEDATALEN);
- StrNCpy(column, strchr(object, '.') + 1, NAMEDATALEN);
- strcat(descbuf, "SELECT DISTINCT description ");
- strcat(descbuf, "FROM pg_class, pg_attribute, pg_description ");
- strcat(descbuf, "WHERE pg_class.relname = '");
- strcat(descbuf, table);
- strcat(descbuf, "' and ");
- strcat(descbuf, "pg_class.oid = pg_attribute.attrelid and ");
- strcat(descbuf, "pg_attribute.attname = '");
- strcat(descbuf, column);
- strcat(descbuf, "' and ");
- strcat(descbuf, " pg_attribute.oid = pg_description.objoid ");
- if (!(res = PSQLexec(pset, descbuf)))
- return -1;
- }
- else
- {
- strcat(descbuf, "SELECT DISTINCT description ");
- strcat(descbuf, "FROM pg_class, pg_description ");
- strcat(descbuf, "WHERE pg_class.relname ~ '^");
- strcat(descbuf, object);
- strcat(descbuf, "'");
- strcat(descbuf, " and pg_class.oid = pg_description.objoid ");
- if (!(res = PSQLexec(pset, descbuf)))
- return -1;
- else if (PQntuples(res) <= 0)
- {
- PQclear(res);
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT DISTINCT description ");
- strcat(descbuf, "FROM pg_type, pg_description ");
- strcat(descbuf, "WHERE pg_type.typname ~ '^");
- strcat(descbuf, object);
- strcat(descbuf, "' and ");
- strcat(descbuf, " pg_type.oid = pg_description.objoid ");
- if (!(res = PSQLexec(pset, descbuf)))
- return -1;
- else if (PQntuples(res) <= 0)
- {
- PQclear(res);
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT DISTINCT description ");
- strcat(descbuf, "FROM pg_proc, pg_description ");
- strcat(descbuf, "WHERE pg_proc.proname ~ '^");
- strcat(descbuf, object);
- strcat(descbuf, "'");
- strcat(descbuf, " and pg_proc.oid = pg_description.objoid ");
- if (!(res = PSQLexec(pset, descbuf)))
- return -1;
- else if (PQntuples(res) <= 0)
- {
- PQclear(res);
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT DISTINCT description ");
- strcat(descbuf, "FROM pg_operator, pg_description ");
- strcat(descbuf, "WHERE pg_operator.oprname ~ '^");
- strcat(descbuf, object);
- strcat(descbuf, "'");
- /* operator descriptions are attached to the proc */
- strcat(descbuf, " and RegprocToOid(pg_operator.oprcode) = pg_description.objoid ");
- if (!(res = PSQLexec(pset, descbuf)))
- return -1;
- else if (PQntuples(res) <= 0)
- {
- PQclear(res);
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT DISTINCT description ");
- strcat(descbuf, "FROM pg_aggregate, pg_description ");
- strcat(descbuf, "WHERE pg_aggregate.aggname ~ '^");
- strcat(descbuf, object);
- strcat(descbuf, "'");
- strcat(descbuf, " and pg_aggregate.oid = pg_description.objoid ");
- if (!(res = PSQLexec(pset, descbuf)))
- return -1;
- else if (PQntuples(res) <= 0)
- {
- PQclear(res);
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT 'no description' as description ");
- if (!(res = PSQLexec(pset, descbuf)))
- return -1;
- }
- }
- }
- }
- }
- }
-
- PQclear(res);
-
- success = SendQuery(pset, descbuf, NULL, NULL);
-
- return 0;
-}
-
-/*
- * Basic routines to read a line of input
- *
- * All three routines will return a malloc'd string of indefinite size.
- */
-typedef char *(*READ_ROUTINE) (char *prompt, FILE *source);
-
-/*
- * gets_noreadline
- * gets a line of interactive input (without using readline)
- *
- * the source is ignored
- */
-static char *
-gets_noreadline(char *prompt, FILE *source)
-{
- fputs(prompt, stdout);
- fflush(stdout);
- return gets_fromFile(prompt, stdin);
-}
-
-/*
- * gets_readline
- * gets a line of interactive input using readline library
- *
- * the source is ignored
- */
-static char *
-gets_readline(char *prompt, FILE *source)
-{
- char *s;
-
-#ifdef USE_READLINE
- s = readline(prompt);
-#else
- s = gets_noreadline(prompt, source);
-#endif
- fputc('\r', stdout);
- fflush(stdout);
- return s;
-}
-
-/*
- * gets_fromFile
- * gets a line of noninteractive input from a file
- *
- * the prompt is ignored
- */
-static char *
-gets_fromFile(char *prompt, FILE *source)
-{
- PQExpBufferData buffer;
- char line[COPYBUFSIZ];
-
- initPQExpBuffer(&buffer);
-
- while (fgets(line, COPYBUFSIZ, source) != NULL)
- {
- appendPQExpBufferStr(&buffer, line);
- if (buffer.data[buffer.len-1] == '\n')
- return buffer.data;
- }
-
- if (buffer.len > 0)
- return buffer.data; /* EOF after reading some bufferload(s) */
-
- /* EOF, so return null */
- termPQExpBuffer(&buffer);
- return NULL;
-}
-
-/*
- * SendQuery: send the query string to the backend.
- *
- * Return true if the query executed successfully, false otherwise.
- *
- * If not NULL, copy_in_stream and copy_out_stream are files to redirect
- * copy in/out data to.
- */
-static bool
-SendQuery(PsqlSettings *pset, const char *query,
- FILE *copy_in_stream, FILE *copy_out_stream)
-{
- bool success = false;
- PGresult *results;
- PGnotify *notify;
-
- if (pset->singleStep)
- fprintf(stdout, "\n**************************************"
- "*****************************************\n");
-
- if (pset->echoQuery || pset->singleStep)
- {
- fprintf(stderr, "QUERY: %s\n", query);
- fflush(stderr);
- }
- if (pset->singleStep)
- {
- fprintf(stdout, "\n**************************************"
- "*****************************************\n");
- fflush(stdout);
- printf("\npress return to continue ..\n");
- gets_fromFile("", stdin);
- }
- results = PQexec(pset->db, query);
- if (results == NULL)
- {
- fprintf(stderr, "%s", PQerrorMessage(pset->db));
- success = false;
- }
- else
- {
- switch (PQresultStatus(results))
- {
- case PGRES_TUPLES_OK:
- if (pset->gfname)
- {
- PsqlSettings settings_copy = *pset;
- FILE *fp;
-
- settings_copy.queryFout = stdout;
- fp = setFout(&settings_copy, pset->gfname);
- if (!fp || fp == stdout)
- {
- success = false;
- break;
- }
- PQprint(fp,
- results,
- &pset->opt);
- if (settings_copy.pipe)
- pclose(fp);
- else
- fclose(fp);
- free(pset->gfname);
- pset->gfname = NULL;
- success = true;
- break;
- }
- else
- {
- success = true;
- PQprint(pset->queryFout,
- results,
- &(pset->opt));
- fflush(pset->queryFout);
- }
- break;
- case PGRES_EMPTY_QUERY:
- success = true;
- break;
- case PGRES_COMMAND_OK:
- success = true;
- if (!pset->quiet)
- printf("%s\n", PQcmdStatus(results));
- break;
- case PGRES_COPY_OUT:
- if (copy_out_stream)
- success = handleCopyOut(pset->db, copy_out_stream);
- else
- {
- if (pset->queryFout == stdout && !pset->quiet)
- printf("Copy command returns...\n");
-
- success = handleCopyOut(pset->db, pset->queryFout);
- }
- break;
- case PGRES_COPY_IN:
- if (copy_in_stream)
- success = handleCopyIn(pset->db, false, copy_in_stream);
- else
- success = handleCopyIn(pset->db,
- cur_cmd_interactive && !pset->quiet,
- cur_cmd_source);
- break;
- case PGRES_NONFATAL_ERROR:
- case PGRES_FATAL_ERROR:
- case PGRES_BAD_RESPONSE:
- success = false;
- fprintf(stderr, "%s", PQerrorMessage(pset->db));
- break;
- }
-
- if (PQstatus(pset->db) == CONNECTION_BAD)
- {
- fprintf(stderr,
- "We have lost the connection to the backend, so "
- "further processing is impossible. "
- "Terminating.\n");
- exit(2); /* we are out'ta here */
- }
- /* check for asynchronous returns */
- while ((notify = PQnotifies(pset->db)) != NULL)
- {
- fprintf(stderr,
- "ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
- notify->relname, notify->be_pid);
- free(notify);
- }
- if (results)
- PQclear(results);
- }
- return success;
-}
-
-
-
-static void
-editFile(char *fname)
-{
- char *editorName;
- char *sys;
-
- editorName = getenv("EDITOR");
- if (!editorName)
- editorName = DEFAULT_EDITOR;
- sys = malloc(strlen(editorName) + strlen(fname) + 32 + 1);
- if (!sys)
- {
- perror("malloc");
- exit(1);
- }
- sprintf(sys, "exec '%s' '%s'", editorName, fname);
- system(sys);
- free(sys);
-}
-
-static bool
-toggle(PsqlSettings *pset, bool *sw, char *msg)
-{
- *sw = !*sw;
- if (!pset->quiet)
- printf("turned %s %s\n", on(*sw), msg);
- return *sw;
-}
-
-
-
-static void
-unescape(char *dest, const char *source)
-{
- /*-----------------------------------------------------------------------------
- Return as the string <dest> the value of string <source> with escape
- sequences turned into the bytes they represent.
- -----------------------------------------------------------------------------*/
- char *p;
- bool esc; /* Last character we saw was the escape
- * character (/) */
-
- esc = false; /* Haven't seen escape character yet */
- for (p = (char *) source; *p; p++)
- {
- char c; /* Our output character */
-
- if (esc)
- {
- switch (*p)
- {
- case 'n':
- c = '\n';
- break;
- case 'r':
- c = '\r';
- break;
- case 't':
- c = '\t';
- break;
- case 'f':
- c = '\f';
- break;
- case '\\':
- c = '\\';
- break;
- default:
- c = *p;
- }
- esc = false;
- }
- else if (*p == '\\')
- {
- esc = true;
- c = ' '; /* meaningless, but compiler doesn't know
- * that */
- }
- else
- {
- c = *p;
- esc = false;
- }
- if (!esc)
- *dest++ = c;
- }
- *dest = '\0'; /* Terminating null character */
-}
-
-
-
-static void
-parse_slash_copy(const char *args, char *table, const int table_len,
- char *file, const int file_len,
- bool *from_p, bool *error_p)
-{
-
- char work_args[200];
-
- /*
- * A copy of the \copy command arguments, except that we modify it as
- * we parse to suit our parsing needs.
- */
- char *table_tok,
- *fromto_tok;
-
- strncpy(work_args, args, sizeof(work_args));
- work_args[sizeof(work_args) - 1] = '\0';
-
- *error_p = false; /* initial assumption */
-
- table_tok = strtok(work_args, " ");
- if (table_tok == NULL)
- {
- fprintf(stderr, "\\copy needs arguments.\n");
- *error_p = true;
- }
- else
- {
- strncpy(table, table_tok, table_len);
- file[table_len - 1] = '\0';
-
- fromto_tok = strtok(NULL, " ");
- if (fromto_tok == NULL)
- {
- fprintf(stderr, "'FROM' or 'TO' must follow table name.\n");
- *error_p = true;
- }
- else
- {
- if (strcasecmp(fromto_tok, "from") == 0)
- *from_p = true;
- else if (strcasecmp(fromto_tok, "to") == 0)
- *from_p = false;
- else
- {
- fprintf(stderr,
- "Unrecognized token found where "
- "'FROM' or 'TO' expected: '%s'.\n",
- fromto_tok);
- *error_p = true;
- }
- if (!*error_p)
- {
- char *file_tok;
-
- file_tok = strtok(NULL, " ");
- if (file_tok == NULL)
- {
- fprintf(stderr, "A file pathname must follow '%s'.\n",
- fromto_tok);
- *error_p = true;
- }
- else
- {
- strncpy(file, file_tok, file_len);
- file[file_len - 1] = '\0';
- if (strtok(NULL, " ") != NULL)
- {
- fprintf(stderr,
- "You have extra tokens after the filename.\n");
- *error_p = true;
- }
- }
- }
- }
- }
-}
-
-
-
-static void
-do_copy(const char *args, PsqlSettings *pset)
-{
- /*---------------------------------------------------------------------------
- Execute a \copy command (frontend copy). We have to open a file, then
- submit a COPY query to the backend and either feed it data from the
- file or route its response into the file.
-
- We do a text copy with default (tab) column delimiters. Some day, we
- should do all the things a backend copy can do.
-
- ----------------------------------------------------------------------------*/
- char query[200];
-
- /* The COPY command we send to the back end */
- bool from;
-
- /* The direction of the copy is from a file to a table. */
- char file[MAXPGPATH];
-
- /* The pathname of the file from/to which we copy */
- char table[NAMEDATALEN];
-
- /* The name of the table from/to which we copy */
- bool syntax_error;
-
- /* The \c command has invalid syntax */
- FILE *copystream;
-
- parse_slash_copy(args, table, sizeof(table), file, sizeof(file),
- &from, &syntax_error);
-
- if (!syntax_error)
- {
- strcpy(query, "COPY ");
- strcat(query, table);
-
- if (from)
- strcat(query, " FROM stdin");
- else
- strcat(query, " TO stdout");
-
- if (from)
-#ifndef __CYGWIN32__
- copystream = fopen(file, "r");
-#else
- copystream = fopen(file, "rb");
-#endif
- else
-#ifndef __CYGWIN32__
- copystream = fopen(file, "w");
-#else
- copystream = fopen(file, "wb");
-#endif
- if (copystream == NULL)
- fprintf(stderr,
- "Unable to open file %s which to copy, errno = %s (%d).",
- from ? "from" : "to", strerror(errno), errno);
- else
- {
- bool success;/* The query succeeded at the backend */
-
- success = SendQuery(pset, query,
- from ? copystream : (FILE *) NULL,
- !from ? copystream : (FILE *) NULL);
- fclose(copystream);
- if (!pset->quiet)
- {
- if (success)
- printf("Successfully copied.\n");
- else
- printf("Copy failed.\n");
- }
- }
- }
-}
-
-
-static void
-do_connect(const char *new_dbname,
- const char *new_user,
- PsqlSettings *pset)
-{
- if (!new_dbname)
- fprintf(stderr, "\\connect must be followed by a database name\n");
- else if (new_user != NULL && pset->getPassword)
- fprintf(stderr, "You can't specify a username when using passwords.\n");
- else
- {
- PGconn *olddb = pset->db;
- const char *dbparam;
- const char *userparam;
- const char *pwparam;
-
- if (strcmp(new_dbname, "-") != 0)
- dbparam = new_dbname;
- else
- dbparam = PQdb(olddb);
-
- if (new_user != NULL && strcmp(new_user, "-") != 0)
- userparam = new_user;
- else
- userparam = PQuser(olddb);
-
- /* FIXME: if changing user, ought to prompt for a new password? */
- pwparam = PQpass(olddb);
-
-#ifdef MULTIBYTE
-
- /*
- * PGCLIENTENCODING may be set by the previous connection. if a
- * user does not explicitly set PGCLIENTENCODING, we should
- * discard PGCLIENTENCODING so that libpq could get the backend
- * encoding as the default PGCLIENTENCODING value. -- 1998/12/12
- * Tatsuo Ishii
- */
-
- if (!has_client_encoding)
- {
- static const char ev[] = "PGCLIENTENCODING=";
-
- putenv(ev);
- }
-#endif
-
- pset->db = PQsetdbLogin(PQhost(olddb), PQport(olddb),
- NULL, NULL, dbparam, userparam, pwparam);
-
- if (!pset->quiet)
- {
- if (!new_user)
- printf("connecting to new database: %s\n", dbparam);
- else if (dbparam != new_dbname)
- printf("connecting as new user: %s\n", new_user);
- else
- printf("connecting to new database: %s as user: %s\n",
- dbparam, new_user);
- }
-
- if (PQstatus(pset->db) == CONNECTION_BAD)
- {
- fprintf(stderr, "%s\n", PQerrorMessage(pset->db));
- fprintf(stderr, "Could not connect to new database. exiting\n");
- exit(2);
- }
- else
- {
- cancelConn = pset->db; /* redirect sigint's loving
- * attentions */
- PQfinish(olddb);
- free(pset->prompt);
- pset->prompt = malloc(strlen(PQdb(pset->db)) + 10);
- sprintf(pset->prompt, "%s%s", PQdb(pset->db), PROMPT);
- }
- }
-}
-
-
-static void
-do_edit(const char *filename_arg, PQExpBuffer query_buf, int *status_p)
-{
- int fd;
- char fnametmp[64];
- char *fname;
- int cc;
- int ql = query_buf->len;
- bool error;
- char line[COPYBUFSIZ+1];
-
- if (filename_arg)
- {
- fname = (char *) filename_arg;
- error = false;
- }
- else
- {
-#ifndef WIN32
- sprintf(fnametmp, "/tmp/psql.%ld.%ld",
- (long) geteuid(), (long) getpid());
-#else
- GetTempFileName(".", "psql", 0, fnametmp);
-#endif
- fname = fnametmp;
- unlink(fname);
- if ((fd = open(fname, O_EXCL | O_CREAT | O_WRONLY, 0600)) < 0)
- {
- perror(fname);
- error = true;
- }
- else
- {
- if (ql == 0 || query_buf->data[ql - 1] != '\n')
- {
- appendPQExpBufferChar(query_buf, '\n');
- ql++;
- }
- if (write(fd, query_buf->data, ql) != ql)
- {
- perror(fname);
- close(fd);
- unlink(fname);
- error = true;
- }
- else
- {
- close(fd);
- error = false;
- }
- }
- }
-
- if (error)
- *status_p = CMD_SKIP_LINE;
- else
- {
- editFile(fname);
- if ((fd = open(fname, O_RDONLY, 0)) < 0)
- {
- perror(fname);
- *status_p = CMD_SKIP_LINE;
- }
- else
- {
- resetPQExpBuffer(query_buf);
- while ((cc = (int) read(fd, line, COPYBUFSIZ)) > 0)
- {
- line[cc] = '\0';
- appendPQExpBufferStr(query_buf, line);
- }
- close(fd);
- rightTrim(query_buf->data);
- query_buf->len = strlen(query_buf->data);
- *status_p = CMD_NEWEDIT;
- }
- if (!filename_arg)
- unlink(fname);
- }
-}
-
-
-static void
-do_help(PsqlSettings *pset, const char *topic)
-{
-
- if (!topic)
- {
- char left_center_right; /* Which column we're displaying */
- int i; /* Index into QL_HELP[] */
-
- printf("type \\h <cmd> where <cmd> is one of the following:\n");
-
- left_center_right = 'L';/* Start with left column */
- i = 0;
- while (QL_HELP[i].cmd != NULL)
- {
- switch (left_center_right)
- {
- case 'L':
- printf(" %-25s", QL_HELP[i].cmd);
- left_center_right = 'C';
- break;
- case 'C':
- printf("%-25s", QL_HELP[i].cmd);
- left_center_right = 'R';
- break;
- case 'R':
- printf("%-25s\n", QL_HELP[i].cmd);
- left_center_right = 'L';
- break;
- }
- i++;
- }
- if (left_center_right != 'L')
- puts("\n");
- printf("type \\h * for a complete description of all commands\n");
- }
- else
- {
- int i; /* Index into QL_HELP[] */
- bool help_found; /* We found the help he asked for */
-
- int usePipe = 0;
- char *pagerenv;
- FILE *fout;
-
- if (strcmp(topic, "*") == 0 &&
- (pset->notty == 0) &&
- (pagerenv = getenv("PAGER")) &&
- (pagerenv[0] != '\0') &&
- (fout = popen(pagerenv, "w")))
- {
- usePipe = 1;
- pqsignal(SIGPIPE, SIG_IGN);
- }
- else
- fout = stdout;
-
- help_found = false; /* Haven't found it yet */
- for (i = 0; QL_HELP[i].cmd; i++)
- {
- if (strcasecmp(QL_HELP[i].cmd, topic) == 0 ||
- strcmp(topic, "*") == 0)
- {
- help_found = true;
- fprintf(fout, "Command: %s\n", QL_HELP[i].cmd);
- fprintf(fout, "Description: %s\n", QL_HELP[i].help);
- fprintf(fout, "Syntax:\n");
- fprintf(fout, "%s\n", QL_HELP[i].syntax);
- fprintf(fout, "\n");
- }
- }
-
- if (usePipe)
- {
- pclose(fout);
- pqsignal(SIGPIPE, SIG_DFL);
- }
-
- if (!help_found)
- fprintf(stderr, "command not found, "
- "try \\h with no arguments to see available help\n");
- }
-}
-
-
-
-static void
-do_shell(const char *command)
-{
-
- if (!command)
- {
- char *sys;
- char *shellName;
-
- shellName = getenv("SHELL");
- if (shellName == NULL)
- shellName = DEFAULT_SHELL;
- sys = malloc(strlen(shellName) + 16);
- if (!sys)
- {
- perror("malloc");
- exit(1);
- }
- sprintf(sys, "exec %s", shellName);
- system(sys);
- free(sys);
- }
- else
- system(command);
-}
-
-
-
-/*----------
- * HandleSlashCmds:
- *
- * Handles all the different commands that start with \
- *
- * 'line' is the current input line (ie, the backslash command)
- * 'query_buf' contains the query-so-far, which may be modified by
- * execution of the backslash command (for example, \r clears it)
- *
- * query_buf can be NULL if there is no query-so-far.
- *
- * Returns a status code:
- * 0 - send currently constructed query to backend (i.e. we got a \g)
- * 1 - skip processing of this line, continue building up query
- * 2 - terminate processing (i.e. we got a \q)
- * 3 - new query supplied by edit
- *----------
- */
-static int
-HandleSlashCmds(PsqlSettings *pset,
- char *line,
- PQExpBuffer query_buf)
-{
- int status = CMD_SKIP_LINE;
- bool success;
- char *cmd;
- /*
- * String: value of the slash command, less the slash and with escape
- * sequences decoded.
- */
- char *optarg;
- /*
- * Pointer inside the <cmd> string to the argument of the slash
- * command, assuming it is a one-character slash command. If it's not
- * a one-character command, this is meaningless.
- */
- char *optarg2;
- /*
- * Pointer inside the <cmd> string to the argument of the slash
- * command assuming it's not a one-character command. If it's a
- * one-character command, this is meaningless.
- */
- int blank_loc;
- /* Offset within <cmd> of first blank */
-
- cmd = malloc(strlen(line)); /* unescaping better not make string grow. */
-
- unescape(cmd, line + 1); /* sets cmd string */
-
- if (strlen(cmd) >= 1 && cmd[strlen(cmd) - 1] == ';') /* strip trailing ; */
- cmd[strlen(cmd) - 1] = '\0';
-
- /*
- * Originally, there were just single character commands. Now, we
- * define some longer, friendly commands, but we have to keep the old
- * single character commands too. \c used to be what \connect is now.
- * Complicating matters is the fact that with the single-character
- * commands, you can start the argument right after the single
- * character, so "\copy" would mean "connect to database named 'opy'".
- */
-
- if (strlen(cmd) > 1)
- optarg = cmd + 1 + strspn(cmd + 1, " \t");
- else
- optarg = NULL;
-
- blank_loc = strcspn(cmd, " \t");
- if (blank_loc == 0 || !cmd[blank_loc])
- optarg2 = NULL;
- else
- optarg2 = cmd + blank_loc + strspn(cmd + blank_loc, " \t");
-
- switch (cmd[0])
- {
- case 'a': /* toggles to align fields on output */
- toggle(pset, &pset->opt.align, "field alignment");
- break;
-
- case 'C': /* define new caption */
- if (pset->opt.caption)
- {
- free(pset->opt.caption);
- pset->opt.caption = NULL;
- }
- if (optarg && !(pset->opt.caption = strdup(optarg)))
- {
- perror("malloc");
- exit(CMD_TERMINATE);
- }
- break;
-
- case 'c':
- {
- if (strncmp(cmd, "copy ", strlen("copy ")) == 0 ||
- strncmp(cmd, "copy ", strlen("copy ")) == 0)
- do_copy(optarg2, pset);
- else if (strcmp(cmd, "copy") == 0)
- {
- fprintf(stderr, "See \\? for help\n");
- break;
- }
- else if (strncmp(cmd, "connect ", strlen("connect ")) == 0 ||
- strcmp(cmd, "connect") == 0 /* issue error message */ )
- {
- char *optarg3 = NULL;
- int blank_loc2;
-
- if (optarg2)
- {
- blank_loc2 = strcspn(optarg2, " \t");
- if (blank_loc2 == 0 || *(optarg2 + blank_loc2) == '\0')
- optarg3 = NULL;
- else
- {
- optarg3 = optarg2 + blank_loc2 +
- strspn(optarg2 + blank_loc2, " \t");
- *(optarg2 + blank_loc2) = '\0';
- }
- }
- do_connect(optarg2, optarg3, pset);
- }
- else
- {
- char *optarg3 = NULL;
- int blank_loc2;
-
- if (optarg)
- {
- blank_loc2 = strcspn(optarg, " \t");
- if (blank_loc2 == 0 || *(optarg + blank_loc2) == '\0')
- optarg3 = NULL;
- else
- {
- optarg3 = optarg + blank_loc2 +
- strspn(optarg + blank_loc2, " \t");
- *(optarg + blank_loc2) = '\0';
- }
- }
- do_connect(optarg, optarg3, pset);
- }
- }
- break;
-
- case 'd': /* \d describe database information */
-
- /*
- * if the optarg2 name is surrounded by double-quotes, then
- * don't convert case
- */
- if (optarg2)
- {
- if (*optarg2 == '"')
- {
- optarg2++;
- if (*(optarg2 + strlen(optarg2) - 1) == '"')
- *(optarg2 + strlen(optarg2) - 1) = '\0';
- }
- else
- {
- int i;
-
-#ifdef MULTIBYTE
- for (i = 0; optarg2[i]; i += PQmblen(optarg2 + i))
-#else
- for (i = 0; optarg2[i]; i++)
-#endif
- if (isupper(optarg2[i]))
- optarg2[i] = tolower(optarg2[i]);
- }
- }
-
-#ifdef TIOCGWINSZ
- if (pset->notty == 0 &&
- (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 ||
- screen_size.ws_col == 0 ||
- screen_size.ws_row == 0))
- {
-#endif
- screen_size.ws_row = 24;
- screen_size.ws_col = 80;
-#ifdef TIOCGWINSZ
- }
-#endif
- if (strncmp(cmd, "da", 2) == 0)
- {
- char descbuf[4096];
-
- /* aggregates */
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT a.aggname AS aggname, ");
- strcat(descbuf, " t.typname AS type, ");
- strcat(descbuf, " obj_description(a.oid) as description ");
- strcat(descbuf, "FROM pg_aggregate a, pg_type t ");
- strcat(descbuf, "WHERE a.aggbasetype = t.oid ");
- if (optarg2)
- {
- strcat(descbuf, "AND a.aggname ~ '^");
- strcat(descbuf, optarg2);
- strcat(descbuf, "' ");
- }
- strcat(descbuf, "UNION ");
- strcat(descbuf, "SELECT a.aggname AS aggname, ");
- strcat(descbuf, " 'all types' as type, ");
- strcat(descbuf, " obj_description(a.oid) as description ");
- strcat(descbuf, "FROM pg_aggregate a ");
- strcat(descbuf, "WHERE a.aggbasetype = 0 ");
- if (optarg2)
- {
- strcat(descbuf, "AND a.aggname ~ '^");
- strcat(descbuf, optarg2);
- strcat(descbuf, "' ");
- }
- strcat(descbuf, "ORDER BY aggname, type;");
- success = SendQuery(pset, descbuf, NULL, NULL);
- }
- else if (strncmp(cmd, "dd", 2) == 0)
- /* descriptions */
- objectDescription(pset, optarg + 1);
- else if (strncmp(cmd, "df", 2) == 0)
- {
- char descbuf[4096];
-
- /* functions/procedures */
-
- /*
- * we skip in/out funcs by excluding functions that take
- * some arguments, but have no types defined for those
- * arguments
- */
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT t.typname as result, ");
- strcat(descbuf, " p.proname as function, ");
- if (screen_size.ws_col <= 80)
- strcat(descbuf, " substr(oid8types(p.proargtypes),1,14) as arguments, ");
- else
- strcat(descbuf, " oid8types(p.proargtypes) as arguments, ");
- if (screen_size.ws_col <= 80)
- strcat(descbuf, " substr(obj_description(p.oid),1,34) as description ");
- else
- strcat(descbuf, " obj_description(p.oid) as description ");
- strcat(descbuf, "FROM pg_proc p, pg_type t ");
- strcat(descbuf, "WHERE p.prorettype = t.oid and ");
- strcat(descbuf, "(pronargs = 0 or oid8types(p.proargtypes) != '') ");
- if (optarg2)
- {
- strcat(descbuf, "AND p.proname ~ '^");
- strcat(descbuf, optarg2);
- strcat(descbuf, "' ");
- }
- strcat(descbuf, "ORDER BY result, function, arguments;");
- success = SendQuery(pset, descbuf, NULL, NULL);
- }
- else if (strncmp(cmd, "di", 2) == 0)
- /* only indices */
- tableList(pset, false, 'i', false);
- else if (strncmp(cmd, "do", 2) == 0)
- {
- char descbuf[4096];
-
- /* operators */
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT o.oprname AS op, ");
- strcat(descbuf, " t1.typname AS left_arg, ");
- strcat(descbuf, " t2.typname AS right_arg, ");
- strcat(descbuf, " t0.typname AS result, ");
- if (screen_size.ws_col <= 80)
- strcat(descbuf, " substr(obj_description(p.oid),1,41) as description ");
- else
- strcat(descbuf, " obj_description(p.oid) as description ");
- strcat(descbuf, "FROM pg_proc p, pg_type t0, ");
- strcat(descbuf, " pg_type t1, pg_type t2, ");
- strcat(descbuf, " pg_operator o ");
- strcat(descbuf, "WHERE p.prorettype = t0.oid AND ");
- strcat(descbuf, " RegprocToOid(o.oprcode) = p.oid AND ");
- strcat(descbuf, " p.pronargs = 2 AND ");
- strcat(descbuf, " o.oprleft = t1.oid AND ");
- strcat(descbuf, " o.oprright = t2.oid ");
- if (optarg2)
- {
- strcat(descbuf, "AND o.oprname ~ '^");
- strcat(descbuf, optarg2);
- strcat(descbuf, "' ");
- }
- strcat(descbuf, "UNION ");
- strcat(descbuf, "SELECT o.oprname as op, ");
- strcat(descbuf, " ''::name AS left_arg, ");
- strcat(descbuf, " t1.typname AS right_arg, ");
- strcat(descbuf, " t0.typname AS result, ");
- if (screen_size.ws_col <= 80)
- strcat(descbuf, " substr(obj_description(p.oid),1,41) as description ");
- else
- strcat(descbuf, " obj_description(p.oid) as description ");
- strcat(descbuf, "FROM pg_operator o, pg_proc p, pg_type t0, pg_type t1 ");
- strcat(descbuf, "WHERE RegprocToOid(o.oprcode) = p.oid AND ");
- strcat(descbuf, " o.oprresult = t0.oid AND ");
- strcat(descbuf, " o.oprkind = 'l' AND ");
- strcat(descbuf, " o.oprright = t1.oid ");
- if (optarg2)
- {
- strcat(descbuf, "AND o.oprname ~ '^");
- strcat(descbuf, optarg2);
- strcat(descbuf, "' ");
- }
- strcat(descbuf, "UNION ");
- strcat(descbuf, "SELECT o.oprname as op, ");
- strcat(descbuf, " t1.typname AS left_arg, ");
- strcat(descbuf, " ''::name AS right_arg, ");
- strcat(descbuf, " t0.typname AS result, ");
- if (screen_size.ws_col <= 80)
- strcat(descbuf, " substr(obj_description(p.oid),1,41) as description ");
- else
- strcat(descbuf, " obj_description(p.oid) as description ");
- strcat(descbuf, "FROM pg_operator o, pg_proc p, pg_type t0, pg_type t1 ");
- strcat(descbuf, "WHERE RegprocToOid(o.oprcode) = p.oid AND ");
- strcat(descbuf, " o.oprresult = t0.oid AND ");
- strcat(descbuf, " o.oprkind = 'r' AND ");
- strcat(descbuf, " o.oprleft = t1.oid ");
- if (optarg2)
- {
- strcat(descbuf, "AND o.oprname ~ '^");
- strcat(descbuf, optarg2);
- strcat(descbuf, "' ");
- }
- strcat(descbuf, "ORDER BY op, left_arg, right_arg, result;");
- success = SendQuery(pset, descbuf, NULL, NULL);
- }
- else if (strncmp(cmd, "ds", 2) == 0)
- /* only sequences */
- tableList(pset, false, 'S', false);
- else if (strncmp(cmd, "dS", 2) == 0)
- /* system tables */
- tableList(pset, false, 'b', true);
- else if (strncmp(cmd, "dt", 2) == 0)
- /* only tables */
- tableList(pset, false, 't', false);
- else if (strncmp(cmd, "dT", 2) == 0)
- {
- char descbuf[4096];
-
- /* types */
- descbuf[0] = '\0';
- strcat(descbuf, "SELECT typname AS type, ");
- strcat(descbuf, " obj_description(oid) as description ");
- strcat(descbuf, "FROM pg_type ");
- strcat(descbuf, "WHERE typrelid = 0 AND ");
- strcat(descbuf, " typname !~ '^_.*' ");
- strcat(descbuf, "ORDER BY type;");
- if (optarg2)
- {
- strcat(descbuf, "AND typname ~ '^");
- strcat(descbuf, optarg2);
- strcat(descbuf, "' ");
- }
- success = SendQuery(pset, descbuf, NULL, NULL);
- }
- else if (!optarg)
- /* show tables, sequences and indices */
- tableList(pset, false, 'b', false);
- else if (strcmp(optarg, "*") == 0)
- { /* show everything */
- if (tableList(pset, false, 'b', false) == 0)
- tableList(pset, true, 'b', false);
- }
- else if (strncmp(cmd, "d ", 2) == 0)
- /* describe the specified table */
- tableDesc(pset, optarg, NULL);
- else
- slashUsage(pset);
- break;
-
- case 'e': /* edit */
- if (query_buf)
- do_edit(optarg, query_buf, &status);
- break;
-
- case 'E':
- {
- FILE *fd;
- static char *lastfile;
- struct stat st,
- st2;
-
- if (optarg)
- {
- if (lastfile)
- free(lastfile);
- lastfile = malloc(strlen(optarg + 1));
- if (!lastfile)
- {
- perror("malloc");
- exit(CMD_TERMINATE);
- }
- strcpy(lastfile, optarg);
- }
- else if (!lastfile)
- {
- fprintf(stderr, "\\r must be followed by a file name initially\n");
- break;
- }
- stat(lastfile, &st);
- editFile(lastfile);
-#ifndef __CYGWIN32__
- if ((stat(lastfile, &st2) == -1) || ((fd = fopen(lastfile, "r")) == NULL))
-#else
- if ((stat(lastfile, &st2) == -1) || ((fd = fopen(lastfile, "rb")) == NULL))
-#endif
- {
- perror(lastfile);
- break;
- }
- if (st2.st_mtime == st.st_mtime)
- {
- if (!pset->quiet)
- fprintf(stderr, "warning: %s not modified. query not executed\n", lastfile);
- fclose(fd);
- break;
- }
- MainLoop(pset, fd);
- fclose(fd);
- break;
- }
-
- case 'f':
- {
- char *fs = DEFAULT_FIELD_SEP;
-
- if (optarg)
- fs = optarg;
- /* handle \f \{space} */
- if (optarg && !*optarg && strlen(cmd) > 1)
- {
- int i;
-
- /* line and cmd match until the first blank space */
- for (i = 2; isspace(line[i]); i++)
- ;
- fs = cmd + i - 1;
- }
- if (pset->opt.fieldSep)
- free(pset->opt.fieldSep);
- if (!(pset->opt.fieldSep = strdup(fs)))
- {
- perror("malloc");
- exit(CMD_TERMINATE);
- }
- if (!pset->quiet)
- printf("field separator changed to '%s'\n", pset->opt.fieldSep);
- break;
- }
- case 'g': /* \g means send query */
- if (!optarg)
- pset->gfname = NULL;
- else if (!(pset->gfname = strdup(optarg)))
- {
- perror("malloc");
- exit(CMD_TERMINATE);
- }
- status = CMD_SEND;
- break;
-
- case 'h': /* help */
- {
- do_help(pset, optarg);
- break;
- }
-
- case 'i': /* \i is include file */
- {
- FILE *fd;
-
- if (!optarg)
- {
- fprintf(stderr, "\\i must be followed by a file name\n");
- break;
- }
-#ifndef __CYGWIN32__
- if ((fd = fopen(optarg, "r")) == NULL)
-#else
- if ((fd = fopen(optarg, "rb")) == NULL)
-#endif
- {
- fprintf(stderr, "file named %s could not be opened\n", optarg);
- break;
- }
- MainLoop(pset, fd);
- fclose(fd);
- break;
- }
-
- case 'H':
- if (toggle(pset, &pset->opt.html3, "HTML3.0 tabular output"))
- pset->opt.standard = 0;
- break;
-
- case 'l': /* \l is list database */
- listAllDbs(pset);
- break;
-
- case 'm': /* monitor like type-setting */
- if (toggle(pset, &pset->opt.standard, "standard SQL separaters and padding"))
- {
- pset->opt.html3 = pset->opt.expanded = 0;
- pset->opt.align = pset->opt.header = 1;
- if (pset->opt.fieldSep)
- free(pset->opt.fieldSep);
- pset->opt.fieldSep = strdup("|");
- if (!pset->quiet)
- printf("field separator changed to '%s'\n", pset->opt.fieldSep);
- }
- else
- {
- if (pset->opt.fieldSep)
- free(pset->opt.fieldSep);
- pset->opt.fieldSep = strdup(DEFAULT_FIELD_SEP);
- if (!pset->quiet)
- printf("field separator changed to '%s'\n", pset->opt.fieldSep);
- }
- break;
-
- case 'o':
- setFout(pset, optarg);
- break;
-
- case 'p':
- if (query_buf && query_buf->len > 0)
- {
- fputs(query_buf->data, stdout);
- fputc('\n', stdout);
- }
- break;
-
- case 'q': /* \q is quit */
- status = CMD_TERMINATE;
- break;
-
- case 'r': /* reset(clear) the buffer */
- if (query_buf)
- {
- resetPQExpBuffer(query_buf);
- if (!pset->quiet)
- printf("buffer reset(cleared)\n");
- }
- break;
-
- case 's': /* \s is save history to a file */
- if (!optarg)
- optarg = "/dev/tty";
-#ifdef USE_HISTORY
- if (write_history(optarg) != 0)
- fprintf(stderr, "cannot write history to %s\n", optarg);
-#endif
- break;
-
- case 't': /* toggle headers */
- toggle(pset, &pset->opt.header, "output headings and row count");
- break;
-
- case 'T': /* define html <table ...> option */
- if (pset->opt.tableOpt)
- free(pset->opt.tableOpt);
- if (!optarg)
- pset->opt.tableOpt = NULL;
- else if (!(pset->opt.tableOpt = strdup(optarg)))
- {
- perror("malloc");
- exit(CMD_TERMINATE);
- }
- break;
-
- case 'w':
- {
- FILE *fd;
-
- if (!optarg)
- {
- fprintf(stderr, "\\w must be followed by a file name\n");
- break;
- }
-#ifndef __CYGWIN32__
- if ((fd = fopen(optarg, "w")) == NULL)
-#else
- if ((fd = fopen(optarg, "w")) == NULL)
-#endif
- {
- fprintf(stderr, "file named %s could not be opened\n", optarg);
- break;
- }
- if (query_buf)
- fputs(query_buf->data, fd);
- fputc('\n', fd);
- fclose(fd);
- break;
- }
-
- case 'x':
- toggle(pset, &pset->opt.expanded, "expanded table representation");
- break;
-
- case 'z': /* list table rights (grant/revoke) */
- rightsList(pset);
- break;
-
- case '!':
- do_shell(optarg);
- break;
- default:
-
- case '?': /* \? is help */
- slashUsage(pset);
- break;
- }
- free(cmd);
- return status;
-}
-
-/* MainLoop()
- * Main processing loop for reading lines of input
- * and sending them to the backend.
- *
- * This loop is re-entrant. May be called by \i command
- * which reads input from a file.
- * db_ptr must be initialized and set.
- */
-
-static int
-MainLoop(PsqlSettings *pset, FILE *source)
-{
- PQExpBuffer query_buf; /* buffer for query being accumulated */
- char *line; /* current line of input */
- char *xcomment; /* start of extended comment */
- int len; /* length of the line */
- int successResult = 1;
- int slashCmdStatus = CMD_SEND;
-
- /*--------------------------------------------------------------
- * slashCmdStatus can be:
- * CMD_UNKNOWN - send currently constructed query to backend
- * (i.e. we got a \g)
- * CMD_SEND - send currently constructed query to backend
- * (i.e. we got a \g)
- * CMD_SKIP_LINE - skip processing of this line, continue building
- * up query
- * CMD_TERMINATE - terminate processing of this query entirely
- * CMD_NEWEDIT - new query supplied by edit
- *---------------------------------------------------------------
- */
-
- bool querySent = false;
- READ_ROUTINE GetNextLine;
- bool eof = false; /* end of our command input? */
- bool success;
- char in_quote; /* == 0 for no in_quote */
- bool was_bslash; /* backslash */
- int paren_level;
- char *query_start;
-
- /* Stack the prior command source */
- FILE *prev_cmd_source = cur_cmd_source;
- bool prev_cmd_interactive = cur_cmd_interactive;
-
- /* Establish new source */
- cur_cmd_source = source;
- cur_cmd_interactive = ((source == stdin) && !pset->notty);
-
- if (cur_cmd_interactive)
- {
- if (pset->prompt)
- free(pset->prompt);
- pset->prompt = malloc(strlen(PQdb(pset->db)) + strlen(PROMPT) + 1);
- if (pset->quiet)
- pset->prompt[0] = '\0';
- else
- sprintf(pset->prompt, "%s%s", PQdb(pset->db), PROMPT);
- if (pset->useReadline)
- {
-#ifdef USE_HISTORY
- using_history();
-#endif
- GetNextLine = gets_readline;
- }
- else
- GetNextLine = gets_noreadline;
- }
- else
- GetNextLine = gets_fromFile;
-
- query_buf = createPQExpBuffer();
- xcomment = NULL;
- in_quote = false;
- paren_level = 0;
- slashCmdStatus = CMD_UNKNOWN; /* set default */
-
- /* main loop to get queries and execute them */
- while (!eof)
- {
- if (slashCmdStatus == CMD_NEWEDIT)
- {
- /*
- * just returned from editing the line? then just copy to the
- * input buffer
- */
- line = strdup(query_buf->data);
- resetPQExpBuffer(query_buf);
- /* reset parsing state since we are rescanning whole query */
- xcomment = NULL;
- in_quote = false;
- paren_level = 0;
- }
- else
- {
- /*
- * otherwise, set interactive prompt if necessary
- * and get another line
- */
- if (cur_cmd_interactive && !pset->quiet)
- {
- if (in_quote && in_quote == PROMPT_SINGLEQUOTE)
- pset->prompt[strlen(pset->prompt) - 3] = PROMPT_SINGLEQUOTE;
- else if (in_quote && in_quote == PROMPT_DOUBLEQUOTE)
- pset->prompt[strlen(pset->prompt) - 3] = PROMPT_DOUBLEQUOTE;
- else if (xcomment != NULL)
- pset->prompt[strlen(pset->prompt) - 3] = PROMPT_COMMENT;
- else if (query_buf->len > 0 && !querySent)
- pset->prompt[strlen(pset->prompt) - 3] = PROMPT_CONTINUE;
- else
- pset->prompt[strlen(pset->prompt) - 3] = PROMPT_READY;
- }
- line = GetNextLine(pset->prompt, source);
-#ifdef USE_HISTORY
- if (cur_cmd_interactive && pset->useReadline && line != NULL)
- add_history(line); /* save non-empty lines in history */
-#endif
- }
-
- /*
- * query_buf holds query already accumulated. line is the malloc'd
- * new line of input (note it must be freed before looping around!)
- * query_start is the next command start location within the line.
- */
- if (line == NULL || (!cur_cmd_interactive && *line == '\0'))
- { /* No more input. Time to quit, or \i
- * done */
- if (!pset->quiet)
- printf("EOF\n");/* Goes on prompt line */
- eof = true;
- continue;
- }
-
- /* not currently inside an extended comment? */
- if (xcomment == NULL)
- {
- query_start = line;
- }
- else
- {
- /* otherwise, continue the extended comment... */
- query_start = line;
- xcomment = line;
- }
-
- /* remove whitespaces on the right, incl. \n's */
- line = rightTrim(line);
-
- /* echo back if input is from file */
- if (!cur_cmd_interactive && !pset->singleStep && !pset->quiet)
- fprintf(stderr, "%s\n", line);
-
- slashCmdStatus = CMD_UNKNOWN;
- /* nothing on line after trimming? then ignore */
- if (line[0] == '\0')
- {
- free(line);
- continue;
- }
-
- len = strlen(line);
-
- if (pset->singleLineMode)
- {
- success = SendQuery(pset, line, NULL, NULL);
- successResult &= success;
- querySent = true;
- }
- else
- {
- int i;
-
- /*
- * Parse line, looking for command separators.
- *
- * The current character is at line[i], the prior character at
- * line[i - prevlen], the next character at line[i + thislen].
- */
-#ifdef MULTIBYTE
- int prevlen = 0;
- int thislen = (len > 0) ? PQmblen(line) : 0;
-
-#define ADVANCE_I (prevlen = thislen, i += thislen, thislen = PQmblen(line+i))
-#else
-#define prevlen 1
-#define thislen 1
-#define ADVANCE_I (i++)
-#endif
-
- was_bslash = false;
- for (i = 0; i < len; ADVANCE_I)
- {
- if (line[i] == '\\' && !in_quote)
- {
- /* backslash command. Copy whatever is before \ to
- * query_buf.
- */
- char hold_char = line[i];
-
- line[i] = '\0';
- if (query_start[0] != '\0')
- {
- if (query_buf->len > 0)
- appendPQExpBufferChar(query_buf, '\n');
- appendPQExpBufferStr(query_buf, query_start);
- }
- line[i] = hold_char;
- query_start = line + i;
- break; /* go handle backslash command */
- }
-
- if (querySent &&
- isascii((unsigned char) (line[i])) &&
- !isspace(line[i]))
- {
- resetPQExpBuffer(query_buf);
- querySent = false;
- }
-
- if (was_bslash)
- was_bslash = false;
- else if (i > 0 && line[i - prevlen] == '\\')
- was_bslash = true;
-
- /* inside a quote? */
- if (in_quote && (line[i] != in_quote || was_bslash))
- /* do nothing */ ;
- /* inside an extended comment? */
- else if (xcomment != NULL)
- {
- if (line[i] == '*' && line[i + thislen] == '/')
- {
- xcomment = NULL;
- ADVANCE_I;
- }
- }
- /* start of extended comment? */
- else if (line[i] == '/' && line[i + thislen] == '*')
- {
- xcomment = line + i;
- ADVANCE_I;
- }
- /* single-line comment? truncate line */
- else if ((line[i] == '-' && line[i + thislen] == '-') ||
- (line[i] == '/' && line[i + thislen] == '/'))
- {
- /* print comment at top of query */
- if (pset->singleStep)
- fprintf(stdout, "%s\n", line + i);
- line[i] = '\0'; /* remove comment */
- break;
- }
- else if (in_quote && line[i] == in_quote)
- in_quote = false;
- else if (!in_quote && (line[i] == '\'' || line[i] == '"'))
- in_quote = line[i];
- /* semi-colon? then send query now */
- else if (!paren_level && line[i] == ';')
- {
- char hold_char = line[i + thislen];
-
- line[i + thislen] = '\0';
- if (query_start[0] != '\0')
- {
- if (query_buf->len > 0)
- appendPQExpBufferChar(query_buf, '\n');
- appendPQExpBufferStr(query_buf, query_start);
- }
- success = SendQuery(pset, query_buf->data, NULL, NULL);
- successResult &= success;
- line[i + thislen] = hold_char;
- query_start = line + i + thislen;
- /* sometimes, people do ';\g', don't execute twice */
- if (*query_start == '\\' &&
- *(query_start + 1) == 'g')
- query_start += 2;
- querySent = true;
- }
- else if (line[i] == '(')
- {
- paren_level++;
-
- }
- else if (paren_level && line[i] == ')')
- paren_level--;
- }
- }
-
- /* nothing on line after trimming? then ignore */
- if (line[0] == '\0')
- {
- free(line);
- continue;
- }
-
- if (!in_quote && query_start[0] == '\\')
- {
- /* loop to handle \p\g and other backslash combinations */
- while (query_start[0] != '\0')
- {
- char hold_char;
-
-#ifndef WIN32
- /* I believe \w \dos\system\x would cause a problem */
- /* do we have '\p\g' or '\p \g' ? */
- if (strlen(query_start) > 2 &&
- query_start[2 + strspn(query_start + 2, " \t")] == '\\')
- {
- hold_char = query_start[2 + strspn(query_start + 2, " \t")];
- query_start[2 + strspn(query_start + 2, " \t")] = '\0';
- }
- else
-/* spread over #endif */
-#endif
- hold_char = '\0';
-
- slashCmdStatus = HandleSlashCmds(pset,
- query_start,
- query_buf);
-
- if (slashCmdStatus == CMD_SKIP_LINE && !hold_char)
- {
- if (query_buf->len == 0)
- paren_level = 0;
- break;
- }
- if (slashCmdStatus == CMD_TERMINATE)
- break;
-
- query_start += strlen(query_start);
- if (hold_char)
- query_start[0] = hold_char;
- }
- free(line);
- if (slashCmdStatus == CMD_TERMINATE)
- break; /* They did \q, leave the loop */
- }
- else
- {
- if (query_start[0] != '\0')
- {
- querySent = false;
- if (query_buf->len > 0)
- appendPQExpBufferChar(query_buf, '\n');
- appendPQExpBufferStr(query_buf, query_start);
- }
- free(line);
- }
-
- /* had a backslash-g? force the query to be sent */
- if (slashCmdStatus == CMD_SEND)
- {
- success = SendQuery(pset, query_buf->data, NULL, NULL);
- successResult &= success;
- xcomment = NULL;
- in_quote = false;
- paren_level = 0;
- querySent = true;
- }
- } /* while */
-
- destroyPQExpBuffer(query_buf);
-
- cur_cmd_source = prev_cmd_source;
- cur_cmd_interactive = prev_cmd_interactive;
-
- return successResult;
-} /* MainLoop() */
-
-int
-main(int argc, char **argv)
-{
- extern char *optarg;
- extern int optind;
-
- char *dbname = NULL;
- char *host = NULL;
- char *port = NULL;
- char *qfilename = NULL;
-
- PsqlSettings settings;
-
- char *singleQuery = NULL;
-
- bool listDatabases = 0;
- int successResult = 1;
- bool singleSlashCmd = 0;
- int c;
-
- char *home = NULL; /* Used to store $HOME */
- char *version = NULL; /* PostgreSQL version */
-
- /*
- * initialize cur_cmd_source in case we do not use MainLoop ... some
- * systems fail if we try to use a static initializer for this :-(
- */
- cur_cmd_source = stdin;
- cur_cmd_interactive = false;
-
- MemSet(&settings, 0, sizeof settings);
- settings.opt.align = 1;
- settings.opt.header = 1;
- settings.queryFout = stdout;
- settings.opt.fieldSep = strdup(DEFAULT_FIELD_SEP);
- settings.opt.pager = 1;
- if (!isatty(0) || !isatty(1))
- {
- /* Noninteractive defaults */
- settings.notty = 1;
- }
- else
- {
- /* Interactive defaults */
- pqsignal(SIGINT, handle_sigint); /* control-C => cancel */
-#ifdef USE_READLINE
- settings.useReadline = 1;
- {
- /* Set the application name, used for parsing .inputrc */
- char *progname = strrchr(argv[0], SEP_CHAR);
- rl_readline_name = (progname ? progname+1 : argv[0]);
- }
-#endif
- }
-#ifdef PSQL_ALWAYS_GET_PASSWORDS
- settings.getPassword = 1;
-#else
- settings.getPassword = 0;
-#endif
-
-#ifdef MULTIBYTE
- has_client_encoding = getenv("PGCLIENTENCODING");
-#endif
-
- while ((c = getopt(argc, argv, "Aa:c:d:eEf:F:lh:Hnso:p:qStT:ux")) != EOF)
- {
- switch (c)
- {
- case 'A':
- settings.opt.align = 0;
- break;
- case 'a':
-#ifdef NOT_USED /* this no longer does anything */
- fe_setauthsvc(optarg, errbuf);
-#endif
- break;
- case 'c':
- singleQuery = strdup(optarg);
- if (singleQuery[0] == '\\')
- singleSlashCmd = 1;
- break;
- case 'd':
- dbname = optarg;
- break;
- case 'e':
- settings.echoQuery = 1;
- break;
- case 'E':
- settings.echoAllQueries = 1;
- settings.echoQuery = 1;
- break;
- case 'f':
- qfilename = optarg;
- break;
- case 'F':
- settings.opt.fieldSep = strdup(optarg);
- break;
- case 'l':
- listDatabases = 1;
- break;
- case 'h':
- host = optarg;
- break;
- case 'H':
- settings.opt.html3 = 1;
- break;
- case 'n':
- settings.useReadline = 0;
- break;
- case 'o':
- setFout(&settings, optarg);
- break;
- case 'p':
- port = optarg;
- break;
- case 'q':
- settings.quiet = 1;
- break;
- case 's':
- settings.singleStep = 1;
- break;
- case 'S':
- settings.singleLineMode = 1;
- break;
- case 't':
- settings.opt.header = 0;
- break;
- case 'T':
- settings.opt.tableOpt = strdup(optarg);
- break;
- case 'u':
- settings.getPassword = 1;
- break;
- case 'x':
- settings.opt.expanded = 1;
- break;
- default:
- usage(argv[0]);
- break;
- }
- }
- /* if we still have an argument, use it as the database name */
- if (argc - optind == 1)
- dbname = argv[optind];
-
- if (listDatabases)
- dbname = "template1";
-
- if (settings.getPassword)
- {
- char username[100];
- char password[100];
-
- prompt_for_password(username, password);
-
- settings.db = PQsetdbLogin(host, port, NULL, NULL, dbname,
- username, password);
- }
- else
- settings.db = PQsetdb(host, port, NULL, NULL, dbname);
-
- dbname = PQdb(settings.db);
-
- if (PQstatus(settings.db) == CONNECTION_BAD)
- {
- fprintf(stderr, "Connection to database '%s' failed.\n", dbname);
- fprintf(stderr, "%s\n", PQerrorMessage(settings.db));
- PQfinish(settings.db);
- exit(1);
- }
-
- cancelConn = settings.db; /* enable SIGINT to send cancel */
-
- if (listDatabases)
- exit(listAllDbs(&settings));
- if (!settings.quiet && !settings.notty && !singleQuery && !qfilename)
- {
- printf("Welcome to the POSTGRESQL interactive sql monitor:\n");
- printf(" Please read the file COPYRIGHT for copyright terms "
- "of POSTGRESQL\n");
-
- if ((version = selectVersion(&settings)) != NULL)
- printf("[%s]\n", version);
-
- printf("\n");
- printf(" type \\? for help on slash commands\n");
- printf(" type \\q to quit\n");
- printf(" type \\g or terminate with semicolon to execute query\n");
- printf(" You are currently connected to the database: %s\n\n", dbname);
- }
-
- /*
- * 20.06.97 ACRM See if we've got a /etc/psqlrc or .psqlrc file
- */
- if (!access("/etc/psqlrc", R_OK))
- HandleSlashCmds(&settings, "\\i /etc/psqlrc", NULL);
- if ((home = getenv("HOME")) != NULL)
- {
- char *psqlrc = NULL,
- *line = NULL;
-
- if ((psqlrc = (char *) malloc(strlen(home) + 10)) != NULL)
- {
- sprintf(psqlrc, "%s/.psqlrc", home);
- if (!access(psqlrc, R_OK))
- {
- if ((line = (char *) malloc(strlen(psqlrc) + 5)) != NULL)
- {
- sprintf(line, "\\i %s", psqlrc);
- HandleSlashCmds(&settings, line, NULL);
- free(line);
- }
- }
- free(psqlrc);
- }
- }
- /* End of check for psqlrc files */
-
- if (qfilename || singleSlashCmd)
- {
-
- /*
- * read in a file full of queries instead of reading in queries
- * interactively
- */
- char *line;
-
- if (singleSlashCmd)
- {
- /* Not really a query, but "Do what I mean, not what I say." */
- line = singleQuery;
- }
- else
- {
- line = malloc(strlen(qfilename) + 5);
- sprintf(line, "\\i %s", qfilename);
- }
- HandleSlashCmds(&settings, line, NULL);
- free(line);
- }
- else
- {
- if (singleQuery)
- successResult = SendQuery(&settings, singleQuery, NULL, NULL);
- else
- successResult = MainLoop(&settings, stdin);
- }
-
- PQfinish(settings.db);
- free(settings.opt.fieldSep);
- if (settings.prompt)
- free(settings.prompt);
-
- return !successResult;
-}
-
-static bool
-handleCopyOut(PGconn *conn, FILE *copystream)
-{
- bool copydone;
- char copybuf[COPYBUFSIZ];
- int ret;
-
- copydone = false; /* Can't be done; haven't started. */
-
- while (!copydone)
- {
- ret = PQgetline(conn, copybuf, COPYBUFSIZ);
-
- if (copybuf[0] == '\\' &&
- copybuf[1] == '.' &&
- copybuf[2] == '\0')
- {
- copydone = true; /* don't print this... */
- }
- else
- {
- fputs(copybuf, copystream);
- switch (ret)
- {
- case EOF:
- copydone = true;
- /* FALLTHROUGH */
- case 0:
- fputc('\n', copystream);
- break;
- case 1:
- break;
- }
- }
- }
- fflush(copystream);
- return !PQendcopy(conn);
-}
-
-
-
-static bool
-handleCopyIn(PGconn *conn, const bool mustprompt, FILE *copystream)
-{
- bool copydone = false;
- bool firstload;
- bool linedone;
- char copybuf[COPYBUFSIZ];
- char *s;
- int buflen;
- int c = 0;
-
- if (mustprompt)
- {
- fputs("Enter info followed by a newline\n", stdout);
- fputs("End with a backslash and a "
- "period on a line by itself.\n", stdout);
- }
- while (!copydone)
- { /* for each input line ... */
- if (mustprompt)
- {
- fputs(">> ", stdout);
- fflush(stdout);
- }
- firstload = true;
- linedone = false;
- while (!linedone)
- { /* for each buffer ... */
- s = copybuf;
- for (buflen = COPYBUFSIZ; buflen > 1; buflen--)
- {
- c = getc(copystream);
- if (c == '\n' || c == EOF)
- {
- linedone = true;
- break;
- }
- *s++ = c;
- }
- *s = '\0';
- if (c == EOF)
- {
- PQputline(conn, "\\.");
- copydone = true;
- break;
- }
- PQputline(conn, copybuf);
- if (firstload)
- {
- if (!strcmp(copybuf, "\\."))
- copydone = true;
- firstload = false;
- }
- }
- PQputline(conn, "\n");
- }
- return !PQendcopy(conn);
-}
-
-
-
-/*
- * try to open fname and return a FILE *, if it fails, use stdout, instead
- */
-
-static FILE *
-setFout(PsqlSettings *pset, char *fname)
-{
- if (pset->queryFout && pset->queryFout != stdout)
- {
- if (pset->pipe)
- pclose(pset->queryFout);
- else
- fclose(pset->queryFout);
- }
- if (!fname)
- {
- pset->queryFout = stdout;
- pqsignal(SIGPIPE, SIG_DFL);
- }
- else
- {
- if (*fname == '|')
- {
- pqsignal(SIGPIPE, SIG_IGN);
-#ifndef __CYGWIN32__
- pset->queryFout = popen(fname + 1, "w");
-#else
- pset->queryFout = popen(fname + 1, "wb");
-#endif
- pset->pipe = 1;
- }
- else
- {
- pset->queryFout = fopen(fname, "w");
- pqsignal(SIGPIPE, SIG_DFL);
- pset->pipe = 0;
- }
- if (!pset->queryFout)
- {
- perror(fname);
- pset->queryFout = stdout;
- }
- }
- return pset->queryFout;
-}
-
-static void
-prompt_for_password(char *username, char *password)
-{
- char buf[512];
- int length;
-
-#ifdef HAVE_TERMIOS_H
- struct termios t_orig,
- t;
-
-#endif
-
- printf("Username: ");
- fgets(username, 100, stdin);
- length = strlen(username);
- /* skip rest of the line */
- if (length > 0 && username[length - 1] != '\n')
- {
- do
- {
- fgets(buf, 512, stdin);
- } while (buf[strlen(buf) - 1] != '\n');
- }
- if (length > 0 && username[length - 1] == '\n')
- username[length - 1] = '\0';
-
- printf("Password: ");
-#ifdef HAVE_TERMIOS_H
- tcgetattr(0, &t);
- t_orig = t;
- t.c_lflag &= ~ECHO;
- tcsetattr(0, TCSADRAIN, &t);
-#endif
- fgets(password, 100, stdin);
-#ifdef HAVE_TERMIOS_H
- tcsetattr(0, TCSADRAIN, &t_orig);
-#endif
-
- length = strlen(password);
- /* skip rest of the line */
- if (length > 0 && password[length - 1] != '\n')
- {
- do
- {
- fgets(buf, 512, stdin);
- } while (buf[strlen(buf) - 1] != '\n');
- }
- if (length > 0 && password[length - 1] == '\n')
- password[length - 1] = '\0';
-
- printf("\n\n");
-}
-
-static char *
-selectVersion(PsqlSettings *pset)
-{
-#define PGVERSIONBUFSZ 128
- static char version[PGVERSIONBUFSZ + 1];
- PGresult *res;
- char *query = "select version();";
-
- if (!(res = PQexec(pset->db, query)))
- return (NULL);
-
- if (PQresultStatus(res) == PGRES_COMMAND_OK ||
- PQresultStatus(res) == PGRES_TUPLES_OK)
- {
- strncpy(version, PQgetvalue(res, 0, 0), PGVERSIONBUFSZ);
- version[PGVERSIONBUFSZ] = '\0';
- PQclear(res);
- return (version);
- }
- else
- {
- PQclear(res);
- return (NULL);
- }
-}
diff --git a/src/bin/psql/psqlHelp.h b/src/bin/psql/psqlHelp.h
index 0d4bc1c687..81bee606f5 100644
--- a/src/bin/psql/psqlHelp.h
+++ b/src/bin/psql/psqlHelp.h
@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: psqlHelp.h,v 1.80 1999/10/29 23:52:22 momjian Exp $
+ * $Id: psqlHelp.h,v 1.81 1999/11/04 23:14:29 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -384,5 +384,6 @@ TIMEZONE|XACTISOLEVEL|CLIENT_ENCODING|SERVER_ENCODING"},
\tVACUUM [VERBOSE] [ANALYZE] [table]\n\
\tor\n\
\tVACUUM [VERBOSE] ANALYZE [table [(column_name1, ...column_nameN)]];"},
- {NULL, NULL, NULL} /* important to keep a NULL terminator here!*/
+ {NULL, NULL, NULL} /* important to keep a NULL terminator
+ * here! */
};
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index 6ceefd8b44..5687e1801f 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -20,24 +20,27 @@
typedef struct _psqlSettings
{
- PGconn *db; /* connection to backend */
- FILE *queryFout; /* where to send the query results */
- bool queryFoutPipe; /* queryFout is from a popen() */
-
- printQueryOpt popt;
- VariableSpace vars; /* "shell variable" repository */
-
- char *gfname; /* one-shot file output argument for \g */
-
- bool notty; /* stdin or stdout is not a tty (as determined on startup) */
- bool useReadline; /* use libreadline routines */
- bool useHistory;
- bool getPassword; /* prompt the user for a username and
- password */
- FILE * cur_cmd_source; /* describe the status of the current main loop */
- bool cur_cmd_interactive;
-
- bool has_client_encoding; /* was PGCLIENTENCODING set on startup? */
+ PGconn *db; /* connection to backend */
+ FILE *queryFout; /* where to send the query results */
+ bool queryFoutPipe; /* queryFout is from a popen() */
+
+ printQueryOpt popt;
+ VariableSpace vars; /* "shell variable" repository */
+
+ char *gfname; /* one-shot file output argument for \g */
+
+ bool notty; /* stdin or stdout is not a tty (as
+ * determined on startup) */
+ bool useReadline; /* use libreadline routines */
+ bool useHistory;
+ bool getPassword; /* prompt the user for a username and
+ * password */
+ FILE *cur_cmd_source; /* describe the status of the current main
+ * loop */
+ bool cur_cmd_interactive;
+
+ bool has_client_encoding; /* was PGCLIENTENCODING set on
+ * startup? */
} PsqlSettings;
diff --git a/src/bin/psql/sql_help.h b/src/bin/psql/sql_help.h
index 60d5a40147..f37a63fcc7 100644
--- a/src/bin/psql/sql_help.h
+++ b/src/bin/psql/sql_help.h
@@ -7,251 +7,251 @@
struct _helpStruct
{
- char *cmd; /* the command name */
- char *help; /* the help associated with it */
- char *syntax; /* the syntax associated with it */
+ char *cmd; /* the command name */
+ char *help; /* the help associated with it */
+ char *syntax; /* the syntax associated with it */
};
static struct _helpStruct QL_HELP[] = {
- { "TRUNCATE",
- "Empty a table",
- "TRUNCATE [ TABLE ] name" },
+ {"TRUNCATE",
+ "Empty a table",
+ "TRUNCATE [ TABLE ] name"},
- { "ABORT",
- "Aborts the current transaction",
- "ABORT [ WORK | TRANSACTION ]" },
+ {"ABORT",
+ "Aborts the current transaction",
+ "ABORT [ WORK | TRANSACTION ]"},
- { "ALTER TABLE",
- "Modifies table properties",
- "ALTER TABLE table\n [ * ] ADD [ COLUMN ] ER\">coBLE> type\nALTER TABLE table\n [ * ] RENAME [ COLUMN ] ER\">coBLE> TO newcolumn\nALTER TABLE table\n RENAME TO newtable" },
+ {"ALTER TABLE",
+ "Modifies table properties",
+ "ALTER TABLE table\n [ * ] ADD [ COLUMN ] ER\">coBLE> type\nALTER TABLE table\n [ * ] RENAME [ COLUMN ] ER\">coBLE> TO newcolumn\nALTER TABLE table\n RENAME TO newtable"},
- { "ALTER USER",
- "Modifies user account information",
- "ALTER USER username [ WITH PASSWORD password ]\n [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ]\n [ IN GROUP groupname [, ...] ]\n [ VALID UNTIL 'abstime' ]" },
+ {"ALTER USER",
+ "Modifies user account information",
+ "ALTER USER username [ WITH PASSWORD password ]\n [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ]\n [ IN GROUP groupname [, ...] ]\n [ VALID UNTIL 'abstime' ]"},
- { "BEGIN",
- "Begins a transaction in chained mode",
- "BEGIN [ WORK | TRANSACTION ]" },
+ {"BEGIN",
+ "Begins a transaction in chained mode",
+ "BEGIN [ WORK | TRANSACTION ]"},
- { "CLOSE",
- "Close a cursor",
- "CLOSE cursor" },
+ {"CLOSE",
+ "Close a cursor",
+ "CLOSE cursor"},
- { "CLUSTER",
- "Gives storage clustering advice to the server",
- "CLUSTER indexname ON table" },
+ {"CLUSTER",
+ "Gives storage clustering advice to the server",
+ "CLUSTER indexname ON table"},
- { "COMMIT",
- "Commits the current transaction",
- "COMMIT [ WORK | TRANSACTION ]" },
+ {"COMMIT",
+ "Commits the current transaction",
+ "COMMIT [ WORK | TRANSACTION ]"},
- { "COPY",
- "Copies data between files and tables",
- "COPY [ BINARY ] table [ WITH OIDS ]\n FROM { 'filename' | stdin }\n [ [USING] DELIMITERS 'delimiter' ]\nCOPY [ BINARY ] table [ WITH OIDS ]\n TO { 'filename' | stdout }\n [ [USING] DELIMITERS 'delimiter' ]" },
+ {"COPY",
+ "Copies data between files and tables",
+ "COPY [ BINARY ] table [ WITH OIDS ]\n FROM { 'filename' | stdin }\n [ [USING] DELIMITERS 'delimiter' ]\nCOPY [ BINARY ] table [ WITH OIDS ]\n TO { 'filename' | stdout }\n [ [USING] DELIMITERS 'delimiter' ]"},
- { "CREATE AGGREGATE",
- "Defines a new aggregate function",
- "CREATE AGGREGATE name [ AS ] ( BASETYPE = data_type\n [ , SFUNC1 = sfunc1, STYPE1 = sfunc1_return_type ]\n [ , SFUNC2 = sfunc2, STYPE2 = sfunc2_return_type ]\n [ , FINALFUNC = ffunc ]\n [ , INITCOND1 = initial_condition1 ]\n [ , INITCOND2 = initial_condition2 ] )" },
+ {"CREATE AGGREGATE",
+ "Defines a new aggregate function",
+ "CREATE AGGREGATE name [ AS ] ( BASETYPE = data_type\n [ , SFUNC1 = sfunc1, STYPE1 = sfunc1_return_type ]\n [ , SFUNC2 = sfunc2, STYPE2 = sfunc2_return_type ]\n [ , FINALFUNC = ffunc ]\n [ , INITCOND1 = initial_condition1 ]\n [ , INITCOND2 = initial_condition2 ] )"},
- { "CREATE DATABASE",
- "Creates a new database",
- "CREATE DATABASE name [ WITH LOCATION = 'dbpath' ]" },
+ {"CREATE DATABASE",
+ "Creates a new database",
+ "CREATE DATABASE name [ WITH LOCATION = 'dbpath' ]"},
- { "CREATE FUNCTION",
- "Defines a new function",
- "CREATE FUNCTION name ( [ ftype [, ...] ] )\n RETURNS rtype\n [ WITH ( attribute [, ...] ) ]\n AS definition \n LANGUAGE 'langname'\n\n\nCREATE FUNCTION name ( [ ftype [, ...] ] )\n RETURNS rtype\n [ WITH ( attribute [, ...] ) ]\n AS obj_file , link_symbol \n LANGUAGE 'C'" },
+ {"CREATE FUNCTION",
+ "Defines a new function",
+ "CREATE FUNCTION name ( [ ftype [, ...] ] )\n RETURNS rtype\n [ WITH ( attribute [, ...] ) ]\n AS definition \n LANGUAGE 'langname'\n\n\nCREATE FUNCTION name ( [ ftype [, ...] ] )\n RETURNS rtype\n [ WITH ( attribute [, ...] ) ]\n AS obj_file , link_symbol \n LANGUAGE 'C'"},
- { "CREATE INDEX",
- "Constructs a secondary index",
- "CREATE [ UNIQUE ] INDEX index_name ON table\n [ USING acc_name ] ( column [ ops_name] [, ...] )\nCREATE [ UNIQUE ] INDEX index_name ON table\n [ USING acc_name ] ( func_name( r\">colle> [, ... ]) ops_name )" },
+ {"CREATE INDEX",
+ "Constructs a secondary index",
+ "CREATE [ UNIQUE ] INDEX index_name ON table\n [ USING acc_name ] ( column [ ops_name] [, ...] )\nCREATE [ UNIQUE ] INDEX index_name ON table\n [ USING acc_name ] ( func_name( r\">colle> [, ... ]) ops_name )"},
- { "CREATE LANGUAGE",
- "Defines a new language for functions",
- "CREATE [ TRUSTED ] PROCEDURAL LANGUAGE 'langname'\n HANDLER call_handler\n LANCOMPILER 'comment'" },
+ {"CREATE LANGUAGE",
+ "Defines a new language for functions",
+ "CREATE [ TRUSTED ] PROCEDURAL LANGUAGE 'langname'\n HANDLER call_handler\n LANCOMPILER 'comment'"},
- { "CREATE OPERATOR",
- "Defines a new user operator",
- "CREATE OPERATOR name ( PROCEDURE = func_name\n [, LEFTARG = type1 ] [, RIGHTARG = type2 ]\n [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ]\n [, RESTRICT = res_proc ] [, JOIN = join_proc ]\n [, HASHES ] [, SORT1 = left_sort_op ] [, SORT2 = right_sort_op ] )" },
+ {"CREATE OPERATOR",
+ "Defines a new user operator",
+ "CREATE OPERATOR name ( PROCEDURE = func_name\n [, LEFTARG = type1 ] [, RIGHTARG = type2 ]\n [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ]\n [, RESTRICT = res_proc ] [, JOIN = join_proc ]\n [, HASHES ] [, SORT1 = left_sort_op ] [, SORT2 = right_sort_op ] )"},
- { "CREATE RULE",
- "Defines a new rule",
- "CREATE RULE name AS ON event\n TO object [ WHERE condition ]\n DO [ INSTEAD ] [ action | NOTHING ]" },
+ {"CREATE RULE",
+ "Defines a new rule",
+ "CREATE RULE name AS ON event\n TO object [ WHERE condition ]\n DO [ INSTEAD ] [ action | NOTHING ]"},
- { "CREATE SEQUENCE",
- "Creates a new sequence number generator",
- "CREATE SEQUENCE seqname [ INCREMENT increment ]\n [ MINVALUE minvalue ] [ MAXVALUE maxvalue ]\n [ START start ] [ CACHE cache ] [ CYCLE ]" },
+ {"CREATE SEQUENCE",
+ "Creates a new sequence number generator",
+ "CREATE SEQUENCE seqname [ INCREMENT increment ]\n [ MINVALUE minvalue ] [ MAXVALUE maxvalue ]\n [ START start ] [ CACHE cache ] [ CYCLE ]"},
- { "CREATE TABLE",
- "Creates a new table",
- "CREATE [ TEMPORARY | TEMP ] TABLE table (\n column type\n [ NULL | NOT NULL ] [ UNIQUE ] [ DEFAULT value ]\n [column_constraint_clause | PRIMARY KEY } [ ... ] ]\n [, ... ]\n [, PRIMARY KEY ( column [, ...] ) ]\n [, CHECK ( condition ) ]\n [, table_constraint_clause ]\n ) [ INHERITS ( inherited_table [, ...] ) ]" },
+ {"CREATE TABLE",
+ "Creates a new table",
+ "CREATE [ TEMPORARY | TEMP ] TABLE table (\n column type\n [ NULL | NOT NULL ] [ UNIQUE ] [ DEFAULT value ]\n [column_constraint_clause | PRIMARY KEY } [ ... ] ]\n [, ... ]\n [, PRIMARY KEY ( column [, ...] ) ]\n [, CHECK ( condition ) ]\n [, table_constraint_clause ]\n ) [ INHERITS ( inherited_table [, ...] ) ]"},
- { "CREATE TABLE AS",
- "Creates a new table",
- "CREATE TABLE table [ (column [, ...] ) ]\n AS select_clause" },
+ {"CREATE TABLE AS",
+ "Creates a new table",
+ "CREATE TABLE table [ (column [, ...] ) ]\n AS select_clause"},
- { "CREATE TRIGGER",
- "Creates a new trigger",
- "CREATE TRIGGER name { BEFORE | AFTER } { event [OR ...] }\n ON table FOR EACH { ROW | STATEMENT }\n EXECUTE PROCEDURE ER\">funcBLE> ( arguments )" },
+ {"CREATE TRIGGER",
+ "Creates a new trigger",
+ "CREATE TRIGGER name { BEFORE | AFTER } { event [OR ...] }\n ON table FOR EACH { ROW | STATEMENT }\n EXECUTE PROCEDURE ER\">funcBLE> ( arguments )"},
- { "CREATE TYPE",
- "Defines a new base data type",
- "CREATE TYPE typename ( INPUT = input_function, OUTPUT = output_function\n , INTERNALLENGTH = { internallength | VARIABLE } [ , EXTERNALLENGTH = { externallength | VARIABLE } ]\n [ , DEFAULT = \"default\" ]\n [ , ELEMENT = element ] [ , DELIMITER = delimiter ]\n [ , SEND = send_function ] [ , RECEIVE = receive_function ]\n [ , PASSEDBYVALUE ] )" },
+ {"CREATE TYPE",
+ "Defines a new base data type",
+ "CREATE TYPE typename ( INPUT = input_function, OUTPUT = output_function\n , INTERNALLENGTH = { internallength | VARIABLE } [ , EXTERNALLENGTH = { externallength | VARIABLE } ]\n [ , DEFAULT = \"default\" ]\n [ , ELEMENT = element ] [ , DELIMITER = delimiter ]\n [ , SEND = send_function ] [ , RECEIVE = receive_function ]\n [ , PASSEDBYVALUE ] )"},
- { "CREATE USER",
- "Creates account information for a new user",
- "CREATE USER username\n [ WITH PASSWORD password ]\n [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ]\n [ IN GROUP groupname [, ...] ]\n [ VALID UNTIL 'abstime' ]" },
+ {"CREATE USER",
+ "Creates account information for a new user",
+ "CREATE USER username\n [ WITH PASSWORD password ]\n [ CREATEDB | NOCREATEDB ] [ CREATEUSER | NOCREATEUSER ]\n [ IN GROUP groupname [, ...] ]\n [ VALID UNTIL 'abstime' ]"},
- { "CREATE VIEW",
- "Constructs a virtual table",
- "CREATE VIEW view AS SELECT query" },
+ {"CREATE VIEW",
+ "Constructs a virtual table",
+ "CREATE VIEW view AS SELECT query"},
- { "DECLARE",
- "Defines a cursor for table access",
- "DECLARE cursor [ BINARY ] [ INSENSITIVE ] [ SCROLL ]\n CURSOR FOR query\n [ FOR { READ ONLY | UPDATE [ OF column [, ...] ] ]" },
+ {"DECLARE",
+ "Defines a cursor for table access",
+ "DECLARE cursor [ BINARY ] [ INSENSITIVE ] [ SCROLL ]\n CURSOR FOR query\n [ FOR { READ ONLY | UPDATE [ OF column [, ...] ] ]"},
- { "DELETE",
- "Removes rows from a table",
- "DELETE FROM table [ WHERE condition ]" },
+ {"DELETE",
+ "Removes rows from a table",
+ "DELETE FROM table [ WHERE condition ]"},
- { "DROP AGGREGATE",
- "Removes the definition of an aggregate function",
- "DROP AGGREGATE name type" },
+ {"DROP AGGREGATE",
+ "Removes the definition of an aggregate function",
+ "DROP AGGREGATE name type"},
- { "FETCH",
- "Gets rows using a cursor",
- "FETCH [ selector ] [ count ] { IN | FROM } cursor\nFETCH [ RELATIVE ] [ { [ # | ALL | NEXT | PRIOR ] } ] FROM ] cursor" },
+ {"FETCH",
+ "Gets rows using a cursor",
+ "FETCH [ selector ] [ count ] { IN | FROM } cursor\nFETCH [ RELATIVE ] [ { [ # | ALL | NEXT | PRIOR ] } ] FROM ] cursor"},
- { "DROP DATABASE",
- "Destroys an existing database",
- "DROP DATABASE name" },
+ {"DROP DATABASE",
+ "Destroys an existing database",
+ "DROP DATABASE name"},
- { "DROP FUNCTION",
- "Removes a user-defined C function",
- "DROP FUNCTION name ( [ type [, ...] ] )" },
+ {"DROP FUNCTION",
+ "Removes a user-defined C function",
+ "DROP FUNCTION name ( [ type [, ...] ] )"},
- { "DROP INDEX",
- "Removes an index from a database",
- "DROP INDEX index_name" },
+ {"DROP INDEX",
+ "Removes an index from a database",
+ "DROP INDEX index_name"},
- { "DROP LANGUAGE",
- "Removes a user-defined procedural language",
- "DROP PROCEDURAL LANGUAGE 'name'" },
+ {"DROP LANGUAGE",
+ "Removes a user-defined procedural language",
+ "DROP PROCEDURAL LANGUAGE 'name'"},
- { "DROP OPERATOR",
- "Removes an operator from the database",
- "DROP OPERATOR id ( type | NONE [,...] )" },
+ {"DROP OPERATOR",
+ "Removes an operator from the database",
+ "DROP OPERATOR id ( type | NONE [,...] )"},
- { "DROP RULE",
- "Removes an existing rule from the database",
- "DROP RULE name" },
+ {"DROP RULE",
+ "Removes an existing rule from the database",
+ "DROP RULE name"},
- { "DROP SEQUENCE",
- "Removes an existing sequence",
- "DROP SEQUENCE name [, ...]" },
+ {"DROP SEQUENCE",
+ "Removes an existing sequence",
+ "DROP SEQUENCE name [, ...]"},
- { "DROP TABLE",
- "Removes existing tables from a database",
- "DROP TABLE name [, ...]" },
+ {"DROP TABLE",
+ "Removes existing tables from a database",
+ "DROP TABLE name [, ...]"},
- { "DROP TRIGGER",
- "Removes the definition of a trigger",
- "DROP TRIGGER name ON table" },
+ {"DROP TRIGGER",
+ "Removes the definition of a trigger",
+ "DROP TRIGGER name ON table"},
- { "DROP TYPE",
- "Removes a user-defined type from the system catalogs",
- "DROP TYPE typename" },
+ {"DROP TYPE",
+ "Removes a user-defined type from the system catalogs",
+ "DROP TYPE typename"},
- { "DROP USER",
- "Removes an user account information",
- "DROP USER name" },
+ {"DROP USER",
+ "Removes an user account information",
+ "DROP USER name"},
- { "DROP VIEW",
- "Removes an existing view from a database",
- "DROP VIEW name" },
+ {"DROP VIEW",
+ "Removes an existing view from a database",
+ "DROP VIEW name"},
- { "EXPLAIN",
- "Shows statement execution details",
- "EXPLAIN [ VERBOSE ] query" },
+ {"EXPLAIN",
+ "Shows statement execution details",
+ "EXPLAIN [ VERBOSE ] query"},
- { "GRANT",
- "Grants access privilege to a user, a group or all users",
- "GRANT privilege [, ...] ON object [, ...]\n TO { PUBLIC | GROUP group | username }" },
+ {"GRANT",
+ "Grants access privilege to a user, a group or all users",
+ "GRANT privilege [, ...] ON object [, ...]\n TO { PUBLIC | GROUP group | username }"},
- { "INSERT",
- "Inserts new rows into a table",
- "INSERT INTO table [ ( column [, ...] ) ]\n { VALUES ( expression [, ...] ) | SELECT query }" },
+ {"INSERT",
+ "Inserts new rows into a table",
+ "INSERT INTO table [ ( column [, ...] ) ]\n { VALUES ( expression [, ...] ) | SELECT query }"},
- { "LISTEN",
- "Listen for a response on a notify condition",
- "LISTEN name" },
+ {"LISTEN",
+ "Listen for a response on a notify condition",
+ "LISTEN name"},
- { "LOAD",
- "Dynamically loads an object file",
- "LOAD 'filename'" },
+ {"LOAD",
+ "Dynamically loads an object file",
+ "LOAD 'filename'"},
- { "LOCK",
- "Explicitly lock a table inside a transaction",
- "LOCK [ TABLE ] name\nLOCK [ TABLE ] name IN [ ROW | ACCESS ] { SHARE | EXCLUSIVE } MODE\nLOCK [ TABLE ] name IN SHARE ROW EXCLUSIVE MODE" },
+ {"LOCK",
+ "Explicitly lock a table inside a transaction",
+ "LOCK [ TABLE ] name\nLOCK [ TABLE ] name IN [ ROW | ACCESS ] { SHARE | EXCLUSIVE } MODE\nLOCK [ TABLE ] name IN SHARE ROW EXCLUSIVE MODE"},
- { "MOVE",
- "Moves cursor position",
- "MOVE [ selector ] [ count ] \n { IN | FROM } cursor\n FETCH [ RELATIVE ] [ { [ # | ALL | NEXT | PRIOR ] } ] FROM ] cursor" },
+ {"MOVE",
+ "Moves cursor position",
+ "MOVE [ selector ] [ count ] \n { IN | FROM } cursor\n FETCH [ RELATIVE ] [ { [ # | ALL | NEXT | PRIOR ] } ] FROM ] cursor"},
- { "NOTIFY",
- "Signals all frontends and backends listening on a notify condition",
- "NOTIFY name" },
+ {"NOTIFY",
+ "Signals all frontends and backends listening on a notify condition",
+ "NOTIFY name"},
- { "RESET",
- "Restores run-time parameters for session to default values",
- "RESET variable" },
+ {"RESET",
+ "Restores run-time parameters for session to default values",
+ "RESET variable"},
- { "REVOKE",
- "Revokes access privilege from a user, a group or all users.",
- "REVOKE privilege [, ...]\n ON object [, ...]\n FROM { PUBLIC | GROUP ER\">gBLE> | username }" },
+ {"REVOKE",
+ "Revokes access privilege from a user, a group or all users.",
+ "REVOKE privilege [, ...]\n ON object [, ...]\n FROM { PUBLIC | GROUP ER\">gBLE> | username }"},
- { "ROLLBACK",
- "Aborts the current transaction",
- "ROLLBACK [ WORK | TRANSACTION ]" },
+ {"ROLLBACK",
+ "Aborts the current transaction",
+ "ROLLBACK [ WORK | TRANSACTION ]"},
- { "SELECT",
- "Retrieve rows from a table or view.",
- "SELECT [ ALL | DISTINCT [ ON column ] ]\n expression [ AS name ] [, ...]\n [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ]\n [ FROM table [ alias ] [, ...] ]\n [ WHERE condition ]\n [ GROUP BY column [, ...] ]\n [ HAVING condition [, ...] ]\n [ { UNION [ ALL ] | INTERSECT | EXCEPT } select ]\n [ ORDER BY column [ ASC | DESC ] [, ...] ]\n [ FOR UPDATE [ OF class_name... ] ]\n [ LIMIT { count | ALL } [ { OFFSET | , } count ] ]" },
+ {"SELECT",
+ "Retrieve rows from a table or view.",
+ "SELECT [ ALL | DISTINCT [ ON column ] ]\n expression [ AS name ] [, ...]\n [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ]\n [ FROM table [ alias ] [, ...] ]\n [ WHERE condition ]\n [ GROUP BY column [, ...] ]\n [ HAVING condition [, ...] ]\n [ { UNION [ ALL ] | INTERSECT | EXCEPT } select ]\n [ ORDER BY column [ ASC | DESC ] [, ...] ]\n [ FOR UPDATE [ OF class_name... ] ]\n [ LIMIT { count | ALL } [ { OFFSET | , } count ] ]"},
- { "SELECT INTO",
- "Create a new table from an existing table or view",
- "SELECT [ ALL | DISTINCT ] expression [ AS name ] [, ...]\n INTO [TEMP] [ TABLE ] new_table ]\n [ FROM table [alias] [, ...] ]\n [ WHERE condition ]\n [ GROUP BY column [, ...] ]\n [ HAVING condition [, ...] ]\n [ { UNION [ALL] | INTERSECT | EXCEPT } select]\n [ ORDER BY column [ ASC | DESC ] [, ...] ]\n [ FOR UPDATE [OF class_name...]]\n [ LIMIT count [OFFSET|, count]]" },
+ {"SELECT INTO",
+ "Create a new table from an existing table or view",
+ "SELECT [ ALL | DISTINCT ] expression [ AS name ] [, ...]\n INTO [TEMP] [ TABLE ] new_table ]\n [ FROM table [alias] [, ...] ]\n [ WHERE condition ]\n [ GROUP BY column [, ...] ]\n [ HAVING condition [, ...] ]\n [ { UNION [ALL] | INTERSECT | EXCEPT } select]\n [ ORDER BY column [ ASC | DESC ] [, ...] ]\n [ FOR UPDATE [OF class_name...]]\n [ LIMIT count [OFFSET|, count]]"},
- { "SET",
- "Set run-time parameters for session",
- "SET variable { TO | = } { 'value' | DEFAULT }\nSET TIME ZONE { 'timezone' | LOCAL | DEFAULT }\nSET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE }" },
+ {"SET",
+ "Set run-time parameters for session",
+ "SET variable { TO | = } { 'value' | DEFAULT }\nSET TIME ZONE { 'timezone' | LOCAL | DEFAULT }\nSET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE }"},
- { "SHOW",
- "Shows run-time parameters for session",
- "SHOW keyword" },
+ {"SHOW",
+ "Shows run-time parameters for session",
+ "SHOW keyword"},
- { "UNLISTEN",
- "Stop listening for notification",
- "UNLISTEN { notifyname | * }" },
+ {"UNLISTEN",
+ "Stop listening for notification",
+ "UNLISTEN { notifyname | * }"},
- { "UPDATE",
- "Replaces values of columns in a table",
- "UPDATE table SET R\">colle> = expression [, ...]\n [ FROM fromlist ]\n [ WHERE condition ]" },
+ {"UPDATE",
+ "Replaces values of columns in a table",
+ "UPDATE table SET R\">colle> = expression [, ...]\n [ FROM fromlist ]\n [ WHERE condition ]"},
- { "VACUUM",
- "Clean and analyze a Postgres database",
- "VACUUM [ VERBOSE ] [ ANALYZE ] [ table ]\nVACUUM [ VERBOSE ] ANALYZE [ ER\">tBLE> [ (column [, ...] ) ] ]" },
+ {"VACUUM",
+ "Clean and analyze a Postgres database",
+ "VACUUM [ VERBOSE ] [ ANALYZE ] [ table ]\nVACUUM [ VERBOSE ] ANALYZE [ ER\">tBLE> [ (column [, ...] ) ] ]"},
- { "END",
- "Commits the current transaction",
- "END [ WORK | TRANSACTION ]" },
+ {"END",
+ "Commits the current transaction",
+ "END [ WORK | TRANSACTION ]"},
- { "COMMENT",
- "Add comment to an object",
- "COMMENT ON\n[\n [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]\n object_name |\n COLUMN table_name.column_name|\n AGGREGATE agg_name agg_type|\n FUNCTION func_name (arg1, arg2, ...)|\n OPERATOR op (leftoperand_type rightoperand_type) |\n TRIGGER trigger_name ON table_name\n] IS 'text'" },
+ {"COMMENT",
+ "Add comment to an object",
+ "COMMENT ON\n[\n [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]\n object_name |\n COLUMN table_name.column_name|\n AGGREGATE agg_name agg_type|\n FUNCTION func_name (arg1, arg2, ...)|\n OPERATOR op (leftoperand_type rightoperand_type) |\n TRIGGER trigger_name ON table_name\n] IS 'text'"},
- { NULL, NULL, NULL } /* End of list marker */
+ {NULL, NULL, NULL} /* End of list marker */
};
-#endif /* SQL_HELP_H */
+#endif /* SQL_HELP_H */
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 480e1bc01b..350b7f4937 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -37,35 +37,38 @@
static void
-process_psqlrc(PsqlSettings * pset);
+ process_psqlrc(PsqlSettings *pset);
static void
-showVersion(PsqlSettings *pset, bool verbose);
+ showVersion(PsqlSettings *pset, bool verbose);
/* Structures to pass information between the option parsing routine
* and the main function
*/
-enum _actions { ACT_NOTHING = 0,
- ACT_SINGLE_SLASH,
- ACT_LIST_DB,
- ACT_SHOW_VER,
- ACT_SINGLE_QUERY,
- ACT_FILE
+enum _actions
+{
+ ACT_NOTHING = 0,
+ ACT_SINGLE_SLASH,
+ ACT_LIST_DB,
+ ACT_SHOW_VER,
+ ACT_SINGLE_QUERY,
+ ACT_FILE
};
-struct adhoc_opts {
- char * dbname;
- char * host;
- char * port;
- char * username;
- enum _actions action;
- char * action_string;
- bool no_readline;
+struct adhoc_opts
+{
+ char *dbname;
+ char *host;
+ char *port;
+ char *username;
+ enum _actions action;
+ char *action_string;
+ bool no_readline;
};
static void
-parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * options);
+ parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * options);
@@ -77,133 +80,140 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
int
main(int argc, char **argv)
{
- PsqlSettings settings;
- struct adhoc_opts options;
- int successResult;
+ PsqlSettings settings;
+ struct adhoc_opts options;
+ int successResult;
- char * username = NULL;
- char * password = NULL;
- bool need_pass;
+ char *username = NULL;
+ char *password = NULL;
+ bool need_pass;
- MemSet(&settings, 0, sizeof settings);
+ MemSet(&settings, 0, sizeof settings);
- settings.cur_cmd_source = stdin;
- settings.cur_cmd_interactive = false;
+ settings.cur_cmd_source = stdin;
+ settings.cur_cmd_interactive = false;
- settings.vars = CreateVariableSpace();
- settings.popt.topt.format = PRINT_ALIGNED;
- settings.queryFout = stdout;
- settings.popt.topt.fieldSep = strdup(DEFAULT_FIELD_SEP);
- settings.popt.topt.border = 1;
+ settings.vars = CreateVariableSpace();
+ settings.popt.topt.format = PRINT_ALIGNED;
+ settings.queryFout = stdout;
+ settings.popt.topt.fieldSep = strdup(DEFAULT_FIELD_SEP);
+ settings.popt.topt.border = 1;
- SetVariable(settings.vars, "prompt1", DEFAULT_PROMPT1);
- SetVariable(settings.vars, "prompt2", DEFAULT_PROMPT2);
- SetVariable(settings.vars, "prompt3", DEFAULT_PROMPT3);
+ SetVariable(settings.vars, "prompt1", DEFAULT_PROMPT1);
+ SetVariable(settings.vars, "prompt2", DEFAULT_PROMPT2);
+ SetVariable(settings.vars, "prompt3", DEFAULT_PROMPT3);
- settings.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
+ settings.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
- /* This is obsolete and will be removed very soon. */
+ /* This is obsolete and will be removed very soon. */
#ifdef PSQL_ALWAYS_GET_PASSWORDS
- settings.getPassword = true;
+ settings.getPassword = true;
#else
- settings.getPassword = false;
+ settings.getPassword = false;
#endif
#ifdef MULTIBYTE
- settings.has_client_encoding = (getenv("PGCLIENTENCODING") != NULL);
+ settings.has_client_encoding = (getenv("PGCLIENTENCODING") != NULL);
#endif
- parse_options(argc, argv, &settings, &options);
+ parse_options(argc, argv, &settings, &options);
- if (options.action==ACT_LIST_DB || options.action==ACT_SHOW_VER)
- options.dbname = "template1";
+ if (options.action == ACT_LIST_DB || options.action == ACT_SHOW_VER)
+ options.dbname = "template1";
- if (options.username) {
- if (strcmp(options.username, "?")==0)
- username = simple_prompt("Username: ", 100, true);
- else
- username = strdup(options.username);
- }
-
- if (settings.getPassword)
- password = simple_prompt("Password: ", 100, false);
-
- /* loop until we have a password if requested by backend */
- do {
- need_pass = false;
- settings.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
-
- if (PQstatus(settings.db)==CONNECTION_BAD &&
- strcmp(PQerrorMessage(settings.db), "fe_sendauth: no password supplied\n")==0) {
- need_pass = true;
- free(password);
- password = NULL;
- password = simple_prompt("Password: ", 100, false);
+ if (options.username)
+ {
+ if (strcmp(options.username, "?") == 0)
+ username = simple_prompt("Username: ", 100, true);
+ else
+ username = strdup(options.username);
}
- } while (need_pass);
- free(username);
- free(password);
+ if (settings.getPassword)
+ password = simple_prompt("Password: ", 100, false);
- if (PQstatus(settings.db) == CONNECTION_BAD) {
- fprintf(stderr, "Connection to database '%s' failed.\n%s\n", PQdb(settings.db), PQerrorMessage(settings.db));
- PQfinish(settings.db);
- exit(EXIT_BADCONN);
- }
+ /* loop until we have a password if requested by backend */
+ do
+ {
+ need_pass = false;
+ settings.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
+
+ if (PQstatus(settings.db) == CONNECTION_BAD &&
+ strcmp(PQerrorMessage(settings.db), "fe_sendauth: no password supplied\n") == 0)
+ {
+ need_pass = true;
+ free(password);
+ password = NULL;
+ password = simple_prompt("Password: ", 100, false);
+ }
+ } while (need_pass);
- if (options.action == ACT_LIST_DB) {
- int success = listAllDbs(&settings);
- PQfinish(settings.db);
- exit (!success);
- }
+ free(username);
+ free(password);
+
+ if (PQstatus(settings.db) == CONNECTION_BAD)
+ {
+ fprintf(stderr, "Connection to database '%s' failed.\n%s\n", PQdb(settings.db), PQerrorMessage(settings.db));
+ PQfinish(settings.db);
+ exit(EXIT_BADCONN);
+ }
+
+ if (options.action == ACT_LIST_DB)
+ {
+ int success = listAllDbs(&settings);
+
+ PQfinish(settings.db);
+ exit(!success);
+ }
+
+ if (options.action == ACT_SHOW_VER)
+ {
+ showVersion(&settings, true);
+ PQfinish(settings.db);
+ exit(EXIT_SUCCESS);
+ }
+
+
+ if (!GetVariable(settings.vars, "quiet") && !settings.notty && !options.action)
+ {
+ puts("Welcome to psql, the PostgreSQL interactive terminal.\n"
+ "(Please type \\copyright to see the distribution terms of PostgreSQL.)");
- if (options.action == ACT_SHOW_VER) {
- showVersion(&settings, true);
+ //showVersion(&settings, false);
+
+ puts("\n"
+ "Type \\h for help with SQL commands,\n"
+ " \\? for help on internal slash commands,\n"
+ " \\q to quit,\n"
+ " \\g or terminate with semicolon to execute query.");
+ }
+
+ process_psqlrc(&settings);
+
+ initializeInput(options.no_readline ? 0 : 1);
+
+ /* Now find something to do */
+
+ /* process file given by -f */
+ if (options.action == ACT_FILE)
+ successResult = process_file(options.action_string, &settings) ? 0 : 1;
+ /* process slash command if one was given to -c */
+ else if (options.action == ACT_SINGLE_SLASH)
+ successResult = HandleSlashCmds(&settings, options.action_string, NULL, NULL) != CMD_ERROR ? 0 : 1;
+ /* If the query given to -c was a normal one, send it */
+ else if (options.action == ACT_SINGLE_QUERY)
+ successResult = SendQuery(&settings, options.action_string) ? 0 : 1;
+ /* or otherwise enter interactive main loop */
+ else
+ successResult = MainLoop(&settings, stdin);
+
+ /* clean up */
+ finishInput();
PQfinish(settings.db);
- exit (EXIT_SUCCESS);
- }
-
-
- if (!GetVariable(settings.vars, "quiet") && !settings.notty && !options.action)
- {
- puts("Welcome to psql, the PostgreSQL interactive terminal.\n"
- "(Please type \\copyright to see the distribution terms of PostgreSQL.)");
-
-// showVersion(&settings, false);
-
- puts("\n"
- "Type \\h for help with SQL commands,\n"
- " \\? for help on internal slash commands,\n"
- " \\q to quit,\n"
- " \\g or terminate with semicolon to execute query.");
- }
-
- process_psqlrc(&settings);
-
- initializeInput(options.no_readline ? 0 : 1);
-
- /* Now find something to do */
-
- /* process file given by -f */
- if (options.action == ACT_FILE)
- successResult = process_file(options.action_string, &settings) ? 0 : 1;
- /* process slash command if one was given to -c */
- else if (options.action == ACT_SINGLE_SLASH)
- successResult = HandleSlashCmds(&settings, options.action_string, NULL, NULL) != CMD_ERROR ? 0 : 1;
- /* If the query given to -c was a normal one, send it */
- else if (options.action == ACT_SINGLE_QUERY)
- successResult = SendQuery(&settings, options.action_string) ? 0 : 1;
- /* or otherwise enter interactive main loop */
- else
- successResult = MainLoop(&settings, stdin);
-
- /* clean up */
- finishInput();
- PQfinish(settings.db);
- setQFout(NULL, &settings);
- DestroyVariableSpace(settings.vars);
-
- return successResult;
+ setQFout(NULL, &settings);
+ DestroyVariableSpace(settings.vars);
+
+ return successResult;
}
@@ -214,215 +224,231 @@ main(int argc, char **argv)
#ifdef WIN32
/* getopt is not in the standard includes on Win32 */
-int getopt(int, char *const[], const char *);
+int getopt(int, char *const[], const char *);
+
#endif
static void
-parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * options)
+parse_options(int argc, char *argv[], PsqlSettings *pset, struct adhoc_opts * options)
{
#ifdef HAVE_GETOPT_LONG
- static struct option long_options[] = {
- { "no-align", no_argument, NULL, 'A' },
- { "command", required_argument, NULL, 'c' },
- { "database", required_argument, NULL, 'd' },
- { "dbname", required_argument, NULL, 'd' },
- { "echo", no_argument, NULL, 'e' },
- { "echo-queries", no_argument, NULL, 'e' },
- { "echo-all", no_argument, NULL, 'E' },
- { "echo-all-queries", no_argument, NULL, 'E' },
- { "file", required_argument, NULL, 'f' },
- { "field-sep", required_argument, NULL, 'F' },
- { "host", required_argument, NULL, 'h' },
- { "html", no_argument, NULL, 'H' },
- { "list", no_argument, NULL, 'l' },
- { "no-readline", no_argument, NULL, 'n' },
- { "out", required_argument, NULL, 'o' },
- { "to-file", required_argument, NULL, 'o' },
- { "port", required_argument, NULL, 'p' },
- { "pset", required_argument, NULL, 'P' },
- { "quiet", no_argument, NULL, 'q' },
- { "single-step", no_argument, NULL, 's' },
- { "single-line", no_argument, NULL, 'S' },
- { "tuples-only", no_argument, NULL, 't' },
- { "table-attr", required_argument, NULL, 'T' },
- { "username", required_argument, NULL, 'U' },
- { "expanded", no_argument, NULL, 'x' },
- { "set", required_argument, NULL, 'v' },
- { "variable", required_argument, NULL, 'v' },
- { "version", no_argument, NULL, 'V' },
- { "password", no_argument, NULL, 'W' },
- { "help", no_argument, NULL, '?' },
- };
-
- int optindex;
+ static struct option long_options[] = {
+ {"no-align", no_argument, NULL, 'A'},
+ {"command", required_argument, NULL, 'c'},
+ {"database", required_argument, NULL, 'd'},
+ {"dbname", required_argument, NULL, 'd'},
+ {"echo", no_argument, NULL, 'e'},
+ {"echo-queries", no_argument, NULL, 'e'},
+ {"echo-all", no_argument, NULL, 'E'},
+ {"echo-all-queries", no_argument, NULL, 'E'},
+ {"file", required_argument, NULL, 'f'},
+ {"field-sep", required_argument, NULL, 'F'},
+ {"host", required_argument, NULL, 'h'},
+ {"html", no_argument, NULL, 'H'},
+ {"list", no_argument, NULL, 'l'},
+ {"no-readline", no_argument, NULL, 'n'},
+ {"out", required_argument, NULL, 'o'},
+ {"to-file", required_argument, NULL, 'o'},
+ {"port", required_argument, NULL, 'p'},
+ {"pset", required_argument, NULL, 'P'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"single-step", no_argument, NULL, 's'},
+ {"single-line", no_argument, NULL, 'S'},
+ {"tuples-only", no_argument, NULL, 't'},
+ {"table-attr", required_argument, NULL, 'T'},
+ {"username", required_argument, NULL, 'U'},
+ {"expanded", no_argument, NULL, 'x'},
+ {"set", required_argument, NULL, 'v'},
+ {"variable", required_argument, NULL, 'v'},
+ {"version", no_argument, NULL, 'V'},
+ {"password", no_argument, NULL, 'W'},
+ {"help", no_argument, NULL, '?'},
+ };
+
+ int optindex;
+
#endif
- extern char *optarg;
- extern int optind;
- int c;
+ extern char *optarg;
+ extern int optind;
+ int c;
- MemSet(options, 0, sizeof *options);
+ MemSet(options, 0, sizeof *options);
#ifdef HAVE_GETOPT_LONG
- while ((c = getopt_long(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?", long_options, &optindex)) != -1)
+ while ((c = getopt_long(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?", long_options, &optindex)) != -1)
#else
- /* Be sure to leave the '-' in here, so we can catch accidental long options. */
- while ((c = getopt(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?-")) != -1)
+
+ /*
+ * Be sure to leave the '-' in here, so we can catch accidental long
+ * options.
+ */
+ while ((c = getopt(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qsStT:uU:v:VWx?-")) != -1)
#endif
- {
- switch (c)
- {
- case 'A':
- pset->popt.topt.format = PRINT_UNALIGNED;
- break;
- case 'c':
- options->action_string = optarg;
- if (optarg[0] == '\\')
- options->action = ACT_SINGLE_SLASH;
- else
- options->action = ACT_SINGLE_QUERY;
- break;
- case 'd':
- options->dbname = optarg;
- break;
- case 'e':
- SetVariable(pset->vars, "echo", "");
- break;
- case 'E':
- SetVariable(pset->vars, "echo_secret", "");
- break;
- case 'f':
- options->action = ACT_FILE;
- options->action_string = optarg;
- break;
- case 'F':
- pset->popt.topt.fieldSep = strdup(optarg);
- break;
- case 'h':
- options->host = optarg;
- break;
- case 'H':
- pset->popt.topt.format = PRINT_HTML;
- break;
- case 'l':
- options->action = ACT_LIST_DB;
- break;
- case 'n':
- options->no_readline = true;
- break;
- case 'o':
- setQFout(optarg, pset);
- break;
- case 'p':
- options->port = optarg;
- break;
- case 'P':
- {
- char *value;
- char *equal_loc;
- bool result;
-
- value = xstrdup(optarg);
- equal_loc = strchr(value, '=');
- if (!equal_loc)
- result = do_pset(value, NULL, &pset->popt, true);
- else {
- *equal_loc = '\0';
- result = do_pset(value, equal_loc+1, &pset->popt, true);
- }
-
- if (!result) {
- fprintf(stderr, "Couldn't set printing paramter %s.\n", value);
- exit(EXIT_FAILURE);
- }
-
- free(value);
- break;
- }
- case 'q':
- SetVariable(pset->vars, "quiet", "");
- break;
- case 's':
- SetVariable(pset->vars, "singlestep", "");
- break;
- case 'S':
- SetVariable(pset->vars, "singleline", "");
- break;
- case 't':
- pset->popt.topt.tuples_only = true;
- break;
- case 'T':
- pset->popt.topt.tableAttr = xstrdup(optarg);
- break;
- case 'u':
- pset->getPassword = true;
- options->username = "?";
- break;
- case 'U':
- options->username = optarg;
- break;
- case 'x':
- pset->popt.topt.expanded = true;
- break;
- case 'v':
{
- char *value;
- char *equal_loc;
-
- value = xstrdup(optarg);
- equal_loc = strchr(value, '=');
- if (!equal_loc) {
- if (!DeleteVariable(pset->vars, value)) {
- fprintf(stderr, "Couldn't delete variable %s.\n", value);
- exit(EXIT_FAILURE);
- }
- }
- else {
- *equal_loc = '\0';
- if (!SetVariable(pset->vars, value, equal_loc+1)) {
- fprintf(stderr, "Couldn't set variable %s to %s.\n", value, equal_loc);
- exit(EXIT_FAILURE);
- }
- }
-
- free(value);
- break;
- }
- case 'V':
- options->action = ACT_SHOW_VER;
- break;
- case 'W':
- pset->getPassword = true;
- break;
- case '?':
- usage();
- exit(EXIT_SUCCESS);
- break;
+ switch (c)
+ {
+ case 'A':
+ pset->popt.topt.format = PRINT_UNALIGNED;
+ break;
+ case 'c':
+ options->action_string = optarg;
+ if (optarg[0] == '\\')
+ options->action = ACT_SINGLE_SLASH;
+ else
+ options->action = ACT_SINGLE_QUERY;
+ break;
+ case 'd':
+ options->dbname = optarg;
+ break;
+ case 'e':
+ SetVariable(pset->vars, "echo", "");
+ break;
+ case 'E':
+ SetVariable(pset->vars, "echo_secret", "");
+ break;
+ case 'f':
+ options->action = ACT_FILE;
+ options->action_string = optarg;
+ break;
+ case 'F':
+ pset->popt.topt.fieldSep = strdup(optarg);
+ break;
+ case 'h':
+ options->host = optarg;
+ break;
+ case 'H':
+ pset->popt.topt.format = PRINT_HTML;
+ break;
+ case 'l':
+ options->action = ACT_LIST_DB;
+ break;
+ case 'n':
+ options->no_readline = true;
+ break;
+ case 'o':
+ setQFout(optarg, pset);
+ break;
+ case 'p':
+ options->port = optarg;
+ break;
+ case 'P':
+ {
+ char *value;
+ char *equal_loc;
+ bool result;
+
+ value = xstrdup(optarg);
+ equal_loc = strchr(value, '=');
+ if (!equal_loc)
+ result = do_pset(value, NULL, &pset->popt, true);
+ else
+ {
+ *equal_loc = '\0';
+ result = do_pset(value, equal_loc + 1, &pset->popt, true);
+ }
+
+ if (!result)
+ {
+ fprintf(stderr, "Couldn't set printing paramter %s.\n", value);
+ exit(EXIT_FAILURE);
+ }
+
+ free(value);
+ break;
+ }
+ case 'q':
+ SetVariable(pset->vars, "quiet", "");
+ break;
+ case 's':
+ SetVariable(pset->vars, "singlestep", "");
+ break;
+ case 'S':
+ SetVariable(pset->vars, "singleline", "");
+ break;
+ case 't':
+ pset->popt.topt.tuples_only = true;
+ break;
+ case 'T':
+ pset->popt.topt.tableAttr = xstrdup(optarg);
+ break;
+ case 'u':
+ pset->getPassword = true;
+ options->username = "?";
+ break;
+ case 'U':
+ options->username = optarg;
+ break;
+ case 'x':
+ pset->popt.topt.expanded = true;
+ break;
+ case 'v':
+ {
+ char *value;
+ char *equal_loc;
+
+ value = xstrdup(optarg);
+ equal_loc = strchr(value, '=');
+ if (!equal_loc)
+ {
+ if (!DeleteVariable(pset->vars, value))
+ {
+ fprintf(stderr, "Couldn't delete variable %s.\n", value);
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ *equal_loc = '\0';
+ if (!SetVariable(pset->vars, value, equal_loc + 1))
+ {
+ fprintf(stderr, "Couldn't set variable %s to %s.\n", value, equal_loc);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ free(value);
+ break;
+ }
+ case 'V':
+ options->action = ACT_SHOW_VER;
+ break;
+ case 'W':
+ pset->getPassword = true;
+ break;
+ case '?':
+ usage();
+ exit(EXIT_SUCCESS);
+ break;
#ifndef HAVE_GETOPT_LONG
- case '-':
- fprintf(stderr, "This version of psql was compiled without support for long options.\n"
- "Use -? for help on invocation options.\n");
- exit(EXIT_FAILURE);
- break;
+ case '-':
+ fprintf(stderr, "This version of psql was compiled without support for long options.\n"
+ "Use -? for help on invocation options.\n");
+ exit(EXIT_FAILURE);
+ break;
#endif
- default:
- usage();
- exit(EXIT_FAILURE);
- break;
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ break;
+ }
}
- }
-
- /* if we still have arguments, use it as the database name and username */
- while (argc - optind >= 1) {
- if (!options->dbname)
- options->dbname = argv[optind];
- else if (!options->username)
- options->username = argv[optind];
- else
- fprintf(stderr, "Warning: extra option %s ignored.\n", argv[optind]);
- optind++;
- }
+ /*
+ * if we still have arguments, use it as the database name and
+ * username
+ */
+ while (argc - optind >= 1)
+ {
+ if (!options->dbname)
+ options->dbname = argv[optind];
+ else if (!options->username)
+ options->username = argv[optind];
+ else
+ fprintf(stderr, "Warning: extra option %s ignored.\n", argv[optind]);
+
+ optind++;
+ }
}
@@ -431,41 +457,44 @@ parse_options(int argc, char *argv[], PsqlSettings * pset, struct adhoc_opts * o
* Load /etc/psqlrc or .psqlrc file, if found.
*/
static void
-process_psqlrc(PsqlSettings * pset)
+process_psqlrc(PsqlSettings *pset)
{
- char *psqlrc;
- char * home;
+ char *psqlrc;
+ char *home;
#ifdef WIN32
#define R_OK 0
#endif
- /* System-wide startup file */
- if (access("/etc/psqlrc-"PG_RELEASE"."PG_VERSION"."PG_SUBVERSION, R_OK) == 0)
- process_file("/etc/psqlrc-"PG_RELEASE"."PG_VERSION"."PG_SUBVERSION, pset);
- else if (access("/etc/psqlrc", R_OK) == 0)
- process_file("/etc/psqlrc", pset);
+ /* System-wide startup file */
+ if (access("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, R_OK) == 0)
+ process_file("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, pset);
+ else if (access("/etc/psqlrc", R_OK) == 0)
+ process_file("/etc/psqlrc", pset);
- /* Look for one in the home dir */
- home = getenv("HOME");
+ /* Look for one in the home dir */
+ home = getenv("HOME");
- if (home) {
- psqlrc = (char *) malloc(strlen(home) + 20);
- if (!psqlrc) {
- perror("malloc");
- exit(EXIT_FAILURE);
- }
+ if (home)
+ {
+ psqlrc = (char *) malloc(strlen(home) + 20);
+ if (!psqlrc)
+ {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
- sprintf(psqlrc, "%s/.psqlrc-"PG_RELEASE"."PG_VERSION"."PG_SUBVERSION, home);
- if (access(psqlrc, R_OK) == 0)
- process_file(psqlrc, pset);
- else {
- sprintf(psqlrc, "%s/.psqlrc", home);
- if (access(psqlrc, R_OK) == 0)
- process_file(psqlrc, pset);
+ sprintf(psqlrc, "%s/.psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, home);
+ if (access(psqlrc, R_OK) == 0)
+ process_file(psqlrc, pset);
+ else
+ {
+ sprintf(psqlrc, "%s/.psqlrc", home);
+ if (access(psqlrc, R_OK) == 0)
+ process_file(psqlrc, pset);
+ }
+ free(psqlrc);
}
- free(psqlrc);
- }
}
@@ -482,62 +511,68 @@ process_psqlrc(PsqlSettings * pset)
static void
showVersion(PsqlSettings *pset, bool verbose)
{
- PGresult *res;
- char *versionstr = NULL;
- long int release = 0, version = 0, subversion = 0;
-
- /* get backend version */
- res = PSQLexec(pset, "SELECT version()");
- if (PQresultStatus(res) == PGRES_TUPLES_OK)
- versionstr = PQgetvalue(res, 0, 0);
-
- if (!verbose) {
- if (versionstr) puts(versionstr);
- PQclear(res);
- return;
- }
+ PGresult *res;
+ char *versionstr = NULL;
+ long int release = 0,
+ version = 0,
+ subversion = 0;
+
+ /* get backend version */
+ res = PSQLexec(pset, "SELECT version()");
+ if (PQresultStatus(res) == PGRES_TUPLES_OK)
+ versionstr = PQgetvalue(res, 0, 0);
+
+ if (!verbose)
+ {
+ if (versionstr)
+ puts(versionstr);
+ PQclear(res);
+ return;
+ }
+
+ if (strncmp(versionstr, "PostgreSQL ", 11) == 0)
+ {
+ char *tmp;
- if (strncmp(versionstr, "PostgreSQL ", 11) == 0) {
- char *tmp;
- release = strtol(&versionstr[11], &tmp, 10);
- version = strtol(tmp+1, &tmp, 10);
- subversion = strtol(tmp+1, &tmp, 10);
- }
+ release = strtol(&versionstr[11], &tmp, 10);
+ version = strtol(tmp + 1, &tmp, 10);
+ subversion = strtol(tmp + 1, &tmp, 10);
+ }
- printf("Server: %s\npsql", versionstr ? versionstr : "(could not connected)");
+ printf("Server: %s\npsql", versionstr ? versionstr : "(could not connected)");
- if (strcmp(versionstr, PG_VERSION_STR) != 0)
- printf(&PG_VERSION_STR[strcspn(PG_VERSION_STR, " ")]);
- printf(" ("__DATE__" "__TIME__")");
+ if (strcmp(versionstr, PG_VERSION_STR) != 0)
+ printf(&PG_VERSION_STR[strcspn(PG_VERSION_STR, " ")]);
+ printf(" (" __DATE__ " " __TIME__ ")");
#ifdef MULTIBYTE
- printf(", multibyte");
+ printf(", multibyte");
#endif
#ifdef HAVE_GETOPT_LONG
- printf(", long options");
+ printf(", long options");
#endif
#ifdef USE_READLINE
- printf(", readline");
+ printf(", readline");
#endif
#ifdef USE_HISTORY
- printf(", history");
+ printf(", history");
#endif
#ifdef USE_LOCALE
- printf(", locale");
+ printf(", locale");
#endif
#ifdef PSQL_ALWAYS_GET_PASSWORDS
- printf(", always password");
+ printf(", always password");
#endif
#ifdef USE_ASSERT_CHECKING
- printf(", assert checks");
+ printf(", assert checks");
#endif
- puts("");
+ puts("");
- if (release < 6 || (release == 6 && version < 5))
- puts ("\nWarning: The server you are connected to is potentially too old for this client\n"
- "version. You should ideally be using clients and servers from the same\n"
- "distribution.");
+ if (release < 6 || (release == 6 && version < 5))
+ puts("\nWarning: The server you are connected to is potentially too old for this client\n"
+ "version. You should ideally be using clients and servers from the same\n"
+ "distribution.");
- PQclear(res);
+ PQclear(res);
}
diff --git a/src/bin/psql/stringutils.c b/src/bin/psql/stringutils.c
index c495fd4966..b4f5be926b 100644
--- a/src/bin/psql/stringutils.c
+++ b/src/bin/psql/stringutils.c
@@ -2,11 +2,13 @@
#include <c.h>
#include "stringutils.h"
-//#include <ctype.h>
+//
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-//#include <stdio.h>
+//
+#include <stdio.h>
#include <postgres.h>
#ifndef HAVE_STRDUP
@@ -17,118 +19,130 @@
static void
-unescape_quotes(char *source, char quote, char escape);
+ unescape_quotes(char *source, char quote, char escape);
/*
* Replacement for strtok() (a.k.a. poor man's flex)
*
* The calling convention is similar to that of strtok.
- * s - string to parse, if NULL continue parsing the last string
- * delim - set of characters that delimit tokens (usually whitespace)
- * quote - set of characters that quote stuff, they're not part of the token
- * escape - character than can quote quotes
+ * s - string to parse, if NULL continue parsing the last string
+ * delim - set of characters that delimit tokens (usually whitespace)
+ * quote - set of characters that quote stuff, they're not part of the token
+ * escape - character than can quote quotes
* was_quoted - if not NULL, stores the quoting character if any was encountered
- * token_pos - if not NULL, receives a count to the start of the token in the
- * parsed string
+ * token_pos - if not NULL, receives a count to the start of the token in the
+ * parsed string
*
* Note that the string s is _not_ overwritten in this implementation.
*/
-char * strtokx(const char *s,
- const char *delim,
- const char *quote,
- char escape,
- char * was_quoted,
- unsigned int * token_pos)
+char *
+strtokx(const char *s,
+ const char *delim,
+ const char *quote,
+ char escape,
+ char *was_quoted,
+ unsigned int *token_pos)
{
- static char * storage = NULL; /* store the local copy of the users string here */
- static char * string = NULL; /* pointer into storage where to continue on next call */
- /* variously abused variables: */
- unsigned int offset;
- char * start;
- char *cp = NULL;
-
- if (s) {
- free(storage);
- storage = strdup(s);
- string = storage;
- }
-
- if (!storage)
- return NULL;
-
- /* skip leading "whitespace" */
- offset = strspn(string, delim);
-
- /* end of string reached */
- if (string[offset] == '\0') {
- /* technically we don't need to free here, but we're nice */
- free(storage);
- storage = NULL;
- string = NULL;
- return NULL;
- }
-
- /* test if quoting character */
- if (quote)
- cp = strchr(quote, string[offset]);
-
- if (cp) {
- /* okay, we have a quoting character, now scan for the closer */
- char *p;
- start = &string[offset+1];
+ static char *storage = NULL;/* store the local copy of the users
+ * string here */
+ static char *string = NULL; /* pointer into storage where to continue
+ * on next call */
+
+ /* variously abused variables: */
+ unsigned int offset;
+ char *start;
+ char *cp = NULL;
+
+ if (s)
+ {
+ free(storage);
+ storage = strdup(s);
+ string = storage;
+ }
- if (token_pos)
- *token_pos = start - storage;
+ if (!storage)
+ return NULL;
+
+ /* skip leading "whitespace" */
+ offset = strspn(string, delim);
+
+ /* end of string reached */
+ if (string[offset] == '\0')
+ {
+ /* technically we don't need to free here, but we're nice */
+ free(storage);
+ storage = NULL;
+ string = NULL;
+ return NULL;
+ }
- for(p = start;
- *p && (*p != *cp || *(p-1) == escape) ;
+ /* test if quoting character */
+ if (quote)
+ cp = strchr(quote, string[offset]);
+
+ if (cp)
+ {
+ /* okay, we have a quoting character, now scan for the closer */
+ char *p;
+
+ start = &string[offset + 1];
+
+ if (token_pos)
+ *token_pos = start - storage;
+
+ for (p = start;
+ *p && (*p != *cp || *(p - 1) == escape);
#ifdef MULTIBYTE
- p += PQmblen(p)
+ p += PQmblen(p)
#else
- p++
+ p++
#endif
- );
-
- /* not yet end of string? */
- if (*p != '\0') {
- *p = '\0';
- string = p + 1;
- if (was_quoted)
- *was_quoted = *cp;
- unescape_quotes (start, *cp, escape);
- return start;
+ );
+
+ /* not yet end of string? */
+ if (*p != '\0')
+ {
+ *p = '\0';
+ string = p + 1;
+ if (was_quoted)
+ *was_quoted = *cp;
+ unescape_quotes(start, *cp, escape);
+ return start;
+ }
+ else
+ {
+ if (was_quoted)
+ *was_quoted = *cp;
+ string = p;
+
+ unescape_quotes(start, *cp, escape);
+ return start;
+ }
}
- else {
- if (was_quoted)
- *was_quoted = *cp;
- string = p;
- unescape_quotes (start, *cp, escape);
- return start;
- }
- }
+ /* otherwise no quoting character. scan till next delimiter */
+ start = &string[offset];
- /* otherwise no quoting character. scan till next delimiter */
- start = &string[offset];
-
- if (token_pos)
- *token_pos = start - storage;
+ if (token_pos)
+ *token_pos = start - storage;
- offset = strcspn(start, delim);
- if (was_quoted)
- *was_quoted = 0;
+ offset = strcspn(start, delim);
+ if (was_quoted)
+ *was_quoted = 0;
- if (start[offset] != '\0') {
- start[offset] = '\0';
- string = &start[offset]+1;
+ if (start[offset] != '\0')
+ {
+ start[offset] = '\0';
+ string = &start[offset] + 1;
- return start;
- }
- else {
- string = &start[offset];
- return start;
- }
+ return start;
+ }
+ else
+ {
+ string = &start[offset];
+ return start;
+ }
}
@@ -142,38 +156,41 @@ char * strtokx(const char *s,
static void
unescape_quotes(char *source, char quote, char escape)
{
- char *p;
- char *destination, *tmp;
+ char *p;
+ char *destination,
+ *tmp;
#ifdef USE_ASSERT_CHECKING
- assert(source);
+ assert(source);
#endif
- destination = (char *) calloc(1, strlen(source)+1);
- if (!destination) {
- perror("calloc");
- exit(EXIT_FAILURE);
- }
+ destination = (char *) calloc(1, strlen(source) + 1);
+ if (!destination)
+ {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
- tmp = destination;
+ tmp = destination;
- for (p = source; *p; p++)
- {
- char c;
+ for (p = source; *p; p++)
+ {
+ char c;
- if (*p == escape && *(p+1) && quote == *(p+1)) {
- c = *(p+1);
- p++;
- }
- else
- c = *p;
+ if (*p == escape && *(p + 1) && quote == *(p + 1))
+ {
+ c = *(p + 1);
+ p++;
+ }
+ else
+ c = *p;
- *tmp = c;
- tmp ++;
- }
+ *tmp = c;
+ tmp++;
+ }
- /* Terminating null character */
- *tmp = '\0';
+ /* Terminating null character */
+ *tmp = '\0';
- strcpy(source, destination);
+ strcpy(source, destination);
}
diff --git a/src/bin/psql/stringutils.h b/src/bin/psql/stringutils.h
index f505a7b2c1..5d72006c8e 100644
--- a/src/bin/psql/stringutils.h
+++ b/src/bin/psql/stringutils.h
@@ -3,12 +3,11 @@
/* The cooler version of strtok() which knows about quotes and doesn't
* overwrite your input */
-extern char *
-strtokx(const char *s,
- const char *delim,
- const char *quote,
- char escape,
- char * was_quoted,
- unsigned int * token_pos);
+extern char *strtokx(const char *s,
+ const char *delim,
+ const char *quote,
+ char escape,
+ char *was_quoted,
+ unsigned int *token_pos);
#endif /* STRINGUTILS_H */
diff --git a/src/bin/psql/variables.c b/src/bin/psql/variables.c
index ea824cff69..132ecc9322 100644
--- a/src/bin/psql/variables.c
+++ b/src/bin/psql/variables.c
@@ -6,127 +6,145 @@
#include <assert.h>
-VariableSpace CreateVariableSpace(void)
+VariableSpace
+CreateVariableSpace(void)
{
- struct _variable *ptr;
-
- ptr = calloc(1, sizeof *ptr);
- if (!ptr) return NULL;
+ struct _variable *ptr;
+
+ ptr = calloc(1, sizeof *ptr);
+ if (!ptr)
+ return NULL;
+
+ ptr->name = strdup("@");
+ ptr->value = strdup("");
+ if (!ptr->name || !ptr->value)
+ {
+ free(ptr->name);
+ free(ptr->value);
+ free(ptr);
+ return NULL;
+ }
- ptr->name = strdup("@");
- ptr->value = strdup("");
- if (!ptr->name || !ptr->value) {
- free(ptr->name);
- free(ptr->value);
- free(ptr);
- return NULL;
- }
-
- return ptr;
+ return ptr;
}
-const char * GetVariable(VariableSpace space, const char * name)
+const char *
+GetVariable(VariableSpace space, const char *name)
{
- struct _variable *current;
+ struct _variable *current;
- if (!space)
- return NULL;
+ if (!space)
+ return NULL;
- if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name)) return NULL;
+ if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name))
+ return NULL;
- for (current = space; current; current = current->next) {
+ for (current = space; current; current = current->next)
+ {
#ifdef USE_ASSERT_CHECKING
- assert(current->name);
- assert(current->value);
+ assert(current->name);
+ assert(current->value);
#endif
- if (strcmp(current->name, name)==0)
- return current->value;
- }
+ if (strcmp(current->name, name) == 0)
+ return current->value;
+ }
- return NULL;
+ return NULL;
}
-bool GetVariableBool(VariableSpace space, const char * name)
+bool
+GetVariableBool(VariableSpace space, const char *name)
{
- return GetVariable(space, name)!=NULL ? true : false;
+ return GetVariable(space, name) != NULL ? true : false;
}
-bool SetVariable(VariableSpace space, const char * name, const char * value)
+bool
+SetVariable(VariableSpace space, const char *name, const char *value)
{
- struct _variable *current, *previous;
+ struct _variable *current,
+ *previous;
- if (!space)
- return false;
+ if (!space)
+ return false;
- if (!value)
- return DeleteVariable(space, name);
+ if (!value)
+ return DeleteVariable(space, name);
- if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name)) return false;
+ if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name))
+ return false;
- for (current = space; current; previous = current, current = current->next) {
+ for (current = space; current; previous = current, current = current->next)
+ {
#ifdef USE_ASSERT_CHECKING
- assert(current->name);
- assert(current->value);
+ assert(current->name);
+ assert(current->value);
#endif
- if (strcmp(current->name, name)==0) {
- free (current->value);
- current->value = strdup(value);
- return current->value ? true : false;
+ if (strcmp(current->name, name) == 0)
+ {
+ free(current->value);
+ current->value = strdup(value);
+ return current->value ? true : false;
+ }
}
- }
-
- previous->next = calloc(1, sizeof *(previous->next));
- if (!previous->next)
- return false;
- previous->next->name = strdup(name);
- if (!previous->next->name)
- return false;
- previous->next->value = strdup(value);
- return previous->next->value ? true : false;
+
+ previous->next = calloc(1, sizeof *(previous->next));
+ if (!previous->next)
+ return false;
+ previous->next->name = strdup(name);
+ if (!previous->next->name)
+ return false;
+ previous->next->value = strdup(value);
+ return previous->next->value ? true : false;
}
-bool DeleteVariable(VariableSpace space, const char * name)
+bool
+DeleteVariable(VariableSpace space, const char *name)
{
- struct _variable *current, *previous;
+ struct _variable *current,
+ *previous;
- if (!space)
- return false;
+ if (!space)
+ return false;
- if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name)) return false;
+ if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name))
+ return false;
- for (current = space, previous = NULL; current; previous = current, current = current->next) {
+ for (current = space, previous = NULL; current; previous = current, current = current->next)
+ {
#ifdef USE_ASSERT_CHECKING
- assert(current->name);
- assert(current->value);
+ assert(current->name);
+ assert(current->value);
#endif
- if (strcmp(current->name, name)==0) {
- free (current->name);
- free (current->value);
- if (previous)
- previous->next = current->next;
- free(current);
- return true;
+ if (strcmp(current->name, name) == 0)
+ {
+ free(current->name);
+ free(current->value);
+ if (previous)
+ previous->next = current->next;
+ free(current);
+ return true;
+ }
}
- }
- return true;
+ return true;
}
-void DestroyVariableSpace(VariableSpace space)
+void
+DestroyVariableSpace(VariableSpace space)
{
- if (!space)
- return;
+ if (!space)
+ return;
- DestroyVariableSpace(space->next);
- free(space);
+ DestroyVariableSpace(space->next);
+ free(space);
}
diff --git a/src/bin/psql/variables.h b/src/bin/psql/variables.h
index 9e2dd2e3a7..c8c3a0adae 100644
--- a/src/bin/psql/variables.h
+++ b/src/bin/psql/variables.h
@@ -13,21 +13,22 @@
#define VALID_VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_"
-struct _variable {
- char * name;
- char * value;
- struct _variable * next;
+struct _variable
+{
+ char *name;
+ char *value;
+ struct _variable *next;
};
-typedef struct _variable * VariableSpace;
+typedef struct _variable *VariableSpace;
VariableSpace CreateVariableSpace(void);
-const char * GetVariable(VariableSpace space, const char * name);
-bool GetVariableBool(VariableSpace space, const char * name);
-bool SetVariable(VariableSpace space, const char * name, const char * value);
-bool DeleteVariable(VariableSpace space, const char * name);
-void DestroyVariableSpace(VariableSpace space);
+const char *GetVariable(VariableSpace space, const char *name);
+bool GetVariableBool(VariableSpace space, const char *name);
+bool SetVariable(VariableSpace space, const char *name, const char *value);
+bool DeleteVariable(VariableSpace space, const char *name);
+void DestroyVariableSpace(VariableSpace space);
-#endif /* VARIABLES_H */
+#endif /* VARIABLES_H */