mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Invent an assign-hook mechanism for psql variables similar to the one
existing for backend GUC variables, and use this to eliminate repeated fetching/parsing of psql variables in psql's inner loops. In a trivial test with lots of 'select 1;' commands, psql's CPU time went down almost 10%, although of course the effect on total elapsed time was much less. Per discussion about how to ensure the upcoming FETCH_COUNT patch doesn't cost any performance when not being used.
This commit is contained in:
parent
b681bfdd59
commit
0434c46db0
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.171 2006/07/18 17:42:01 momjian Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.172 2006/08/29 15:19:50 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
@ -55,8 +55,6 @@ static backslashResult exec_command(const char *cmd,
|
|||||||
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
|
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
|
||||||
static bool do_connect(char *dbname, char *user, char *host, char *port);
|
static bool do_connect(char *dbname, char *user, char *host, char *port);
|
||||||
static bool do_shell(const char *command);
|
static bool do_shell(const char *command);
|
||||||
static void SyncVerbosityVariable(void);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*----------
|
/*----------
|
||||||
@ -196,7 +194,6 @@ exec_command(const char *cmd,
|
|||||||
{
|
{
|
||||||
bool success = true; /* indicate here if the command ran ok or
|
bool success = true; /* indicate here if the command ran ok or
|
||||||
* failed */
|
* failed */
|
||||||
bool quiet = QUIET();
|
|
||||||
backslashResult status = PSQL_CMD_SKIP_LINE;
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -206,9 +203,9 @@ exec_command(const char *cmd,
|
|||||||
if (strcmp(cmd, "a") == 0)
|
if (strcmp(cmd, "a") == 0)
|
||||||
{
|
{
|
||||||
if (pset.popt.topt.format != PRINT_ALIGNED)
|
if (pset.popt.topt.format != PRINT_ALIGNED)
|
||||||
success = do_pset("format", "aligned", &pset.popt, quiet);
|
success = do_pset("format", "aligned", &pset.popt, pset.quiet);
|
||||||
else
|
else
|
||||||
success = do_pset("format", "unaligned", &pset.popt, quiet);
|
success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \C -- override table title (formerly change HTML caption) */
|
/* \C -- override table title (formerly change HTML caption) */
|
||||||
@ -217,7 +214,7 @@ exec_command(const char *cmd,
|
|||||||
char *opt = psql_scan_slash_option(scan_state,
|
char *opt = psql_scan_slash_option(scan_state,
|
||||||
OT_NORMAL, NULL, true);
|
OT_NORMAL, NULL, true);
|
||||||
|
|
||||||
success = do_pset("title", opt, &pset.popt, quiet);
|
success = do_pset("title", opt, &pset.popt, pset.quiet);
|
||||||
free(opt);
|
free(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,7 +490,7 @@ exec_command(const char *cmd,
|
|||||||
char *fname = psql_scan_slash_option(scan_state,
|
char *fname = psql_scan_slash_option(scan_state,
|
||||||
OT_NORMAL, NULL, false);
|
OT_NORMAL, NULL, false);
|
||||||
|
|
||||||
success = do_pset("fieldsep", fname, &pset.popt, quiet);
|
success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
|
||||||
free(fname);
|
free(fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,9 +525,9 @@ exec_command(const char *cmd,
|
|||||||
else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
|
else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
|
||||||
{
|
{
|
||||||
if (pset.popt.topt.format != PRINT_HTML)
|
if (pset.popt.topt.format != PRINT_HTML)
|
||||||
success = do_pset("format", "html", &pset.popt, quiet);
|
success = do_pset("format", "html", &pset.popt, pset.quiet);
|
||||||
else
|
else
|
||||||
success = do_pset("format", "aligned", &pset.popt, quiet);
|
success = do_pset("format", "aligned", &pset.popt, pset.quiet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -638,7 +635,7 @@ exec_command(const char *cmd,
|
|||||||
{
|
{
|
||||||
if (query_buf && query_buf->len > 0)
|
if (query_buf && query_buf->len > 0)
|
||||||
puts(query_buf->data);
|
puts(query_buf->data);
|
||||||
else if (!quiet)
|
else if (!pset.quiet)
|
||||||
puts(_("Query buffer is empty."));
|
puts(_("Query buffer is empty."));
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
@ -712,7 +709,7 @@ exec_command(const char *cmd,
|
|||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
success = do_pset(opt0, opt1, &pset.popt, quiet);
|
success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
|
||||||
|
|
||||||
free(opt0);
|
free(opt0);
|
||||||
free(opt1);
|
free(opt1);
|
||||||
@ -727,7 +724,7 @@ exec_command(const char *cmd,
|
|||||||
{
|
{
|
||||||
resetPQExpBuffer(query_buf);
|
resetPQExpBuffer(query_buf);
|
||||||
psql_scan_reset(scan_state);
|
psql_scan_reset(scan_state);
|
||||||
if (!quiet)
|
if (!pset.quiet)
|
||||||
puts(_("Query buffer reset (cleared)."));
|
puts(_("Query buffer reset (cleared)."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -740,7 +737,7 @@ exec_command(const char *cmd,
|
|||||||
expand_tilde(&fname);
|
expand_tilde(&fname);
|
||||||
/* This scrolls off the screen when using /dev/tty */
|
/* This scrolls off the screen when using /dev/tty */
|
||||||
success = saveHistory(fname ? fname : DEVTTY, false);
|
success = saveHistory(fname ? fname : DEVTTY, false);
|
||||||
if (success && !quiet && fname)
|
if (success && !pset.quiet && fname)
|
||||||
printf(gettext("Wrote history to file \"%s/%s\".\n"),
|
printf(gettext("Wrote history to file \"%s/%s\".\n"),
|
||||||
pset.dirname ? pset.dirname : ".", fname);
|
pset.dirname ? pset.dirname : ".", fname);
|
||||||
if (!fname)
|
if (!fname)
|
||||||
@ -786,13 +783,7 @@ exec_command(const char *cmd,
|
|||||||
free(opt);
|
free(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SetVariable(pset.vars, opt0, newval))
|
if (!SetVariable(pset.vars, opt0, newval))
|
||||||
{
|
|
||||||
/* Check for special variables */
|
|
||||||
if (strcmp(opt0, "VERBOSITY") == 0)
|
|
||||||
SyncVerbosityVariable();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
psql_error("\\%s: error\n", cmd);
|
psql_error("\\%s: error\n", cmd);
|
||||||
success = false;
|
success = false;
|
||||||
@ -804,7 +795,7 @@ exec_command(const char *cmd,
|
|||||||
|
|
||||||
/* \t -- turn off headers and row count */
|
/* \t -- turn off headers and row count */
|
||||||
else if (strcmp(cmd, "t") == 0)
|
else if (strcmp(cmd, "t") == 0)
|
||||||
success = do_pset("tuples_only", NULL, &pset.popt, quiet);
|
success = do_pset("tuples_only", NULL, &pset.popt, pset.quiet);
|
||||||
|
|
||||||
|
|
||||||
/* \T -- define html <table ...> attributes */
|
/* \T -- define html <table ...> attributes */
|
||||||
@ -813,7 +804,7 @@ exec_command(const char *cmd,
|
|||||||
char *value = psql_scan_slash_option(scan_state,
|
char *value = psql_scan_slash_option(scan_state,
|
||||||
OT_NORMAL, NULL, false);
|
OT_NORMAL, NULL, false);
|
||||||
|
|
||||||
success = do_pset("tableattr", value, &pset.popt, quiet);
|
success = do_pset("tableattr", value, &pset.popt, pset.quiet);
|
||||||
free(value);
|
free(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,7 +812,7 @@ exec_command(const char *cmd,
|
|||||||
else if (strcmp(cmd, "timing") == 0)
|
else if (strcmp(cmd, "timing") == 0)
|
||||||
{
|
{
|
||||||
pset.timing = !pset.timing;
|
pset.timing = !pset.timing;
|
||||||
if (!quiet)
|
if (!pset.quiet)
|
||||||
{
|
{
|
||||||
if (pset.timing)
|
if (pset.timing)
|
||||||
puts(_("Timing is on."));
|
puts(_("Timing is on."));
|
||||||
@ -916,7 +907,7 @@ exec_command(const char *cmd,
|
|||||||
|
|
||||||
/* \x -- toggle expanded table representation */
|
/* \x -- toggle expanded table representation */
|
||||||
else if (strcmp(cmd, "x") == 0)
|
else if (strcmp(cmd, "x") == 0)
|
||||||
success = do_pset("expanded", NULL, &pset.popt, quiet);
|
success = do_pset("expanded", NULL, &pset.popt, pset.quiet);
|
||||||
|
|
||||||
/* \z -- list table rights (equivalent to \dp) */
|
/* \z -- list table rights (equivalent to \dp) */
|
||||||
else if (strcmp(cmd, "z") == 0)
|
else if (strcmp(cmd, "z") == 0)
|
||||||
@ -1114,7 +1105,7 @@ do_connect(char *dbname, char *user, char *host, char *port)
|
|||||||
SyncVariables();
|
SyncVariables();
|
||||||
|
|
||||||
/* Tell the user about the new connection */
|
/* Tell the user about the new connection */
|
||||||
if (!QUIET())
|
if (!pset.quiet)
|
||||||
{
|
{
|
||||||
printf(_("You are now connected to database \"%s\""), PQdb(pset.db));
|
printf(_("You are now connected to database \"%s\""), PQdb(pset.db));
|
||||||
|
|
||||||
@ -1148,6 +1139,7 @@ SyncVariables(void)
|
|||||||
/* get stuff from connection */
|
/* get stuff from connection */
|
||||||
pset.encoding = PQclientEncoding(pset.db);
|
pset.encoding = PQclientEncoding(pset.db);
|
||||||
pset.popt.topt.encoding = pset.encoding;
|
pset.popt.topt.encoding = pset.encoding;
|
||||||
|
pset.sversion = PQserverVersion(pset.db);
|
||||||
|
|
||||||
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));
|
||||||
@ -1156,7 +1148,7 @@ SyncVariables(void)
|
|||||||
SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
|
SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
|
||||||
|
|
||||||
/* send stuff to it, too */
|
/* send stuff to it, too */
|
||||||
SyncVerbosityVariable();
|
PQsetErrorVerbosity(pset.db, pset.verbosity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1174,32 +1166,6 @@ UnsyncVariables(void)
|
|||||||
SetVariable(pset.vars, "ENCODING", NULL);
|
SetVariable(pset.vars, "ENCODING", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Update connection state from VERBOSITY variable
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
SyncVerbosityVariable(void)
|
|
||||||
{
|
|
||||||
switch (SwitchVariable(pset.vars, "VERBOSITY",
|
|
||||||
"default", "terse", "verbose", NULL))
|
|
||||||
{
|
|
||||||
case 1: /* default */
|
|
||||||
pset.verbosity = PQERRORS_DEFAULT;
|
|
||||||
break;
|
|
||||||
case 2: /* terse */
|
|
||||||
pset.verbosity = PQERRORS_TERSE;
|
|
||||||
break;
|
|
||||||
case 3: /* verbose */
|
|
||||||
pset.verbosity = PQERRORS_VERBOSE;
|
|
||||||
break;
|
|
||||||
default: /* not set or unrecognized value */
|
|
||||||
pset.verbosity = PQERRORS_DEFAULT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
PQsetErrorVerbosity(pset.db, pset.verbosity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do_edit -- handler for \e
|
* do_edit -- handler for \e
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.125 2006/08/25 04:06:54 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.126 2006/08/29 15:19:50 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -515,7 +515,6 @@ PGresult *
|
|||||||
PSQLexec(const char *query, bool start_xact)
|
PSQLexec(const char *query, bool start_xact)
|
||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
int echo_hidden;
|
|
||||||
|
|
||||||
if (!pset.db)
|
if (!pset.db)
|
||||||
{
|
{
|
||||||
@ -523,8 +522,7 @@ PSQLexec(const char *query, bool start_xact)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
echo_hidden = SwitchVariable(pset.vars, "ECHO_HIDDEN", "noexec", NULL);
|
if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
|
||||||
if (echo_hidden != VAR_NOTSET)
|
|
||||||
{
|
{
|
||||||
printf(_("********* QUERY **********\n"
|
printf(_("********* QUERY **********\n"
|
||||||
"%s\n"
|
"%s\n"
|
||||||
@ -539,14 +537,15 @@ PSQLexec(const char *query, bool start_xact)
|
|||||||
fflush(pset.logfile);
|
fflush(pset.logfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (echo_hidden == 1) /* noexec? */
|
if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetCancelConn();
|
SetCancelConn();
|
||||||
|
|
||||||
if (start_xact && PQtransactionStatus(pset.db) == PQTRANS_IDLE &&
|
if (start_xact &&
|
||||||
!GetVariableBool(pset.vars, "AUTOCOMMIT"))
|
!pset.autocommit &&
|
||||||
|
PQtransactionStatus(pset.db) == PQTRANS_IDLE)
|
||||||
{
|
{
|
||||||
res = PQexec(pset.db, "BEGIN");
|
res = PQexec(pset.db, "BEGIN");
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||||
@ -693,7 +692,7 @@ PrintQueryStatus(PGresult *results)
|
|||||||
{
|
{
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
|
||||||
if (!QUIET())
|
if (!pset.quiet)
|
||||||
{
|
{
|
||||||
if (pset.popt.topt.format == PRINT_HTML)
|
if (pset.popt.topt.format == PRINT_HTML)
|
||||||
{
|
{
|
||||||
@ -789,7 +788,6 @@ SendQuery(const char *query)
|
|||||||
on_error_rollback_savepoint = false;
|
on_error_rollback_savepoint = false;
|
||||||
PGTransactionStatusType transaction_status;
|
PGTransactionStatusType transaction_status;
|
||||||
static bool on_error_rollback_warning = false;
|
static bool on_error_rollback_warning = false;
|
||||||
const char *rollback_str;
|
|
||||||
|
|
||||||
if (!pset.db)
|
if (!pset.db)
|
||||||
{
|
{
|
||||||
@ -797,7 +795,7 @@ SendQuery(const char *query)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetVariableBool(pset.vars, "SINGLESTEP"))
|
if (pset.singlestep)
|
||||||
{
|
{
|
||||||
char buf[3];
|
char buf[3];
|
||||||
|
|
||||||
@ -810,7 +808,7 @@ SendQuery(const char *query)
|
|||||||
if (buf[0] == 'x')
|
if (buf[0] == 'x')
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (VariableEquals(pset.vars, "ECHO", "queries"))
|
else if (pset.echo == PSQL_ECHO_QUERIES)
|
||||||
{
|
{
|
||||||
puts(query);
|
puts(query);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@ -830,7 +828,7 @@ SendQuery(const char *query)
|
|||||||
transaction_status = PQtransactionStatus(pset.db);
|
transaction_status = PQtransactionStatus(pset.db);
|
||||||
|
|
||||||
if (transaction_status == PQTRANS_IDLE &&
|
if (transaction_status == PQTRANS_IDLE &&
|
||||||
!GetVariableBool(pset.vars, "AUTOCOMMIT") &&
|
!pset.autocommit &&
|
||||||
!command_no_begin(query))
|
!command_no_begin(query))
|
||||||
{
|
{
|
||||||
results = PQexec(pset.db, "BEGIN");
|
results = PQexec(pset.db, "BEGIN");
|
||||||
@ -846,11 +844,9 @@ SendQuery(const char *query)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (transaction_status == PQTRANS_INTRANS &&
|
if (transaction_status == PQTRANS_INTRANS &&
|
||||||
(rollback_str = GetVariable(pset.vars, "ON_ERROR_ROLLBACK")) != NULL &&
|
pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF &&
|
||||||
/* !off and !interactive is 'on' */
|
|
||||||
pg_strcasecmp(rollback_str, "off") != 0 &&
|
|
||||||
(pset.cur_cmd_interactive ||
|
(pset.cur_cmd_interactive ||
|
||||||
pg_strcasecmp(rollback_str, "interactive") != 0))
|
pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON))
|
||||||
{
|
{
|
||||||
if (on_error_rollback_warning == false && pset.sversion < 80000)
|
if (on_error_rollback_warning == false && pset.sversion < 80000)
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.66 2006/06/14 16:49:02 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.67 2006/08/29 15:19:50 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
@ -704,7 +704,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary)
|
|||||||
/* Prompt if interactive input */
|
/* Prompt if interactive input */
|
||||||
if (isatty(fileno(copystream)))
|
if (isatty(fileno(copystream)))
|
||||||
{
|
{
|
||||||
if (!QUIET())
|
if (!pset.quiet)
|
||||||
puts(_("Enter data to be copied followed by a newline.\n"
|
puts(_("Enter data to be copied followed by a newline.\n"
|
||||||
"End with a backslash and a period on a line by itself."));
|
"End with a backslash and a period on a line by itself."));
|
||||||
prompt = get_prompt(PROMPT_COPY);
|
prompt = get_prompt(PROMPT_COPY);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.143 2006/08/25 04:06:54 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.144 2006/08/29 15:19:51 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "describe.h"
|
#include "describe.h"
|
||||||
@ -673,7 +673,7 @@ describeTableDetails(const char *pattern, bool verbose)
|
|||||||
|
|
||||||
if (PQntuples(res) == 0)
|
if (PQntuples(res) == 0)
|
||||||
{
|
{
|
||||||
if (!QUIET())
|
if (!pset.quiet)
|
||||||
fprintf(stderr, _("Did not find any relation named \"%s\".\n"),
|
fprintf(stderr, _("Did not find any relation named \"%s\".\n"),
|
||||||
pattern);
|
pattern);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@ -768,7 +768,7 @@ describeOneTableDetails(const char *schemaname,
|
|||||||
/* Did we get anything? */
|
/* Did we get anything? */
|
||||||
if (PQntuples(res) == 0)
|
if (PQntuples(res) == 0)
|
||||||
{
|
{
|
||||||
if (!QUIET())
|
if (!pset.quiet)
|
||||||
fprintf(stderr, _("Did not find any relation with OID %s.\n"),
|
fprintf(stderr, _("Did not find any relation with OID %s.\n"),
|
||||||
oid);
|
oid);
|
||||||
goto error_return;
|
goto error_return;
|
||||||
@ -1582,7 +1582,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose)
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (PQntuples(res) == 0 && !QUIET())
|
if (PQntuples(res) == 0 && !pset.quiet)
|
||||||
{
|
{
|
||||||
if (pattern)
|
if (pattern)
|
||||||
fprintf(pset.queryFout, _("No matching relations found.\n"));
|
fprintf(pset.queryFout, _("No matching relations found.\n"));
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.58 2006/08/27 15:05:20 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.59 2006/08/29 15:19:51 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
|
|
||||||
@ -34,14 +34,6 @@ char *psql_history;
|
|||||||
* for this purpose.
|
* for this purpose.
|
||||||
*/
|
*/
|
||||||
#define NL_IN_HISTORY 0x01
|
#define NL_IN_HISTORY 0x01
|
||||||
|
|
||||||
enum histcontrol
|
|
||||||
{
|
|
||||||
hctl_none = 0,
|
|
||||||
hctl_ignorespace = 1,
|
|
||||||
hctl_ignoredups = 2,
|
|
||||||
hctl_ignoreboth = hctl_ignorespace | hctl_ignoredups
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ATEXIT
|
#ifdef HAVE_ATEXIT
|
||||||
@ -52,31 +44,6 @@ static void finishInput(int, void *);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_READLINE
|
|
||||||
static enum histcontrol
|
|
||||||
GetHistControlConfig(void)
|
|
||||||
{
|
|
||||||
enum histcontrol HC;
|
|
||||||
const char *var;
|
|
||||||
|
|
||||||
var = GetVariable(pset.vars, "HISTCONTROL");
|
|
||||||
|
|
||||||
if (!var)
|
|
||||||
HC = hctl_none;
|
|
||||||
else if (strcmp(var, "ignorespace") == 0)
|
|
||||||
HC = hctl_ignorespace;
|
|
||||||
else if (strcmp(var, "ignoredups") == 0)
|
|
||||||
HC = hctl_ignoredups;
|
|
||||||
else if (strcmp(var, "ignoreboth") == 0)
|
|
||||||
HC = hctl_ignoreboth;
|
|
||||||
else
|
|
||||||
HC = hctl_none;
|
|
||||||
|
|
||||||
return HC;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gets_interactive()
|
* gets_interactive()
|
||||||
*
|
*
|
||||||
@ -147,10 +114,10 @@ pg_send_history(PQExpBuffer history_buf)
|
|||||||
|
|
||||||
if (useHistory && s[0])
|
if (useHistory && s[0])
|
||||||
{
|
{
|
||||||
enum histcontrol HC = GetHistControlConfig();
|
if (((pset.histcontrol & hctl_ignorespace) &&
|
||||||
|
s[0] == ' ') ||
|
||||||
if (((HC & hctl_ignorespace) && s[0] == ' ') ||
|
((pset.histcontrol & hctl_ignoredups) &&
|
||||||
((HC & hctl_ignoredups) && prev_hist && strcmp(s, prev_hist) == 0))
|
prev_hist && strcmp(s, prev_hist) == 0))
|
||||||
{
|
{
|
||||||
/* Ignore this line as far as history is concerned */
|
/* Ignore this line as far as history is concerned */
|
||||||
}
|
}
|
||||||
@ -287,17 +254,17 @@ initializeInput(int flags)
|
|||||||
#ifdef USE_READLINE
|
#ifdef USE_READLINE
|
||||||
if (flags & 1)
|
if (flags & 1)
|
||||||
{
|
{
|
||||||
|
const char *histfile;
|
||||||
char home[MAXPGPATH];
|
char home[MAXPGPATH];
|
||||||
|
|
||||||
useReadline = true;
|
useReadline = true;
|
||||||
initialize_readline();
|
initialize_readline();
|
||||||
|
|
||||||
useHistory = true;
|
useHistory = true;
|
||||||
if (GetVariable(pset.vars, "HISTSIZE") == NULL)
|
|
||||||
SetVariable(pset.vars, "HISTSIZE", "500");
|
|
||||||
using_history();
|
using_history();
|
||||||
|
|
||||||
if (GetVariable(pset.vars, "HISTFILE") == NULL)
|
histfile = GetVariable(pset.vars, "HISTFILE");
|
||||||
|
if (histfile == NULL)
|
||||||
{
|
{
|
||||||
if (get_home_path(home))
|
if (get_home_path(home))
|
||||||
{
|
{
|
||||||
@ -308,7 +275,7 @@ initializeInput(int flags)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
psql_history = pg_strdup(GetVariable(pset.vars, "HISTFILE"));
|
psql_history = pg_strdup(histfile);
|
||||||
expand_tilde(&psql_history);
|
expand_tilde(&psql_history);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,7 +353,7 @@ finishInput(int exitstatus, void *arg)
|
|||||||
{
|
{
|
||||||
int hist_size;
|
int hist_size;
|
||||||
|
|
||||||
hist_size = GetVariableNum(pset.vars, "HISTSIZE", -1, -1, true);
|
hist_size = GetVariableNum(pset.vars, "HISTSIZE", 500, -1, true);
|
||||||
if (hist_size >= 0)
|
if (hist_size >= 0)
|
||||||
stifle_history(hist_size);
|
stifle_history(hist_size);
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.45 2006/07/14 14:52:26 momjian Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/large_obj.c,v 1.46 2006/08/29 15:19:51 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "large_obj.h"
|
#include "large_obj.h"
|
||||||
@ -67,8 +67,7 @@ finish_lo_xact(const char *operation, bool own_transaction)
|
|||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
if (own_transaction &&
|
if (own_transaction && pset.autocommit)
|
||||||
GetVariableBool(pset.vars, "AUTOCOMMIT"))
|
|
||||||
{
|
{
|
||||||
/* close out our own xact */
|
/* close out our own xact */
|
||||||
if (!(res = PSQLexec("COMMIT", false)))
|
if (!(res = PSQLexec("COMMIT", false)))
|
||||||
@ -91,8 +90,7 @@ fail_lo_xact(const char *operation, bool own_transaction)
|
|||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
if (own_transaction &&
|
if (own_transaction && pset.autocommit)
|
||||||
GetVariableBool(pset.vars, "AUTOCOMMIT"))
|
|
||||||
{
|
{
|
||||||
/* close out our own xact */
|
/* close out our own xact */
|
||||||
res = PSQLexec("ROLLBACK", false);
|
res = PSQLexec("ROLLBACK", false);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.82 2006/08/11 19:20:59 momjian Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.83 2006/08/29 15:19:51 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "mainloop.h"
|
#include "mainloop.h"
|
||||||
@ -146,12 +146,12 @@ MainLoop(FILE *source)
|
|||||||
|
|
||||||
if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false))
|
if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false))
|
||||||
{
|
{
|
||||||
if (!QUIET())
|
if (!pset.quiet)
|
||||||
printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
|
printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
puts(QUIET() ? "" : "\\q");
|
puts(pset.quiet ? "" : "\\q");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -168,8 +168,7 @@ MainLoop(FILE *source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* echo back if flag is set */
|
/* echo back if flag is set */
|
||||||
if (!pset.cur_cmd_interactive &&
|
if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
|
||||||
VariableEquals(pset.vars, "ECHO", "all"))
|
|
||||||
puts(line);
|
puts(line);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
@ -183,7 +182,7 @@ MainLoop(FILE *source)
|
|||||||
added_nl_pos = -1; /* flag we didn't add one */
|
added_nl_pos = -1; /* flag we didn't add one */
|
||||||
|
|
||||||
/* Setting this will not have effect until next line. */
|
/* Setting this will not have effect until next line. */
|
||||||
die_on_error = GetVariableBool(pset.vars, "ON_ERROR_STOP");
|
die_on_error = pset.on_error_stop;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse line, looking for command separators.
|
* Parse line, looking for command separators.
|
||||||
@ -205,8 +204,7 @@ MainLoop(FILE *source)
|
|||||||
* single-line mode.
|
* single-line mode.
|
||||||
*/
|
*/
|
||||||
if (scan_result == PSCAN_SEMICOLON ||
|
if (scan_result == PSCAN_SEMICOLON ||
|
||||||
(scan_result == PSCAN_EOL &&
|
(scan_result == PSCAN_EOL && pset.singleline))
|
||||||
GetVariableBool(pset.vars, "SINGLELINE")))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Save query in history. We use history_buf to accumulate
|
* Save query in history. We use history_buf to accumulate
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/prompt.c,v 1.47 2006/07/15 03:35:21 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/prompt.c,v 1.48 2006/08/29 15:19:51 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
|
|
||||||
@ -72,12 +72,11 @@ get_prompt(promptStatus_t status)
|
|||||||
bool esc = false;
|
bool esc = false;
|
||||||
const char *p;
|
const char *p;
|
||||||
const char *prompt_string = "? ";
|
const char *prompt_string = "? ";
|
||||||
const char *prompt_name = NULL;
|
|
||||||
|
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case PROMPT_READY:
|
case PROMPT_READY:
|
||||||
prompt_name = "PROMPT1";
|
prompt_string = pset.prompt1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROMPT_CONTINUE:
|
case PROMPT_CONTINUE:
|
||||||
@ -86,21 +85,18 @@ get_prompt(promptStatus_t status)
|
|||||||
case PROMPT_DOLLARQUOTE:
|
case PROMPT_DOLLARQUOTE:
|
||||||
case PROMPT_COMMENT:
|
case PROMPT_COMMENT:
|
||||||
case PROMPT_PAREN:
|
case PROMPT_PAREN:
|
||||||
prompt_name = "PROMPT2";
|
prompt_string = pset.prompt2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROMPT_COPY:
|
case PROMPT_COPY:
|
||||||
prompt_name = "PROMPT3";
|
prompt_string = pset.prompt3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prompt_name)
|
|
||||||
prompt_string = GetVariable(pset.vars, prompt_name);
|
|
||||||
|
|
||||||
destination[0] = '\0';
|
destination[0] = '\0';
|
||||||
|
|
||||||
for (p = prompt_string;
|
for (p = prompt_string;
|
||||||
p && *p && strlen(destination) < MAX_PROMPT_SIZE;
|
*p && strlen(destination) < MAX_PROMPT_SIZE;
|
||||||
p++)
|
p++)
|
||||||
{
|
{
|
||||||
memset(buf, 0, MAX_PROMPT_SIZE + 1);
|
memset(buf, 0, MAX_PROMPT_SIZE + 1);
|
||||||
@ -182,7 +178,7 @@ get_prompt(promptStatus_t status)
|
|||||||
case PROMPT_READY:
|
case PROMPT_READY:
|
||||||
if (!pset.db)
|
if (!pset.db)
|
||||||
buf[0] = '!';
|
buf[0] = '!';
|
||||||
else if (!GetVariableBool(pset.vars, "SINGLELINE"))
|
else if (!pset.singleline)
|
||||||
buf[0] = '=';
|
buf[0] = '=';
|
||||||
else
|
else
|
||||||
buf[0] = '^';
|
buf[0] = '^';
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/settings.h,v 1.28 2006/08/11 19:20:59 momjian Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/settings.h,v 1.29 2006/08/29 15:19:51 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef SETTINGS_H
|
#ifndef SETTINGS_H
|
||||||
#define SETTINGS_H
|
#define SETTINGS_H
|
||||||
@ -26,16 +26,44 @@
|
|||||||
#define DEFAULT_PROMPT2 "%/%R%# "
|
#define DEFAULT_PROMPT2 "%/%R%# "
|
||||||
#define DEFAULT_PROMPT3 ">> "
|
#define DEFAULT_PROMPT3 ">> "
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PSQL_ECHO_NONE,
|
||||||
|
PSQL_ECHO_QUERIES,
|
||||||
|
PSQL_ECHO_ALL
|
||||||
|
} PSQL_ECHO;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PSQL_ECHO_HIDDEN_OFF,
|
||||||
|
PSQL_ECHO_HIDDEN_ON,
|
||||||
|
PSQL_ECHO_HIDDEN_NOEXEC
|
||||||
|
} PSQL_ECHO_HIDDEN;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PSQL_ERROR_ROLLBACK_OFF,
|
||||||
|
PSQL_ERROR_ROLLBACK_INTERACTIVE,
|
||||||
|
PSQL_ERROR_ROLLBACK_ON
|
||||||
|
} PSQL_ERROR_ROLLBACK;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
hctl_none = 0,
|
||||||
|
hctl_ignorespace = 1,
|
||||||
|
hctl_ignoredups = 2,
|
||||||
|
hctl_ignoreboth = hctl_ignorespace | hctl_ignoredups
|
||||||
|
} HistControl;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _psqlSettings
|
typedef struct _psqlSettings
|
||||||
{
|
{
|
||||||
PGconn *db; /* connection to backend */
|
PGconn *db; /* connection to backend */
|
||||||
int encoding;
|
int encoding; /* client_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() */
|
||||||
|
|
||||||
printQueryOpt popt;
|
printQueryOpt popt;
|
||||||
VariableSpace vars; /* "shell variable" repository */
|
|
||||||
|
|
||||||
char *gfname; /* one-shot file output argument for \g */
|
char *gfname; /* one-shot file output argument for \g */
|
||||||
|
|
||||||
@ -54,16 +82,33 @@ typedef struct _psqlSettings
|
|||||||
|
|
||||||
bool timing; /* enable timing of all queries */
|
bool timing; /* enable timing of all queries */
|
||||||
|
|
||||||
PGVerbosity verbosity; /* current error verbosity level */
|
|
||||||
FILE *logfile; /* session log file handle */
|
FILE *logfile; /* session log file handle */
|
||||||
|
|
||||||
|
VariableSpace vars; /* "shell variable" repository */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The remaining fields are set by assign hooks associated with
|
||||||
|
* entries in "vars". They should not be set directly except by
|
||||||
|
* those hook functions.
|
||||||
|
*/
|
||||||
|
bool autocommit;
|
||||||
|
bool on_error_stop;
|
||||||
|
bool quiet;
|
||||||
|
bool singleline;
|
||||||
|
bool singlestep;
|
||||||
|
PSQL_ECHO echo;
|
||||||
|
PSQL_ECHO_HIDDEN echo_hidden;
|
||||||
|
PSQL_ERROR_ROLLBACK on_error_rollback;
|
||||||
|
HistControl histcontrol;
|
||||||
|
const char *prompt1;
|
||||||
|
const char *prompt2;
|
||||||
|
const char *prompt3;
|
||||||
|
PGVerbosity verbosity; /* current error verbosity level */
|
||||||
} PsqlSettings;
|
} PsqlSettings;
|
||||||
|
|
||||||
extern PsqlSettings pset;
|
extern PsqlSettings pset;
|
||||||
|
|
||||||
|
|
||||||
#define QUIET() (GetVariableBool(pset.vars, "QUIET"))
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef EXIT_SUCCESS
|
#ifndef EXIT_SUCCESS
|
||||||
#define EXIT_SUCCESS 0
|
#define EXIT_SUCCESS 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.135 2006/07/14 14:52:26 momjian Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.136 2006/08/29 15:19:51 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
|
|
||||||
@ -84,14 +84,14 @@ static void parse_psql_options(int argc, char *argv[],
|
|||||||
static void process_psqlrc(char *argv0);
|
static void process_psqlrc(char *argv0);
|
||||||
static void process_psqlrc_file(char *filename);
|
static void process_psqlrc_file(char *filename);
|
||||||
static void showVersion(void);
|
static void showVersion(void);
|
||||||
|
static void EstablishVariableSpace(void);
|
||||||
|
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
static void printSSLInfo(void);
|
static void printSSLInfo(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
static void
|
static void checkWin32Codepage(void);
|
||||||
checkWin32Codepage(void);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -134,34 +134,19 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
pset.progname = get_progname(argv[0]);
|
pset.progname = get_progname(argv[0]);
|
||||||
|
|
||||||
|
pset.db = NULL;
|
||||||
setDecimalLocale();
|
setDecimalLocale();
|
||||||
|
pset.encoding = PQenv2encoding();
|
||||||
|
pset.queryFout = stdout;
|
||||||
|
pset.queryFoutPipe = false;
|
||||||
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();
|
|
||||||
if (!pset.vars)
|
|
||||||
{
|
|
||||||
fprintf(stderr, _("%s: out of memory\n"), pset.progname);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
pset.popt.topt.format = PRINT_ALIGNED;
|
pset.popt.topt.format = PRINT_ALIGNED;
|
||||||
pset.queryFout = stdout;
|
|
||||||
pset.popt.topt.border = 1;
|
pset.popt.topt.border = 1;
|
||||||
pset.popt.topt.pager = 1;
|
pset.popt.topt.pager = 1;
|
||||||
pset.popt.default_footer = true;
|
pset.popt.default_footer = true;
|
||||||
|
|
||||||
SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
|
|
||||||
|
|
||||||
/* Default values for variables */
|
|
||||||
SetVariableBool(pset.vars, "AUTOCOMMIT");
|
|
||||||
SetVariable(pset.vars, "VERBOSITY", "default");
|
|
||||||
SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
|
|
||||||
SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
|
|
||||||
SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
|
|
||||||
|
|
||||||
pset.verbosity = PQERRORS_DEFAULT;
|
|
||||||
|
|
||||||
pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
|
pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
|
||||||
|
|
||||||
/* This is obsolete and should be removed sometime. */
|
/* This is obsolete and should be removed sometime. */
|
||||||
@ -171,6 +156,17 @@ main(int argc, char *argv[])
|
|||||||
pset.getPassword = false;
|
pset.getPassword = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
EstablishVariableSpace();
|
||||||
|
|
||||||
|
SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
|
||||||
|
|
||||||
|
/* Default values for variables */
|
||||||
|
SetVariableBool(pset.vars, "AUTOCOMMIT");
|
||||||
|
SetVariable(pset.vars, "VERBOSITY", "default");
|
||||||
|
SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
|
||||||
|
SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
|
||||||
|
SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
|
||||||
|
|
||||||
parse_psql_options(argc, argv, &options);
|
parse_psql_options(argc, argv, &options);
|
||||||
|
|
||||||
if (!pset.popt.topt.fieldSep)
|
if (!pset.popt.topt.fieldSep)
|
||||||
@ -239,9 +235,6 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
SyncVariables();
|
SyncVariables();
|
||||||
|
|
||||||
/* Grab the backend server version */
|
|
||||||
pset.sversion = PQserverVersion(pset.db);
|
|
||||||
|
|
||||||
if (options.action == ACT_LIST_DB)
|
if (options.action == ACT_LIST_DB)
|
||||||
{
|
{
|
||||||
int success = listAllDbs(false);
|
int success = listAllDbs(false);
|
||||||
@ -280,7 +273,7 @@ main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
PsqlScanState scan_state;
|
PsqlScanState scan_state;
|
||||||
|
|
||||||
if (VariableEquals(pset.vars, "ECHO", "all"))
|
if (pset.echo == PSQL_ECHO_ALL)
|
||||||
puts(options.action_string);
|
puts(options.action_string);
|
||||||
|
|
||||||
scan_state = psql_scan_create();
|
scan_state = psql_scan_create();
|
||||||
@ -299,7 +292,7 @@ main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
else if (options.action == ACT_SINGLE_QUERY)
|
else if (options.action == ACT_SINGLE_QUERY)
|
||||||
{
|
{
|
||||||
if (VariableEquals(pset.vars, "ECHO", "all"))
|
if (pset.echo == PSQL_ECHO_ALL)
|
||||||
puts(options.action_string);
|
puts(options.action_string);
|
||||||
|
|
||||||
successResult = SendQuery(options.action_string)
|
successResult = SendQuery(options.action_string)
|
||||||
@ -314,7 +307,7 @@ main(int argc, char *argv[])
|
|||||||
if (!options.no_psqlrc)
|
if (!options.no_psqlrc)
|
||||||
process_psqlrc(argv[0]);
|
process_psqlrc(argv[0]);
|
||||||
|
|
||||||
if (!QUIET() && !pset.notty)
|
if (!pset.quiet && !pset.notty)
|
||||||
{
|
{
|
||||||
int client_ver = parse_version(PG_VERSION);
|
int client_ver = parse_version(PG_VERSION);
|
||||||
|
|
||||||
@ -644,14 +637,14 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
|
|||||||
options->dbname = argv[optind];
|
options->dbname = argv[optind];
|
||||||
else if (!options->username)
|
else if (!options->username)
|
||||||
options->username = argv[optind];
|
options->username = argv[optind];
|
||||||
else if (!QUIET())
|
else if (!pset.quiet)
|
||||||
fprintf(stderr, _("%s: warning: extra command-line argument \"%s\" ignored\n"),
|
fprintf(stderr, _("%s: warning: extra command-line argument \"%s\" ignored\n"),
|
||||||
pset.progname, argv[optind]);
|
pset.progname, argv[optind]);
|
||||||
|
|
||||||
optind++;
|
optind++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (used_old_u_option && !QUIET())
|
if (used_old_u_option && !pset.quiet)
|
||||||
fprintf(stderr, _("%s: Warning: The -u option is deprecated. Use -U.\n"), pset.progname);
|
fprintf(stderr, _("%s: Warning: The -u option is deprecated. Use -U.\n"), pset.progname);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -743,7 +736,6 @@ printSSLInfo(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* checkWin32Codepage
|
* checkWin32Codepage
|
||||||
*
|
*
|
||||||
@ -768,3 +760,151 @@ checkWin32Codepage(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assign hooks for psql variables.
|
||||||
|
*
|
||||||
|
* This isn't an amazingly good place for them, but neither is anywhere else.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
autocommit_hook(const char *newval)
|
||||||
|
{
|
||||||
|
pset.autocommit = ParseVariableBool(newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_error_stop_hook(const char *newval)
|
||||||
|
{
|
||||||
|
pset.on_error_stop = ParseVariableBool(newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
quiet_hook(const char *newval)
|
||||||
|
{
|
||||||
|
pset.quiet = ParseVariableBool(newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
singleline_hook(const char *newval)
|
||||||
|
{
|
||||||
|
pset.singleline = ParseVariableBool(newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
singlestep_hook(const char *newval)
|
||||||
|
{
|
||||||
|
pset.singlestep = ParseVariableBool(newval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
echo_hook(const char *newval)
|
||||||
|
{
|
||||||
|
if (newval == NULL)
|
||||||
|
pset.echo = PSQL_ECHO_NONE;
|
||||||
|
else if (strcmp(newval, "queries") == 0)
|
||||||
|
pset.echo = PSQL_ECHO_QUERIES;
|
||||||
|
else if (strcmp(newval, "all") == 0)
|
||||||
|
pset.echo = PSQL_ECHO_ALL;
|
||||||
|
else
|
||||||
|
pset.echo = PSQL_ECHO_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
echo_hidden_hook(const char *newval)
|
||||||
|
{
|
||||||
|
if (newval == NULL)
|
||||||
|
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
|
||||||
|
else if (strcmp(newval, "noexec") == 0)
|
||||||
|
pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC;
|
||||||
|
else if (pg_strcasecmp(newval, "off") == 0)
|
||||||
|
pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
|
||||||
|
else
|
||||||
|
pset.echo_hidden = PSQL_ECHO_HIDDEN_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_error_rollback_hook(const char *newval)
|
||||||
|
{
|
||||||
|
if (newval == NULL)
|
||||||
|
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
|
||||||
|
else if (pg_strcasecmp(newval, "interactive") == 0)
|
||||||
|
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE;
|
||||||
|
else if (pg_strcasecmp(newval, "off") == 0)
|
||||||
|
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
|
||||||
|
else
|
||||||
|
pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
histcontrol_hook(const char *newval)
|
||||||
|
{
|
||||||
|
if (newval == NULL)
|
||||||
|
pset.histcontrol = hctl_none;
|
||||||
|
else if (strcmp(newval, "ignorespace") == 0)
|
||||||
|
pset.histcontrol = hctl_ignorespace;
|
||||||
|
else if (strcmp(newval, "ignoredups") == 0)
|
||||||
|
pset.histcontrol = hctl_ignoredups;
|
||||||
|
else if (strcmp(newval, "ignoreboth") == 0)
|
||||||
|
pset.histcontrol = hctl_ignoreboth;
|
||||||
|
else
|
||||||
|
pset.histcontrol = hctl_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
prompt1_hook(const char *newval)
|
||||||
|
{
|
||||||
|
pset.prompt1 = newval ? newval : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
prompt2_hook(const char *newval)
|
||||||
|
{
|
||||||
|
pset.prompt2 = newval ? newval : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
prompt3_hook(const char *newval)
|
||||||
|
{
|
||||||
|
pset.prompt3 = newval ? newval : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
verbosity_hook(const char *newval)
|
||||||
|
{
|
||||||
|
if (newval == NULL)
|
||||||
|
pset.verbosity = PQERRORS_DEFAULT;
|
||||||
|
else if (strcmp(newval, "default") == 0)
|
||||||
|
pset.verbosity = PQERRORS_DEFAULT;
|
||||||
|
else if (strcmp(newval, "terse") == 0)
|
||||||
|
pset.verbosity = PQERRORS_TERSE;
|
||||||
|
else if (strcmp(newval, "verbose") == 0)
|
||||||
|
pset.verbosity = PQERRORS_VERBOSE;
|
||||||
|
else
|
||||||
|
pset.verbosity = PQERRORS_DEFAULT;
|
||||||
|
|
||||||
|
if (pset.db)
|
||||||
|
PQsetErrorVerbosity(pset.db, pset.verbosity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
EstablishVariableSpace(void)
|
||||||
|
{
|
||||||
|
pset.vars = CreateVariableSpace();
|
||||||
|
|
||||||
|
SetVariableAssignHook(pset.vars, "AUTOCOMMIT", autocommit_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "ON_ERROR_STOP", on_error_stop_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "QUIET", quiet_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "SINGLELINE", singleline_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "SINGLESTEP", singlestep_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "ECHO", echo_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "ECHO_HIDDEN", echo_hidden_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "ON_ERROR_ROLLBACK", on_error_rollback_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "HISTCONTROL", histcontrol_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "PROMPT1", prompt1_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "PROMPT3", prompt3_hook);
|
||||||
|
SetVariableAssignHook(pset.vars, "VERBOSITY", verbosity_hook);
|
||||||
|
}
|
||||||
|
@ -3,20 +3,27 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/variables.c,v 1.25 2006/06/21 16:05:11 tgl Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/variables.c,v 1.26 2006/08/29 15:19:51 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A "variable space" is represented by an otherwise-unused struct _variable
|
||||||
|
* that serves as list header.
|
||||||
|
*/
|
||||||
VariableSpace
|
VariableSpace
|
||||||
CreateVariableSpace(void)
|
CreateVariableSpace(void)
|
||||||
{
|
{
|
||||||
struct _variable *ptr;
|
struct _variable *ptr;
|
||||||
|
|
||||||
ptr = pg_calloc(1, sizeof *ptr);
|
ptr = pg_malloc(sizeof *ptr);
|
||||||
ptr->name = pg_strdup("@");
|
ptr->name = NULL;
|
||||||
ptr->value = pg_strdup("");
|
ptr->value = NULL;
|
||||||
|
ptr->assign_hook = NULL;
|
||||||
|
ptr->next = NULL;
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
@ -33,7 +40,7 @@ GetVariable(VariableSpace space, const char *name)
|
|||||||
{
|
{
|
||||||
if (strcmp(current->name, name) == 0)
|
if (strcmp(current->name, name) == 0)
|
||||||
{
|
{
|
||||||
psql_assert(current->value);
|
/* this is correct answer when value is NULL, too */
|
||||||
return current->value;
|
return current->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,11 +49,8 @@ GetVariable(VariableSpace space, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GetVariableBool(VariableSpace space, const char *name)
|
ParseVariableBool(const char *val)
|
||||||
{
|
{
|
||||||
const char *val;
|
|
||||||
|
|
||||||
val = GetVariable(space, name);
|
|
||||||
if (val == NULL)
|
if (val == NULL)
|
||||||
return false; /* not set -> assume "off" */
|
return false; /* not set -> assume "off" */
|
||||||
if (pg_strcasecmp(val, "off") == 0)
|
if (pg_strcasecmp(val, "off") == 0)
|
||||||
@ -59,35 +63,28 @@ GetVariableBool(VariableSpace space, const char *name)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
/*
|
||||||
VariableEquals(VariableSpace space, const char name[], const char value[])
|
* Read numeric variable, or defaultval if it is not set, or faultval if its
|
||||||
{
|
* value is not a valid numeric string. If allowtrail is false, this will
|
||||||
const char *var;
|
* include the case where there are trailing characters after the number.
|
||||||
|
*/
|
||||||
var = GetVariable(space, name);
|
|
||||||
return var && (strcmp(var, value) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
GetVariableNum(VariableSpace space,
|
ParseVariableNum(const char *val,
|
||||||
const char name[],
|
|
||||||
int defaultval,
|
int defaultval,
|
||||||
int faultval,
|
int faultval,
|
||||||
bool allowtrail)
|
bool allowtrail)
|
||||||
{
|
{
|
||||||
const char *var;
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
var = GetVariable(space, name);
|
if (!val)
|
||||||
if (!var)
|
|
||||||
result = defaultval;
|
result = defaultval;
|
||||||
else if (!var[0])
|
else if (!val[0])
|
||||||
result = faultval;
|
result = faultval;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
result = strtol(var, &end, 0);
|
result = strtol(val, &end, 0);
|
||||||
if (!allowtrail && *end)
|
if (!allowtrail && *end)
|
||||||
result = faultval;
|
result = faultval;
|
||||||
}
|
}
|
||||||
@ -96,27 +93,16 @@ GetVariableNum(VariableSpace space,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SwitchVariable(VariableSpace space, const char name[], const char *opt,...)
|
GetVariableNum(VariableSpace space,
|
||||||
|
const char *name,
|
||||||
|
int defaultval,
|
||||||
|
int faultval,
|
||||||
|
bool allowtrail)
|
||||||
{
|
{
|
||||||
int result;
|
const char *val;
|
||||||
const char *var;
|
|
||||||
|
|
||||||
var = GetVariable(space, name);
|
val = GetVariable(space, name);
|
||||||
if (var)
|
return ParseVariableNum(val, defaultval, faultval, allowtrail);
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, opt);
|
|
||||||
for (result = 1; opt && (strcmp(var, opt) != 0); result++)
|
|
||||||
opt = va_arg(args, const char *);
|
|
||||||
if (!opt)
|
|
||||||
result = VAR_NOTFOUND;
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result = VAR_NOTSET;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -129,6 +115,7 @@ PrintVariables(VariableSpace space)
|
|||||||
|
|
||||||
for (ptr = space->next; ptr; ptr = ptr->next)
|
for (ptr = space->next; ptr; ptr = ptr->next)
|
||||||
{
|
{
|
||||||
|
if (ptr->value)
|
||||||
printf("%s = '%s'\n", ptr->name, ptr->value);
|
printf("%s = '%s'\n", ptr->name, ptr->value);
|
||||||
if (cancel_pressed)
|
if (cancel_pressed)
|
||||||
break;
|
break;
|
||||||
@ -156,16 +143,62 @@ SetVariable(VariableSpace space, const char *name, const char *value)
|
|||||||
{
|
{
|
||||||
if (strcmp(current->name, name) == 0)
|
if (strcmp(current->name, name) == 0)
|
||||||
{
|
{
|
||||||
psql_assert(current->value);
|
/* found entry, so update */
|
||||||
|
if (current->value)
|
||||||
free(current->value);
|
free(current->value);
|
||||||
current->value = pg_strdup(value);
|
current->value = pg_strdup(value);
|
||||||
|
if (current->assign_hook)
|
||||||
|
(*current->assign_hook) (current->value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
previous->next = pg_calloc(1, sizeof *(previous->next));
|
/* not present, make new entry */
|
||||||
previous->next->name = pg_strdup(name);
|
current = pg_malloc(sizeof *current);
|
||||||
previous->next->value = pg_strdup(value);
|
current->name = pg_strdup(name);
|
||||||
|
current->value = pg_strdup(value);
|
||||||
|
current->assign_hook = NULL;
|
||||||
|
current->next = NULL;
|
||||||
|
previous->next = current;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This both sets a hook function, and calls it on the current value (if any)
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook hook)
|
||||||
|
{
|
||||||
|
struct _variable *current,
|
||||||
|
*previous;
|
||||||
|
|
||||||
|
if (!space)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (strspn(name, VALID_VARIABLE_CHARS) != strlen(name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (previous = space, current = space->next;
|
||||||
|
current;
|
||||||
|
previous = current, current = current->next)
|
||||||
|
{
|
||||||
|
if (strcmp(current->name, name) == 0)
|
||||||
|
{
|
||||||
|
/* found entry, so update */
|
||||||
|
current->assign_hook = hook;
|
||||||
|
(*hook) (current->value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not present, make new entry */
|
||||||
|
current = pg_malloc(sizeof *current);
|
||||||
|
current->name = pg_strdup(name);
|
||||||
|
current->value = NULL;
|
||||||
|
current->assign_hook = hook;
|
||||||
|
current->next = NULL;
|
||||||
|
previous->next = current;
|
||||||
|
(*hook) (NULL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,11 +223,18 @@ DeleteVariable(VariableSpace space, const char *name)
|
|||||||
{
|
{
|
||||||
if (strcmp(current->name, name) == 0)
|
if (strcmp(current->name, name) == 0)
|
||||||
{
|
{
|
||||||
psql_assert(current->value);
|
if (current->value)
|
||||||
|
free(current->value);
|
||||||
|
current->value = NULL;
|
||||||
|
/* Physically delete only if no hook function to remember */
|
||||||
|
if (current->assign_hook)
|
||||||
|
(*current->assign_hook) (NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
previous->next = current->next;
|
previous->next = current->next;
|
||||||
free(current->name);
|
free(current->name);
|
||||||
free(current->value);
|
|
||||||
free(current);
|
free(current);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,62 +3,57 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/psql/variables.h,v 1.18 2006/03/05 15:58:52 momjian Exp $
|
* $PostgreSQL: pgsql/src/bin/psql/variables.h,v 1.19 2006/08/29 15:19:51 tgl 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
|
|
||||||
* datastructures you can store name/value pairs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef VARIABLES_H
|
#ifndef VARIABLES_H
|
||||||
#define VARIABLES_H
|
#define VARIABLES_H
|
||||||
|
|
||||||
#define VALID_VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyz"\
|
/*
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789_"
|
* This implements a sort of variable repository. One could also think of it
|
||||||
|
* as a cheap version of an associative array. In each one of these
|
||||||
|
* datastructures you can store name/value pairs. There can also be an
|
||||||
|
* "assign hook" function that is called whenever the variable's value is
|
||||||
|
* changed.
|
||||||
|
*
|
||||||
|
* An "unset" operation causes the hook to be called with newval == NULL.
|
||||||
|
*
|
||||||
|
* Note: if value == NULL then the variable is logically unset, but we are
|
||||||
|
* keeping the struct around so as not to forget about its hook function.
|
||||||
|
*/
|
||||||
|
typedef void (*VariableAssignHook) (const char *newval);
|
||||||
|
|
||||||
struct _variable
|
struct _variable
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
char *value;
|
char *value;
|
||||||
|
VariableAssignHook assign_hook;
|
||||||
struct _variable *next;
|
struct _variable *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _variable *VariableSpace;
|
typedef struct _variable *VariableSpace;
|
||||||
|
|
||||||
|
/* Allowed chars in a variable's name */
|
||||||
|
#define VALID_VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyz"\
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789_"
|
||||||
|
|
||||||
VariableSpace CreateVariableSpace(void);
|
VariableSpace CreateVariableSpace(void);
|
||||||
const char *GetVariable(VariableSpace space, const char *name);
|
const char *GetVariable(VariableSpace space, const char *name);
|
||||||
bool GetVariableBool(VariableSpace space, const char *name);
|
|
||||||
bool VariableEquals(VariableSpace space, const char name[], const char *opt);
|
|
||||||
|
|
||||||
/* Read numeric variable, or defaultval if it is not set, or faultval if its
|
bool ParseVariableBool(const char *val);
|
||||||
* value is not a valid numeric string. If allowtrail is false, this will
|
int ParseVariableNum(const char *val,
|
||||||
* include the case where there are trailing characters after the number.
|
int defaultval,
|
||||||
*/
|
int faultval,
|
||||||
|
bool allowtrail);
|
||||||
int GetVariableNum(VariableSpace space,
|
int GetVariableNum(VariableSpace space,
|
||||||
const char name[],
|
const char *name,
|
||||||
int defaultval,
|
int defaultval,
|
||||||
int faultval,
|
int faultval,
|
||||||
bool allowtrail);
|
bool allowtrail);
|
||||||
|
|
||||||
|
|
||||||
/* Find value of variable <name> among NULL-terminated list of alternative
|
|
||||||
* options. Returns VAR_NOTSET if the variable was not set, VAR_NOTFOUND
|
|
||||||
* if its value did not occur in the list of options, or the number of the
|
|
||||||
* matching option. The first option is 1, the second is 2 and so on.
|
|
||||||
*/
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
VAR_NOTSET = 0, VAR_NOTFOUND = -1};
|
|
||||||
int
|
|
||||||
SwitchVariable(VariableSpace space, const char name[],
|
|
||||||
const char *opt,...);
|
|
||||||
|
|
||||||
void PrintVariables(VariableSpace space);
|
void PrintVariables(VariableSpace space);
|
||||||
|
|
||||||
bool SetVariable(VariableSpace space, const char *name, const char *value);
|
bool SetVariable(VariableSpace space, const char *name, const char *value);
|
||||||
|
bool SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook hook);
|
||||||
bool SetVariableBool(VariableSpace space, const char *name);
|
bool SetVariableBool(VariableSpace space, const char *name);
|
||||||
bool DeleteVariable(VariableSpace space, const char *name);
|
bool DeleteVariable(VariableSpace space, const char *name);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user