aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2000-02-07 23:10:11 +0000
committerPeter Eisentraut <peter_e@gmx.net>2000-02-07 23:10:11 +0000
commit9ceb5d8a7bfc4a6315f37913afb5f3d6cefa651f (patch)
treecfe54170ff754e064955bb00be586a5b26ab7db3 /src
parent4842ef86247a323de9ec25e799d756c320222fe0 (diff)
downloadpostgresql-9ceb5d8a7bfc4a6315f37913afb5f3d6cefa651f.tar.gz
postgresql-9ceb5d8a7bfc4a6315f37913afb5f3d6cefa651f.zip
Fixed psql double quoting of SQL ids
Fixed libpq printing functions
Diffstat (limited to 'src')
-rw-r--r--src/bin/psql/command.c944
-rw-r--r--src/bin/psql/common.c28
-rw-r--r--src/bin/psql/create_help.pl9
-rw-r--r--src/bin/psql/describe.c62
-rw-r--r--src/bin/psql/help.c115
-rw-r--r--src/bin/psql/input.c18
-rw-r--r--src/bin/psql/input.h6
-rw-r--r--src/bin/psql/large_obj.c6
-rw-r--r--src/bin/psql/mainloop.c10
-rw-r--r--src/bin/psql/print.c6
-rw-r--r--src/bin/psql/prompt.c19
-rw-r--r--src/bin/psql/prompt.h5
-rw-r--r--src/bin/psql/startup.c164
-rw-r--r--src/bin/psql/stringutils.c20
-rw-r--r--src/bin/psql/stringutils.h4
-rw-r--r--src/bin/psql/tab-complete.c6
-rw-r--r--src/interfaces/libpq/fe-auth.c6
-rw-r--r--src/interfaces/libpq/fe-connect.c19
-rw-r--r--src/interfaces/libpq/fe-exec.c26
-rw-r--r--src/interfaces/libpq/fe-lobj.c4
-rw-r--r--src/interfaces/libpq/fe-misc.c4
-rw-r--r--src/interfaces/libpq/fe-print.c21
-rw-r--r--src/interfaces/libpq/libpq-fe.h55
-rw-r--r--src/interfaces/libpq/libpq-int.h7
-rw-r--r--src/interfaces/libpq/pqexpbuffer.c16
-rw-r--r--src/interfaces/libpq/pqexpbuffer.h10
-rw-r--r--src/interfaces/libpq/win32.h4
27 files changed, 930 insertions, 664 deletions
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 63ac6fbff42..ba198d7d914 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3,12 +3,13 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.17 2000/02/05 12:27:56 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.18 2000/02/07 23:10:04 petere Exp $
*/
#include <c.h>
#include "command.h"
#include <errno.h>
+#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -17,54 +18,40 @@
#include <sys/types.h> /* for umask() */
#include <sys/stat.h> /* for umask(), stat() */
#include <unistd.h> /* for geteuid(), getpid(), stat() */
+#else
+#include <win32.h>
#endif
-#include <assert.h>
#include <libpq-fe.h>
#include <pqexpbuffer.h>
-#include "stringutils.h"
-#include "mainloop.h"
+#include "common.h"
#include "copy.h"
+#include "describe.h"
#include "help.h"
-#include "settings.h"
-#include "common.h"
+#include "input.h"
#include "large_obj.h"
+#include "mainloop.h"
#include "print.h"
-#include "describe.h"
-#include "input.h"
+#include "settings.h"
#include "variables.h"
-#ifdef WIN32
-#include "../../interfaces/libpq/win32.h"
-#define popen(x,y) _popen(x,y)
-#define pclose(x) _pclose(x)
-#endif
-
/* functions for use in this file */
static backslashResult exec_command(const char *cmd,
- char *const * options,
const char *options_string,
+ const char ** continue_parse,
PQExpBuffer query_buf);
-static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
-
-static char * unescape(const char *source);
-
-static bool do_connect(const char *new_dbname,
- const char *new_user);
-
+enum option_type { OT_NORMAL, OT_SQLID };
+static char * scan_option(char ** string, enum option_type type, char * quote);
+static char * unescape(const unsigned char *source, size_t len);
+static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
+static bool do_connect(const char *new_dbname, const char *new_user);
static bool do_shell(const char *command);
-/*
- * Perhaps this should be changed to "infinity",
- * but there is no convincing reason to bother
- * at this point.
- */
-#define NR_OPTIONS 16
/*----------
@@ -79,7 +66,7 @@ static bool do_shell(const char *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.
+ * query_buf can be NULL if there is no query so far.
*
* Returns a status code indicating what action is desired, see command.h.
*----------
@@ -92,18 +79,13 @@ HandleSlashCmds(const char *line,
{
backslashResult status = CMD_SKIP_LINE;
char *my_line;
- char *options[NR_OPTIONS+1];
- char *token;
- const char *options_string = NULL;
- const char *cmd;
+ char *options_string = NULL;
size_t blank_loc;
- int i;
const char *continue_parse = NULL; /* tell the mainloop where the
* backslash command ended */
#ifdef USE_ASSERT_CHECKING
assert(line);
- assert(query_buf);
assert(end_of_cmd);
#endif
@@ -129,145 +111,37 @@ HandleSlashCmds(const char *line,
my_line[blank_loc] = '\0';
}
- options[0] = NULL;
-
- 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, pset.encoding);
-
- for (i = 0; token && i < NR_OPTIONS; i++)
- {
- switch (quote)
- {
- case '"':
- options[i] = unescape(token);
- break;
- case '\'':
- options[i] = xstrdup(token);
- break;
- case '`':
- {
- bool error = false;
- FILE *fd = NULL;
- char *file = unescape(token);
- PQExpBufferData output;
- char buf[512];
- size_t result;
-
- fd = popen(file, "r");
- if (!fd)
- {
- psql_error("%s: %s\n", file, strerror(errno));
- error = true;
- }
-
- if (!error)
- {
- initPQExpBuffer(&output);
-
- do
- {
- result = fread(buf, 1, 512, fd);
- if (ferror(fd))
- {
- psql_error("%s: %s\n", file, strerror(errno));
- error = true;
- break;
- }
- appendBinaryPQExpBuffer(&output, buf, result);
- } while (!feof(fd));
- appendPQExpBufferChar(&output, '\0');
-
- if (pclose(fd) == -1)
- {
- psql_error("%s: %s\n", file, strerror(errno));
- 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] == '$')
- {
- const char * value = GetVariable(pset.vars, token+1);
- if (!value)
- value = "";
- options[i] = xstrdup(value);
- }
- else
- options[i] = xstrdup(token);
- }
-
- if (continue_parse)
- break;
-
- token = strtokx(NULL, " \t", "\"'`", '\\', &quote, &pos, pset.encoding);
- } /* for */
-
- options[i] = NULL;
- }
-
- cmd = my_line;
- status = exec_command(cmd, options, options_string, query_buf);
+ status = exec_command(my_line, options_string, &continue_parse, query_buf);
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.
+ * 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[NR_OPTIONS+1];
char new_cmd[2];
- int i;
-
- for (i = 1; i < NR_OPTIONS+1; i++)
- new_options[i] = options[i - 1];
- new_options[0] = cmd + 1;
- new_cmd[0] = cmd[0];
+ new_cmd[0] = my_line[0];
new_cmd[1] = '\0';
- status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf);
+ status = exec_command(new_cmd, my_line + 1, &continue_parse, query_buf);
+
+ if (status != CMD_UNKNOWN && isalpha(new_cmd[0]))
+ psql_error("Warning: this syntax is deprecated\n");
}
if (status == CMD_UNKNOWN)
{
if (pset.cur_cmd_interactive)
- fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", cmd);
+ fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", my_line);
else
- psql_error("invalid command \\%s\n", cmd);
+ psql_error("invalid command \\%s\n", my_line);
status = CMD_ERROR;
}
- if (continue_parse && *(continue_parse + 1) == '\\')
+ if (continue_parse && *continue_parse && *(continue_parse + 1) == '\\')
continue_parse += 2;
@@ -276,10 +150,6 @@ HandleSlashCmds(const char *line,
else
*end_of_cmd = line + strlen(line);
- /* clean up */
- for (i = 0; i < NR_OPTIONS && options[i]; i++)
- free(options[i]);
-
free(my_line);
return status;
@@ -287,19 +157,26 @@ HandleSlashCmds(const char *line,
-
static backslashResult
exec_command(const char *cmd,
- char *const * options,
const char *options_string,
+ const char ** continue_parse,
PQExpBuffer query_buf)
{
bool success = true; /* indicate here if the command ran ok or
* failed */
bool quiet = QUIET();
-
backslashResult status = CMD_SKIP_LINE;
+ char *string, *string_cpy;
+ /*
+ * The 'string' variable will be overwritten to point to the next token,
+ * hence we need an extra pointer so we can free this at the end.
+ */
+ if (options_string)
+ string = string_cpy = xstrdup(options_string);
+ else
+ string = string_cpy = NULL;
/* \a -- toggle field alignment This makes little sense but we keep it around. */
if (strcmp(cmd, "a") == 0)
@@ -310,44 +187,53 @@ exec_command(const char *cmd,
success = do_pset("format", "unaligned", &pset.popt, quiet);
}
-
/* \C -- override table title (formerly change HTML caption) */
else if (strcmp(cmd, "C") == 0)
- success = do_pset("title", options[0], &pset.popt, quiet);
-
+ {
+ char * opt = scan_option(&string, OT_NORMAL, NULL);
+ success = do_pset("title", opt, &pset.popt, quiet);
+ free(opt);
+ }
/*----------
* \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
+ * \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])
+ char *opt1, *opt2;
+ char opt1q, opt2q;
+
+ opt1 = scan_option(&string, OT_NORMAL, &opt1q);
+ opt2 = scan_option(&string, OT_NORMAL, &opt2q);
+
+ if (opt2)
/* gave username */
- success = do_connect(options[0], options[1]);
- else
- {
- if (options[0])
- /* gave database name */
- success = do_connect(options[0], ""); /* 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);
- }
- }
+ success = do_connect(!opt1q && (strcmp(opt1, "-")==0 || strcmp(opt1, "")==0) ? "" : opt1,
+ !opt2q && (strcmp(opt2, "-")==0 || strcmp(opt2, "")==0) ? "" : opt2);
+ else if (opt1)
+ /* gave database name */
+ success = do_connect(!opt1q && (strcmp(opt1, "-")==0 || strcmp(opt1, "")==0) ? "" : opt1, "");
+ else
+ /* connect to default db as default user */
+ success = do_connect(NULL, NULL);
+ free(opt1);
+ free(opt2);
+ }
/* \copy */
else if (strcasecmp(cmd, "copy") == 0)
+ {
success = do_copy(options_string);
+ if (options_string)
+ string += strlen(string);
+ }
/* \copyright */
else if (strcmp(cmd, "copyright") == 0)
@@ -356,38 +242,42 @@ exec_command(const char *cmd,
/* \d* commands */
else if (cmd[0] == 'd')
{
- bool show_verbose = strchr(cmd, '+') ? true : false;
+ char * name;
+ bool show_verbose;
+
+ name = scan_option(&string, OT_SQLID, NULL);
+ show_verbose = strchr(cmd, '+') ? true : false;
switch (cmd[1])
{
case '\0':
case '+':
- if (options[0])
- success = describeTableDetails(options[0], show_verbose);
+ if (name)
+ success = describeTableDetails(name, show_verbose);
else
/* standard listing of interesting things */
success = listTables("tvs", NULL, show_verbose);
break;
case 'a':
- success = describeAggregates(options[0]);
+ success = describeAggregates(name);
break;
case 'd':
- success = objectDescription(options[0]);
+ success = objectDescription(name);
break;
case 'f':
- success = describeFunctions(options[0], show_verbose);
+ success = describeFunctions(name, show_verbose);
break;
case 'l':
success = do_lo_list();
break;
case 'o':
- success = describeOperators(options[0]);
+ success = describeOperators(name);
break;
case 'p':
- success = permissionsList(options[0]);
+ success = permissionsList(name);
break;
case 'T':
- success = describeTypes(options[0], show_verbose);
+ success = describeTypes(name, show_verbose);
break;
case 't':
case 'v':
@@ -397,11 +287,12 @@ exec_command(const char *cmd,
if (cmd[1] == 'S' && cmd[2] == '\0')
success = listTables("Stvs", NULL, show_verbose);
else
- success = listTables(&cmd[1], options[0], show_verbose);
+ success = listTables(&cmd[1], name, show_verbose);
break;
default:
status = CMD_UNKNOWN;
}
+ free(name);
}
@@ -410,46 +301,81 @@ exec_command(const char *cmd,
* the query buffer
*/
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
- status = do_edit(options[0], query_buf) ? CMD_NEWEDIT : CMD_ERROR;
+ {
+ char * fname;
+ if (!query_buf)
+ {
+ psql_error("no query buffer");
+ status = CMD_ERROR;
+ }
+ else
+ {
+ fname = scan_option(&string, OT_NORMAL, NULL);
+ status = do_edit(fname, query_buf) ? CMD_NEWEDIT : CMD_ERROR;
+ free(fname);
+ }
+ }
- /* \echo */
- else if (strcmp(cmd, "echo") == 0)
+ /* \echo and \qecho */
+ else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho")==0)
{
- int i;
+ char * value;
+ char quoted;
+ bool no_newline = false;
+ bool first = true;
+ FILE * fout;
+
+ if (strcmp(cmd, "qecho")==0)
+ fout = pset.queryFout;
+ else
+ fout = stdout;
- for (i = 0; i < 16 && options[i]; i++)
- fputs(options[i], stdout);
- fputs("\n", stdout);
+ while((value = scan_option(&string, OT_NORMAL, &quoted)))
+ {
+ if (!quoted && strcmp(value, "-n")==0)
+ no_newline = true;
+ else
+ {
+ if (first)
+ first = false;
+ else
+ fputc(' ', fout);
+ fputs(value, fout);
+ }
+ free(value);
+ }
+ if (!no_newline)
+ fputs("\n", fout);
}
/* \f -- change field separator */
else if (strcmp(cmd, "f") == 0)
- success = do_pset("fieldsep", options[0], &pset.popt, quiet);
+ {
+ char * fname = scan_option(&string, OT_NORMAL, NULL);
+ success = do_pset("fieldsep", fname, &pset.popt, quiet);
+ free(fname);
+ }
/* \g means send query */
else if (strcmp(cmd, "g") == 0)
{
- if (!options[0])
+ char * fname = scan_option(&string, OT_NORMAL, NULL);
+ if (!fname)
pset.gfname = NULL;
else
- pset.gfname = xstrdup(options[0]);
+ pset.gfname = xstrdup(fname);
+ free(fname);
status = CMD_SEND;
}
/* help */
else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
{
- char buf[256] = "";
- int i;
- for (i=0; options && options[i] && strlen(buf)<255; i++)
- {
- strncat(buf, options[i], 255 - strlen(buf));
- if (strlen(buf)<255 && options[i+1])
- strcat(buf, " ");
- }
- buf[255] = '\0';
- helpSQL(buf);
+ helpSQL(options_string ? &options_string[strspn(options_string, " \t")] : NULL);
+ /* set pointer to end of line */
+ if (string)
+ string += strlen(string);
}
/* HTML mode */
@@ -465,46 +391,55 @@ exec_command(const char *cmd,
/* \i is include file */
else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
{
- if (!options[0])
+ char * fname = scan_option(&string, OT_NORMAL, NULL);
+ if (!fname)
{
psql_error("\\%s: missing required argument\n", cmd);
success = false;
}
else
- success = process_file(options[0]);
+ {
+ success = process_file(fname);
+ free (fname);
+ }
}
-
/* \l is list databases */
else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
success = listAllDbs(false);
else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
success = listAllDbs(true);
-
- /* large object things */
+ /*
+ * large object things
+ */
else if (strncmp(cmd, "lo_", 3) == 0)
{
+ char *opt1, *opt2;
+
+ opt1 = scan_option(&string, OT_NORMAL, NULL);
+ opt2 = scan_option(&string, OT_NORMAL, NULL);
+
if (strcmp(cmd + 3, "export") == 0)
{
- if (!options[1])
+ if (!opt2)
{
psql_error("\\%s: missing required argument\n", cmd);
success = false;
}
else
- success = do_lo_export(options[0], options[1]);
+ success = do_lo_export(opt1, opt2);
}
else if (strcmp(cmd + 3, "import") == 0)
{
- if (!options[0])
+ if (!opt1)
{
psql_error("\\%s: missing required argument\n", cmd);
success = false;
}
else
- success = do_lo_import(options[0], options[1]);
+ success = do_lo_import(opt1, opt2);
}
else if (strcmp(cmd + 3, "list") == 0)
@@ -512,23 +447,30 @@ exec_command(const char *cmd,
else if (strcmp(cmd + 3, "unlink") == 0)
{
- if (!options[0])
+ if (!opt1)
{
psql_error("\\%s: missing required argument\n", cmd);
success = false;
}
else
- success = do_lo_unlink(options[0]);
+ success = do_lo_unlink(opt1);
}
else
status = CMD_UNKNOWN;
+
+ free(opt1);
+ free(opt2);
}
+
/* \o -- set query output */
else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
- success = setQFout(options[0]);
-
+ {
+ char * fname = scan_option(&string, OT_NORMAL, NULL);
+ success = setQFout(fname);
+ free(fname);
+ }
/* \p prints the current query buffer */
else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
@@ -543,29 +485,24 @@ exec_command(const char *cmd,
/* \pset -- set printing parameters */
else if (strcmp(cmd, "pset") == 0)
{
- if (!options[0])
+ char * opt0 = scan_option(&string, OT_NORMAL, NULL);
+ char * opt1 = scan_option(&string, OT_NORMAL, NULL);
+ if (!opt0)
{
psql_error("\\%s: missing required argument\n", cmd);
success = false;
}
else
- success = do_pset(options[0], options[1], &pset.popt, quiet);
+ success = do_pset(opt0, opt1, &pset.popt, quiet);
+
+ free(opt0);
+ free(opt1);
}
/* \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)
{
@@ -574,34 +511,31 @@ exec_command(const char *cmd,
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;
+ char *fname = scan_option(&string, OT_NORMAL, NULL);
- if (!options[0])
- fname = "/dev/tty";
- else
- fname = options[0];
-
- success = saveHistory(fname);
+ success = saveHistory(fname ? fname : "/dev/tty");
- if (success && !quiet && options[0])
+ if (success && !quiet && fname)
printf("Wrote history to %s.\n", fname);
+ free(fname);
}
-
- /* \set -- generalized set option command */
+ /* \set -- generalized set variable/option command */
else if (strcmp(cmd, "set") == 0)
{
- if (!options[0])
+ char * opt0 = scan_option(&string, OT_NORMAL, NULL);
+
+ if (!opt0)
{
/* list all variables */
/*
- * (This is in utter violation of the GetVariable abstraction,
- * but I have not dreamt up a better way.)
+ * XXX
+ * This is in utter violation of the GetVariable abstraction, but I
+ * have not bothered to do it better.
*/
struct _variable *ptr;
@@ -611,15 +545,36 @@ exec_command(const char *cmd,
}
else
{
- const char * val = options[1];
- if (!val)
- val = "";
- if (!SetVariable(pset.vars, options[0], val))
+ /*
+ * Set variable to the concatenation of the arguments.
+ */
+ char * newval = NULL;
+ char * opt;
+
+ opt = scan_option(&string, OT_NORMAL, NULL);
+ newval = xstrdup(opt ? opt : "");
+ free(opt);
+
+ while ((opt = scan_option(&string, OT_NORMAL, NULL)))
+ {
+ newval = realloc(newval, strlen(newval) + strlen(opt) + 1);
+ if (!newval)
+ {
+ psql_error("out of memory");
+ exit(EXIT_FAILURE);
+ }
+ strcat(newval, opt);
+ free(opt);
+ }
+
+ if (!SetVariable(pset.vars, opt0, newval))
{
psql_error("\\%s: error\n", cmd);
success = false;
}
+ free(newval);
}
+ free(opt0);
}
/* \t -- turn off headers and row count */
@@ -629,48 +584,67 @@ exec_command(const char *cmd,
/* \T -- define html <table ...> attributes */
else if (strcmp(cmd, "T") == 0)
- success = do_pset("tableattr", options[0], &pset.popt, quiet);
+ {
+ char * value = scan_option(&string, OT_NORMAL, NULL);
+ success = do_pset("tableattr", value, &pset.popt, quiet);
+ free(value);
+ }
/* \unset */
else if (strcmp(cmd, "unset") == 0)
{
- if (!SetVariable(pset.vars, options[0], NULL))
+ char * opt = scan_option(&string, OT_NORMAL, NULL);
+ if (!opt)
+ {
+ psql_error("\\%s: missing required argument", cmd);
+ success = false;
+ }
+ if (!SetVariable(pset.vars, opt, NULL))
{
psql_error("\\%s: error\n", cmd);
-
success = false;
- }
+ }
+ free(opt);
}
/* \w -- write query buffer to file */
else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
{
FILE *fd = NULL;
- bool pipe = false;
+ bool is_pipe = false;
+ char *fname = NULL;
- if (!options[0])
- {
- psql_error("\\%s: missing required argument\n", cmd);
- success = false;
- }
- else
- {
- if (options[0][0] == '|')
- {
- pipe = true;
- fd = popen(&options[0][1], "w");
- }
- else
- {
- fd = fopen(options[0], "w");
- }
+ if (!query_buf)
+ {
+ psql_error("no query buffer");
+ status = CMD_ERROR;
+ }
+ else
+ {
+ fname = scan_option(&string, OT_NORMAL, NULL);
- if (!fd)
- {
- psql_error("%s: %s\n", options[0], strerror(errno));
- success = false;
- }
- }
+ if (!fname)
+ {
+ psql_error("\\%s: missing required argument\n", cmd);
+ success = false;
+ }
+ else
+ {
+ if (fname[0] == '|')
+ {
+ is_pipe = true;
+ fd = popen(&fname[1], "w");
+ }
+ else
+ fd = fopen(fname, "w");
+
+ if (!fd)
+ {
+ psql_error("%s: %s\n", fname, strerror(errno));
+ success = false;
+ }
+ }
+ }
if (fd)
{
@@ -679,17 +653,19 @@ exec_command(const char *cmd,
if (query_buf && query_buf->len > 0)
fprintf(fd, "%s\n", query_buf->data);
- if (pipe)
+ if (is_pipe)
result = pclose(fd);
else
result = fclose(fd);
if (result == EOF)
{
- psql_error("%s: %s\n", options[0], strerror(errno));
+ psql_error("%s: %s\n", fname, strerror(errno));
success = false;
}
}
+
+ free(fname);
}
/* \x -- toggle expanded table representation */
@@ -697,30 +673,43 @@ exec_command(const char *cmd,
success = do_pset("expanded", NULL, &pset.popt, quiet);
- /* list table rights (grant/revoke) */
+ /* \z -- list table rights (grant/revoke) */
else if (strcmp(cmd, "z") == 0)
- success = permissionsList(options[0]);
-
+ {
+ char * opt = scan_option(&string, OT_SQLID, NULL);
+ success = permissionsList(opt);
+ free(opt);
+ }
+ /* \! -- shell escape */
else if (strcmp(cmd, "!") == 0)
+ {
success = do_shell(options_string);
+ /* wind pointer to end of line */
+ if (string)
+ string += strlen(string);
+ }
+ /* \? -- slash command help */
else if (strcmp(cmd, "?") == 0)
slashUsage();
-
-#if 0
+#if 1
/*
* 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;
+ int i = 0;
+ char *value;
- fprintf(stderr, "+ optline = |%s|\n", options_string);
- for (i = 0; options[i]; i++)
- fprintf(stderr, "+ opt%d = |%s|\n", i, options[i]);
+ fprintf(stderr, "+ optstr = |%s|\n", options_string);
+ while((value = scan_option(&string, OT_NORMAL, NULL)))
+ {
+ fprintf(stderr, "+ opt(%d) = |%s|\n", i++, value);
+ free(value);
+ }
}
#endif
@@ -729,23 +718,300 @@ exec_command(const char *cmd,
if (!success)
status = CMD_ERROR;
+
+ /* eat the rest of the options string */
+ while(scan_option(&string, OT_NORMAL, NULL)) ;
+
+ if (options_string && continue_parse)
+ *continue_parse = options_string + (string - string_cpy);
+ free(string_cpy);
+
return status;
}
/*
+ * scan_option()
+ */
+static char *
+scan_option(char ** string, enum option_type type, char * quote)
+{
+ unsigned int pos = 0;
+ char * options_string;
+ char * return_val;
+
+ if (quote)
+ *quote = 0;
+
+ if (!string || !(*string))
+ return NULL;
+
+ options_string = *string;
+ /* skip leading whitespace */
+ pos += strspn(options_string+pos, " \t");
+
+ switch (options_string[pos])
+ {
+ /*
+ * Double quoted string
+ */
+ case '"':
+ {
+ unsigned int jj;
+ unsigned short int bslash_count = 0;
+
+ /* scan for end of quote */
+ for (jj = pos+1; options_string[jj]; jj += PQmblen(&options_string[jj], pset.encoding))
+ {
+ if (options_string[jj] == '"' && bslash_count % 2 == 0)
+ break;
+
+ if (options_string[jj] == '\\')
+ bslash_count++;
+ else
+ bslash_count=0;
+ }
+
+ if (options_string[jj] == 0)
+ {
+ psql_error("parse error at end of line\n");
+ *string = &options_string[jj];
+ return NULL;
+ }
+
+ return_val = malloc(jj-pos+2);
+ if (!return_val)
+ {
+ psql_error("out of memory\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (type == OT_NORMAL)
+ {
+ strncpy(return_val, &options_string[pos], jj-pos+1);
+ return_val[jj-pos+1] = '\0';
+ }
+ /*
+ * If this is expected to be an SQL identifier like option
+ * then we strip out the double quotes
+ */
+ else if (type == OT_SQLID)
+ {
+ unsigned int k, cc;
+
+ bslash_count = 0;
+ cc = 0;
+ for (k = pos+1; options_string[k]; k += PQmblen(&options_string[k], pset.encoding))
+ {
+ if (options_string[k] == '"' && bslash_count % 2 == 0)
+ break;
+
+ if (options_string[jj] == '\\')
+ bslash_count++;
+ else
+ bslash_count=0;
+
+ return_val[cc++] = options_string[k];
+ }
+ return_val[cc] = '\0';
+ }
+
+ *string = options_string + jj+1;
+ if (quote)
+ *quote = '"';
+
+ return return_val;
+ }
+
+ /*
+ * A single quote has a psql internal meaning, such as
+ * for delimiting file names, and it also allows for such
+ * escape sequences as \t.
+ */
+ case '\'':
+ {
+ unsigned int jj;
+ unsigned short int bslash_count = 0;
+
+ for (jj = pos+1; options_string[jj]; jj += PQmblen(&options_string[jj], pset.encoding))
+ {
+ if (options_string[jj] == '\'' && bslash_count % 2 == 0)
+ break;
+
+ if (options_string[jj] == '\\')
+ bslash_count++;
+ else
+ bslash_count=0;
+ }
+
+ if (options_string[jj] == 0)
+ {
+ psql_error("parse error at end of line\n");
+ *string = &options_string[jj];
+ return NULL;
+ }
+
+ return_val = unescape(&options_string[pos+1], jj-pos-1);
+ *string = &options_string[jj + 1];
+ if (quote)
+ *quote = '\'';
+ return return_val;
+ }
+
+ /*
+ * Backticks are for command substitution, like in shells
+ */
+ case '`':
+ {
+ bool error = false;
+ FILE *fd = NULL;
+ char *file;
+ PQExpBufferData output;
+ char buf[512];
+ size_t result, len;
+
+ len = strcspn(options_string + pos + 1, "`");
+ if (options_string[pos + 1 + len] == 0)
+ {
+ psql_error("parse error at end of line\n");
+ *string = &options_string[pos + 1 + len];
+ return NULL;
+ }
+
+ options_string[pos + 1 + len] = '\0';
+ file = options_string + pos + 1;
+
+ fd = popen(file, "r");
+ if (!fd)
+ {
+ psql_error("%s: %s\n", file, strerror(errno));
+ error = true;
+ }
+
+ if (!error)
+ {
+ initPQExpBuffer(&output);
+
+ do
+ {
+ result = fread(buf, 1, 512, fd);
+ if (ferror(fd))
+ {
+ psql_error("%s: %s\n", file, strerror(errno));
+ error = true;
+ break;
+ }
+ appendBinaryPQExpBuffer(&output, buf, result);
+ } while (!feof(fd));
+ appendPQExpBufferChar(&output, '\0');
+
+ if (pclose(fd) == -1)
+ {
+ psql_error("%s: %s\n", file, strerror(errno));
+ error = true;
+ }
+ }
+
+ if (!error)
+ {
+ if (output.data[strlen(output.data) - 1] == '\n')
+ output.data[strlen(output.data) - 1] = '\0';
+ }
+
+ if (!error)
+ return_val = output.data;
+ else
+ {
+ return_val = xstrdup("");
+ termPQExpBuffer(&output);
+ }
+ options_string[pos + 1 + len] = '`';
+ *string = options_string + pos + len + 2;
+ if (quote)
+ *quote = '`';
+ return return_val;
+ }
+
+ /*
+ * end of line
+ */
+ case 0:
+ *string = &options_string[pos];
+ return NULL;
+
+ /*
+ * Variable substitution
+ */
+ case ':':
+ {
+ size_t token_end;
+ const char * value;
+ char save_char;
+
+ token_end = strcspn(&options_string[pos+1], " \t");
+ save_char = options_string[pos+token_end+1];
+ options_string[pos+token_end+1] = '\0';
+ value = GetVariable(pset.vars, options_string+pos+1);
+ if (!value)
+ value = "";
+ return_val = xstrdup(value);
+ options_string[pos+token_end+1] = save_char;
+ *string = &options_string[pos + token_end+1];
+ return return_val;
+ }
+
+ /*
+ * Next command
+ */
+ case '\\':
+ *string = options_string + pos;
+ return NULL;
+ break;
+
+ /*
+ * A normal word
+ */
+ default:
+ {
+ size_t token_end;
+ char * cp;
+
+ token_end = strcspn(&options_string[pos], " \t");
+ return_val = malloc(token_end + 1);
+ if (!return_val)
+ {
+ psql_error("out of memory\n");
+ exit(EXIT_FAILURE);
+ }
+ strncpy(return_val, &options_string[pos], token_end);
+ return_val[token_end] = 0;
+
+ if (type == OT_SQLID)
+ for (cp = return_val; *cp; cp += PQmblen(cp, pset.encoding))
+ if (isascii(*cp))
+ *cp = tolower(*cp);
+
+ *string = &options_string[pos+token_end];
+ return return_val;
+ }
+
+ }
+}
+
+
+
+/*
* unescape
*
* Replaces \n, \t, and the like.
- * Also interpolates ${variables}.
*
* The return value is malloc()'ed.
*/
static char *
-unescape(const char *source)
+unescape(const unsigned char *source, size_t len)
{
- unsigned char *p;
+ const unsigned char *p;
bool esc = false; /* Last character we saw was the escape
* character */
char *destination,
@@ -756,16 +1022,16 @@ unescape(const char *source)
assert(source);
#endif
- length = strlen(source) + 1;
+ length = Min(len, strlen(source)) + 1;
- tmp = destination = (char *) malloc(length);
+ tmp = destination = malloc(length);
if (!tmp)
{
psql_error("out of memory\n");
exit(EXIT_FAILURE);
}
- for (p = (char *) source; *p; p += PQmblen(p, pset.encoding))
+ for (p = source; p-source < len && *p; p += PQmblen(p, pset.encoding))
{
if (esc)
{
@@ -776,12 +1042,15 @@ unescape(const char *source)
case 'n':
c = '\n';
break;
- case 'r':
- c = '\r';
- break;
case 't':
c = '\t';
break;
+ case 'b':
+ c = '\b';
+ break;
+ case 'r':
+ c = '\r';
+ break;
case 'f':
c = '\f';
break;
@@ -814,44 +1083,6 @@ unescape(const char *source)
else if (*p == '\\')
esc = true;
- else if (*p == '$')
- {
- if (*(p + 1) == '{')
- {
- unsigned int len;
- char *copy;
- const char *value;
-#ifndef WIN32
- void *new;
-#else
- char *new;
-#endif
-
- len = strcspn(p + 2, "}");
- copy = xstrdup(p + 2);
- copy[len] = '\0';
- value = GetVariable(pset.vars, copy);
- if (!value)
- value = "";
- length += strlen(value) - (len + 3);
- new = realloc(destination, length);
- if (!new)
- {
- psql_error("out of memory\n");
- exit(EXIT_FAILURE);
- }
- tmp = new + (tmp - destination);
- destination = new;
-
- strcpy(tmp, value);
- tmp += strlen(value);
- p += len + 2;
- free(copy);
- }
- else
- *tmp++ = '$';
- }
-
else
{
*tmp++ = *p;
@@ -865,7 +1096,6 @@ unescape(const char *source)
-
/* do_connect
* -- handler for \connect
*
@@ -893,8 +1123,8 @@ do_connect(const char *new_dbname, const char *new_user)
SetVariable(pset.vars, "HOST", NULL);
SetVariable(pset.vars, "PORT", NULL);
- /* If dbname is "-" then use old name, else new one (even if NULL) */
- if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "-") == 0)
+ /* If dbname is "" then use old name, else new one (even if NULL) */
+ if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "") == 0)
dbparam = PQdb(oldconn);
else
dbparam = new_dbname;
@@ -1001,7 +1231,7 @@ do_connect(const char *new_dbname, const char *new_user)
/*
* Test if the given user is a database superuser.
- * (Used to set up the prompt right.)
+ * (Is used to set up the prompt right.)
*/
bool
test_superuser(const char * username)
@@ -1037,7 +1267,7 @@ test_superuser(const char * username)
static bool
editFile(const char *fname)
{
- char *editorName;
+ const char *editorName;
char *sys;
int result;
@@ -1063,7 +1293,7 @@ editFile(const char *fname)
sprintf(sys, "exec %s %s", editorName, fname);
result = system(sys);
if (result == -1)
- psql_error("could not start editor\n");
+ psql_error("could not start editor %s\n", editorName);
else if (result == 127)
psql_error("could not start /bin/sh\n");
free(sys);
@@ -1087,14 +1317,6 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
#endif
-#ifdef USE_ASSERT_CHECKING
- assert(query_buf);
-#else
- if (!query_buf)
- return false;
-#endif
-
-
if (filename_arg)
fname = filename_arg;
@@ -1233,11 +1455,7 @@ process_file(char *filename)
if (!filename)
return false;
-#ifdef __CYGWIN32__
- fd = fopen(filename, "rb");
-#else
fd = fopen(filename, "r");
-#endif
if (!fd)
{
@@ -1454,7 +1672,7 @@ do_pset(const char *param, const char *value, printQueryOpt * popt, bool quiet)
-#define DEFAULT_SHELL "/bin/sh"
+#define DEFAULT_SHELL "/bin/sh"
static bool
do_shell(const char *command)
@@ -1464,7 +1682,7 @@ do_shell(const char *command)
if (!command)
{
char *sys;
- char *shellName;
+ const char *shellName;
shellName = getenv("SHELL");
if (shellName == NULL)
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 700542cd4d1..084d8790e6f 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.11 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.12 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
#include "common.h"
@@ -24,6 +24,7 @@
#include <unistd.h> /* for write() */
#else
#include <io.h> /* for _write() */
+#include <win32.h>
#endif
#include <libpq-fe.h>
@@ -37,18 +38,10 @@
#include "prompt.h"
#include "print.h"
-#ifdef WIN32
-#define popen(x,y) _popen(x,y)
-#define pclose(x) _pclose(x)
-#define write(a,b,c) _write(a,b,c)
-#endif
-
-/* xstrdup()
- *
+/*
* "Safe" wrapper around strdup()
- * (Using this also avoids writing #ifdef HAVE_STRDUP in every file :)
*/
char *
xstrdup(const char *string)
@@ -57,7 +50,8 @@ xstrdup(const char *string)
if (!string)
{
- fprintf(stderr, "%s: xstrdup: cannot duplicate null pointer\n", pset.progname);
+ fprintf(stderr, "%s: xstrdup: cannot duplicate null pointer (internal error)\n",
+ pset.progname);
exit(EXIT_FAILURE);
}
tmp = strdup(string);
@@ -133,7 +127,7 @@ setQFout(const char *fname)
/*
* Error reporting for scripts. Errors should look like
- * filename:lineno: message
+ * psql:filename:lineno: message
*
*/
void
@@ -152,8 +146,11 @@ psql_error(const char *fmt, ...)
va_end(ap);
}
-/* for backend NOTICES */
+
+/*
+ * for backend NOTICES
+ */
void
NoticeProcessor(void * arg, const char * message)
{
@@ -184,7 +181,6 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
#ifdef HAVE_TERMIOS_H
struct termios t_orig,
t;
-
#endif
destination = (char *) malloc(maxlen + 2);
@@ -240,8 +236,8 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
* Before we start a query, 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 because PQrequestCancel() is written to make it
- * so. We have to be very careful what else we do in the signal handler. This
- * includes using write() for output.
+ * so. We use write() to print to stdout because it's better to use simple
+ * facilities in a signal handler.
*/
static PGconn *cancelConn;
diff --git a/src/bin/psql/create_help.pl b/src/bin/psql/create_help.pl
index f802d5ed791..638b96600f8 100644
--- a/src/bin/psql/create_help.pl
+++ b/src/bin/psql/create_help.pl
@@ -5,7 +5,7 @@
#
# Copyright 2000 by PostgreSQL Global Development Group
#
-# $Header: /cvsroot/pgsql/src/bin/psql/create_help.pl,v 1.3 2000/01/29 16:58:48 petere Exp $
+# $Header: /cvsroot/pgsql/src/bin/psql/create_help.pl,v 1.4 2000/02/07 23:10:06 petere Exp $
#################################################################
#
@@ -56,6 +56,8 @@ struct _helpStruct
static struct _helpStruct QL_HELP[] = {
";
+$count = 0;
+
foreach $file (sort readdir DIR) {
my ($cmdname, $cmddesc, $cmdsynopsis);
$file =~ /\.sgml$/ || next;
@@ -84,6 +86,7 @@ foreach $file (sort readdir DIR) {
$cmdsynopsis =~ s/\"/\\"/g;
print OUT " { \"$cmdname\",\n \"$cmddesc\",\n \"$cmdsynopsis\" },\n\n";
+ $count++;
}
else {
print STDERR "$0: parsing file '$file' failed at or near line $. (N='$cmdname' D='$cmddesc')\n";
@@ -94,6 +97,10 @@ print OUT "
{ NULL, NULL, NULL } /* End of list marker */
};
+
+#define QL_HELP_COUNT $count
+
+
#endif /* $define */
";
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index bb259b31d37..6ab7c2f519e 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.15 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.16 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
#include "describe.h"
@@ -56,7 +56,7 @@ describeAggregates(const char *name)
if (name)
{
- strcat(buf, " AND a.aggname ~* '");
+ strcat(buf, " AND a.aggname ~* '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -71,7 +71,7 @@ describeAggregates(const char *name)
if (name)
{
- strcat(buf, " AND a.aggname ~* '");
+ strcat(buf, " AND a.aggname ~* '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -125,7 +125,7 @@ describeFunctions(const char *name, bool verbose)
if (name)
{
- strcat(buf, " AND p.proname ~* '");
+ strcat(buf, " AND p.proname ~* '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -169,7 +169,7 @@ describeTypes(const char *name, bool verbose)
if (name)
{
- strcat(buf, " AND t.typname ~* '");
+ strcat(buf, " AND t.typname ~* '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "' ");
}
@@ -215,7 +215,7 @@ describeOperators(const char *name)
" o.oprright = t2.oid\n");
if (name)
{
- strcat(buf, " AND o.oprname ~ '");
+ strcat(buf, " AND o.oprname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -233,7 +233,7 @@ describeOperators(const char *name)
" o.oprright = t1.oid\n");
if (name)
{
- strcat(buf, "AND o.oprname ~ '");
+ strcat(buf, "AND o.oprname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -251,7 +251,7 @@ describeOperators(const char *name)
" o.oprleft = t1.oid\n");
if (name)
{
- strcat(buf, "AND o.oprname ~ '");
+ strcat(buf, "AND o.oprname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -346,7 +346,7 @@ permissionsList(const char *name)
" relname !~ '^pg_'\n");
if (name)
{
- strcat(descbuf, " AND relname ~ '");
+ strcat(descbuf, " AND relname ~ '^");
strncat(descbuf, name, REGEXP_CUTOFF);
strcat(descbuf, "'\n");
}
@@ -391,7 +391,7 @@ objectDescription(const char *object)
"WHERE a.oid = d.objoid\n");
if (object)
{
- strcat(descbuf, " AND a.aggname ~* '");
+ strcat(descbuf, " AND a.aggname ~* '^");
strncat(descbuf, object, REGEXP_CUTOFF);
strcat(descbuf, "'\n");
}
@@ -403,7 +403,7 @@ objectDescription(const char *object)
"WHERE p.oid = d.objoid AND (p.pronargs = 0 or oidvectortypes(p.proargtypes) != '')\n");
if (object)
{
- strcat(descbuf, " AND p.proname ~* '");
+ strcat(descbuf, " AND p.proname ~* '^");
strncat(descbuf, object, REGEXP_CUTOFF);
strcat(descbuf, "'\n");
}
@@ -416,7 +416,7 @@ objectDescription(const char *object)
"WHERE RegprocToOid(o.oprcode) = d.objoid\n");
if (object)
{
- strcat(descbuf, " AND o.oprname ~ '");
+ strcat(descbuf, " AND o.oprname ~ '^");
strncat(descbuf, object, REGEXP_CUTOFF);
strcat(descbuf, "'\n");
}
@@ -428,7 +428,7 @@ objectDescription(const char *object)
"WHERE t.oid = d.objoid\n");
if (object)
{
- strcat(descbuf, " AND t.typname ~* '");
+ strcat(descbuf, " AND t.typname ~* '^");
strncat(descbuf, object, REGEXP_CUTOFF);
strcat(descbuf, "'\n");
}
@@ -440,7 +440,7 @@ objectDescription(const char *object)
"WHERE c.oid = d.objoid\n");
if (object)
{
- strcat(descbuf, " AND c.relname ~* '");
+ strcat(descbuf, " AND c.relname ~* '^");
strncat(descbuf, object, REGEXP_CUTOFF);
strcat(descbuf, "'\n");
}
@@ -452,7 +452,7 @@ objectDescription(const char *object)
"WHERE r.oid = d.objoid AND r.rulename !~ '^_RET'\n");
if (object)
{
- strcat(descbuf, " AND r.rulename ~* '");
+ strcat(descbuf, " AND r.rulename ~* '^");
strncat(descbuf, object, REGEXP_CUTOFF);
strcat(descbuf, "'\n");
}
@@ -464,7 +464,7 @@ objectDescription(const char *object)
"WHERE t.oid = d.objoid\n");
if (object)
{
- strcat(descbuf, " AND t.tgname ~* '");
+ strcat(descbuf, " AND t.tgname ~* '^");
strncat(descbuf, object, REGEXP_CUTOFF);
strcat(descbuf, "'\n");
}
@@ -504,7 +504,7 @@ xmalloc(size_t size)
tmp = malloc(size);
if (!tmp)
{
- psql_error("out of memory");
+ psql_error("out of memory\n");
exit(EXIT_FAILURE);
}
return tmp;
@@ -626,7 +626,7 @@ describeTableDetails(const char *name, bool desc)
bool isarray = false;
/* Name */
- cells[i * cols + 0] = (char *)PQgetvalue(res, i, 0); /* don't free this afterwards */
+ cells[i * cols + 0] = PQgetvalue(res, i, 0); /* don't free this afterwards */
/* Type */
if (attype[0] == '_')
@@ -701,7 +701,7 @@ describeTableDetails(const char *name, bool desc)
/* Description */
if (desc)
- cells[i * cols + cols-1] = (char*)PQgetvalue(res, i, 7);
+ cells[i * cols + cols-1] = PQgetvalue(res, i, 7);
}
/* Make title */
@@ -960,7 +960,7 @@ listTables(const char *infotype, const char *name, bool desc)
strcat(buf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
if (name)
{
- strcat(buf, " AND c.relname ~ '");
+ strcat(buf, " AND c.relname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -976,7 +976,7 @@ listTables(const char *infotype, const char *name, bool desc)
strcat(buf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
if (name)
{
- strcat(buf, " AND c.relname ~ '");
+ strcat(buf, " AND c.relname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -997,7 +997,7 @@ listTables(const char *infotype, const char *name, bool desc)
strcat(buf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
if (name)
{
- strcat(buf, " AND c.relname ~ '");
+ strcat(buf, " AND c.relname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -1013,7 +1013,7 @@ listTables(const char *infotype, const char *name, bool desc)
strcat(buf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
if (name)
{
- strcat(buf, " AND c.relname ~ '");
+ strcat(buf, " AND c.relname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -1049,7 +1049,7 @@ listTables(const char *infotype, const char *name, bool desc)
strcat(buf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
if (name)
{
- strcat(buf, " AND c.relname ~ '");
+ strcat(buf, " AND c.relname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -1079,7 +1079,7 @@ listTables(const char *infotype, const char *name, bool desc)
strcat(buf, showSystem ? " AND c.relname ~ '^pg_'\n" : " AND c.relname !~ '^pg_'\n");
if (name)
{
- strcat(buf, " AND c.relname ~ '");
+ strcat(buf, " AND c.relname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -1098,7 +1098,7 @@ listTables(const char *infotype, const char *name, bool desc)
"WHERE c.relowner = u.usesysid AND c.relkind = 's'\n");
if (name)
{
- strcat(buf, " AND c.relname ~ '");
+ strcat(buf, " AND c.relname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -1112,7 +1112,7 @@ listTables(const char *infotype, const char *name, bool desc)
" AND not exists (select 1 from pg_user where usesysid = c.relowner)");
if (name)
{
- strcat(buf, " AND c.relname ~ '");
+ strcat(buf, " AND c.relname ~ '^");
strncat(buf, name, REGEXP_CUTOFF);
strcat(buf, "'\n");
}
@@ -1127,10 +1127,10 @@ listTables(const char *infotype, const char *name, bool desc)
if (PQntuples(res) == 0 && !QUIET())
{
- if (name)
- fprintf(pset.queryFout, "No matching relations found.\n");
- else
- fprintf(pset.queryFout, "No relations found.\n");
+ if (name)
+ fprintf(pset.queryFout, "No matching relations found.\n");
+ else
+ fprintf(pset.queryFout, "No relations found.\n");
}
else
{
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 70100c7791f..261f1344203 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/help.c,v 1.15 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/help.c,v 1.16 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
#include "help.h"
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
+#include <errno.h>
#ifndef WIN32
#include <sys/ioctl.h> /* for ioctl() */
@@ -20,9 +21,7 @@
#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)
-#define pclose(x) _pclose(x)
+#include <win32.h>
#endif
#include <pqsignal.h>
@@ -48,7 +47,6 @@ usage(void)
#ifndef WIN32
struct passwd *pw = NULL;
-
#endif
/* Find default user, in case we need it. */
@@ -61,7 +59,7 @@ usage(void)
user = pw->pw_name;
else
{
- perror("getpwuid()");
+ psql_error("could not get current user name: %s", strerror(errno));
exit(EXIT_FAILURE);
}
#else
@@ -70,10 +68,11 @@ usage(void)
}
/* If this " is the start of the string then it ought to end there to fit in 80 columns >> " */
- puts( "This is psql, the PostgreSQL interactive terminal.");
- puts( "\nUsage:");
- puts( " psql [options] [dbname [username]]");
- puts( "\nOptions:");
+ puts( "This is psql, the PostgreSQL interactive terminal.\n");
+ puts( "Usage:");
+ puts( " psql [options] [dbname [username]]\n");
+ puts( "Options:");
+/* puts( " -a Echo all input from script");*/
puts( " -A Unaligned table output mode (-P format=unaligned)");
puts( " -c <query> Run only single query (or slash command) and exit");
@@ -83,7 +82,7 @@ usage(void)
env = user;
printf(" -d <dbname> Specify database name to connect to (default: %s)\n", env);
- puts( " -e Echo all input in non-interactive mode");
+ puts( " -e Echo queries sent to backend");
puts( " -E Display queries that internal commands generate");
puts( " -f <filename> Execute queries from file, then exit");
puts( " -F <string> Set field separator (default: \"" DEFAULT_FIELD_SEP "\") (-P fieldsep=)");
@@ -99,7 +98,6 @@ usage(void)
puts( " -H HTML table output mode (-P format=html)");
puts( " -l List available databases, then exit");
- puts( " -n Do not use readline or history");
puts( " -o <filename> Send query output to filename (or |pipe)");
/* Display default port */
@@ -109,6 +107,7 @@ usage(void)
puts( " -P var[=arg] Set printing option 'var' to 'arg' (see \\pset command)");
puts( " -q Run quietly (no messages, only query output)");
+ puts( " -R <string> Set record separator (default: newline) (-P recordsep=)");
puts( " -s Single step mode (confirm each query)");
puts( " -S Single line mode (newline terminates query)");
puts( " -t Don't print headings and row count (-P tuples_only)");
@@ -118,7 +117,7 @@ usage(void)
env = getenv("PGUSER");
if (!env)
env = user;
- printf(" -U <username> Specifiy username, \"?\"=prompt (default user: %s)\n", env);
+ printf(" -U <username> Specify database username (default: %s)\n", env);
puts( " -x Turn on expanded table output (-P expanded)");
puts( " -v name=val Set psql variable 'name' to 'value'");
@@ -190,10 +189,9 @@ slashUsage(void)
fout = stdout;
/* if you add/remove a line here, change the row test above */
- fprintf(fout, " \\? help\n");
- fprintf(fout, " \\c[onnect] [dbname|- [user|?]]\n"
+ fprintf(fout, " \\c[onnect] [dbname|- [user]]\n"
" connect to new database (currently '%s')\n", PQdb(pset.db));
- fprintf(fout, " \\copy ... perform SQL COPY with data stream to the client machine");
+ fprintf(fout, " \\copy ... perform SQL COPY with data stream to the client machine\n");
fprintf(fout, " \\copyright show PostgreSQL usage and distribution terms\n");
fprintf(fout, " \\d <table> describe table (or view, index, sequence)\n");
fprintf(fout, " \\d{i|s|t|v|S} list only indices/sequences/tables/views/system tables\n");
@@ -209,10 +207,11 @@ slashUsage(void)
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\n"
- " large object operations\n");
+ " large object operations\n");
fprintf(fout, " \\o [fname] send all query results to <fname>, or |pipe\n");
fprintf(fout, " \\p show the content of the current query buffer\n");
- fprintf(fout, " \\pset [opt] set table output options\n");
+ fprintf(fout, " \\pset {format|border|expanded|fieldsep|recordsep|tuples_only|title|tableattr\n"
+ " |pager} set table output options\n");
fprintf(fout, " \\q quit psql\n");
fprintf(fout, " \\qecho <text> write text to query output stream (see \\o)\n");
fprintf(fout, " \\r reset (clear) the query buffer\n");
@@ -243,36 +242,24 @@ slashUsage(void)
void
helpSQL(const char *topic)
{
+#define VALUE_OR_NULL(a) ((a) ? (a) : "")
+
if (!topic || strlen(topic) == 0)
{
- char left_center_right; /* Which column we're displaying */
- int i; /* Index into QL_HELP[] */
+ int i;
+ int items_per_column = (QL_HELP_COUNT + 2)/3;
puts("Available help:");
- left_center_right = 'L';/* Start with left column */
- i = 0;
- while (QL_HELP[i].cmd != NULL)
+ for (i = 0; i < items_per_column; i++)
{
- 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++;
+ printf(" %-25s%-25s%-25s\n",
+ VALUE_OR_NULL(QL_HELP[i].cmd),
+ VALUE_OR_NULL(QL_HELP[i + items_per_column].cmd),
+ VALUE_OR_NULL(QL_HELP[i + 2*items_per_column].cmd)
+ );
}
- if (left_center_right != 'L')
- puts("\n");
+ putc('\n', stdout);
}
else
@@ -286,8 +273,10 @@ helpSQL(const char *topic)
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);
+ printf("Command: %s\n"
+ "Description: %s\n"
+ "Syntax:\n%s\n\n",
+ QL_HELP[i].cmd, QL_HELP[i].help, QL_HELP[i].syntax);
}
}
@@ -298,28 +287,28 @@ helpSQL(const char *topic)
-
void
print_copyright(void)
{
puts(
- "PostgreSQL Data Base Management System\n\n"
- "Portions Copyright (c) 1996-2000, PostgreSQL, Inc\n\n"
- "This software is based on Postgres95, formerly known as Postgres, which\n"
- "contains the following notice:\n\n"
- "Portions Copyright(c) 1994 - 7 Regents of the University of California\n\n"
- "Permission to use, copy, modify, and distribute this software and its\n"
- "documentation for any purpose, without fee, and without a written agreement\n"
- "is hereby granted, provided that the above copyright notice and this paragraph\n"
- "and the following two paragraphs appear in all copies.\n\n"
- "IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\n"
- "DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST\n"
- "PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF\n"
- "THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\n"
- "DAMAGE.\n\n"
- "THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\n"
- "BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n"
- "PARTICULAR PURPOSE.THE SOFTWARE PROVIDED HEREUNDER IS ON AN \"AS IS\" BASIS,\n"
- "AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,\n"
- "SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.");
+ "PostgreSQL Data Base Management System\n\n"
+ "Portions Copyright (c) 1996-2000, PostgreSQL, Inc\n\n"
+ "This software is based on Postgres95, formerly known as Postgres, which\n"
+ "contains the following notice:\n\n"
+ "Portions Copyright(c) 1994 - 7 Regents of the University of California\n\n"
+ "Permission to use, copy, modify, and distribute this software and its\n"
+ "documentation for any purpose, without fee, and without a written agreement\n"
+ "is hereby granted, provided that the above copyright notice and this paragraph\n"
+ "and the following two paragraphs appear in all copies.\n\n"
+ "IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\n"
+ "DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST\n"
+ "PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF\n"
+ "THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\n"
+ "DAMAGE.\n\n"
+ "THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,\n"
+ "BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n"
+ "PARTICULAR PURPOSE.THE SOFTWARE PROVIDED HEREUNDER IS ON AN \"AS IS\" BASIS,\n"
+ "AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,\n"
+ "SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ );
}
diff --git a/src/bin/psql/input.c b/src/bin/psql/input.c
index 2adff9d3422..560d5b2c382 100644
--- a/src/bin/psql/input.c
+++ b/src/bin/psql/input.c
@@ -3,15 +3,18 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.8 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.9 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
#include "input.h"
+#include <errno.h>
+
#include <pqexpbuffer.h>
#include "settings.h"
#include "tab-complete.h"
+#include "common.h"
/* Runtime options for turning off readline and history */
/* (of course there is no runtime command for doing that :) */
@@ -32,7 +35,7 @@ static bool useHistory;
* The result is malloced.
*/
char *
-gets_interactive(const char *prompt)
+gets_interactive(char *prompt)
{
char *s;
#ifdef USE_HISTORY
@@ -42,7 +45,7 @@ gets_interactive(const char *prompt)
#ifdef USE_READLINE
if (useReadline)
- s = readline((char *) prompt);
+ s = readline(prompt);
else
{
#endif
@@ -120,7 +123,6 @@ initializeInput(int flags)
if (flags == 1)
{
useReadline = true;
- rl_readline_name = "psql";
initialize_readline();
}
#endif
@@ -152,14 +154,14 @@ initializeInput(int flags)
bool
-saveHistory(const char *fname)
+saveHistory(char *fname)
{
#ifdef USE_HISTORY
- if (useHistory)
+ if (useHistory && fname)
{
- if (write_history((char *) fname) != 0)
+ if (write_history(fname) != 0)
{
- perror(fname);
+ psql_error("could not save history to %s: %s", fname, strerror(errno));
return false;
}
return true;
diff --git a/src/bin/psql/input.h b/src/bin/psql/input.h
index 6e078cbfbea..d12b45bfa30 100644
--- a/src/bin/psql/input.h
+++ b/src/bin/psql/input.h
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/input.h,v 1.6 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/input.h,v 1.7 2000/02/07 23:10:06 petere Exp $
*/
#ifndef INPUT_H
#define INPUT_H
@@ -37,11 +37,11 @@
# endif
#endif
-char * gets_interactive(const char *prompt);
+char * gets_interactive(char *prompt);
char * gets_fromFile(FILE *source);
void initializeInput(int flags);
-bool saveHistory(const char *fname);
+bool saveHistory(char *fname);
void finishInput(void);
#endif /* INPUT_H */
diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c
index 164956fded9..add2f77cfc1 100644
--- a/src/bin/psql/large_obj.c
+++ b/src/bin/psql/large_obj.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.7 2000/01/29 16:58:48 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.8 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
#include "large_obj.h"
@@ -113,7 +113,7 @@ do_lo_export(const char *loid_arg, const char *filename_arg)
PQclear(res);
}
- status = lo_export(pset.db, atol(loid_arg), (char *) filename_arg);
+ status = lo_export(pset.db, atol(loid_arg), filename_arg);
if (status != 1)
{ /* of course this status is documented
* nowhere :( */
@@ -182,7 +182,7 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
PQclear(res);
}
- loid = lo_import(pset.db, (char *) filename_arg);
+ loid = lo_import(pset.db, filename_arg);
if (loid == InvalidOid)
{
fputs(PQerrorMessage(pset.db), stderr);
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index cf07b42d31f..325a6b5ed85 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.16 2000/01/24 19:34:17 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.17 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
#include "mainloop.h"
@@ -47,10 +47,10 @@ MainLoop(FILE *source)
bool xcomment; /* in extended comment */
int paren_level;
unsigned int query_start;
- int count_eof;
+ int count_eof = 0;
const char *var;
bool was_bslash;
- unsigned int bslash_count;
+ unsigned int bslash_count = 0;
int i,
prevlen,
@@ -123,6 +123,8 @@ MainLoop(FILE *source)
prompt_status = PROMPT_DOUBLEQUOTE;
else if (xcomment)
prompt_status = PROMPT_COMMENT;
+ else if (paren_level)
+ prompt_status = PROMPT_PAREN;
else if (query_buf->len > 0)
prompt_status = PROMPT_CONTINUE;
else
@@ -251,7 +253,7 @@ MainLoop(FILE *source)
}
/* start of quote */
- else if (line[i] == '\'' || line[i] == '"')
+ else if (!was_bslash && (line[i] == '\'' || line[i] == '"'))
in_quote = line[i];
/* in extended comment? */
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 3ff0d27c227..44faad5850f 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/print.c,v 1.9 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/print.c,v 1.10 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
#include "print.h"
@@ -266,7 +266,9 @@ print_aligned_text(const char *title, const char * const * headers,
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), "");
+ 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)
{
diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c
index a06a712e401..1149fd65abc 100644
--- a/src/bin/psql/prompt.c
+++ b/src/bin/psql/prompt.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.7 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.8 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
#include "prompt.h"
@@ -19,8 +19,8 @@
#include "variables.h"
#ifdef WIN32
-#define popen(x,y) _popen(x,y)
-#define pclose(x) _pclose(x)
+#include <io.h>
+#include <win32.h>
#endif
@@ -53,14 +53,14 @@
*
* %`command` - The result of executing command in /bin/sh with trailing
* newline stripped.
- * %$name$ - The value of the psql variable 'name'
+ * %:name: - The value of the psql variable 'name'
* (those will not be rescanned for more escape sequences!)
*
* If the application-wide prompts became NULL somehow, the returned string
* will be empty (not NULL!).
*--------------------------
*/
-const char *
+char *
get_prompt(promptStatus_t status)
{
#define MAX_PROMPT_SIZE 256
@@ -72,7 +72,7 @@ get_prompt(promptStatus_t status)
if (status == PROMPT_READY)
prompt_string = GetVariable(pset.vars, "PROMPT1");
- else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT)
+ else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT || status == PROMPT_PAREN)
prompt_string = GetVariable(pset.vars, "PROMPT2");
else if (status == PROMPT_COPY)
prompt_string = GetVariable(pset.vars, "PROMPT3");
@@ -183,6 +183,9 @@ get_prompt(promptStatus_t status)
case PROMPT_COMMENT:
buf[0] = '*';
break;
+ case PROMPT_PAREN:
+ buf[0] = '(';
+ break;
default:
buf[0] = '\0';
break;
@@ -226,14 +229,14 @@ get_prompt(promptStatus_t status)
}
/* interpolate variable */
- case '$':
+ case ':':
{
char *name;
const char *val;
int nameend;
name = strdup(p + 1);
- nameend = strcspn(name, "$");
+ nameend = strcspn(name, ":");
name[nameend] = '\0';
val = GetVariable(pset.vars, name);
if (val)
diff --git a/src/bin/psql/prompt.h b/src/bin/psql/prompt.h
index f70a334a54d..61b4b9f543a 100644
--- a/src/bin/psql/prompt.h
+++ b/src/bin/psql/prompt.h
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/prompt.h,v 1.5 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/prompt.h,v 1.6 2000/02/07 23:10:06 petere Exp $
*/
#ifndef PROMPT_H
#define PROMPT_H
@@ -17,9 +17,10 @@ typedef enum _promptStatus
PROMPT_COMMENT,
PROMPT_SINGLEQUOTE,
PROMPT_DOUBLEQUOTE,
+ PROMPT_PAREN,
PROMPT_COPY
} promptStatus_t;
-const char *get_prompt(promptStatus_t status);
+char *get_prompt(promptStatus_t status);
#endif /* PROMPT_H */
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 478356deb55..fa6e9fbf202 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -3,53 +3,48 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.21 2000/02/05 12:27:56 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.22 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
-#include <signal.h>
-#include <errno.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
-#include <assert.h>
-#ifdef WIN32
+#ifndef WIN32
+#include <unistd.h>
+#else /* WIN32 */
#include <io.h>
#include <windows.h>
-#else
-#include <unistd.h>
-#endif
+#include <win32.h>
+#endif /* WIN32 */
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <libpq-fe.h>
-#include <pqsignal.h>
#include <version.h>
-#include "settings.h"
#include "command.h"
-#include "help.h"
-#include "mainloop.h"
#include "common.h"
+#include "describe.h"
+#include "help.h"
#include "input.h"
-#include "variables.h"
+#include "mainloop.h"
#include "print.h"
-#include "describe.h"
+#include "settings.h"
+#include "variables.h"
+/*
+ * Global psql options
+ */
PsqlSettings pset;
-static void
-process_psqlrc(void);
-static void
-showVersion(void);
-
-
-/* Structures to pass information between the option parsing routine
+/*
+ * Structures to pass information between the option parsing routine
* and the main function
*/
enum _actions
@@ -75,15 +70,21 @@ struct adhoc_opts
static void
parse_options(int argc, char *argv[], struct adhoc_opts * options);
+static void
+process_psqlrc(void);
+
+static void
+showVersion(void);
+
/*
*
- * main()
+ * main
*
*/
int
-main(int argc, char **argv)
+main(int argc, char *argv[])
{
struct adhoc_opts options;
int successResult;
@@ -92,8 +93,6 @@ main(int argc, char **argv)
char *password = NULL;
bool need_pass;
- memset(&pset, 0, sizeof pset);
-
if (!strrchr(argv[0], SEP_CHAR))
pset.progname = argv[0];
else
@@ -104,21 +103,21 @@ main(int argc, char **argv)
pset.encoding = PQenv2encoding();
pset.vars = CreateVariableSpace();
+ if (!pset.vars)
+ {
+ fprintf(stderr, "%s: out of memory\n", pset.progname);
+ exit(EXIT_FAILURE);
+ }
pset.popt.topt.format = PRINT_ALIGNED;
pset.queryFout = stdout;
- pset.popt.topt.fieldSep = xstrdup(DEFAULT_FIELD_SEP);
- pset.popt.topt.recordSep = xstrdup(DEFAULT_RECORD_SEP);
pset.popt.topt.border = 1;
pset.popt.topt.pager = true;
- SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
- SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
- SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
- /* This is obsolete and will be removed very soon. */
+ /* This is obsolete and should be removed sometime. */
#ifdef PSQL_ALWAYS_GET_PASSWORDS
pset.getPassword = true;
#else
@@ -127,11 +126,18 @@ main(int argc, char **argv)
parse_options(argc, argv, &options);
- if (options.action == ACT_LIST_DB)
- options.dbname = "template1";
+ if (!pset.popt.topt.fieldSep)
+ pset.popt.topt.fieldSep = xstrdup(DEFAULT_FIELD_SEP);
+ if (!pset.popt.topt.recordSep)
+ pset.popt.topt.recordSep = xstrdup(DEFAULT_RECORD_SEP);
if (options.username)
{
+ /*
+ * The \001 is a hack to support the deprecated -u option which issues
+ * a username prompt. The recommended option is -U followed by the name
+ * on the command line.
+ */
if (strcmp(options.username, "\001") == 0)
username = simple_prompt("Username: ", 100, true);
else
@@ -145,7 +151,9 @@ main(int argc, char **argv)
do
{
need_pass = false;
- pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.dbname, username, password);
+ pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
+ options.action == ACT_LIST_DB ? "template1" : options.dbname,
+ username, password);
if (PQstatus(pset.db) == CONNECTION_BAD &&
strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0)
@@ -162,8 +170,7 @@ main(int argc, char **argv)
if (PQstatus(pset.db) == CONNECTION_BAD)
{
- fprintf(stderr, "%s: %s",
- pset.progname, PQerrorMessage(pset.db));
+ fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db));
PQfinish(pset.db);
exit(EXIT_BADCONN);
}
@@ -188,44 +195,62 @@ main(int argc, char **argv)
SetVariable(pset.vars, "HOST", PQhost(pset.db));
SetVariable(pset.vars, "PORT", PQport(pset.db));
- pset.issuper = test_superuser(PQuser(pset.db));
-
- if (!QUIET() && !pset.notty && !options.action)
- {
- printf("Welcome to %s, the PostgreSQL interactive terminal.\n\n"
- "Type: \\copyright for distribution terms\n"
- " \\h for help with SQL commands\n"
- " \\? for help on internal slash commands\n"
- " \\g or terminate with semicolon to execute query\n"
- " \\q to quit\n", pset.progname);
- }
-
- /* Now find something to do */
+ /*
+ * Now find something to do
+ */
- /* process file given by -f */
+ /*
+ * process file given by -f
+ */
if (options.action == ACT_FILE)
successResult = process_file(options.action_string) ? 0 : 1;
- /* process slash command if one was given to -c */
+ /*
+ * process slash command if one was given to -c
+ */
else if (options.action == ACT_SINGLE_SLASH)
{
- if (GetVariable(pset.vars, "ECHO") && strcmp(GetVariable(pset.vars, "ECHO"), "full")==0)
+ const char * value;
+
+ if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "full")==0)
puts(options.action_string);
successResult = HandleSlashCmds(options.action_string, NULL, NULL) != CMD_ERROR ? 0 : 1;
}
- /* If the query given to -c was a normal one, send it */
+ /*
+ * If the query given to -c was a normal one, send it
+ */
else if (options.action == ACT_SINGLE_QUERY)
{
- if (GetVariable(pset.vars, "ECHO") && strcmp(GetVariable(pset.vars, "ECHO"), "full")==0)
+ const char * value;
+
+ if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "full")==0)
puts(options.action_string);
- successResult = SendQuery( options.action_string) ? 0 : 1;
+ successResult = SendQuery(options.action_string) ? 0 : 1;
}
- /* or otherwise enter interactive main loop */
+ /*
+ * or otherwise enter interactive main loop
+ */
else
{
+ pset.issuper = test_superuser(PQuser(pset.db));
+ if (!QUIET() && !pset.notty)
+ {
+ printf("Welcome to %s, the PostgreSQL interactive terminal.\n\n"
+ "Type: \\copyright for distribution terms\n"
+ " \\h for help with SQL commands\n"
+ " \\? for help on internal slash commands\n"
+ " \\g or terminate with semicolon to execute query\n"
+ " \\q to quit\n\n", pset.progname);
+ }
+
+ SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
+ SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
+ SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
process_psqlrc();
- initializeInput(options.no_readline ? 0 : 1);
+ if (!pset.notty)
+ initializeInput(options.no_readline ? 0 : 1);
successResult = MainLoop(stdin);
- finishInput();
+ if (!pset.notty)
+ finishInput();
}
/* clean up */
@@ -253,7 +278,8 @@ static void
parse_options(int argc, char *argv[], struct adhoc_opts * options)
{
#ifdef HAVE_GETOPT_LONG
- static struct option long_options[] = {
+ static struct option long_options[] =
+ {
{"no-align", no_argument, NULL, 'A'},
{"command", required_argument, NULL, 'c'},
{"dbname", required_argument, NULL, 'd'},
@@ -269,6 +295,7 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
{"port", required_argument, NULL, 'p'},
{"pset", required_argument, NULL, 'P'},
{"quiet", no_argument, NULL, 'q'},
+ {"record-separator", required_argument, NULL, 'R'},
{"single-step", no_argument, NULL, 's'},
{"single-line", no_argument, NULL, 'S'},
{"tuples-only", no_argument, NULL, 't'},
@@ -283,7 +310,7 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
};
int optindex;
-#endif
+#endif /* HAVE_GETOPT_LONG */
extern char *optarg;
extern int optind;
@@ -293,15 +320,15 @@ parse_options(int argc, char *argv[], struct adhoc_opts * 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)
-#else
+ while ((c = getopt_long(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWx?", long_options, &optindex)) != -1)
+#else /* not HAVE_GETOPT_LONG */
/*
* 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
+ while ((c = getopt(argc, argv, "Ac:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWx?-")) != -1)
+#endif /* not HAVE_GETOPT_LONG */
{
switch (c)
{
@@ -329,7 +356,7 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
options->action_string = optarg;
break;
case 'F':
- pset.popt.topt.fieldSep = strdup(optarg);
+ pset.popt.topt.fieldSep = xstrdup(optarg);
break;
case 'h':
options->host = optarg;
@@ -377,6 +404,9 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
case 'q':
SetVariable(pset.vars, "QUIET", "");
break;
+ case 'R':
+ pset.popt.topt.recordSep = xstrdup(optarg);
+ break;
case 's':
SetVariable(pset.vars, "SINGLESTEP", "");
break;
@@ -507,7 +537,7 @@ process_psqlrc(void)
if (home)
{
- psqlrc = (char *) malloc(strlen(home) + 20);
+ psqlrc = malloc(strlen(home) + 20);
if (!psqlrc)
{
fprintf(stderr, "%s: out of memory\n", pset.progname);
@@ -570,7 +600,7 @@ showVersion(void)
#endif
puts("Portions Copyright (c) 1996-2000, PostgreSQL, Inc");
- puts("Portions Copyright (C) 1996 Regents of the University of California");
+ puts("Portions Copyright (c) 1996 Regents of the University of California");
puts("Read the file COPYRIGHT or use the command \\copyright to see the");
puts("usage and distribution terms.");
}
diff --git a/src/bin/psql/stringutils.c b/src/bin/psql/stringutils.c
index 5ba48dc454c..a0d3769fd23 100644
--- a/src/bin/psql/stringutils.c
+++ b/src/bin/psql/stringutils.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.c,v 1.23 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.c,v 1.24 2000/02/07 23:10:06 petere Exp $
*/
#include <c.h>
#include "stringutils.h"
@@ -12,19 +12,13 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-
#include <stdio.h>
-#include <postgres.h>
-#ifndef HAVE_STRDUP
-#include <strdup.h>
-#endif
#include <libpq-fe.h>
-static void
- unescape_quotes(char *source, char quote, char escape);
+static void unescape_quotes(char *source, int quote, int escape);
/*
@@ -45,7 +39,7 @@ char *
strtokx(const char *s,
const char *delim,
const char *quote,
- char escape,
+ int escape,
char *was_quoted,
unsigned int *token_pos,
int encoding)
@@ -60,6 +54,10 @@ strtokx(const char *s,
char *start;
char *cp = NULL;
+#ifndef MULTIBYTE
+ (void)encoding; /*not used*/
+#endif
+
if (s)
{
free(storage);
@@ -160,7 +158,7 @@ strtokx(const char *s,
* Resolves escaped quotes. Used by strtokx above.
*/
static void
-unescape_quotes(char *source, char quote, char escape)
+unescape_quotes(char *source, int quote, int escape)
{
char *p;
char *destination,
@@ -170,7 +168,7 @@ unescape_quotes(char *source, char quote, char escape)
assert(source);
#endif
- destination = (char *) calloc(1, strlen(source) + 1);
+ destination = calloc(1, strlen(source) + 1);
if (!destination)
{
perror("calloc");
diff --git a/src/bin/psql/stringutils.h b/src/bin/psql/stringutils.h
index 914871d94eb..4201fd53001 100644
--- a/src/bin/psql/stringutils.h
+++ b/src/bin/psql/stringutils.h
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.h,v 1.13 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.h,v 1.14 2000/02/07 23:10:07 petere Exp $
*/
#ifndef STRINGUTILS_H
#define STRINGUTILS_H
@@ -13,7 +13,7 @@
extern char *strtokx(const char *s,
const char *delim,
const char *quote,
- char escape,
+ int escape,
char *was_quoted,
unsigned int *token_pos,
int encoding);
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 92112cead07..50a15fc7d0b 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.9 2000/01/29 16:58:49 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.10 2000/02/07 23:10:07 petere Exp $
*/
/*-----------
@@ -121,9 +121,7 @@ pgsql_thing_t words_after_create[] = {
{ "TYPE", "SELECT typname FROM pg_type WHERE substr(typname,1,%d)='%s'" },
{ "UNIQUE", NULL }, /* for CREATE UNIQUE INDEX ... */
{ "USER", "SELECT usename FROM pg_user WHERE substr(usename,1,%d)='%s'" },
- { "VIEW", NULL }, /* Telling a view from a table is not the easiest
- thing in the world, and the solutions I've seen
- don't really work, so I'll wait on this. */
+ { "VIEW", "SELECT viewname FROM pg_views WHERE substr(viewname,1,%d)='%s'" },
{ NULL, NULL } /* end of list */
};
diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c
index 96589497d30..7a3bff45e92 100644
--- a/src/interfaces/libpq/fe-auth.c
+++ b/src/interfaces/libpq/fe-auth.c
@@ -10,7 +10,7 @@
* exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.36 2000/01/26 05:58:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.37 2000/02/07 23:10:08 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -474,6 +474,10 @@ int
fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
const char *password, char *PQerrormsg)
{
+#if !defined(KRB4) && !defined(KRB5)
+ (void)hostname; /*not used*/
+#endif
+
switch (areq)
{
case AUTH_REQ_OK:
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 92d32917ef2..94bf6bf0b86 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.117 2000/02/05 12:33:22 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.118 2000/02/07 23:10:09 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2291,7 +2291,7 @@ conninfo_free()
}
/* =========== accessor functions for PGconn ========= */
-const char *
+char *
PQdb(const PGconn *conn)
{
if (!conn)
@@ -2299,7 +2299,7 @@ PQdb(const PGconn *conn)
return conn->dbName;
}
-const char *
+char *
PQuser(const PGconn *conn)
{
if (!conn)
@@ -2307,7 +2307,7 @@ PQuser(const PGconn *conn)
return conn->pguser;
}
-const char *
+char *
PQpass(const PGconn *conn)
{
if (!conn)
@@ -2315,7 +2315,7 @@ PQpass(const PGconn *conn)
return conn->pgpass;
}
-const char *
+char *
PQhost(const PGconn *conn)
{
if (!conn)
@@ -2323,7 +2323,7 @@ PQhost(const PGconn *conn)
return conn->pghost;
}
-const char *
+char *
PQport(const PGconn *conn)
{
if (!conn)
@@ -2331,7 +2331,7 @@ PQport(const PGconn *conn)
return conn->pgport;
}
-const char *
+char *
PQtty(const PGconn *conn)
{
if (!conn)
@@ -2339,7 +2339,7 @@ PQtty(const PGconn *conn)
return conn->pgtty;
}
-const char *
+char *
PQoptions(const PGconn *conn)
{
if (!conn)
@@ -2355,7 +2355,7 @@ PQstatus(const PGconn *conn)
return conn->status;
}
-const char *
+char *
PQerrorMessage(const PGconn *conn)
{
static char noConn[] = "PQerrorMessage: conn pointer is NULL\n";
@@ -2478,6 +2478,7 @@ PQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg)
static void
defaultNoticeProcessor(void *arg, const char *message)
{
+ (void)arg; /*not used*/
/* Note: we expect the supplied string to end with a newline already. */
fprintf(stderr, "%s", message);
}
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 406ab499030..8bba82e788e 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.89 2000/01/26 05:58:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.90 2000/02/07 23:10:10 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,7 +27,7 @@
#endif
/* keep this in same order as ExecStatusType in libpq-fe.h */
-const char *const pgresStatus[] = {
+char * const pgresStatus[] = {
"PGRES_EMPTY_QUERY",
"PGRES_COMMAND_OK",
"PGRES_TUPLES_OK",
@@ -1760,15 +1760,15 @@ PQresultStatus(const PGresult *res)
return res->resultStatus;
}
-const char *
+char *
PQresStatus(ExecStatusType status)
{
- if ((int)status < 0 || (size_t)status >= sizeof pgresStatus / sizeof pgresStatus[0])
+ if (status < 0 || status >= sizeof pgresStatus / sizeof pgresStatus[0])
return "Invalid ExecStatusType code";
return pgresStatus[status];
}
-const char *
+char *
PQresultErrorMessage(const PGresult *res)
{
if (!res || !res->errMsg)
@@ -1862,7 +1862,7 @@ check_tuple_field_number(const char *routineName, const PGresult *res,
/*
returns NULL if the field_num is invalid
*/
-const char *
+char *
PQfname(const PGresult *res, int field_num)
{
if (!check_field_number("PQfname", res, field_num))
@@ -1947,8 +1947,8 @@ PQfmod(const PGresult *res, int field_num)
return 0;
}
-const char *
-PQcmdStatus(const PGresult *res)
+char *
+PQcmdStatus(PGresult *res)
{
if (!res)
return NULL;
@@ -1960,7 +1960,7 @@ PQcmdStatus(const PGresult *res)
if the last command was an INSERT, return the oid string
if not, return ""
*/
-const char *
+char *
PQoidStatus(const PGresult *res)
{
/*
@@ -2011,8 +2011,8 @@ PQoidValue(const PGresult *res)
if the last command was an INSERT/UPDATE/DELETE, return number
of inserted/affected tuples, if not, return ""
*/
-const char *
-PQcmdTuples(const PGresult *res)
+char *
+PQcmdTuples(PGresult *res)
{
char noticeBuf[128];
@@ -2023,7 +2023,7 @@ PQcmdTuples(const PGresult *res)
strncmp(res->cmdStatus, "DELETE", 6) == 0 ||
strncmp(res->cmdStatus, "UPDATE", 6) == 0)
{
- const char *p = res->cmdStatus + 6;
+ char *p = res->cmdStatus + 6;
if (*p == 0)
{
@@ -2067,7 +2067,7 @@ PQcmdTuples(const PGresult *res)
if res is not binary, a null-terminated ASCII string is returned.
*/
-const char *
+char *
PQgetvalue(const PGresult *res, int tup_num, int field_num)
{
if (!check_tuple_field_number("PQgetvalue", res, tup_num, field_num))
diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c
index e31b66a28b3..6a7fd71f440 100644
--- a/src/interfaces/libpq/fe-lobj.c
+++ b/src/interfaces/libpq/fe-lobj.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.27 2000/01/26 05:58:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.28 2000/02/07 23:10:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -168,7 +168,7 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len)
*
*/
int
-lo_write(PGconn *conn, int fd, const char *buf, size_t len)
+lo_write(PGconn *conn, int fd, char *buf, size_t len)
{
PQArgBlock argv[2];
PGresult *res;
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index ff6acefea8f..d171c457d96 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -25,7 +25,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.38 2000/01/29 16:58:51 petere Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.39 2000/02/07 23:10:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -782,6 +782,8 @@ PQenv2encoding(void)
int
PQmblen(const unsigned char *s, int encoding)
{
+ (void)s;
+ (void)encoding;
return 1;
}
int
diff --git a/src/interfaces/libpq/fe-print.c b/src/interfaces/libpq/fe-print.c
index e54167cc1fe..3b9102d4d84 100644
--- a/src/interfaces/libpq/fe-print.c
+++ b/src/interfaces/libpq/fe-print.c
@@ -10,7 +10,7 @@
* didn't really belong there.
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.34 2000/02/05 12:33:22 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-print.c,v 1.35 2000/02/07 23:10:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -59,7 +59,7 @@ static char *do_header(FILE *fout, const PQprintOpt *po, const int nFields,
static void output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
unsigned char *fieldNotNum, int *fieldMax, char *border,
const int row_index);
-
+static void fill(int length, int max, char filler, FILE *fp);
/*
* PQprint()
@@ -440,7 +440,6 @@ do_header(FILE *fout, const PQprintOpt *po, const int nFields, int *fieldMax,
fputs("<tr>", fout);
else
{
- int j; /* for loop index */
int tot = 0;
int n = 0;
char *p = NULL;
@@ -557,7 +556,6 @@ output_row(FILE *fout, const PQprintOpt *po, const int nFields, char **fields,
-#if 0
/*
* really old printing routines
*/
@@ -728,4 +726,17 @@ PQprintTuples(const PGresult *res,
}
}
}
-#endif
+
+
+
+/* simply send out max-length number of filler characters to fp */
+
+static void
+fill(int length, int max, char filler, FILE *fp)
+{
+ int count;
+
+ count = max - length;
+ while (count-- >= 0)
+ putc(filler, fp);
+}
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 8acb622ad16..66437a903fd 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: libpq-fe.h,v 1.59 2000/02/05 12:33:22 ishii Exp $
+ * $Id: libpq-fe.h,v 1.60 2000/02/07 23:10:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -74,11 +74,6 @@ extern "C"
PGRES_FATAL_ERROR
} ExecStatusType;
-/* String descriptions of the ExecStatusTypes.
- * NB: direct use of this array is now deprecated; call PQresStatus() instead.
- */
- extern const char *const pgresStatus[];
-
/* PGconn encapsulates a connection to the backend.
* The contents of this struct are not supposed to be known to applications.
*/
@@ -115,16 +110,17 @@ extern "C"
typedef void (*PQnoticeProcessor) (void *arg, const char *message);
/* Print options for PQprint() */
+ typedef char pqbool;
typedef struct _PQprintOpt
{
- int header; /* print output field headings and row
+ pqbool header; /* print output field headings and row
* count */
- int align; /* fill align the fields */
- int standard; /* old brain dead format */
- int html3; /* output html tables */
- int expanded; /* expand tables */
- int pager; /* use pager for output if needed */
+ pqbool align; /* fill align the fields */
+ pqbool standard; /* old brain dead format */
+ pqbool html3; /* output html tables */
+ pqbool expanded; /* expand tables */
+ pqbool pager; /* use pager for output if needed */
char *fieldSep; /* field separator */
char *tableOpt; /* insert to HTML <table ...> */
char *caption; /* HTML <caption> */
@@ -207,15 +203,15 @@ extern "C"
extern int PQrequestCancel(PGconn *conn);
/* Accessor functions for PGconn objects */
- extern const char *PQdb(const PGconn *conn);
- extern const char *PQuser(const PGconn *conn);
- extern const char *PQpass(const PGconn *conn);
- extern const char *PQhost(const PGconn *conn);
- extern const char *PQport(const PGconn *conn);
- extern const char *PQtty(const PGconn *conn);
- extern const char *PQoptions(const PGconn *conn);
+ extern char *PQdb(const PGconn *conn);
+ extern char *PQuser(const PGconn *conn);
+ extern char *PQpass(const PGconn *conn);
+ extern char *PQhost(const PGconn *conn);
+ extern char *PQport(const PGconn *conn);
+ extern char *PQtty(const PGconn *conn);
+ extern char *PQoptions(const PGconn *conn);
extern ConnStatusType PQstatus(const PGconn *conn);
- extern const char *PQerrorMessage(const PGconn *conn);
+ extern char *PQerrorMessage(const PGconn *conn);
extern int PQsocket(const PGconn *conn);
extern int PQbackendPID(const PGconn *conn);
extern int PQclientEncoding(const PGconn *conn);
@@ -279,21 +275,21 @@ extern "C"
/* Accessor functions for PGresult objects */
extern ExecStatusType PQresultStatus(const PGresult *res);
- extern const char *PQresStatus(ExecStatusType status);
- extern const char *PQresultErrorMessage(const PGresult *res);
+ extern char *PQresStatus(ExecStatusType status);
+ extern char *PQresultErrorMessage(const PGresult *res);
extern int PQntuples(const PGresult *res);
extern int PQnfields(const PGresult *res);
extern int PQbinaryTuples(const PGresult *res);
- extern const char *PQfname(const PGresult *res, int field_num);
+ extern char *PQfname(const PGresult *res, int field_num);
extern int PQfnumber(const PGresult *res, const char *field_name);
extern Oid PQftype(const PGresult *res, int field_num);
extern int PQfsize(const PGresult *res, int field_num);
extern int PQfmod(const PGresult *res, int field_num);
- extern const char *PQcmdStatus(const PGresult *res);
- extern const char *PQoidStatus(const PGresult *res); /* old and ugly */
+ extern char *PQcmdStatus(PGresult *res);
+ extern char *PQoidStatus(const PGresult *res); /* old and ugly */
extern Oid PQoidValue(const PGresult *res); /* new and improved */
- extern const char *PQcmdTuples(const PGresult *res);
- extern const char *PQgetvalue(const PGresult *res, int tup_num, int field_num);
+ extern char *PQcmdTuples(PGresult *res);
+ extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num);
extern int PQgetlength(const PGresult *res, int tup_num, int field_num);
extern int PQgetisnull(const PGresult *res, int tup_num, int field_num);
@@ -313,7 +309,6 @@ extern "C"
const PGresult *res,
const PQprintOpt *ps); /* option structure */
-#if 0
/*
* really old printing routines
*/
@@ -330,7 +325,7 @@ extern "C"
int terseOutput, /* delimiter bars */
int width); /* width of column, if
* 0, use variable width */
-#endif
+
/* === in fe-lobj.c === */
@@ -338,7 +333,7 @@ extern "C"
extern int lo_open(PGconn *conn, Oid lobjId, int mode);
extern int lo_close(PGconn *conn, int fd);
extern int lo_read(PGconn *conn, int fd, char *buf, size_t len);
- extern int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
+ extern int lo_write(PGconn *conn, int fd, char *buf, size_t len);
extern int lo_lseek(PGconn *conn, int fd, int offset, int whence);
extern Oid lo_creat(PGconn *conn, int mode);
extern int lo_tell(PGconn *conn, int fd);
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index bb6f193bfe8..16555d98852 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: libpq-int.h,v 1.18 2000/01/26 05:58:46 momjian Exp $
+ * $Id: libpq-int.h,v 1.19 2000/02/07 23:10:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -244,6 +244,11 @@ struct pg_conn
int client_encoding; /* encoding id */
};
+/* String descriptions of the ExecStatusTypes.
+ * direct use of this array is deprecated; call PQresStatus() instead.
+ */
+extern char *const pgresStatus[];
+
/* ----------------
* Internal functions of libpq
* Functions declared here need to be visible across files of libpq,
diff --git a/src/interfaces/libpq/pqexpbuffer.c b/src/interfaces/libpq/pqexpbuffer.c
index dc006e55c8e..f70d9139c2e 100644
--- a/src/interfaces/libpq/pqexpbuffer.c
+++ b/src/interfaces/libpq/pqexpbuffer.c
@@ -17,7 +17,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.4 2000/01/26 05:58:46 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.5 2000/02/07 23:10:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -124,9 +124,9 @@ resetPQExpBuffer(PQExpBuffer str)
* Returns 1 if OK, 0 if failed to enlarge buffer.
*/
int
-enlargePQExpBuffer(PQExpBuffer str, int needed)
+enlargePQExpBuffer(PQExpBuffer str, size_t needed)
{
- int newlen;
+ size_t newlen;
char *newdata;
needed += str->len + 1; /* total space required now */
@@ -164,8 +164,8 @@ void
printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
va_list args;
- int avail,
- nprinted;
+ size_t avail;
+ int nprinted;
resetPQExpBuffer(str);
@@ -214,8 +214,8 @@ void
appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
va_list args;
- int avail,
- nprinted;
+ size_t avail;
+ int nprinted;
for (;;)
{
@@ -286,7 +286,7 @@ appendPQExpBufferChar(PQExpBuffer str, char ch)
* if necessary.
*/
void
-appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, int datalen)
+appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, size_t datalen)
{
/* Make more room if needed */
if (! enlargePQExpBuffer(str, datalen))
diff --git a/src/interfaces/libpq/pqexpbuffer.h b/src/interfaces/libpq/pqexpbuffer.h
index b70170d61a5..014254465aa 100644
--- a/src/interfaces/libpq/pqexpbuffer.h
+++ b/src/interfaces/libpq/pqexpbuffer.h
@@ -18,7 +18,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pqexpbuffer.h,v 1.3 2000/01/26 05:58:46 momjian Exp $
+ * $Id: pqexpbuffer.h,v 1.4 2000/02/07 23:10:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,8 +40,8 @@
typedef struct PQExpBufferData
{
char *data;
- int len;
- int maxlen;
+ size_t len;
+ size_t maxlen;
} PQExpBufferData;
typedef PQExpBufferData *PQExpBuffer;
@@ -113,7 +113,7 @@ extern void resetPQExpBuffer(PQExpBuffer str);
*
* Returns 1 if OK, 0 if failed to enlarge buffer.
*/
-extern int enlargePQExpBuffer(PQExpBuffer str, int needed);
+extern int enlargePQExpBuffer(PQExpBuffer str, size_t needed);
/*------------------------
* printfPQExpBuffer
@@ -153,6 +153,6 @@ extern void appendPQExpBufferChar(PQExpBuffer str, char ch);
* if necessary.
*/
extern void appendBinaryPQExpBuffer(PQExpBuffer str,
- const char *data, int datalen);
+ const char *data, size_t datalen);
#endif /* PQEXPBUFFER_H */
diff --git a/src/interfaces/libpq/win32.h b/src/interfaces/libpq/win32.h
index 6988bcd98fe..91f7df1a2d3 100644
--- a/src/interfaces/libpq/win32.h
+++ b/src/interfaces/libpq/win32.h
@@ -11,9 +11,11 @@
* Some compat functions
*/
#define open(a,b,c) _open(a,b,c)
+#define close(a) _close(a)
#define read(a,b,c) _read(a,b,c)
#define write(a,b,c) _write(a,b,c)
-
+#define popen(a,b) _popen(a,b)
+#define pclose(a) _pclose(a)
/*
* crypt not available (yet)