another set of cleanups

This commit is contained in:
Peter Eisentraut 2000-01-18 23:30:24 +00:00
parent 80c5fea99d
commit f565cf41ab
30 changed files with 588 additions and 370 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.20 2000/01/14 22:18:01 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.21 2000/01/18 23:30:19 petere Exp $
Postgres documentation Postgres documentation
--> -->
@ -851,6 +851,16 @@ lo_import 152801
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><literal>recordsep</literal></term>
<listitem>
<para>
Specifies the record (line) separator to use in unaligned output mode. The default
is a newline character.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><literal>tuples_only</literal> (or <literal>t</literal>)</term> <term><literal>tuples_only</literal> (or <literal>t</literal>)</term>
<listitem> <listitem>
@ -1900,12 +1910,14 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><literal>%M</literal></term> <term><literal>%M</literal></term>
<listitem><para>The hostname of the database server (or <quote>.</quote> if Unix domain socket).</para></listitem> <listitem><para>The hostname of the database server (or <quote>.</quote>
if Unix domain socket).</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><literal>%m</literal></term> <term><literal>%m</literal></term>
<listitem><para>The hostname of the database server truncated after the first dot.</para></listitem> <listitem><para>The hostname of the database server truncated after the
first dot.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -1915,7 +1927,8 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
<varlistentry> <varlistentry>
<term><literal>%n</literal></term> <term><literal>%n</literal></term>
<listitem><para>The username you are connected as (not your local system user name).</para></listitem> <listitem><para>The username you are connected as (not your local system
user name).</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -1925,37 +1938,39 @@ testdb=> <userinput>\set content `sed -e "s/'/\\\\\\'/g" < my_file.txt`</userinp
<varlistentry> <varlistentry>
<term><literal>%~</literal></term> <term><literal>%~</literal></term>
<listitem><para>Like <literal>%/</literal>, but the output is <quote>~</quote> (tilde) if the database <listitem><para>Like <literal>%/</literal>, but the output is <quote>~</quote>
is your default database.</para></listitem> (tilde) if the database is your default database.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><literal>%#</literal></term> <term><literal>%#</literal></term>
<listitem><para>If the username is <literal>postgres</literal>, a <quote>#</quote>, otherwise a <quote>&gt;</quote>.</para></listitem> <listitem><para>If the username is <literal>postgres</literal>, a
<quote>#</quote>, otherwise a <quote>&gt;</quote>.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><literal>%R</literal></term> <term><literal>%R</literal></term>
<listitem><para> <listitem><para>
In prompt 1 normally <quote>=</quote>, but <quote>^</quote> if in single-line mode, and In prompt 1 normally <quote>=</quote>, but <quote>^</quote> if in single-line
<quote>!</quote> if the session is disconnected from the database (which can only mode, and <quote>!</quote> if the session is disconnected from the database
happen if <command>\connect</command> fails). (which can happen if <command>\connect</command> fails). In prompt 2 the
In prompt 2 the sequence is replaced by <quote>-</quote>, <quote>*</quote>, a single quote, sequence is replaced by <quote>-</quote>, <quote>*</quote>, a single quote,
or a double quote, depending on whether <application>psql</application> expects more input or a double quote, depending on whether <application>psql</application>
because the query wasn't terminated yet, because you are inside a <literal>/* ... */</literal> expects more input because the query wasn't terminated yet, because you are
comment, or because you are inside a quote. inside a <literal>/* ... */</literal> comment, or because you are inside
In prompt 3 the sequence doesn't resolve to anything.</para> a quote. In prompt 3 the sequence doesn't resolve to anything.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><literal>%</literal><replaceable class="parameter">digits</replaceable></term> <term><literal>%</literal><replaceable class="parameter">digits</replaceable></term>
<listitem><para> <listitem><para>
If <replaceable class="parameter">digits</replaceable> starts with <literal>0x</literal> If <replaceable class="parameter">digits</replaceable> starts with
the rest of the characters are interpreted at a hexadecimal digit and the <literal>0x</literal> the rest of the characters are interpreted at a
character with the corresponding code is subsituted. If the first digit is <literal>0</literal> hexadecimal digit and the character with the corresponding code is
the characters are interpreted as on octal number and the corresponding character subsituted. If the first digit is <literal>0</literal> the characters are
is substituted. Otherwise a decimal number is assumed.</para> interpreted as on octal number and the corresponding character is
substituted. Otherwise a decimal number is assumed.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.130 2000/01/18 19:08:13 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.131 2000/01/18 23:30:20 petere Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -854,6 +854,7 @@ AlterTableStmt:
| ALTER TABLE relation_name opt_inh_star DROP CONSTRAINT name drop_behavior | ALTER TABLE relation_name opt_inh_star DROP CONSTRAINT name drop_behavior
{ {
AlterTableStmt *n = makeNode(AlterTableStmt); AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'X';
n->relname = $3; n->relname = $3;
n->inh = $4; n->inh = $4;
n->name = $7; n->name = $7;

View File

@ -1,6 +1,14 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.13 2000/01/18 23:30:22 petere Exp $
*/
#include <c.h> #include <c.h>
#include "command.h" #include "command.h"
#include <errno.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -39,12 +47,11 @@
static backslashResult exec_command(const char *cmd, static backslashResult exec_command(const char *cmd,
char *const * options, char *const * options,
const char *options_string, const char *options_string,
PQExpBuffer query_buf, PQExpBuffer query_buf);
int encoding);
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf); static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
static char * unescape(const char *source, int encoding); static char * unescape(const char *source);
static bool do_connect(const char *new_dbname, static bool do_connect(const char *new_dbname,
const char *new_user); const char *new_user);
@ -81,8 +88,7 @@ static bool do_shell(const char *command);
backslashResult backslashResult
HandleSlashCmds(const char *line, HandleSlashCmds(const char *line,
PQExpBuffer query_buf, PQExpBuffer query_buf,
const char **end_of_cmd, const char **end_of_cmd)
int encoding)
{ {
backslashResult status = CMD_SKIP_LINE; backslashResult status = CMD_SKIP_LINE;
char *my_line; char *my_line;
@ -134,14 +140,14 @@ HandleSlashCmds(const char *line,
* whitespace */ * whitespace */
i = 0; i = 0;
token = strtokx(options_string, " \t", "\"'`", '\\', &quote, &pos, encoding); token = strtokx(options_string, " \t", "\"'`", '\\', &quote, &pos, pset.encoding);
for (i = 0; token && i < NR_OPTIONS; i++) for (i = 0; token && i < NR_OPTIONS; i++)
{ {
switch (quote) switch (quote)
{ {
case '"': case '"':
options[i] = unescape(token, encoding); options[i] = unescape(token);
break; break;
case '\'': case '\'':
options[i] = xstrdup(token); options[i] = xstrdup(token);
@ -150,7 +156,7 @@ HandleSlashCmds(const char *line,
{ {
bool error = false; bool error = false;
FILE *fd = NULL; FILE *fd = NULL;
char *file = unescape(token, encoding); char *file = unescape(token);
PQExpBufferData output; PQExpBufferData output;
char buf[512]; char buf[512];
size_t result; size_t result;
@ -158,7 +164,7 @@ HandleSlashCmds(const char *line,
fd = popen(file, "r"); fd = popen(file, "r");
if (!fd) if (!fd)
{ {
perror(file); psql_error("%s: %s\n", file, strerror(errno));
error = true; error = true;
} }
@ -171,7 +177,7 @@ HandleSlashCmds(const char *line,
result = fread(buf, 1, 512, fd); result = fread(buf, 1, 512, fd);
if (ferror(fd)) if (ferror(fd))
{ {
perror(file); psql_error("%s: %s\n", file, strerror(errno));
error = true; error = true;
break; break;
} }
@ -181,7 +187,7 @@ HandleSlashCmds(const char *line,
if (pclose(fd) == -1) if (pclose(fd) == -1)
{ {
perror(file); psql_error("%s: %s\n", file, strerror(errno));
error = true; error = true;
} }
} }
@ -220,14 +226,14 @@ HandleSlashCmds(const char *line,
if (continue_parse) if (continue_parse)
break; break;
token = strtokx(NULL, " \t", "\"'`", '\\', &quote, &pos, encoding); token = strtokx(NULL, " \t", "\"'`", '\\', &quote, &pos, pset.encoding);
} /* for */ } /* for */
options[i] = NULL; options[i] = NULL;
} }
cmd = my_line; cmd = my_line;
status = exec_command(cmd, options, options_string, query_buf, encoding); status = exec_command(cmd, options, options_string, query_buf);
if (status == CMD_UNKNOWN) if (status == CMD_UNKNOWN)
{ {
@ -249,7 +255,7 @@ HandleSlashCmds(const char *line,
new_cmd[0] = cmd[0]; new_cmd[0] = cmd[0];
new_cmd[1] = '\0'; new_cmd[1] = '\0';
status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf, encoding); status = exec_command(new_cmd, (char *const *) new_options, my_line + 2, query_buf);
} }
if (status == CMD_UNKNOWN) if (status == CMD_UNKNOWN)
@ -257,7 +263,7 @@ HandleSlashCmds(const char *line,
if (pset.cur_cmd_interactive) if (pset.cur_cmd_interactive)
fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", cmd); fprintf(stderr, "Invalid command \\%s. Try \\? for help.\n", cmd);
else else
fprintf(stderr, "%s: invalid command \\%s", pset.progname, cmd); psql_error("invalid command \\%s\n", cmd);
status = CMD_ERROR; status = CMD_ERROR;
} }
@ -286,8 +292,7 @@ static backslashResult
exec_command(const char *cmd, exec_command(const char *cmd,
char *const * options, char *const * options,
const char *options_string, const char *options_string,
PQExpBuffer query_buf, PQExpBuffer query_buf)
int encoding)
{ {
bool success = true; /* indicate here if the command ran ok or bool success = true; /* indicate here if the command ran ok or
* failed */ * failed */
@ -342,7 +347,7 @@ exec_command(const char *cmd,
/* \copy */ /* \copy */
else if (strcasecmp(cmd, "copy") == 0) else if (strcasecmp(cmd, "copy") == 0)
success = do_copy(options_string, encoding); success = do_copy(options_string);
/* \copyright */ /* \copyright */
else if (strcmp(cmd, "copyright") == 0) else if (strcmp(cmd, "copyright") == 0)
@ -461,15 +466,12 @@ exec_command(const char *cmd,
else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0) else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
{ {
if (!options[0]) if (!options[0])
{ {
if (pset.cur_cmd_interactive) psql_error("\\%s: missing required argument\n", cmd);
fprintf(stderr, "\\%s: missing required argument\n", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false; success = false;
} }
else else
success = process_file(options[0], encoding); success = process_file(options[0]);
} }
@ -487,10 +489,7 @@ exec_command(const char *cmd,
{ {
if (!options[1]) if (!options[1])
{ {
if (pset.cur_cmd_interactive) psql_error("\\%s: missing required argument\n", cmd);
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false; success = false;
} }
else else
@ -501,10 +500,7 @@ exec_command(const char *cmd,
{ {
if (!options[0]) if (!options[0])
{ {
if (pset.cur_cmd_interactive) psql_error("\\%s: missing required argument\n", cmd);
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false; success = false;
} }
else else
@ -518,10 +514,7 @@ exec_command(const char *cmd,
{ {
if (!options[0]) if (!options[0])
{ {
if (pset.cur_cmd_interactive) psql_error("\\%s: missing required argument\n", cmd);
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false; success = false;
} }
else else
@ -552,10 +545,7 @@ exec_command(const char *cmd,
{ {
if (!options[0]) if (!options[0])
{ {
if (pset.cur_cmd_interactive) psql_error("\\%s: missing required argument\n", cmd);
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false; success = false;
} }
else else
@ -626,11 +616,7 @@ exec_command(const char *cmd,
val = ""; val = "";
if (!SetVariable(pset.vars, options[0], val)) if (!SetVariable(pset.vars, options[0], val))
{ {
if (pset.cur_cmd_interactive) psql_error("\\%s: error\n", cmd);
fprintf(stderr, "\\%s: error\n", cmd);
else
fprintf(stderr, "%s: \\%s: error\n", pset.progname, cmd);
success = false; success = false;
} }
} }
@ -650,10 +636,7 @@ exec_command(const char *cmd,
{ {
if (!SetVariable(pset.vars, options[0], NULL)) if (!SetVariable(pset.vars, options[0], NULL))
{ {
if (pset.cur_cmd_interactive) psql_error("\\%s: error\n", cmd);
fprintf(stderr, "\\%s: error\n", cmd);
else
fprintf(stderr, "%s: \\%s: error\n", pset.progname, cmd);
success = false; success = false;
} }
@ -667,10 +650,7 @@ exec_command(const char *cmd,
if (!options[0]) if (!options[0])
{ {
if (pset.cur_cmd_interactive) psql_error("\\%s: missing required argument\n", cmd);
fprintf(stderr, "\\%s: missing required argument", cmd);
else
fprintf(stderr, "%s: \\%s: missing required argument", pset.progname, cmd);
success = false; success = false;
} }
else else
@ -678,24 +658,16 @@ exec_command(const char *cmd,
if (options[0][0] == '|') if (options[0][0] == '|')
{ {
pipe = true; pipe = true;
#ifndef __CYGWIN32__
fd = popen(&options[0][1], "w"); fd = popen(&options[0][1], "w");
#else
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");
#endif
} }
if (!fd) if (!fd)
{ {
perror(options[0]); psql_error("%s: %s\n", options[0], strerror(errno));
success = false; success = false;
} }
} }
@ -714,7 +686,7 @@ exec_command(const char *cmd,
if (result == EOF) if (result == EOF)
{ {
perror("close"); psql_error("%s: %s\n", options[0], strerror(errno));
success = false; success = false;
} }
} }
@ -737,9 +709,8 @@ exec_command(const char *cmd,
slashUsage(); slashUsage();
#ifdef NOT_USED #if 0
/*
/*
* These commands don't do anything. I just use them to test the * These commands don't do anything. I just use them to test the
* parser. * parser.
*/ */
@ -772,7 +743,7 @@ exec_command(const char *cmd,
* The return value is malloc()'ed. * The return value is malloc()'ed.
*/ */
static char * static char *
unescape(const char *source, int encoding) unescape(const char *source)
{ {
unsigned char *p; unsigned char *p;
bool esc = false; /* Last character we saw was the escape bool esc = false; /* Last character we saw was the escape
@ -790,11 +761,11 @@ unescape(const char *source, int encoding)
tmp = destination = (char *) malloc(length); tmp = destination = (char *) malloc(length);
if (!tmp) if (!tmp)
{ {
perror("malloc"); psql_error("out of memory\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for (p = (char *) source; *p; p += PQmblen(p, encoding)) for (p = (char *) source; *p; p += PQmblen(p, pset.encoding))
{ {
if (esc) if (esc)
{ {
@ -866,7 +837,7 @@ unescape(const char *source, int encoding)
new = realloc(destination, length); new = realloc(destination, length);
if (!new) if (!new)
{ {
perror("realloc"); psql_error("out of memory\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
tmp = new + (tmp - destination); tmp = new + (tmp - destination);
@ -946,20 +917,6 @@ do_connect(const char *new_dbname, const char *new_user)
if (!pwparam && oldconn) if (!pwparam && oldconn)
pwparam = PQpass(oldconn); 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=");
#endif
do do
{ {
need_pass = false; need_pass = false;
@ -986,7 +943,7 @@ do_connect(const char *new_dbname, const char *new_user)
{ {
if (pset.cur_cmd_interactive) if (pset.cur_cmd_interactive)
{ {
fprintf(stderr, "%s", PQerrorMessage(pset.db)); psql_error("%s", PQerrorMessage(pset.db));
PQfinish(pset.db); PQfinish(pset.db);
if (oldconn) if (oldconn)
{ {
@ -1000,7 +957,7 @@ do_connect(const char *new_dbname, const char *new_user)
{ {
/* we don't want unpredictable things to /* we don't want unpredictable things to
* happen in scripting mode */ * happen in scripting mode */
fprintf(stderr, "%s: \\connect: %s", pset.progname, PQerrorMessage(pset.db)); psql_error("\\connect: %s", PQerrorMessage(pset.db));
PQfinish(pset.db); PQfinish(pset.db);
if (oldconn) if (oldconn)
PQfinish(oldconn); PQfinish(oldconn);
@ -1026,6 +983,9 @@ do_connect(const char *new_dbname, const char *new_user)
success = true; success = true;
} }
PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
pset.encoding = PQclientencoding(pset.db);
/* Update variables */ /* Update variables */
SetVariable(pset.vars, "DBNAME", PQdb(pset.db)); SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
SetVariable(pset.vars, "USER", PQuser(pset.db)); SetVariable(pset.vars, "USER", PQuser(pset.db));
@ -1072,8 +1032,10 @@ editFile(const char *fname)
return false; return false;
sprintf(sys, "exec %s %s", editorName, fname); sprintf(sys, "exec %s %s", editorName, fname);
result = system(sys); result = system(sys);
if (result == -1 || result == 127) if (result == -1)
perror(sys); psql_error("could not start editor\n");
else if (result == 127)
psql_error("could not start /bin/sh\n");
free(sys); free(sys);
return result == 0; return result == 0;
@ -1131,7 +1093,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
if (!stream) if (!stream)
{ {
perror(fname); psql_error("couldn't open temp file %s: %s\n", fname, strerror(errno));
error = true; error = true;
} }
else else
@ -1146,7 +1108,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
if (fwrite(query_buf->data, 1, ql, stream) != ql) if (fwrite(query_buf->data, 1, ql, stream) != ql)
{ {
perror(fname); psql_error("%s: %s\n", fname, strerror(errno));
fclose(stream); fclose(stream);
remove(fname); remove(fname);
error = true; error = true;
@ -1159,7 +1121,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
#ifndef WIN32 #ifndef WIN32
if (!error && stat(fname, &before) != 0) if (!error && stat(fname, &before) != 0)
{ {
perror(fname); psql_error("%s: %s\n", fname, strerror(errno));
error = true; error = true;
} }
#endif #endif
@ -1171,7 +1133,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
#ifndef WIN32 #ifndef WIN32
if (!error && stat(fname, &after) != 0) if (!error && stat(fname, &after) != 0)
{ {
perror(fname); psql_error("%s: %s\n", fname, strerror(errno));
error = true; error = true;
} }
@ -1184,7 +1146,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
stream = fopen(fname, "r"); stream = fopen(fname, "r");
if (!stream) if (!stream)
{ {
perror(fname); psql_error("%s: %s\n", fname, strerror(errno));
error = true; error = true;
} }
else else
@ -1199,7 +1161,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
result = fread(line, 1, 1024, stream); result = fread(line, 1, 1024, stream);
if (ferror(stream)) if (ferror(stream))
{ {
perror(fname); psql_error("%s: %s\n", fname, strerror(errno));
error = true; error = true;
break; break;
} }
@ -1212,9 +1174,14 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
/* remove temp file */ /* remove temp file */
if (!filename_arg) if (!filename_arg)
remove(fname); {
} if (remove(fname)==-1)
{
psql_error("%s: %s\n", fname, strerror(errno));
error=true;
}
}
}
return !error; return !error;
} }
@ -1227,7 +1194,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf)
* Handler for \i, but can be used for other things as well. * Handler for \i, but can be used for other things as well.
*/ */
bool bool
process_file(const char *filename, int encoding) process_file(char *filename)
{ {
FILE *fd; FILE *fd;
int result; int result;
@ -1243,13 +1210,12 @@ process_file(const char *filename, int encoding)
if (!fd) if (!fd)
{ {
if (!pset.cur_cmd_interactive) psql_error("%s: %s\n", filename, strerror(errno));
fprintf(stderr, "%s: ", pset.progname);
perror(filename);
return false; return false;
} }
result = MainLoop(fd, encoding); pset.inputfile = filename;
result = MainLoop(fd);
fclose(fd); fclose(fd);
return (result == EXIT_SUCCESS); return (result == EXIT_SUCCESS);
} }
@ -1315,7 +1281,7 @@ do_pset(const char *param, const char *value, printQueryOpt * popt, bool quiet)
popt->topt.format = PRINT_LATEX; popt->topt.format = PRINT_LATEX;
else else
{ {
fprintf(stderr, "Allowed formats are unaligned, aligned, html, latex.\n"); psql_error("\\pset: allowed formats are unaligned, aligned, html, latex\n");
return false; return false;
} }
@ -1362,7 +1328,23 @@ do_pset(const char *param, const char *value, printQueryOpt * popt, bool quiet)
popt->topt.fieldSep = xstrdup(value); popt->topt.fieldSep = xstrdup(value);
} }
if (!quiet) if (!quiet)
printf("Field separator is \"%s\".\n", popt->topt.fieldSep); printf("Field separator is '%s'.\n", popt->topt.fieldSep);
}
/* record separator for unaligned text */
else if (strcmp(param, "recordsep") == 0)
{
if (value)
{
free(popt->topt.recordSep);
popt->topt.recordSep = xstrdup(value);
}
if (!quiet) {
if (strcmp(popt->topt.recordSep, "\n")==0)
printf("Record separator is <newline>.");
else
printf("Record separator is '%s'.\n", popt->topt.recordSep);
}
} }
/* toggle between full and barebones format */ /* toggle between full and barebones format */
@ -1430,7 +1412,7 @@ do_pset(const char *param, const char *value, printQueryOpt * popt, bool quiet)
else else
{ {
fprintf(stderr, "Unknown option: %s\n", param); psql_error("\\pset: unknown option: %s\n", param);
return false; return false;
} }
@ -1456,8 +1438,13 @@ do_shell(const char *command)
shellName = DEFAULT_SHELL; shellName = DEFAULT_SHELL;
sys = malloc(strlen(shellName) + 16); sys = malloc(strlen(shellName) + 16);
if (!sys) if (!sys) {
return false; psql_error("out of memory\n");
if (pset.cur_cmd_interactive)
return false;
else
exit(EXIT_FAILURE);
}
sprintf(sys, "exec %s", shellName); sprintf(sys, "exec %s", shellName);
result = system(sys); result = system(sys);
free(sys); free(sys);
@ -1467,7 +1454,7 @@ do_shell(const char *command)
if (result == 127 || result == -1) if (result == 127 || result == -1)
{ {
perror("system"); psql_error("\\!: failed\n");
return false; return false;
} }
return true; return true;

View File

@ -1,7 +1,13 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/command.h,v 1.6 2000/01/18 23:30:23 petere Exp $
*/
#ifndef COMMAND_H #ifndef COMMAND_H
#define COMMAND_H #define COMMAND_H
#include <config.h>
#include <c.h> #include <c.h>
#include <pqexpbuffer.h> #include <pqexpbuffer.h>
@ -10,7 +16,6 @@
#include "print.h" #include "print.h"
typedef enum _backslashResult typedef enum _backslashResult
{ {
CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */ CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */
@ -23,14 +28,13 @@ typedef enum _backslashResult
} backslashResult; } backslashResult;
backslashResult backslashResult
HandleSlashCmds(const char *line, HandleSlashCmds(const char *line,
PQExpBuffer query_buf, PQExpBuffer query_buf,
const char **end_of_cmd, int encoding); const char **end_of_cmd);
bool bool
process_file(const char *filename, int encoding); process_file(char *filename);
bool bool
do_pset(const char *param, do_pset(const char *param,
@ -38,4 +42,4 @@ do_pset(const char *param,
printQueryOpt * popt, printQueryOpt * popt,
bool quiet); bool quiet);
#endif #endif /* COMMAND_H */

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.9 2000/01/18 23:30:23 petere Exp $
*/
#include <c.h> #include <c.h>
#include "common.h" #include "common.h"
@ -5,6 +12,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#ifdef HAVE_TERMIOS_H #ifdef HAVE_TERMIOS_H
#include <termios.h> #include <termios.h>
#endif #endif
@ -49,13 +57,13 @@ xstrdup(const char *string)
if (!string) if (!string)
{ {
fprintf(stderr, "xstrdup: Cannot duplicate null pointer.\n"); fprintf(stderr, "%s: xstrdup: cannot duplicate null pointer\n", pset.progname);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
tmp = strdup(string); tmp = strdup(string);
if (!tmp) if (!tmp)
{ {
perror("strdup"); psql_error("out of memory\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
return tmp; return tmp;
@ -104,7 +112,7 @@ setQFout(const char *fname)
if (!(pset.queryFout)) if (!(pset.queryFout))
{ {
fprintf(stderr, "%s: %s: %s\n", pset.progname, fname, strerror(errno)); psql_error("%s: %s\n", fname, strerror(errno));
pset.queryFout = stdout; pset.queryFout = stdout;
pset.queryFoutPipe = false; pset.queryFoutPipe = false;
status = false; status = false;
@ -123,6 +131,38 @@ setQFout(const char *fname)
/*
* Error reporting for scripts. Errors should look like
* filename:lineno: message
*
*/
void
psql_error(const char *fmt, ...)
{
va_list ap;
fflush(stdout);
if (pset.queryFout!=stdout)
fflush(pset.queryFout);
if (pset.inputfile)
fprintf(stderr, "%s:%u: ", pset.inputfile ? pset.inputfile : pset.progname, pset.lineno);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
/* for backend NOTICES */
void
NoticeProcessor(void * arg, const char * message)
{
(void)arg; /* not used */
psql_error("%s", message);
}
/* /*
* simple_prompt * simple_prompt
* *
@ -239,7 +279,7 @@ PSQLexec(const char *query)
if (!pset.db) if (!pset.db)
{ {
fputs("You are currently not connected to a database.\n", stderr); psql_error("You are currently not connected to a database.\n");
return NULL; return NULL;
} }
@ -268,7 +308,7 @@ PSQLexec(const char *query)
{ {
if (!pset.cur_cmd_interactive) if (!pset.cur_cmd_interactive)
{ {
fprintf(stderr, "%s: connection to server was lost", pset.progname); psql_error("connection to server was lost");
exit(EXIT_BADCONN); exit(EXIT_BADCONN);
} }
fputs("The connection to the server was lost. Attempting reset: ", stderr); fputs("The connection to the server was lost. Attempting reset: ", stderr);
@ -297,7 +337,7 @@ PSQLexec(const char *query)
return res; return res;
else else
{ {
fputs(PQerrorMessage(pset.db), stderr); psql_error("%s", PQerrorMessage(pset.db));
PQclear(res); PQclear(res);
return NULL; return NULL;
} }
@ -326,7 +366,7 @@ SendQuery(const char *query)
if (!pset.db) if (!pset.db)
{ {
fputs("You are currently not connected to a database.\n", stderr); psql_error("you are currently not connected to a database.\n");
return false; return false;
} }
@ -436,7 +476,7 @@ SendQuery(const char *query)
case PGRES_FATAL_ERROR: case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE: case PGRES_BAD_RESPONSE:
success = false; success = false;
fputs(PQerrorMessage(pset.db), stderr); psql_error("%s", PQerrorMessage(pset.db));
break; break;
} }
@ -446,7 +486,7 @@ SendQuery(const char *query)
{ {
if (!pset.cur_cmd_interactive) if (!pset.cur_cmd_interactive)
{ {
fprintf(stderr, "%s: connection to server was lost", pset.progname); psql_error("connection to server was lost");
exit(EXIT_BADCONN); exit(EXIT_BADCONN);
} }
fputs("The connection to the server was lost. Attempting reset: ", stderr); fputs("The connection to the server was lost. Attempting reset: ", stderr);

View File

@ -1,22 +1,33 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/common.h,v 1.4 2000/01/18 23:30:23 petere Exp $
*/
#ifndef COMMON_H #ifndef COMMON_H
#define COMMON_H #define COMMON_H
#include <c.h> #include <c.h>
#include "settings.h" #include <libpq-fe.h>
char * char * xstrdup(const char *string);
xstrdup(const char *string);
bool bool setQFout(const char *fname);
setQFout(const char *fname);
char * #ifndef __GNUC__
simple_prompt(const char *prompt, int maxlen, bool echo); void psql_error(const char *fmt, ...);
#else
/* This checks the format string for consistency. */
void psql_error(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
#endif
PGresult * void NoticeProcessor(void * arg, const char * message);
PSQLexec(const char *query);
bool char * simple_prompt(const char *prompt, int maxlen, bool echo);
SendQuery(const char *query);
PGresult * PSQLexec(const char *query);
bool SendQuery(const char *query);
#endif /* COMMON_H */ #endif /* COMMON_H */

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.6 2000/01/18 23:30:23 petere Exp $
*/
#include <c.h> #include <c.h>
#include "copy.h" #include "copy.h"
@ -58,7 +65,7 @@ free_copy_options(struct copy_options * ptr)
static struct copy_options * static struct copy_options *
parse_slash_copy(const char *args, int encoding) parse_slash_copy(const char *args)
{ {
struct copy_options *result; struct copy_options *result;
char *line; char *line;
@ -70,11 +77,11 @@ parse_slash_copy(const char *args, int encoding)
if (!(result = calloc(1, sizeof(struct copy_options)))) if (!(result = calloc(1, sizeof(struct copy_options))))
{ {
perror("calloc"); psql_error("out of memory\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
token = strtokx(line, " \t", "\"", '\\', &quote, NULL, encoding); token = strtokx(line, " \t", "\"", '\\', &quote, NULL, pset.encoding);
if (!token) if (!token)
error = true; error = true;
else else
@ -84,7 +91,7 @@ parse_slash_copy(const char *args, int encoding)
if (!quote && strcasecmp(token, "binary") == 0) if (!quote && strcasecmp(token, "binary") == 0)
{ {
result->binary = true; result->binary = true;
token = strtokx(NULL, " \t", "\"", '\\', &quote, NULL, encoding); token = strtokx(NULL, " \t", "\"", '\\', &quote, NULL, pset.encoding);
if (!token) if (!token)
error = true; error = true;
} }
@ -99,14 +106,14 @@ parse_slash_copy(const char *args, int encoding)
if (!error) if (!error)
{ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, pset.encoding);
if (!token) if (!token)
error = true; error = true;
else else
{ {
if (strcasecmp(token, "with") == 0) if (strcasecmp(token, "with") == 0)
{ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, pset.encoding);
if (!token || strcasecmp(token, "oids") != 0) if (!token || strcasecmp(token, "oids") != 0)
error = true; error = true;
else else
@ -114,7 +121,7 @@ parse_slash_copy(const char *args, int encoding)
if (!error) if (!error)
{ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, pset.encoding);
if (!token) if (!token)
error = true; error = true;
} }
@ -131,7 +138,7 @@ parse_slash_copy(const char *args, int encoding)
if (!error) if (!error)
{ {
token = strtokx(NULL, " \t", "'", '\\', &quote, NULL, encoding); token = strtokx(NULL, " \t", "'", '\\', &quote, NULL, pset.encoding);
if (!token) if (!token)
error = true; error = true;
else if (!quote && (strcasecmp(token, "stdin")==0 || strcasecmp(token, "stdout")==0)) else if (!quote && (strcasecmp(token, "stdin")==0 || strcasecmp(token, "stdout")==0))
@ -142,21 +149,21 @@ parse_slash_copy(const char *args, int encoding)
if (!error) if (!error)
{ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, pset.encoding);
if (token) if (token)
{ {
if (strcasecmp(token, "using") == 0) if (strcasecmp(token, "using") == 0)
{ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, pset.encoding);
if (!token || strcasecmp(token, "delimiters") != 0) if (!token || strcasecmp(token, "delimiters") != 0)
error = true; error = true;
else else
{ {
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", "'", '\\', NULL, NULL, pset.encoding);
if (token) if (token)
{ {
result->delim = xstrdup(token); result->delim = xstrdup(token);
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, pset.encoding);
} }
else else
error = true; error = true;
@ -167,17 +174,17 @@ parse_slash_copy(const char *args, int encoding)
{ {
if (strcasecmp(token, "with") == 0) if (strcasecmp(token, "with") == 0)
{ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, pset.encoding);
if (!token || strcasecmp(token, "null") != 0) if (!token || strcasecmp(token, "null") != 0)
error = true; error = true;
else else
{ {
token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", NULL, '\\', NULL, NULL, pset.encoding);
if (!token || strcasecmp(token, "as") != 0) if (!token || strcasecmp(token, "as") != 0)
error = true; error = true;
else else
{ {
token = strtokx(NULL, " \t", "'", '\\', NULL, NULL, encoding); token = strtokx(NULL, " \t", "'", '\\', NULL, NULL, pset.encoding);
if (token) if (token)
result->null = xstrdup(token); result->null = xstrdup(token);
} }
@ -191,15 +198,11 @@ parse_slash_copy(const char *args, int encoding)
if (error) if (error)
{ {
if (!pset.cur_cmd_interactive) psql_error("\\copy: parse error at %s%s%s\n",
fprintf(stderr, "%s: ", pset.progname); token ? "'" : "",
fputs("\\copy: parse error at ", stderr); token ? token : "end of line",
if (!token) token ? "'" : "");
fputs("end of line", stderr); free_copy_options(result);
else
fprintf(stderr, "'%s'", token);
fputs("\n", stderr);
free(result);
return NULL; return NULL;
} }
else else
@ -214,7 +217,7 @@ parse_slash_copy(const char *args, int encoding)
* file or route its response into the file. * file or route its response into the file.
*/ */
bool bool
do_copy(const char *args, int encoding) do_copy(const char *args)
{ {
char query[128 + NAMEDATALEN]; char query[128 + NAMEDATALEN];
FILE *copystream; FILE *copystream;
@ -223,7 +226,7 @@ do_copy(const char *args, int encoding)
bool success; bool success;
/* parse options */ /* parse options */
options = parse_slash_copy(args, encoding); options = parse_slash_copy(args);
if (!options) if (!options)
return false; return false;
@ -275,11 +278,8 @@ do_copy(const char *args, int encoding)
if (!copystream) if (!copystream)
{ {
if (!pset.cur_cmd_interactive) psql_error("%s: %s\n",
fprintf(stderr, "%s: ", pset.progname); options->file, strerror(errno));
fprintf(stderr,
"unable to open file %s: %s\n",
options->file, strerror(errno));
free_copy_options(options); free_copy_options(options);
return false; return false;
} }
@ -298,24 +298,15 @@ do_copy(const char *args, int encoding)
case PGRES_FATAL_ERROR: case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE: case PGRES_BAD_RESPONSE:
success = false; success = false;
fputs(PQerrorMessage(pset.db), stderr); psql_error("\\copy: %s", PQerrorMessage(pset.db));
break; break;
default: default:
success = false; success = false;
if (!pset.cur_cmd_interactive) psql_error("\\copy: unexpected response (%d)\n", PQresultStatus(result));
fprintf(stderr, "%s: ", pset.progname);
fprintf(stderr, "\\copy: unexpected response (%d)\n", PQresultStatus(result));
} }
PQclear(result); PQclear(result);
if (!success)
{
if (!pset.cur_cmd_interactive)
fprintf(stderr, "%s: ", pset.progname);
fprintf(stderr, "\\copy failed\n");
}
if (copystream != stdout && copystream != stdin) if (copystream != stdout && copystream != stdin)
fclose(copystream); fclose(copystream);
free_copy_options(options); free_copy_options(options);

View File

@ -1,22 +1,23 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/copy.h,v 1.5 2000/01/18 23:30:23 petere Exp $
*/
#ifndef COPY_H #ifndef COPY_H
#define COPY_H #define COPY_H
#include <c.h> #include <c.h>
#include <stdio.h> #include <stdio.h>
#include <libpq-fe.h> #include <libpq-fe.h>
#include "settings.h"
/* handler for \copy */ /* handler for \copy */
bool bool do_copy(const char *args);
do_copy(const char *args, int encoding);
/* lower level processors for copy in/out streams */ /* lower level processors for copy in/out streams */
bool bool handleCopyOut(PGconn *conn, FILE *copystream);
handleCopyOut(PGconn *conn, FILE *copystream); bool handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt);
bool
handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt);
#endif #endif

View File

@ -1,4 +1,10 @@
#include <config.h> /*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.13 2000/01/18 23:30:23 petere Exp $
*/
#include <c.h> #include <c.h>
#include "describe.h" #include "describe.h"
@ -470,7 +476,6 @@ objectDescription(const char *object)
if (!res) if (!res)
return false; return false;
myopt.topt.tuples_only = false;
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = "Object descriptions"; myopt.title = "Object descriptions";
@ -861,10 +866,8 @@ describeTableDetails(const char *name, bool desc)
PQclear(result4); PQclear(result4);
} }
if (!error) { if (!error)
myopt.tuples_only = false; printTable(title, headers, (const char**)cells, (const char**)footers, "llll", &myopt, pset.queryFout);
printTable(title, headers, (const char**)cells, (const char**)footers, "llll", &myopt, pset.queryFout);
}
/* clean up */ /* clean up */
free(title); free(title);
@ -1106,7 +1109,6 @@ listTables(const char *infotype, const char *name, bool desc)
} }
else else
{ {
myopt.topt.tuples_only = false;
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = "List of relations"; myopt.title = "List of relations";

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/describe.h,v 1.6 2000/01/18 23:30:23 petere Exp $
*/
#ifndef DESCRIBE_H #ifndef DESCRIBE_H
#define DESCRIBE_H #define DESCRIBE_H

View File

@ -1,4 +1,10 @@
#include <config.h> /*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/help.c,v 1.11 2000/01/18 23:30:23 petere Exp $
*/
#include <c.h> #include <c.h>
#include "help.h" #include "help.h"
@ -68,23 +74,23 @@ usage(void)
puts( "\nUsage:"); puts( "\nUsage:");
puts( " psql [options] [dbname [username]]"); puts( " psql [options] [dbname [username]]");
puts( "\nOptions:"); puts( "\nOptions:");
puts( " -A Unaligned table output mode (-P format=unaligned"); puts( " -A Unaligned table output mode (-P format=unaligned)");
puts( " -c query Run only single query (or slash command) and exit"); puts( " -c <query> Run only single query (or slash command) and exit");
/* Display default database */ /* Display default database */
env = getenv("PGDATABASE"); env = getenv("PGDATABASE");
if (!env) if (!env)
env = user; env = user;
printf(" -d dbname Specify database name to connect to (default: %s)\n", env); 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 all input in non-interactive mode");
puts( " -E Display queries that internal commands generate"); puts( " -E Display queries that internal commands generate");
puts( " -f filename Execute queries from file, then exit"); puts( " -f <filename> Execute queries from file, then exit");
puts( " -F sep Set field separator (default: \"" DEFAULT_FIELD_SEP "\") (-P fieldsep=)"); puts( " -F <string> Set field separator (default: \"" DEFAULT_FIELD_SEP "\") (-P fieldsep=)");
/* Display default host */ /* Display default host */
env = getenv("PGHOST"); env = getenv("PGHOST");
printf(" -h host Specify database server host (default: "); printf(" -h <host> Specify database server host (default: ");
if (env) if (env)
fputs(env, stdout); fputs(env, stdout);
else else
@ -94,11 +100,11 @@ usage(void)
puts( " -H HTML table output mode (-P format=html)"); puts( " -H HTML table output mode (-P format=html)");
puts( " -l List available databases, then exit"); puts( " -l List available databases, then exit");
puts( " -n Do not use readline or history"); puts( " -n Do not use readline or history");
puts( " -o filename Send query output to filename (or |pipe)"); puts( " -o <filename> Send query output to filename (or |pipe)");
/* Display default port */ /* Display default port */
env = getenv("PGPORT"); env = getenv("PGPORT");
printf(" -p port Specify database server port (default: %s)\n", printf(" -p <port> Specify database server port (default: %s)\n",
env ? env : "hardwired"); env ? env : "hardwired");
puts( " -P var[=arg] Set printing option 'var' to 'arg' (see \\pset command)"); puts( " -P var[=arg] Set printing option 'var' to 'arg' (see \\pset command)");
@ -112,7 +118,7 @@ usage(void)
env = getenv("PGUSER"); env = getenv("PGUSER");
if (!env) if (!env)
env = user; env = user;
printf(" -U [username] Specifiy username, \"?\"=prompt (default user: %s)\n", env); printf(" -U <username> Specifiy username, \"?\"=prompt (default user: %s)\n", env);
puts( " -x Turn on expanded table output (-P expanded)"); puts( " -x Turn on expanded table output (-P expanded)");
puts( " -v name=val Set psql variable 'name' to 'value'"); puts( " -v name=val Set psql variable 'name' to 'value'");
@ -120,9 +126,9 @@ usage(void)
puts( " -W Prompt for password (should happen automatically)"); puts( " -W Prompt for password (should happen automatically)");
puts( "\nFor more information, type \"\\?\" (for internal commands) or \"\\help\""); puts( "\nFor more information, type \"\\?\" (for internal commands) or \"\\help\"");
puts( "(for SQL commands) from within psql, or consult the psql section in the"); puts( "(for SQL commands) from within psql, or consult the psql section in");
puts( "PostgreSQL manual, which accompanies the distribution and is also available at"); puts( "the PostgreSQL manual, which accompanies the distribution and is also");
puts( "<http://www.postgresql.org>."); puts( "available at <http://www.postgresql.org>.");
puts( "Report bugs to <bugs@postgresql.org>."); puts( "Report bugs to <bugs@postgresql.org>.");
#ifndef WIN32 #ifndef WIN32

View File

@ -1,7 +1,14 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/help.h,v 1.4 2000/01/18 23:30:23 petere Exp $
*/
#ifndef HELP_H #ifndef HELP_H
#define HELP_H #define HELP_H
#include "settings.h" #include <c.h>
void usage(void); void usage(void);
@ -11,5 +18,4 @@ void helpSQL(const char *topic);
void print_copyright(void); void print_copyright(void);
#endif #endif

View File

@ -1,4 +1,10 @@
#include <config.h> /*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.7 2000/01/18 23:30:23 petere Exp $
*/
#include <c.h> #include <c.h>
#include "input.h" #include "input.h"
@ -115,7 +121,7 @@ initializeInput(int flags)
{ {
useReadline = true; useReadline = true;
rl_readline_name = "psql"; rl_readline_name = "psql";
initialize_readline(&(pset.db)); initialize_readline();
} }
#endif #endif

View File

@ -1,51 +1,47 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/input.h,v 1.5 2000/01/18 23:30:23 petere Exp $
*/
#ifndef INPUT_H #ifndef INPUT_H
#define INPUT_H #define INPUT_H
#include <config.h>
#include <c.h> #include <c.h>
#include <stdio.h> #include <stdio.h>
#include "settings.h"
/*
/* If some other file needs to have access to readline/history, include this * If some other file needs to have access to readline/history, include this
* file and save yourself all this work. * file and save yourself all this work.
* *
* USE_READLINE and USE_HISTORY are the definite pointers regarding existence or not. * USE_READLINE and USE_HISTORY are the definite pointers regarding existence or not.
*/ */
#ifdef HAVE_LIBREADLINE #ifdef HAVE_LIBREADLINE
#ifdef HAVE_READLINE_H # ifdef HAVE_READLINE_H
#include <readline.h> # include <readline.h>
#define USE_READLINE 1 # define USE_READLINE 1
#else # elif defined(HAVE_READLINE_READLINE_H)
#if defined(HAVE_READLINE_READLINE_H) # include <readline/readline.h>
#include <readline/readline.h> # define USE_READLINE 1
#define USE_READLINE 1 # endif
#endif
#endif
#endif #endif
#if defined(HAVE_LIBHISTORY) || (defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_IN_READLINE)) #if defined(HAVE_LIBHISTORY) || (defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_IN_READLINE))
#if defined(HAVE_HISTORY_H) # ifdef HAVE_HISTORY_H
#include <history.h> # include <history.h>
#define USE_HISTORY 1 # define USE_HISTORY 1
#else # elif defined(HAVE_READLINE_HISTORY_H)
#if defined(HAVE_READLINE_HISTORY_H) # include <readline/history.h>
#include <readline/history.h> # define USE_HISTORY 1
#define USE_HISTORY 1 # endif
#endif #endif
#endif
#endif
char * gets_interactive(const char *prompt); char * gets_interactive(const char *prompt);
char * gets_fromFile(FILE *source); char * gets_fromFile(FILE *source);
void initializeInput(int flags); void initializeInput(int flags);
bool saveHistory(const char *fname); bool saveHistory(const char *fname);
void finishInput(void); void finishInput(void);
#endif #endif /* INPUT_H */

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.6 2000/01/18 23:30:23 petere Exp $
*/
#include <c.h> #include <c.h>
#include "large_obj.h" #include "large_obj.h"

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/large_obj.h,v 1.6 2000/01/18 23:30:23 petere Exp $
*/
#ifndef LARGE_OBJ_H #ifndef LARGE_OBJ_H
#define LARGE_OBJ_H #define LARGE_OBJ_H

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.15 2000/01/18 23:30:23 petere Exp $
*/
#include <c.h> #include <c.h>
#include "mainloop.h" #include "mainloop.h"
@ -25,7 +32,7 @@
* FIXME: rewrite this whole thing with flex * FIXME: rewrite this whole thing with flex
*/ */
int int
MainLoop(FILE *source, int encoding) MainLoop(FILE *source)
{ {
PQExpBuffer query_buf; /* buffer for query being accumulated */ PQExpBuffer query_buf; /* buffer for query being accumulated */
PQExpBuffer previous_buf; /* if there isn't anything in the new buffer PQExpBuffer previous_buf; /* if there isn't anything in the new buffer
@ -52,6 +59,7 @@ MainLoop(FILE *source, int encoding)
FILE *prev_cmd_source; FILE *prev_cmd_source;
bool prev_cmd_interactive; bool prev_cmd_interactive;
unsigned int prev_lineno;
bool die_on_error; bool die_on_error;
@ -68,7 +76,7 @@ MainLoop(FILE *source, int encoding)
previous_buf = createPQExpBuffer(); previous_buf = createPQExpBuffer();
if (!query_buf || !previous_buf) if (!query_buf || !previous_buf)
{ {
perror("createPQExpBuffer"); psql_error("out of memory");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -76,6 +84,8 @@ MainLoop(FILE *source, int encoding)
in_quote = 0; in_quote = 0;
paren_level = 0; paren_level = 0;
slashCmdStatus = CMD_UNKNOWN; /* set default */ slashCmdStatus = CMD_UNKNOWN; /* set default */
prev_lineno = pset.lineno;
pset.lineno = 0;
/* main loop to get queries and execute them */ /* main loop to get queries and execute them */
@ -163,7 +173,10 @@ MainLoop(FILE *source, int encoding)
if (getout) if (getout)
{ {
putc('\n', stdout); /* just newline */ if (QUIET())
putc('\n', stdout);
else
puts("\\q");
break; break;
} }
else else
@ -179,6 +192,8 @@ MainLoop(FILE *source, int encoding)
else else
count_eof = 0; count_eof = 0;
pset.lineno++;
/* strip trailing backslashes, they don't have a clear meaning */ /* strip trailing backslashes, they don't have a clear meaning */
while (1) while (1)
{ {
@ -201,7 +216,7 @@ MainLoop(FILE *source, int encoding)
var = GetVariable(pset.vars, "ECHO"); var = GetVariable(pset.vars, "ECHO");
if (var && strcmp(var, "full")==0) if (var && strcmp(var, "full")==0)
puts(line); puts(line);
fflush(stdout); fflush(stdout);
len = strlen(line); len = strlen(line);
query_start = 0; query_start = 0;
@ -212,10 +227,10 @@ MainLoop(FILE *source, int encoding)
* The current character is at line[i], the prior character at line[i * The current character is at line[i], the prior character at line[i
* - prevlen], the next character at line[i + thislen]. * - prevlen], the next character at line[i + thislen].
*/ */
#define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i, encoding)) #define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i, pset.encoding))
success = true; success = true;
for (i = 0, prevlen = 0, thislen = (len > 0) ? PQmblen(line, encoding) : 0; for (i = 0, prevlen = 0, thislen = (len > 0) ? PQmblen(line, pset.encoding) : 0;
i < len; i < len;
ADVANCE_1) ADVANCE_1)
{ {
@ -293,7 +308,7 @@ MainLoop(FILE *source, int encoding)
new = malloc(len + out_length - (1 + in_length) + 1); new = malloc(len + out_length - (1 + in_length) + 1);
if (!new) if (!new)
{ {
perror("malloc"); psql_error("out of memory");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -374,7 +389,7 @@ MainLoop(FILE *source, int encoding)
/* handle backslash command */ /* handle backslash command */
slashCmdStatus = HandleSlashCmds(&line[i], slashCmdStatus = HandleSlashCmds(&line[i],
query_buf->len>0 ? query_buf : previous_buf, query_buf->len>0 ? query_buf : previous_buf,
&end_of_cmd, encoding); &end_of_cmd);
success = slashCmdStatus != CMD_ERROR; success = slashCmdStatus != CMD_ERROR;
@ -456,6 +471,7 @@ MainLoop(FILE *source, int encoding)
pset.cur_cmd_source = prev_cmd_source; pset.cur_cmd_source = prev_cmd_source;
pset.cur_cmd_interactive = prev_cmd_interactive; pset.cur_cmd_interactive = prev_cmd_interactive;
pset.lineno = prev_lineno;
return successResult; return successResult;
} /* MainLoop() */ } /* MainLoop() */

View File

@ -1,8 +1,15 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/mainloop.h,v 1.5 2000/01/18 23:30:24 petere Exp $
*/
#ifndef MAINLOOP_H #ifndef MAINLOOP_H
#define MAINLOOP_H #define MAINLOOP_H
#include <stdio.h> #include <stdio.h>
int MainLoop(FILE *source, int encoding); int MainLoop(FILE *source);
#endif /* MAINLOOP_H */ #endif /* MAINLOOP_H */

View File

@ -1,4 +1,10 @@
#include <config.h> /*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/print.c,v 1.8 2000/01/18 23:30:24 petere Exp $
*/
#include <c.h> #include <c.h>
#include "print.h" #include "print.h"
@ -30,19 +36,22 @@
static void static void
print_unaligned_text(const char *title, const char * const * headers, print_unaligned_text(const char *title, const char * const * headers,
const char * const * cells, const char * const * footers, const char * const * cells, const char * const * footers,
const char *opt_fieldsep, bool opt_barebones, const char *opt_fieldsep, const char *opt_recordsep, bool opt_barebones,
FILE *fout) FILE *fout)
{ {
unsigned int col_count = 0; unsigned int col_count = 0;
unsigned int i; unsigned int i;
const char * const * ptr; const char * const * ptr;
bool need_recordsep = false;
if (!opt_fieldsep) if (!opt_fieldsep)
opt_fieldsep = ""; opt_fieldsep = "";
if (!opt_recordsep)
opt_recordsep = "";
/* print title */ /* print title */
if (!opt_barebones && title) if (!opt_barebones && title)
fprintf(fout, "%s\n", title); fprintf(fout, "%s%s", title, opt_recordsep);
/* print headers and count columns */ /* print headers and count columns */
for (ptr = headers; *ptr; ptr++) for (ptr = headers; *ptr; ptr++)
@ -56,17 +65,22 @@ print_unaligned_text(const char *title, const char * const * headers,
} }
} }
if (!opt_barebones) if (!opt_barebones)
fputs("\n", fout); need_recordsep = true;
/* print cells */ /* print cells */
i = 0; i = 0;
for (ptr = cells; *ptr; ptr++) for (ptr = cells; *ptr; ptr++)
{ {
if (need_recordsep)
{
fputs(opt_recordsep, fout);
need_recordsep = false;
}
fputs(*ptr, fout); fputs(*ptr, fout);
if ((i + 1) % col_count) if ((i + 1) % col_count)
fputs(opt_fieldsep, fout); fputs(opt_fieldsep, fout);
else else
fputs("\n", fout); need_recordsep = true;
i++; i++;
} }
@ -74,8 +88,19 @@ print_unaligned_text(const char *title, const char * const * headers,
if (!opt_barebones && footers) if (!opt_barebones && footers)
for (ptr = footers; *ptr; ptr++) for (ptr = footers; *ptr; ptr++)
fprintf(fout, "%s\n", *ptr); {
if (need_recordsep)
{
fputs(opt_recordsep, fout);
need_recordsep = false;
}
fputs(*ptr, fout);
need_recordsep = true;
}
/* the last record needs to be concluded with a newline */
if (need_recordsep)
fputc('\n', fout);
} }
@ -83,20 +108,21 @@ print_unaligned_text(const char *title, const char * const * headers,
static void static void
print_unaligned_vertical(const char *title, const char * const * headers, print_unaligned_vertical(const char *title, const char * const * headers,
const char * const * cells, const char * const * footers, const char * const * cells, const char * const * footers,
const char *opt_fieldsep, bool opt_barebones, const char *opt_fieldsep, const char *opt_recordsep, bool opt_barebones,
FILE *fout) FILE *fout)
{ {
unsigned int col_count = 0; unsigned int col_count = 0;
unsigned int i; unsigned int i;
unsigned int record = 1;
const char * const * ptr; const char * const * ptr;
if (!opt_fieldsep) if (!opt_fieldsep)
opt_fieldsep = ""; opt_fieldsep = "";
if (!opt_recordsep)
opt_recordsep = "";
/* print title */ /* print title */
if (!opt_barebones && title) if (!opt_barebones && title)
fprintf(fout, "%s\n", title); fputs(title, fout);
/* count columns */ /* count columns */
for (ptr = headers; *ptr; ptr++) for (ptr = headers; *ptr; ptr++)
@ -105,24 +131,30 @@ print_unaligned_vertical(const char *title, const char * const * headers,
/* print records */ /* print records */
for (i = 0, ptr = cells; *ptr; i++, ptr++) for (i = 0, ptr = cells; *ptr; i++, ptr++)
{ {
if (i % col_count == 0) if (i!=0 || (!opt_barebones && title))
{ {
if (!opt_barebones) fputs(opt_recordsep, fout);
fprintf(fout, "-- RECORD %d\n", record++); if (i % col_count == 0)
else fputs(opt_recordsep, fout); /* another one */
fputc('\n', fout); }
}
fprintf(fout, "%s%s%s\n", headers[i % col_count], opt_fieldsep, *ptr); fputs(headers[i % col_count], fout);
fputs(opt_fieldsep, fout);
fputs(*ptr, fout);
} }
/* print footers */ /* print footers */
if (!opt_barebones && footers && *footers)
if (!opt_barebones && footers)
{ {
fputs("--- END ---\n", fout); fputs(opt_recordsep, fout);
for (ptr = footers; *ptr; ptr++) for (ptr = footers; *ptr; ptr++)
fprintf(fout, "%s\n", *ptr); {
fputs(opt_recordsep, fout);
fputs(*ptr, fout);
}
} }
fputc('\n', fout);
} }
@ -679,9 +711,9 @@ print_latex_text(const char *title, const char * const * headers,
/* print title */ /* print title */
if (!opt_barebones && title) if (!opt_barebones && title)
{ {
fputs("\begin{center}\n", fout); fputs("\\begin{center}\n", fout);
latex_escaped_print(title, fout); latex_escaped_print(title, fout);
fputs("\n\end{center}\n\n", fout); fputs("\n\\end{center}\n\n", fout);
} }
/* begin environment and set alignments and borders */ /* begin environment and set alignments and borders */
@ -776,9 +808,9 @@ print_latex_vertical(const char *title, const char * const * headers,
/* print title */ /* print title */
if (!opt_barebones && title) if (!opt_barebones && title)
{ {
fputs("\begin{center}\n", fout); fputs("\\begin{center}\n", fout);
latex_escaped_print(title, fout); latex_escaped_print(title, fout);
fputs("\n\end{center}\n\n", fout); fputs("\n\\end{center}\n\n", fout);
} }
/* begin environment and set alignments and borders */ /* begin environment and set alignments and borders */
@ -936,9 +968,9 @@ printTable(const char *title,
{ {
case PRINT_UNALIGNED: case PRINT_UNALIGNED:
if (opt->expanded) if (opt->expanded)
print_unaligned_vertical(title, headers, cells, footers, opt->fieldSep, opt->tuples_only, output); print_unaligned_vertical(title, headers, cells, footers, opt->fieldSep, opt->recordSep, opt->tuples_only, output);
else else
print_unaligned_text(title, headers, cells, footers, opt->fieldSep, opt->tuples_only, output); print_unaligned_text(title, headers, cells, footers, opt->fieldSep, opt->recordSep, opt->tuples_only, output);
break; break;
case PRINT_ALIGNED: case PRINT_ALIGNED:
if (opt->expanded) if (opt->expanded)

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/print.h,v 1.5 2000/01/18 23:30:24 petere Exp $
*/
#ifndef PRINT_H #ifndef PRINT_H
#define PRINT_H #define PRINT_H
@ -29,6 +36,7 @@ typedef struct _printTableOpt
unsigned short int border; /* Print a border around the table. unsigned short int border; /* Print a border around the table.
* 0=none, 1=dividing lines, 2=full */ * 0=none, 1=dividing lines, 2=full */
char *fieldSep; /* field separator for unaligned text mode */ char *fieldSep; /* field separator for unaligned text mode */
char *recordSep; /* record separator for unaligned text mode */
char *tableAttr; /* attributes for HTML <table ...> */ char *tableAttr; /* attributes for HTML <table ...> */
} printTableOpt; } printTableOpt;

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.6 2000/01/18 23:30:24 petere Exp $
*/
#include <c.h> #include <c.h>
#include "prompt.h" #include "prompt.h"
@ -22,7 +29,7 @@
* get_prompt * get_prompt
* *
* Returns a statically allocated prompt made by interpolating certain * Returns a statically allocated prompt made by interpolating certain
* tcsh style escape sequences into pset->vars "PROMPT1|2|3". * tcsh style escape sequences into pset.vars "PROMPT1|2|3".
* (might not be completely multibyte safe) * (might not be completely multibyte safe)
* *
* Defined interpolations are: * Defined interpolations are:
@ -49,7 +56,6 @@
* %$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!) * (those will not be rescanned for more escape sequences!)
* *
*
* If the application-wide prompts became NULL somehow, the returned string * If the application-wide prompts became NULL somehow, the returned string
* will be empty (not NULL!). * will be empty (not NULL!).
*-------------------------- *--------------------------

View File

@ -1,7 +1,14 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/prompt.h,v 1.4 2000/01/18 23:30:24 petere Exp $
*/
#ifndef PROMPT_H #ifndef PROMPT_H
#define PROMPT_H #define PROMPT_H
#include "settings.h" #include <c.h>
typedef enum _promptStatus typedef enum _promptStatus
{ {
@ -13,8 +20,6 @@ typedef enum _promptStatus
PROMPT_COPY PROMPT_COPY
} promptStatus_t; } promptStatus_t;
const char * const char *get_prompt(promptStatus_t status);
get_prompt(promptStatus_t status);
#endif /* PROMPT_H */ #endif /* PROMPT_H */

View File

@ -1,6 +1,13 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/settings.h,v 1.7 2000/01/18 23:30:24 petere Exp $
*/
#ifndef SETTINGS_H #ifndef SETTINGS_H
#define SETTINGS_H #define SETTINGS_H
#include <config.h>
#include <c.h> #include <c.h>
#include <stdio.h> #include <stdio.h>
@ -13,6 +20,7 @@
#include "print.h" #include "print.h"
#define DEFAULT_FIELD_SEP "|" #define DEFAULT_FIELD_SEP "|"
#define DEFAULT_RECORD_SEP "\n"
#define DEFAULT_EDITOR "vi" #define DEFAULT_EDITOR "vi"
#define DEFAULT_PROMPT1 "%/%R%# " #define DEFAULT_PROMPT1 "%/%R%# "
@ -23,6 +31,7 @@
typedef struct _psqlSettings typedef struct _psqlSettings
{ {
PGconn *db; /* connection to backend */ PGconn *db; /* connection to backend */
int encoding;
FILE *queryFout; /* where to send the query results */ FILE *queryFout; /* where to send the query results */
bool queryFoutPipe; /* queryFout is from a popen() */ bool queryFoutPipe; /* queryFout is from a popen() */
@ -41,9 +50,9 @@ typedef struct _psqlSettings
* loop */ * loop */
bool cur_cmd_interactive; bool cur_cmd_interactive;
bool has_client_encoding; /* was PGCLIENTENCODING set on
* startup? */
char *progname; /* in case you renamed psql */ char *progname; /* in case you renamed psql */
char *inputfile; /* for error reporting */
unsigned lineno; /* also for error reporting */
} PsqlSettings; } PsqlSettings;
extern PsqlSettings pset; extern PsqlSettings pset;

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.16 2000/01/18 23:30:24 petere Exp $
*/
#include <c.h> #include <c.h>
#include <signal.h> #include <signal.h>
@ -94,13 +101,15 @@ main(int argc, char **argv)
pset.cur_cmd_source = stdin; pset.cur_cmd_source = stdin;
pset.cur_cmd_interactive = false; pset.cur_cmd_interactive = false;
pset.encoding = PQenv2encoding();
pset.vars = CreateVariableSpace(); pset.vars = CreateVariableSpace();
pset.popt.topt.format = PRINT_ALIGNED; pset.popt.topt.format = PRINT_ALIGNED;
pset.queryFout = stdout; pset.queryFout = stdout;
pset.popt.topt.fieldSep = strdup(DEFAULT_FIELD_SEP); pset.popt.topt.fieldSep = xstrdup(DEFAULT_FIELD_SEP);
pset.popt.topt.recordSep = xstrdup(DEFAULT_RECORD_SEP);
pset.popt.topt.border = 1; pset.popt.topt.border = 1;
pset.popt.topt.pager = 1; pset.popt.topt.pager = true;
SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1); SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2); SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
@ -116,10 +125,6 @@ main(int argc, char **argv)
pset.getPassword = false; pset.getPassword = false;
#endif #endif
#ifdef MULTIBYTE
pset.has_client_encoding = (getenv("PGCLIENTENCODING") != NULL);
#endif
parse_options(argc, argv, &options); parse_options(argc, argv, &options);
if (options.action == ACT_LIST_DB) if (options.action == ACT_LIST_DB)
@ -157,12 +162,19 @@ main(int argc, char **argv)
if (PQstatus(pset.db) == CONNECTION_BAD) if (PQstatus(pset.db) == CONNECTION_BAD)
{ {
fprintf(stderr, "%s: connection to database '%s' failed.\n%s", fprintf(stderr, "%s: connection to database \"%s\" failed - %s",
pset.progname, PQdb(pset.db), PQerrorMessage(pset.db)); pset.progname, PQdb(pset.db), PQerrorMessage(pset.db));
PQfinish(pset.db); PQfinish(pset.db);
exit(EXIT_BADCONN); exit(EXIT_BADCONN);
} }
PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
/*
* We need to save the encoding because we want to have it
* available even if the database connection goes bad.
*/
pset.encoding = PQclientencoding(pset.db);
if (options.action == ACT_LIST_DB) if (options.action == ACT_LIST_DB)
{ {
int success = listAllDbs(false); int success = listAllDbs(false);
@ -190,10 +202,10 @@ main(int argc, char **argv)
/* process file given by -f */ /* process file given by -f */
if (options.action == ACT_FILE) if (options.action == ACT_FILE)
successResult = process_file(options.action_string, PQclientencoding(pset.db)) ? 0 : 1; 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) else if (options.action == ACT_SINGLE_SLASH)
successResult = HandleSlashCmds(options.action_string, NULL, NULL, PQclientencoding(pset.db)) != CMD_ERROR ? 0 : 1; 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) else if (options.action == ACT_SINGLE_QUERY)
successResult = SendQuery( options.action_string) ? 0 : 1; successResult = SendQuery( options.action_string) ? 0 : 1;
@ -202,7 +214,7 @@ main(int argc, char **argv)
{ {
process_psqlrc(); process_psqlrc();
initializeInput(options.no_readline ? 0 : 1); initializeInput(options.no_readline ? 0 : 1);
successResult = MainLoop(stdin, PQclientencoding(pset.db)); successResult = MainLoop(stdin);
finishInput(); finishInput();
} }
@ -234,7 +246,6 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
static struct option long_options[] = { static struct option long_options[] = {
{"no-align", no_argument, NULL, 'A'}, {"no-align", no_argument, NULL, 'A'},
{"command", required_argument, NULL, 'c'}, {"command", required_argument, NULL, 'c'},
{"database", required_argument, NULL, 'd'},
{"dbname", required_argument, NULL, 'd'}, {"dbname", required_argument, NULL, 'd'},
{"echo", no_argument, NULL, 'e'}, {"echo", no_argument, NULL, 'e'},
{"echo-hidden", no_argument, NULL, 'E'}, {"echo-hidden", no_argument, NULL, 'E'},
@ -417,8 +428,16 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
pset.getPassword = true; pset.getPassword = true;
break; break;
case '?': case '?':
usage(); if (strcmp(argv[optind-1], "-?")==0)
exit(EXIT_SUCCESS); {
usage();
exit(EXIT_SUCCESS);
}
else
{
fputs("Try -? for help.\n", stderr);
exit(EXIT_FAILURE);
}
break; break;
#ifndef HAVE_GETOPT_LONG #ifndef HAVE_GETOPT_LONG
case '-': case '-':
@ -428,7 +447,7 @@ parse_options(int argc, char *argv[], struct adhoc_opts * options)
break; break;
#endif #endif
default: default:
usage(); fputs("Try -? for help.\n", stderr);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
} }
@ -466,20 +485,16 @@ process_psqlrc(void)
{ {
char *psqlrc; char *psqlrc;
char *home; char *home;
int encoding;
#ifdef WIN32 #ifdef WIN32
#define R_OK 0 #define R_OK 0
#endif #endif
/* get client side encoding from envrionment variable if any */
encoding = PQenv2encoding();
/* System-wide startup file */ /* System-wide startup file */
if (access("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, R_OK) == 0) if (access("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, R_OK) == 0)
process_file("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, encoding); process_file("/etc/psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION);
else if (access("/etc/psqlrc", R_OK) == 0) else if (access("/etc/psqlrc", R_OK) == 0)
process_file("/etc/psqlrc", encoding); process_file("/etc/psqlrc");
/* Look for one in the home dir */ /* Look for one in the home dir */
home = getenv("HOME"); home = getenv("HOME");
@ -489,18 +504,18 @@ process_psqlrc(void)
psqlrc = (char *) malloc(strlen(home) + 20); psqlrc = (char *) malloc(strlen(home) + 20);
if (!psqlrc) if (!psqlrc)
{ {
perror("malloc"); fprintf(stderr, "%s: out of memory\n", pset.progname);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
sprintf(psqlrc, "%s/.psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, home); sprintf(psqlrc, "%s/.psqlrc-" PG_RELEASE "." PG_VERSION "." PG_SUBVERSION, home);
if (access(psqlrc, R_OK) == 0) if (access(psqlrc, R_OK) == 0)
process_file(psqlrc, encoding); process_file(psqlrc);
else else
{ {
sprintf(psqlrc, "%s/.psqlrc", home); sprintf(psqlrc, "%s/.psqlrc", home);
if (access(psqlrc, R_OK) == 0) if (access(psqlrc, R_OK) == 0)
process_file(psqlrc, encoding); process_file(psqlrc);
} }
free(psqlrc); free(psqlrc);
} }

View File

@ -1,4 +1,10 @@
#include <config.h> /*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/stringutils.c,v 1.22 2000/01/18 23:30:24 petere Exp $
*/
#include <c.h> #include <c.h>
#include "stringutils.h" #include "stringutils.h"

View File

@ -1,3 +1,10 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/stringutils.h,v 1.12 2000/01/18 23:30:24 petere Exp $
*/
#ifndef STRINGUTILS_H #ifndef STRINGUTILS_H
#define STRINGUTILS_H #define STRINGUTILS_H

View File

@ -1,3 +1,11 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.7 2000/01/18 23:30:24 petere Exp $
*/
/*----------- /*-----------
This file implements a somewhat more sophisticated readline "TAB completion" This file implements a somewhat more sophisticated readline "TAB completion"
in psql. It is not intended to be AI, to replace learning SQL, or to relieve in psql. It is not intended to be AI, to replace learning SQL, or to relieve
@ -24,7 +32,6 @@
gracefully. gracefully.
-------------*/ -------------*/
#include <config.h>
#include <c.h> #include <c.h>
#include "tab-complete.h" #include "tab-complete.h"
@ -44,17 +51,11 @@
#include <libpq-fe.h> #include <libpq-fe.h>
#include "common.h" #include "common.h"
#include "settings.h"
#define BUF_SIZE 2048 #define BUF_SIZE 2048
#define ERROR_QUERY_TOO_LONG /* empty */ #define ERROR_QUERY_TOO_LONG /* empty */
/* This pointer saves the place where psql stores its own pointer to the
currently active database connection. This is probably a less than ideal way
of passing this around, but this way I only had to make minimal changes to
psql.c. */
static PGconn ** database_connection;
/* Forward declaration of functions */ /* Forward declaration of functions */
static char ** psql_completion(char *text, int start, int end); static char ** psql_completion(char *text, int start, int end);
@ -80,21 +81,10 @@ char * completion_info_charp; /* if you need to pass another string */
static int completion_max_records; static int completion_max_records;
static void * xmalloc(size_t length)
{
void *tmp = malloc(length);
if (!tmp) {
perror("malloc");
exit(EXIT_FAILURE);
}
return tmp;
}
/* Initialize the readline library for our purposes. */ /* Initialize the readline library for our purposes. */
void initialize_readline(PGconn ** conn) void initialize_readline(void)
{ {
rl_readline_name = "psql"; rl_readline_name = pset.progname;
rl_attempted_completion_function = psql_completion; rl_attempted_completion_function = psql_completion;
rl_special_prefixes = "()'"; rl_special_prefixes = "()'";
@ -103,8 +93,6 @@ void initialize_readline(PGconn ** conn)
completion_max_records = 100; completion_max_records = 100;
/* There is a variable rl_completion_query_items for this but apparently /* There is a variable rl_completion_query_items for this but apparently
it's not defined everywhere. */ it's not defined everywhere. */
database_connection = conn;
} }
@ -511,7 +499,8 @@ char ** psql_completion(char *text, int start, int end)
COMPLETE_WITH_LIST(sql_commands); COMPLETE_WITH_LIST(sql_commands);
else if (strcmp(prev_wd, "\\pset")==0) { else if (strcmp(prev_wd, "\\pset")==0) {
char * my_list[] = { "format", "border", "expanded", "null", "fieldsep", char * my_list[] = { "format", "border", "expanded", "null", "fieldsep",
"tuples_only", "title", "tableattr", "pager", NULL }; "tuples_only", "title", "tableattr", "pager",
"recordsep", NULL };
COMPLETE_WITH_LIST(my_list); COMPLETE_WITH_LIST(my_list);
} }
else if( strcmp(prev_wd, "\\e")==0 || strcmp(prev_wd, "\\edit")==0 || else if( strcmp(prev_wd, "\\e")==0 || strcmp(prev_wd, "\\edit")==0 ||
@ -703,7 +692,7 @@ PGresult * exec_query(char * query)
PGresult * result; PGresult * result;
char query_buffer[BUF_SIZE]; char query_buffer[BUF_SIZE];
if (query == NULL || PQstatus(*database_connection) != CONNECTION_OK) if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
return NULL; return NULL;
#ifdef USE_ASSERT_CHECKING #ifdef USE_ASSERT_CHECKING
assert( query[strlen(query)-1] != ';' ); assert( query[strlen(query)-1] != ';' );
@ -714,12 +703,12 @@ PGresult * exec_query(char * query)
return NULL; return NULL;
} }
result = PQexec(*database_connection, query); result = PQexec(pset.db, query);
if (result != NULL && PQresultStatus(result) != PGRES_TUPLES_OK) { if (result != NULL && PQresultStatus(result) != PGRES_TUPLES_OK) {
#ifdef NOT_USED #if 0
fprintf(stderr, "\nThe completion query \"%s\" failed thus: %s\n", psql_error("tab completion: %s failed - %s",
query, PQresStatus(PQresultStatus(result))); query, PQresStatus(PQresultStatus(result)));
#endif #endif
PQclear(result); PQclear(result);
result = NULL; result = NULL;
@ -767,7 +756,16 @@ char * previous_word(int point, int skip) {
} }
/* make a copy */ /* make a copy */
s = (char *)xmalloc(end-start+2); s = (char *)malloc(end-start+2);
if (!s)
{
psql_error("out of memory\n");
if (!pset.cur_cmd_interactive)
exit(EXIT_FAILURE);
else
return NULL;
}
strncpy(s, &rl_line_buffer[start], end-start+1); strncpy(s, &rl_line_buffer[start], end-start+1);
s[end-start+1] = '\0'; s[end-start+1] = '\0';
@ -776,11 +774,13 @@ char * previous_word(int point, int skip) {
#ifdef NOT_USED #if 0
/* Surround a string with single quotes. This works for both SQL and /*
psql internal. Doesn't work so well yet. * Surround a string with single quotes. This works for both SQL and
*/ * psql internal. Currently disable because it is reported not to
* cooperate with certain versions of readline.
*/
char * quote_file_name(char *text, int match_type, char * quote_pointer) char * quote_file_name(char *text, int match_type, char * quote_pointer)
{ {
char *s; char *s;
@ -789,7 +789,7 @@ char * quote_file_name(char *text, int match_type, char * quote_pointer)
(void)quote_pointer; /* not used */ (void)quote_pointer; /* not used */
length = strlen(text) + ( match_type==SINGLE_MATCH ? 3 : 2 ); length = strlen(text) + ( match_type==SINGLE_MATCH ? 3 : 2 );
s = xmalloc(length); s = malloc(length);
s[0] = '\''; s[0] = '\'';
strcpy(s+1, text); strcpy(s+1, text);
if (match_type==SINGLE_MATCH) if (match_type==SINGLE_MATCH)
@ -809,13 +809,13 @@ static char * dequote_file_name(char *text, char quote_char)
return xstrdup(text); return xstrdup(text);
length = strlen(text); length = strlen(text);
s = xmalloc(length-2+1); s = malloc(length-2+1);
strncpy(s, text+1, length-2); strncpy(s, text+1, length-2);
s[length] = '\0'; s[length] = '\0';
return s; return s;
} }
#endif /* NOT_USED */ #endif /* 0 */
#endif /* USE_READLINE */ #endif /* USE_READLINE */

View File

@ -1,8 +1,13 @@
/*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.h,v 1.2 2000/01/18 23:30:24 petere Exp $
*/
#ifndef TAB_COMPLETE_H #ifndef TAB_COMPLETE_H
#define TAB_COMPLETE_H #define TAB_COMPLETE_H
#include <libpq-fe.h> void initialize_readline(void);
void initialize_readline(PGconn ** conn);
#endif #endif

View File

@ -1,4 +1,10 @@
#include <config.h> /*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/variables.c,v 1.4 2000/01/18 23:30:24 petere Exp $
*/
#include <c.h> #include <c.h>
#include "variables.h" #include "variables.h"

View File

@ -1,4 +1,13 @@
/* This implements a sort of variable repository. One could also think of it /*
* psql - the PostgreSQL interactive terminal
*
* Copyright 2000 by PostgreSQL Global Development Team
*
* $Header: /cvsroot/pgsql/src/bin/psql/variables.h,v 1.4 2000/01/18 23:30:24 petere Exp $
*/
/*
* This implements a sort of variable repository. One could also think of it
* as cheap version of an associative array. In each one of these * as cheap version of an associative array. In each one of these
* datastructures you can store name/value pairs. * datastructures you can store name/value pairs.
* *