1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

Update psql for some features of new FE/BE protocol. There is a

client-side AUTOCOMMIT mode now: '\set AUTOCOMMIT off' supports
SQL-spec commit behavior.  Get rid of LO_TRANSACTION hack --- the
LO operations just work now, using libpq's ability to track the
transaction status.  Add a VERBOSE variable to control verboseness
of error message display, and add a %T prompt-string code to show
current transaction-block status.  Superuser state display in the
prompt string correctly follows SET SESSION AUTHORIZATION commands.
Control-C works to get out of COPY IN state.
This commit is contained in:
Tom Lane
2003-06-28 00:12:40 +00:00
parent ea20397b79
commit f9ebf36970
14 changed files with 476 additions and 463 deletions

View File

@ -3,7 +3,7 @@
*
* Copyright 2000-2002 by PostgreSQL Global Development Group
*
* $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.96 2003/05/14 03:26:02 tgl Exp $
* $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.97 2003/06/28 00:12:40 tgl Exp $
*/
#include "postgres_fe.h"
#include "command.h"
@ -457,20 +457,30 @@ exec_command(const char *cmd,
char *encoding = scan_option(&string, OT_NORMAL, NULL, false);
if (!encoding)
/* show encoding */
{
/* show encoding --- first check for change sent from server */
if (pset.encoding != PQclientEncoding(pset.db) &&
PQclientEncoding(pset.db) >= 0)
{
pset.encoding = PQclientEncoding(pset.db);
pset.popt.topt.encoding = pset.encoding;
SetVariable(pset.vars, "ENCODING",
pg_encoding_to_char(pset.encoding));
}
puts(pg_encoding_to_char(pset.encoding));
}
else
{
/* set encoding */
if (PQsetClientEncoding(pset.db, encoding) == -1)
psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
else
{
/* save encoding info into psql internal data */
pset.encoding = PQclientEncoding(pset.db);
pset.popt.topt.encoding = PQclientEncoding(pset.db);
SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
pset.popt.topt.encoding = pset.encoding;
SetVariable(pset.vars, "ENCODING",
pg_encoding_to_char(pset.encoding));
}
free(encoding);
}
@ -694,7 +704,13 @@ exec_command(const char *cmd,
free(opt);
}
if (!SetVariable(pset.vars, opt0, newval))
if (SetVariable(pset.vars, opt0, newval))
{
/* Check for special variables */
if (strcmp(opt0, "VERBOSE") == 0)
SyncVerboseVariable();
}
else
{
psql_error("\\%s: error\n", cmd);
success = false;
@ -1327,11 +1343,7 @@ do_connect(const char *new_dbname, const char *new_user)
bool success = false;
/* Delete variables (in case we fail before setting them anew) */
SetVariable(pset.vars, "DBNAME", NULL);
SetVariable(pset.vars, "USER", NULL);
SetVariable(pset.vars, "HOST", NULL);
SetVariable(pset.vars, "PORT", NULL);
SetVariable(pset.vars, "ENCODING", NULL);
UnsyncVariables();
/* If dbname is "" then use old name, else new one (even if NULL) */
if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "") == 0)
@ -1429,51 +1441,75 @@ do_connect(const char *new_dbname, const char *new_user)
}
PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
pset.encoding = PQclientEncoding(pset.db);
pset.popt.topt.encoding = PQclientEncoding(pset.db);
/* Update variables */
SyncVariables();
return success;
}
/*
* SyncVariables
*
* Make psql's internal variables agree with connection state upon
* establishing a new connection.
*/
void
SyncVariables(void)
{
/* get stuff from connection */
pset.encoding = PQclientEncoding(pset.db);
pset.popt.topt.encoding = pset.encoding;
SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
SetVariable(pset.vars, "USER", PQuser(pset.db));
SetVariable(pset.vars, "HOST", PQhost(pset.db));
SetVariable(pset.vars, "PORT", PQport(pset.db));
SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
pset.issuper = test_superuser(PQuser(pset.db));
return success;
/* send stuff to it, too */
SyncVerboseVariable();
}
/*
* Test if the given user is a database superuser.
* (Is used to set up the prompt right.)
* UnsyncVariables
*
* Clear variables that should be not be set when there is no connection.
*/
bool
test_superuser(const char *username)
void
UnsyncVariables(void)
{
PGresult *res;
PQExpBufferData buf;
bool answer;
if (!username)
return false;
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf, "SELECT usesuper FROM pg_catalog.pg_user WHERE usename = '%s'", username);
res = PSQLexec(buf.data, true);
termPQExpBuffer(&buf);
answer =
(res && PQntuples(res) > 0 && PQnfields(res) > 0
&& !PQgetisnull(res, 0, 0)
&& PQgetvalue(res, 0, 0)
&& strcmp(PQgetvalue(res, 0, 0), "t") == 0);
PQclear(res);
return answer;
SetVariable(pset.vars, "DBNAME", NULL);
SetVariable(pset.vars, "USER", NULL);
SetVariable(pset.vars, "HOST", NULL);
SetVariable(pset.vars, "PORT", NULL);
SetVariable(pset.vars, "ENCODING", NULL);
}
/*
* Update connection state from VERBOSE variable
*/
void
SyncVerboseVariable(void)
{
switch (SwitchVariable(pset.vars, "VERBOSE",
"default", "terse", "verbose", NULL))
{
case 1: /* default */
PQsetErrorVerbosity(pset.db, PQERRORS_DEFAULT);
break;
case 2: /* terse */
PQsetErrorVerbosity(pset.db, PQERRORS_TERSE);
break;
case 3: /* verbose */
PQsetErrorVerbosity(pset.db, PQERRORS_VERBOSE);
break;
default: /* not set or unrecognized value */
PQsetErrorVerbosity(pset.db, PQERRORS_DEFAULT);
break;
}
}
/*