2000-01-19 00:30:24 +01:00
|
|
|
/*
|
|
|
|
* psql - the PostgreSQL interactive terminal
|
|
|
|
*
|
2018-01-03 05:30:12 +01:00
|
|
|
* Copyright (c) 2000-2018, PostgreSQL Global Development Group
|
2000-01-19 00:30:24 +01:00
|
|
|
*
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/bin/psql/command.c
|
2000-01-19 00:30:24 +01:00
|
|
|
*/
|
2001-02-10 03:31:31 +01:00
|
|
|
#include "postgres_fe.h"
|
1999-11-04 22:56:02 +01:00
|
|
|
#include "command.h"
|
|
|
|
|
|
|
|
#include <ctype.h>
|
2013-04-24 18:11:25 +02:00
|
|
|
#include <time.h>
|
2001-05-07 21:31:33 +02:00
|
|
|
#include <pwd.h>
|
1999-11-04 22:56:02 +01:00
|
|
|
#ifndef WIN32
|
2000-11-25 07:21:54 +01:00
|
|
|
#include <sys/stat.h> /* for stat() */
|
|
|
|
#include <fcntl.h> /* open() flags */
|
1999-11-05 00:14:30 +01:00
|
|
|
#include <unistd.h> /* for geteuid(), getpid(), stat() */
|
2000-02-08 00:10:11 +01:00
|
|
|
#else
|
|
|
|
#include <win32.h>
|
Here is a patch to make the current snapshot compile on Win32 (native, libpq
and psql) again. Changes are:
1) psql requires the includes of "io.h" and "fcntl.h" in command.c in order
to make a call to open() work (io.h for _open(), fcntl.h for the O_xxx)
2) PG_VERSION is no longer defined in version.h[.in], but in configure.in.
Since we don't do configure on native win32, we need to put it in
config.h.win32 :-(
3) Added define of SYSCONFDIR to config.h.win32 - libpq won't compile
without it. This functionality is *NOT* tested - it's just defined as "" for
now. May work, may not.
4) DEF_PGPORT renamed to DEF_PGPORT_STR
I have done the "basic tests" on it - it connects to a database, and I can
run queries. Haven't tested any of the fancier functions (yet).
However, I stepped on a much bigger problem when fixing psql to work. It no
longer works when linked against the .DLL version of libpq (which the
Makefile does for it). I have left it linked against this version anyway,
pending the comments I get on this mail :-)
The problem is that there are strings being allocated from libpq.dll using
PQExpBuffers (for example, initPQExpBuffer() on line 92 of input.c). These
are being allocated using the malloc function used by libpq.dll. This
function *may* be different from the malloc function used by psql.exe - only
the resulting pointer must be valid. And with the default linking methods,
it *WILL* be different. Later, psql.exe tries to free() this string, at
which point it crashes because the free() function can't find the allocated
block (it's on the allocated blocks list used by the runtime lib of
libpq.dll).
Shouldn't the right thing to do be to have psql call termPQExpBuffer() on
the data instead? As it is now, gets_fromFile() will just return the pointer
received from the PQExpBuffer.data (this may well be present at several
places - this is the one I was bitten by so far). Isn't that kind of
"accessing the internals of the PQExpBuffer structure" wrong? Instead,
perhaps it shuold make a copy of the string, adn then termPQExpBuffer() it?
In that case, the string will have been allocated from within the same
library as the free() is called.
I can get it to work just fine by doing this - changing from (around line
100 of input.c):
and the same a bit further down in the same function.
But, as I said above, this may be at more places in the code? Perhaps
someone more familiar to it could comment on that?
What do you think shuld be done about this? Personally, I go by the "If you
allocate a piece of memory using an interface, use the same interface to
free it", but the question is how to make it work :-)
Also, AFAIK this only affects psql.exe, so the changes made to the libpq
this patch are required no matter how the other issue is handled.
Regards,
Magnus
2001-01-24 04:42:38 +01:00
|
|
|
#include <io.h>
|
2001-01-27 22:49:59 +01:00
|
|
|
#include <fcntl.h>
|
2002-10-03 19:09:42 +02:00
|
|
|
#include <direct.h>
|
2004-11-04 23:25:14 +01:00
|
|
|
#include <sys/stat.h> /* for stat() */
|
|
|
|
#endif
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2018-04-08 19:59:52 +02:00
|
|
|
#include "catalog/pg_class_d.h"
|
2008-05-14 21:10:29 +02:00
|
|
|
#include "portability/instr_time.h"
|
|
|
|
|
2000-02-16 14:15:26 +01:00
|
|
|
#include "libpq-fe.h"
|
|
|
|
#include "pqexpbuffer.h"
|
2016-03-24 20:55:44 +01:00
|
|
|
#include "fe_utils/string_utils.h"
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2000-02-08 00:10:11 +01:00
|
|
|
#include "common.h"
|
1999-11-04 22:56:02 +01:00
|
|
|
#include "copy.h"
|
2016-04-09 01:23:18 +02:00
|
|
|
#include "crosstabview.h"
|
2000-02-08 00:10:11 +01:00
|
|
|
#include "describe.h"
|
1999-11-04 22:56:02 +01:00
|
|
|
#include "help.h"
|
2000-02-08 00:10:11 +01:00
|
|
|
#include "input.h"
|
1999-11-04 22:56:02 +01:00
|
|
|
#include "large_obj.h"
|
2000-02-08 00:10:11 +01:00
|
|
|
#include "mainloop.h"
|
2016-03-24 23:27:28 +01:00
|
|
|
#include "fe_utils/print.h"
|
Split psql's lexer into two separate .l files for SQL and backslash cases.
This gets us to a point where psqlscan.l can be used by other frontend
programs for the same purpose psql uses it for, ie to detect when it's
collected a complete SQL command from input that is divided across
line boundaries. Moreover, other programs can supply their own lexers
for backslash commands of their own choosing. A follow-on patch will
use this in pgbench.
The end result here is roughly the same as in Kyotaro Horiguchi's
0001-Make-SQL-parser-part-of-psqlscan-independent-from-ps.patch, although
the details of the method for switching between lexers are quite different.
Basically, in this patch we share the entire PsqlScanState, YY_BUFFER_STATE
stack, *and* yyscan_t between different lexers. The only thing we need
to do to switch to a different lexer is to make sure the start_state is
valid for the new lexer. This works because flex doesn't keep any other
persistent state that depends on the specific lexing tables generated for
a particular .l file. (We are assuming that both lexers are built with
the same flex version, or at least versions that are compatible with
respect to the contents of yyscan_t; but that doesn't seem likely to
be a big problem in practice, considering how slowly flex changes.)
Aside from being more efficient than Horiguchi-san's original solution,
this avoids possible corner-case changes in semantics: the original code
was capable of popping the input buffer stack while still staying in
backslash-related parsing states. I'm not sure that that equates to any
useful user-visible behaviors, but I'm not sure it doesn't either, so
I'm loath to assume that we only need to consider the topmost buffer when
parsing a backslash command.
I've attempted to update the MSVC build scripts for the added .l file,
but will rely on the buildfarm to see if I missed anything.
Kyotaro Horiguchi and Tom Lane
2016-03-19 05:24:55 +01:00
|
|
|
#include "psqlscanslash.h"
|
2000-02-08 00:10:11 +01:00
|
|
|
#include "settings.h"
|
2000-01-14 23:18:03 +01:00
|
|
|
#include "variables.h"
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
/*
|
|
|
|
* Editable database object types.
|
|
|
|
*/
|
|
|
|
typedef enum EditableObjectType
|
|
|
|
{
|
|
|
|
EditableFunction,
|
|
|
|
EditableView
|
|
|
|
} EditableObjectType;
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/* local function declarations */
|
1999-11-05 00:14:30 +01:00
|
|
|
static backslashResult exec_command(const char *cmd,
|
2004-08-29 07:07:03 +02:00
|
|
|
PsqlScanState scan_state,
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf,
|
|
|
|
PQExpBuffer previous_buf);
|
|
|
|
static backslashResult exec_command_a(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_C(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
|
|
|
static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_d(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
|
|
|
static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch,
|
|
|
|
PQExpBuffer query_buf, PQExpBuffer previous_buf);
|
2017-09-06 23:32:40 +02:00
|
|
|
static backslashResult exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
|
|
|
|
PQExpBuffer query_buf, bool is_func);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
static backslashResult exec_command_echo(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
|
|
|
static backslashResult exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf);
|
|
|
|
static backslashResult exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf);
|
|
|
|
static backslashResult exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf);
|
|
|
|
static backslashResult exec_command_encoding(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_errverbose(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_f(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_g(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
2017-09-06 00:17:47 +02:00
|
|
|
static backslashResult exec_command_gdesc(PsqlScanState scan_state, bool active_branch);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
static backslashResult exec_command_gexec(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_gset(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_help(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_html(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_include(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
|
|
|
static backslashResult exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf);
|
|
|
|
static backslashResult exec_command_list(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
|
|
|
static backslashResult exec_command_lo(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
|
|
|
static backslashResult exec_command_out(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_print(PsqlScanState scan_state, bool active_branch,
|
2017-04-02 22:50:25 +02:00
|
|
|
PQExpBuffer query_buf, PQExpBuffer previous_buf);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
static backslashResult exec_command_password(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_prompt(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
|
|
|
static backslashResult exec_command_pset(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_quit(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch,
|
|
|
|
PQExpBuffer query_buf);
|
|
|
|
static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
2017-09-06 23:32:40 +02:00
|
|
|
static backslashResult exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd, bool is_func);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_unset(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd);
|
|
|
|
static backslashResult exec_command_write(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd,
|
|
|
|
PQExpBuffer query_buf, PQExpBuffer previous_buf);
|
|
|
|
static backslashResult exec_command_watch(PsqlScanState scan_state, bool active_branch,
|
|
|
|
PQExpBuffer query_buf, PQExpBuffer previous_buf);
|
|
|
|
static backslashResult exec_command_x(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_z(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_shell_escape(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static backslashResult exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch);
|
|
|
|
static char *read_connect_arg(PsqlScanState scan_state);
|
|
|
|
static PQExpBuffer gather_boolean_expression(PsqlScanState scan_state);
|
|
|
|
static bool is_true_boolean_expression(PsqlScanState scan_state, const char *name);
|
|
|
|
static void ignore_boolean_expression(PsqlScanState scan_state);
|
|
|
|
static void ignore_slash_options(PsqlScanState scan_state);
|
|
|
|
static void ignore_slash_filepipe(PsqlScanState scan_state);
|
|
|
|
static void ignore_slash_whole_line(PsqlScanState scan_state);
|
|
|
|
static bool is_branching_command(const char *cmd);
|
|
|
|
static void save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf);
|
|
|
|
static void discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf);
|
|
|
|
static void copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf);
|
2016-08-08 16:07:46 +02:00
|
|
|
static bool do_connect(enum trivalue reuse_previous_specification,
|
|
|
|
char *dbname, char *user, char *host, char *port);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
|
|
|
|
int lineno, bool *edited);
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 05:24:17 +01:00
|
|
|
static bool do_shell(const char *command);
|
2016-03-21 23:34:18 +01:00
|
|
|
static bool do_watch(PQExpBuffer query_buf, double sleep);
|
2015-07-03 21:48:18 +02:00
|
|
|
static bool lookup_object_oid(EditableObjectType obj_type, const char *desc,
|
|
|
|
Oid *obj_oid);
|
|
|
|
static bool get_create_object_cmd(EditableObjectType obj_type, Oid oid,
|
|
|
|
PQExpBuffer buf);
|
|
|
|
static int strip_lineno_from_objdesc(char *obj);
|
|
|
|
static int count_lines_in_buf(PQExpBuffer buf);
|
|
|
|
static void print_with_linenumbers(FILE *output, char *lines,
|
|
|
|
const char *header_keyword);
|
2008-09-06 22:18:08 +02:00
|
|
|
static void minimal_error_message(PGresult *res);
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 05:24:17 +01:00
|
|
|
|
2008-07-01 02:08:18 +02:00
|
|
|
static void printSSLInfo(void);
|
2013-10-03 21:18:02 +02:00
|
|
|
static bool printPsetInfo(const char *param, struct printQueryOpt *popt);
|
2014-10-19 03:58:17 +02:00
|
|
|
static char *pset_value_string(const char *param, struct printQueryOpt *popt);
|
2008-07-01 02:08:18 +02:00
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
static void checkWin32Codepage(void);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
|
1999-11-04 22:56:02 +01:00
|
|
|
/*----------
|
|
|
|
* HandleSlashCmds:
|
|
|
|
*
|
2006-12-28 01:29:13 +01:00
|
|
|
* Handles all the different commands that start with '\'.
|
|
|
|
* Ordinarily called by MainLoop().
|
1999-11-04 22:56:02 +01:00
|
|
|
*
|
2004-02-19 20:40:09 +01:00
|
|
|
* scan_state is a lexer working state that is set to continue scanning
|
|
|
|
* just after the '\'. The lexer is advanced past the command and all
|
|
|
|
* arguments on return.
|
1999-11-04 22:56:02 +01:00
|
|
|
*
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
* cstack is the current \if stack state. This will be examined, and
|
|
|
|
* possibly modified by conditional commands.
|
|
|
|
*
|
|
|
|
* query_buf contains the query-so-far, which may be modified by
|
2004-02-19 20:40:09 +01:00
|
|
|
* execution of the backslash command (for example, \r clears it).
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
*
|
|
|
|
* previous_buf contains the query most recently sent to the server
|
|
|
|
* (empty if none yet). This should not be modified here, but some
|
|
|
|
* commands copy its content into query_buf.
|
|
|
|
*
|
|
|
|
* query_buf and previous_buf will be NULL when executing a "-c"
|
|
|
|
* command-line option.
|
1999-11-04 22:56:02 +01:00
|
|
|
*
|
|
|
|
* Returns a status code indicating what action is desired, see command.h.
|
|
|
|
*----------
|
|
|
|
*/
|
|
|
|
|
|
|
|
backslashResult
|
2004-02-19 20:40:09 +01:00
|
|
|
HandleSlashCmds(PsqlScanState scan_state,
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf,
|
|
|
|
PQExpBuffer previous_buf)
|
1999-11-04 22:56:02 +01:00
|
|
|
{
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
backslashResult status;
|
2004-02-19 20:40:09 +01:00
|
|
|
char *cmd;
|
|
|
|
char *arg;
|
1999-11-05 00:14:30 +01:00
|
|
|
|
2012-12-15 00:03:07 +01:00
|
|
|
Assert(scan_state != NULL);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
Assert(cstack != NULL);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
/* Parse off the command name */
|
|
|
|
cmd = psql_scan_slash_command(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
/* And try to execute it */
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
status = exec_command(cmd, scan_state, cstack, query_buf, previous_buf);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2005-12-18 03:17:16 +01:00
|
|
|
if (status == PSQL_CMD_UNKNOWN)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
if (pset.cur_cmd_interactive)
|
2012-08-26 04:58:42 +02:00
|
|
|
psql_error("Invalid command \\%s. Try \\? for help.\n", cmd);
|
2000-04-12 19:17:23 +02:00
|
|
|
else
|
2004-02-19 20:40:09 +01:00
|
|
|
psql_error("invalid command \\%s\n", cmd);
|
2005-12-18 03:17:16 +01:00
|
|
|
status = PSQL_CMD_ERROR;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2005-12-18 03:17:16 +01:00
|
|
|
if (status != PSQL_CMD_ERROR)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/*
|
|
|
|
* Eat any remaining arguments after a valid command. We want to
|
|
|
|
* suppress evaluation of backticks in this situation, so transiently
|
|
|
|
* push an inactive conditional-stack entry.
|
|
|
|
*/
|
|
|
|
bool active_branch = conditional_active(cstack);
|
|
|
|
|
|
|
|
conditional_stack_push(cstack, IFSTATE_IGNORED);
|
2004-12-19 20:39:47 +01:00
|
|
|
while ((arg = psql_scan_slash_option(scan_state,
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
OT_NORMAL, NULL, false)))
|
2004-12-19 20:39:47 +01:00
|
|
|
{
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
if (active_branch)
|
|
|
|
psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
|
2004-12-19 20:39:47 +01:00
|
|
|
free(arg);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
conditional_stack_pop(cstack);
|
2004-12-19 20:39:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* silently throw away rest of line after an erroneous command */
|
|
|
|
while ((arg = psql_scan_slash_option(scan_state,
|
|
|
|
OT_WHOLE_LINE, NULL, false)))
|
|
|
|
free(arg);
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
/* if there is a trailing \\, swallow it */
|
|
|
|
psql_scan_slash_command_end(scan_state);
|
|
|
|
|
|
|
|
free(cmd);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2006-12-28 01:29:13 +01:00
|
|
|
/* some commands write to queryFout, so make sure output is sent */
|
|
|
|
fflush(pset.queryFout);
|
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
return status;
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
/*
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
* Subroutine to actually try to execute a backslash command.
|
|
|
|
*
|
|
|
|
* The typical "success" result code is PSQL_CMD_SKIP_LINE, although some
|
|
|
|
* commands return something else. Failure results are PSQL_CMD_ERROR,
|
|
|
|
* unless PSQL_CMD_UNKNOWN is more appropriate.
|
2006-04-02 22:08:22 +02:00
|
|
|
*/
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
static backslashResult
|
|
|
|
exec_command(const char *cmd,
|
|
|
|
PsqlScanState scan_state,
|
|
|
|
ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf,
|
|
|
|
PQExpBuffer previous_buf)
|
2006-04-02 22:08:22 +02:00
|
|
|
{
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
backslashResult status;
|
|
|
|
bool active_branch = conditional_active(cstack);
|
2006-04-02 22:08:22 +02:00
|
|
|
|
|
|
|
/*
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
* In interactive mode, warn when we're ignoring a command within a false
|
|
|
|
* \if-branch. But we continue on, so as to parse and discard the right
|
|
|
|
* amount of parameter text. Each individual backslash command subroutine
|
|
|
|
* is responsible for doing nothing after discarding appropriate
|
|
|
|
* arguments, if !active_branch.
|
2006-04-02 22:08:22 +02:00
|
|
|
*/
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
if (pset.cur_cmd_interactive && !active_branch &&
|
|
|
|
!is_branching_command(cmd))
|
|
|
|
{
|
|
|
|
psql_error("\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block\n",
|
|
|
|
cmd);
|
|
|
|
}
|
2006-04-02 22:08:22 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
if (strcmp(cmd, "a") == 0)
|
|
|
|
status = exec_command_a(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "C") == 0)
|
|
|
|
status = exec_command_C(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
|
|
|
|
status = exec_command_connect(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "cd") == 0)
|
|
|
|
status = exec_command_cd(scan_state, active_branch, cmd);
|
|
|
|
else if (strcmp(cmd, "conninfo") == 0)
|
|
|
|
status = exec_command_conninfo(scan_state, active_branch);
|
|
|
|
else if (pg_strcasecmp(cmd, "copy") == 0)
|
|
|
|
status = exec_command_copy(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "copyright") == 0)
|
|
|
|
status = exec_command_copyright(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "crosstabview") == 0)
|
|
|
|
status = exec_command_crosstabview(scan_state, active_branch);
|
|
|
|
else if (cmd[0] == 'd')
|
|
|
|
status = exec_command_d(scan_state, active_branch, cmd);
|
|
|
|
else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
|
|
|
|
status = exec_command_edit(scan_state, active_branch,
|
|
|
|
query_buf, previous_buf);
|
|
|
|
else if (strcmp(cmd, "ef") == 0)
|
2017-09-06 23:32:40 +02:00
|
|
|
status = exec_command_ef_ev(scan_state, active_branch, query_buf, true);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else if (strcmp(cmd, "ev") == 0)
|
2017-09-06 23:32:40 +02:00
|
|
|
status = exec_command_ef_ev(scan_state, active_branch, query_buf, false);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
|
|
|
|
status = exec_command_echo(scan_state, active_branch, cmd);
|
|
|
|
else if (strcmp(cmd, "elif") == 0)
|
|
|
|
status = exec_command_elif(scan_state, cstack, query_buf);
|
|
|
|
else if (strcmp(cmd, "else") == 0)
|
|
|
|
status = exec_command_else(scan_state, cstack, query_buf);
|
|
|
|
else if (strcmp(cmd, "endif") == 0)
|
|
|
|
status = exec_command_endif(scan_state, cstack, query_buf);
|
|
|
|
else if (strcmp(cmd, "encoding") == 0)
|
|
|
|
status = exec_command_encoding(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "errverbose") == 0)
|
|
|
|
status = exec_command_errverbose(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "f") == 0)
|
|
|
|
status = exec_command_f(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "g") == 0 || strcmp(cmd, "gx") == 0)
|
|
|
|
status = exec_command_g(scan_state, active_branch, cmd);
|
2017-09-06 00:17:47 +02:00
|
|
|
else if (strcmp(cmd, "gdesc") == 0)
|
|
|
|
status = exec_command_gdesc(scan_state, active_branch);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else if (strcmp(cmd, "gexec") == 0)
|
|
|
|
status = exec_command_gexec(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "gset") == 0)
|
|
|
|
status = exec_command_gset(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
|
|
|
|
status = exec_command_help(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
|
|
|
|
status = exec_command_html(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0 ||
|
|
|
|
strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
|
|
|
|
status = exec_command_include(scan_state, active_branch, cmd);
|
|
|
|
else if (strcmp(cmd, "if") == 0)
|
|
|
|
status = exec_command_if(scan_state, cstack, query_buf);
|
|
|
|
else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 ||
|
|
|
|
strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
|
|
|
|
status = exec_command_list(scan_state, active_branch, cmd);
|
|
|
|
else if (strncmp(cmd, "lo_", 3) == 0)
|
|
|
|
status = exec_command_lo(scan_state, active_branch, cmd);
|
|
|
|
else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
|
|
|
|
status = exec_command_out(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
|
2017-04-02 22:50:25 +02:00
|
|
|
status = exec_command_print(scan_state, active_branch,
|
|
|
|
query_buf, previous_buf);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else if (strcmp(cmd, "password") == 0)
|
|
|
|
status = exec_command_password(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "prompt") == 0)
|
|
|
|
status = exec_command_prompt(scan_state, active_branch, cmd);
|
|
|
|
else if (strcmp(cmd, "pset") == 0)
|
|
|
|
status = exec_command_pset(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
|
|
|
|
status = exec_command_quit(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
|
|
|
|
status = exec_command_reset(scan_state, active_branch, query_buf);
|
|
|
|
else if (strcmp(cmd, "s") == 0)
|
|
|
|
status = exec_command_s(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "set") == 0)
|
|
|
|
status = exec_command_set(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "setenv") == 0)
|
|
|
|
status = exec_command_setenv(scan_state, active_branch, cmd);
|
|
|
|
else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
|
2017-09-06 23:32:40 +02:00
|
|
|
status = exec_command_sf_sv(scan_state, active_branch, cmd, true);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0)
|
2017-09-06 23:32:40 +02:00
|
|
|
status = exec_command_sf_sv(scan_state, active_branch, cmd, false);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else if (strcmp(cmd, "t") == 0)
|
|
|
|
status = exec_command_t(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "T") == 0)
|
|
|
|
status = exec_command_T(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "timing") == 0)
|
|
|
|
status = exec_command_timing(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "unset") == 0)
|
|
|
|
status = exec_command_unset(scan_state, active_branch, cmd);
|
|
|
|
else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
|
|
|
|
status = exec_command_write(scan_state, active_branch, cmd,
|
|
|
|
query_buf, previous_buf);
|
|
|
|
else if (strcmp(cmd, "watch") == 0)
|
|
|
|
status = exec_command_watch(scan_state, active_branch,
|
|
|
|
query_buf, previous_buf);
|
|
|
|
else if (strcmp(cmd, "x") == 0)
|
|
|
|
status = exec_command_x(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "z") == 0)
|
|
|
|
status = exec_command_z(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "!") == 0)
|
|
|
|
status = exec_command_shell_escape(scan_state, active_branch);
|
|
|
|
else if (strcmp(cmd, "?") == 0)
|
|
|
|
status = exec_command_slash_command_help(scan_state, active_branch);
|
|
|
|
else
|
|
|
|
status = PSQL_CMD_UNKNOWN;
|
2006-04-02 22:08:22 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/*
|
|
|
|
* All the commands that return PSQL_CMD_SEND want to execute previous_buf
|
|
|
|
* if query_buf is empty. For convenience we implement that here, not in
|
|
|
|
* the individual command subroutines.
|
|
|
|
*/
|
|
|
|
if (status == PSQL_CMD_SEND)
|
|
|
|
copy_previous_query(query_buf, previous_buf);
|
2006-04-02 22:08:22 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
2006-04-02 22:08:22 +02:00
|
|
|
}
|
2006-10-04 02:30:14 +02:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
/*
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
* \a -- toggle field alignment
|
|
|
|
*
|
|
|
|
* This makes little sense but we keep it around.
|
2004-02-19 20:40:09 +01:00
|
|
|
*/
|
1999-11-04 22:56:02 +01:00
|
|
|
static backslashResult
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
exec_command_a(PsqlScanState scan_state, bool active_branch)
|
1999-11-04 22:56:02 +01:00
|
|
|
{
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
bool success = true;
|
2000-04-12 19:17:23 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2000-01-14 23:18:03 +01:00
|
|
|
if (pset.popt.topt.format != PRINT_ALIGNED)
|
2006-08-29 17:19:51 +02:00
|
|
|
success = do_pset("format", "aligned", &pset.popt, pset.quiet);
|
1999-11-05 00:14:30 +01:00
|
|
|
else
|
2006-08-29 17:19:51 +02:00
|
|
|
success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \C -- override table title (formerly change HTML caption)
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_C(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2006-08-29 17:19:51 +02:00
|
|
|
success = do_pset("title", opt, &pset.popt, pset.quiet);
|
2000-04-12 19:17:23 +02:00
|
|
|
free(opt);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \c or \connect -- connect to database using the specified parameters.
|
|
|
|
*
|
|
|
|
* \c [-reuse-previous=BOOL] dbname user host port
|
|
|
|
*
|
|
|
|
* Specifying a parameter as '-' is equivalent to omitting it. Examples:
|
|
|
|
*
|
|
|
|
* \c - - hst Connect to current database on current port of
|
|
|
|
* host "hst" as current user.
|
|
|
|
* \c - usr - prt Connect to current database on port "prt" of current host
|
|
|
|
* as user "usr".
|
|
|
|
* \c dbs Connect to database "dbs" on current port of current host
|
|
|
|
* as current user.
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_connect(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2016-08-08 16:07:46 +02:00
|
|
|
static const char prefix[] = "-reuse-previous=";
|
2000-04-12 19:17:23 +02:00
|
|
|
char *opt1,
|
2006-02-12 03:54:30 +01:00
|
|
|
*opt2,
|
|
|
|
*opt3,
|
|
|
|
*opt4;
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
enum trivalue reuse_previous = TRI_DEFAULT;
|
2000-02-08 00:10:11 +01:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
opt1 = read_connect_arg(scan_state);
|
2016-08-08 16:07:46 +02:00
|
|
|
if (opt1 != NULL && strncmp(opt1, prefix, sizeof(prefix) - 1) == 0)
|
|
|
|
{
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
bool on_off;
|
2016-08-08 16:07:46 +02:00
|
|
|
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
success = ParseVariableBool(opt1 + sizeof(prefix) - 1,
|
|
|
|
"-reuse-previous",
|
|
|
|
&on_off);
|
|
|
|
if (success)
|
|
|
|
{
|
|
|
|
reuse_previous = on_off ? TRI_YES : TRI_NO;
|
|
|
|
free(opt1);
|
|
|
|
opt1 = read_connect_arg(scan_state);
|
|
|
|
}
|
2016-08-08 16:07:46 +02:00
|
|
|
}
|
|
|
|
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
if (success) /* give up if reuse_previous was invalid */
|
|
|
|
{
|
|
|
|
opt2 = read_connect_arg(scan_state);
|
|
|
|
opt3 = read_connect_arg(scan_state);
|
|
|
|
opt4 = read_connect_arg(scan_state);
|
2006-04-02 22:08:22 +02:00
|
|
|
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
success = do_connect(reuse_previous, opt1, opt2, opt3, opt4);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
free(opt2);
|
|
|
|
free(opt3);
|
|
|
|
free(opt4);
|
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
free(opt1);
|
2000-02-08 00:10:11 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \cd -- change directory
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2001-05-07 21:31:33 +02:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
2001-10-25 07:50:21 +02:00
|
|
|
char *dir;
|
2001-05-07 21:31:33 +02:00
|
|
|
|
|
|
|
if (opt)
|
|
|
|
dir = opt;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifndef WIN32
|
|
|
|
struct passwd *pw;
|
2014-01-30 02:03:57 +01:00
|
|
|
uid_t user_id = geteuid();
|
2001-05-07 21:31:33 +02:00
|
|
|
|
2014-01-30 02:03:57 +01:00
|
|
|
errno = 0; /* clear errno before call */
|
|
|
|
pw = getpwuid(user_id);
|
2001-05-07 21:31:33 +02:00
|
|
|
if (!pw)
|
|
|
|
{
|
2014-08-29 06:01:34 +02:00
|
|
|
psql_error("could not get home directory for user ID %ld: %s\n",
|
2014-01-30 02:03:57 +01:00
|
|
|
(long) user_id,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
errno ? strerror(errno) : _("user does not exist"));
|
2001-05-07 21:31:33 +02:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
dir = pw->pw_dir;
|
2001-10-25 07:50:21 +02:00
|
|
|
#else /* WIN32 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* On Windows, 'cd' without arguments prints the current
|
|
|
|
* directory, so if someone wants to code this here instead...
|
|
|
|
*/
|
2001-05-07 21:31:33 +02:00
|
|
|
dir = "/";
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:18:54 +02:00
|
|
|
#endif /* WIN32 */
|
2001-05-07 21:31:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (chdir(dir) == -1)
|
|
|
|
{
|
2003-07-23 10:47:41 +02:00
|
|
|
psql_error("\\%s: could not change directory to \"%s\": %s\n",
|
2001-05-07 21:31:33 +02:00
|
|
|
cmd, dir, strerror(errno));
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opt)
|
|
|
|
free(opt);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2001-05-07 21:31:33 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \conninfo -- display information about the current connection
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
if (active_branch)
|
2010-07-20 05:54:19 +02:00
|
|
|
{
|
|
|
|
char *db = PQdb(pset.db);
|
|
|
|
|
2010-07-23 16:56:54 +02:00
|
|
|
if (db == NULL)
|
2011-05-21 23:36:14 +02:00
|
|
|
printf(_("You are currently not connected to a database.\n"));
|
2010-07-20 05:54:19 +02:00
|
|
|
else
|
2010-07-23 16:56:54 +02:00
|
|
|
{
|
2018-08-03 18:20:47 +02:00
|
|
|
char *host = PQhost(pset.db);
|
2018-11-19 18:34:12 +01:00
|
|
|
char *hostaddr = PQhostaddr(pset.db);
|
2014-11-29 18:31:43 +01:00
|
|
|
|
2018-11-19 18:34:12 +01:00
|
|
|
/*
|
|
|
|
* If the host is an absolute path, the connection is via socket
|
|
|
|
* unless overriden by hostaddr
|
|
|
|
*/
|
2010-07-23 16:56:54 +02:00
|
|
|
if (is_absolute_path(host))
|
2018-11-19 18:34:12 +01:00
|
|
|
{
|
|
|
|
if (hostaddr && *hostaddr)
|
|
|
|
printf(_("You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"),
|
|
|
|
db, PQuser(pset.db), hostaddr, PQport(pset.db));
|
|
|
|
else
|
|
|
|
printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
|
|
|
|
db, PQuser(pset.db), host, PQport(pset.db));
|
|
|
|
}
|
2010-07-23 16:56:54 +02:00
|
|
|
else
|
2018-11-19 18:34:12 +01:00
|
|
|
{
|
|
|
|
if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0)
|
|
|
|
printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"),
|
|
|
|
db, PQuser(pset.db), host, hostaddr, PQport(pset.db));
|
|
|
|
else
|
|
|
|
printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
|
|
|
|
db, PQuser(pset.db), host, PQport(pset.db));
|
|
|
|
}
|
2012-06-14 15:43:14 +02:00
|
|
|
printSSLInfo();
|
2010-07-23 16:56:54 +02:00
|
|
|
}
|
2010-07-20 05:54:19 +02:00
|
|
|
}
|
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \copy -- run a COPY command
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_copy(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
2005-10-15 04:49:52 +02:00
|
|
|
OT_WHOLE_LINE, NULL, false);
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
success = do_copy(opt);
|
|
|
|
free(opt);
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_whole_line(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \copyright -- print copyright notice
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_copyright(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
print_copyright();
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \crosstabview -- execute a query and display results in crosstab
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_crosstabview(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
2016-04-09 01:23:18 +02:00
|
|
|
{
|
2016-04-15 04:54:26 +02:00
|
|
|
int i;
|
2016-04-09 01:23:18 +02:00
|
|
|
|
2016-04-15 04:54:26 +02:00
|
|
|
for (i = 0; i < lengthof(pset.ctv_args); i++)
|
|
|
|
pset.ctv_args[i] = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
2016-04-09 01:23:18 +02:00
|
|
|
pset.crosstab_flag = true;
|
|
|
|
status = PSQL_CMD_SEND;
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2016-04-09 01:23:18 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \d* commands
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2002-08-10 05:56:24 +02:00
|
|
|
char *pattern;
|
2009-06-11 16:49:15 +02:00
|
|
|
bool show_verbose,
|
|
|
|
show_system;
|
2001-10-25 07:50:21 +02:00
|
|
|
|
2002-08-10 05:56:24 +02:00
|
|
|
/* We don't do SQLID reduction on the pattern yet */
|
2004-02-19 20:40:09 +01:00
|
|
|
pattern = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
2000-02-08 00:10:11 +01:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
show_verbose = strchr(cmd, '+') ? true : false;
|
2009-01-20 03:13:42 +01:00
|
|
|
show_system = strchr(cmd, 'S') ? true : false;
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 05:24:17 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
switch (cmd[1])
|
|
|
|
{
|
|
|
|
case '\0':
|
2000-04-12 19:17:23 +02:00
|
|
|
case '+':
|
2009-01-20 03:13:42 +01:00
|
|
|
case 'S':
|
2002-08-10 05:56:24 +02:00
|
|
|
if (pattern)
|
2009-01-20 03:13:42 +01:00
|
|
|
success = describeTableDetails(pattern, show_verbose, show_system);
|
1999-11-05 00:14:30 +01:00
|
|
|
else
|
2000-04-12 19:17:23 +02:00
|
|
|
/* standard listing of interesting things */
|
2013-03-04 01:23:31 +01:00
|
|
|
success = listTables("tvmsE", NULL, show_verbose, show_system);
|
1999-11-05 00:14:30 +01:00
|
|
|
break;
|
2016-06-07 23:59:34 +02:00
|
|
|
case 'A':
|
|
|
|
success = describeAccessMethods(pattern, show_verbose);
|
|
|
|
break;
|
1999-11-05 00:14:30 +01:00
|
|
|
case 'a':
|
2009-01-06 22:10:30 +01:00
|
|
|
success = describeAggregates(pattern, show_verbose, show_system);
|
1999-11-05 00:14:30 +01:00
|
|
|
break;
|
2004-06-18 08:14:31 +02:00
|
|
|
case 'b':
|
2004-07-15 05:56:06 +02:00
|
|
|
success = describeTablespaces(pattern, show_verbose);
|
2004-06-18 08:14:31 +02:00
|
|
|
break;
|
2003-01-07 21:56:07 +01:00
|
|
|
case 'c':
|
2011-08-08 18:26:13 +02:00
|
|
|
success = listConversions(pattern, show_verbose, show_system);
|
2003-01-07 21:56:07 +01:00
|
|
|
break;
|
|
|
|
case 'C':
|
2011-08-04 18:22:26 +02:00
|
|
|
success = listCasts(pattern, show_verbose);
|
2003-01-07 21:56:07 +01:00
|
|
|
break;
|
1999-11-05 00:14:30 +01:00
|
|
|
case 'd':
|
2010-04-03 22:55:57 +02:00
|
|
|
if (strncmp(cmd, "ddp", 3) == 0)
|
2009-10-05 21:24:49 +02:00
|
|
|
success = listDefaultACLs(pattern);
|
|
|
|
else
|
|
|
|
success = objectDescription(pattern, show_system);
|
1999-11-05 00:14:30 +01:00
|
|
|
break;
|
2003-01-07 21:56:07 +01:00
|
|
|
case 'D':
|
2011-08-08 18:26:13 +02:00
|
|
|
success = listDomains(pattern, show_verbose, show_system);
|
2003-01-07 21:56:07 +01:00
|
|
|
break;
|
2009-04-21 17:49:06 +02:00
|
|
|
case 'f': /* function subsystem */
|
|
|
|
switch (cmd[2])
|
|
|
|
{
|
|
|
|
case '\0':
|
|
|
|
case '+':
|
|
|
|
case 'S':
|
|
|
|
case 'a':
|
|
|
|
case 'n':
|
2018-07-14 12:17:49 +02:00
|
|
|
case 'p':
|
2009-04-21 17:49:06 +02:00
|
|
|
case 't':
|
|
|
|
case 'w':
|
2009-06-11 16:49:15 +02:00
|
|
|
success = describeFunctions(&cmd[2], pattern, show_verbose, show_system);
|
2009-04-21 17:49:06 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
status = PSQL_CMD_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
break;
|
2003-12-01 23:21:54 +01:00
|
|
|
case 'g':
|
2005-08-14 20:49:30 +02:00
|
|
|
/* no longer distinct from \du */
|
2016-04-08 22:56:27 +02:00
|
|
|
success = describeRoles(pattern, show_verbose, show_system);
|
2003-12-01 23:21:54 +01:00
|
|
|
break;
|
1999-11-05 00:14:30 +01:00
|
|
|
case 'l':
|
2000-01-14 23:18:03 +01:00
|
|
|
success = do_lo_list();
|
1999-11-05 00:14:30 +01:00
|
|
|
break;
|
2011-01-20 06:00:30 +01:00
|
|
|
case 'L':
|
|
|
|
success = listLanguages(pattern, show_verbose, show_system);
|
|
|
|
break;
|
2003-01-07 21:56:07 +01:00
|
|
|
case 'n':
|
2010-11-07 02:41:14 +01:00
|
|
|
success = listSchemas(pattern, show_verbose, show_system);
|
2003-01-07 21:56:07 +01:00
|
|
|
break;
|
1999-11-05 00:14:30 +01:00
|
|
|
case 'o':
|
2014-01-16 21:29:18 +01:00
|
|
|
success = describeOperators(pattern, show_verbose, show_system);
|
1999-11-05 00:14:30 +01:00
|
|
|
break;
|
2011-02-12 14:54:13 +01:00
|
|
|
case 'O':
|
|
|
|
success = listCollations(pattern, show_verbose, show_system);
|
|
|
|
break;
|
1999-11-05 00:14:30 +01:00
|
|
|
case 'p':
|
2002-08-10 05:56:24 +02:00
|
|
|
success = permissionsList(pattern);
|
1999-11-05 00:14:30 +01:00
|
|
|
break;
|
|
|
|
case 'T':
|
2009-01-06 22:10:30 +01:00
|
|
|
success = describeTypes(pattern, show_verbose, show_system);
|
1999-11-05 00:14:30 +01:00
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
case 'v':
|
2013-03-04 01:23:31 +01:00
|
|
|
case 'm':
|
1999-11-05 00:14:30 +01:00
|
|
|
case 'i':
|
|
|
|
case 's':
|
2011-01-02 05:48:11 +01:00
|
|
|
case 'E':
|
2009-01-06 22:10:30 +01:00
|
|
|
success = listTables(&cmd[1], pattern, show_verbose, show_system);
|
1999-11-05 00:14:30 +01:00
|
|
|
break;
|
2009-10-08 00:14:26 +02:00
|
|
|
case 'r':
|
|
|
|
if (cmd[2] == 'd' && cmd[3] == 's')
|
|
|
|
{
|
|
|
|
char *pattern2 = NULL;
|
|
|
|
|
|
|
|
if (pattern)
|
|
|
|
pattern2 = psql_scan_slash_option(scan_state,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
OT_NORMAL, NULL, true);
|
2009-10-08 00:14:26 +02:00
|
|
|
success = listDbRoleSettings(pattern, pattern2);
|
2017-07-27 17:10:38 +02:00
|
|
|
|
|
|
|
if (pattern2)
|
|
|
|
free(pattern2);
|
2009-10-08 00:14:26 +02:00
|
|
|
}
|
|
|
|
else
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
status = PSQL_CMD_UNKNOWN;
|
2009-10-08 00:14:26 +02:00
|
|
|
break;
|
2017-01-19 18:00:00 +01:00
|
|
|
case 'R':
|
|
|
|
switch (cmd[2])
|
|
|
|
{
|
|
|
|
case 'p':
|
|
|
|
if (show_verbose)
|
|
|
|
success = describePublications(pattern);
|
|
|
|
else
|
|
|
|
success = listPublications(pattern);
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
success = describeSubscriptions(pattern, show_verbose);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
status = PSQL_CMD_UNKNOWN;
|
|
|
|
}
|
|
|
|
break;
|
2001-05-09 19:29:10 +02:00
|
|
|
case 'u':
|
2016-04-08 22:56:27 +02:00
|
|
|
success = describeRoles(pattern, show_verbose, show_system);
|
2001-10-25 07:50:21 +02:00
|
|
|
break;
|
2007-08-21 03:11:32 +02:00
|
|
|
case 'F': /* text search subsystem */
|
|
|
|
switch (cmd[2])
|
|
|
|
{
|
|
|
|
case '\0':
|
|
|
|
case '+':
|
|
|
|
success = listTSConfigs(pattern, show_verbose);
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
success = listTSParsers(pattern, show_verbose);
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
success = listTSDictionaries(pattern, show_verbose);
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
success = listTSTemplates(pattern, show_verbose);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
status = PSQL_CMD_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2008-12-19 17:25:19 +01:00
|
|
|
case 'e': /* SQL/MED subsystem */
|
2009-06-11 16:49:15 +02:00
|
|
|
switch (cmd[2])
|
2008-12-19 17:25:19 +01:00
|
|
|
{
|
|
|
|
case 's':
|
|
|
|
success = listForeignServers(pattern, show_verbose);
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
success = listUserMappings(pattern, show_verbose);
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
success = listForeignDataWrappers(pattern, show_verbose);
|
|
|
|
break;
|
2011-01-02 05:48:11 +01:00
|
|
|
case 't':
|
|
|
|
success = listForeignTables(pattern, show_verbose);
|
|
|
|
break;
|
2008-12-19 17:25:19 +01:00
|
|
|
default:
|
|
|
|
status = PSQL_CMD_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2011-04-10 17:42:00 +02:00
|
|
|
case 'x': /* Extensions */
|
2011-02-08 22:08:41 +01:00
|
|
|
if (show_verbose)
|
|
|
|
success = listExtensionContents(pattern);
|
|
|
|
else
|
|
|
|
success = listExtensions(pattern);
|
|
|
|
break;
|
2012-07-18 16:16:16 +02:00
|
|
|
case 'y': /* Event Triggers */
|
|
|
|
success = listEventTriggers(pattern, show_verbose);
|
|
|
|
break;
|
1999-11-05 00:14:30 +01:00
|
|
|
default:
|
2005-12-18 03:17:16 +01:00
|
|
|
status = PSQL_CMD_UNKNOWN;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
2002-08-10 05:56:24 +02:00
|
|
|
|
|
|
|
if (pattern)
|
|
|
|
free(pattern);
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
if (!success)
|
|
|
|
status = PSQL_CMD_ERROR;
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \e or \edit -- edit the current query buffer, or edit a file and
|
|
|
|
* make it the query buffer
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_edit(PsqlScanState scan_state, bool active_branch,
|
|
|
|
PQExpBuffer query_buf, PQExpBuffer previous_buf)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
|
|
|
if (!query_buf)
|
|
|
|
{
|
|
|
|
psql_error("no query buffer\n");
|
2005-12-18 03:17:16 +01:00
|
|
|
status = PSQL_CMD_ERROR;
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-09-06 22:18:08 +02:00
|
|
|
char *fname;
|
2010-08-12 02:40:59 +02:00
|
|
|
char *ln = NULL;
|
|
|
|
int lineno = -1;
|
2008-09-06 22:18:08 +02:00
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
fname = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
2004-08-13 16:47:23 +02:00
|
|
|
if (fname)
|
2010-08-12 02:40:59 +02:00
|
|
|
{
|
|
|
|
/* try to get separate lineno arg */
|
|
|
|
ln = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
|
|
|
if (ln == NULL)
|
|
|
|
{
|
|
|
|
/* only one arg; maybe it is lineno not fname */
|
|
|
|
if (fname[0] &&
|
|
|
|
strspn(fname, "0123456789") == strlen(fname))
|
|
|
|
{
|
|
|
|
/* all digits, so assume it is lineno */
|
|
|
|
ln = fname;
|
|
|
|
fname = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ln)
|
|
|
|
{
|
|
|
|
lineno = atoi(ln);
|
|
|
|
if (lineno < 1)
|
|
|
|
{
|
|
|
|
psql_error("invalid line number: %s\n", ln);
|
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (status != PSQL_CMD_ERROR)
|
|
|
|
{
|
|
|
|
expand_tilde(&fname);
|
|
|
|
if (fname)
|
|
|
|
canonicalize_path(fname);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
|
2017-04-02 22:50:25 +02:00
|
|
|
/* If query_buf is empty, recall previous query for editing */
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
copy_previous_query(query_buf, previous_buf);
|
|
|
|
|
2010-08-12 02:40:59 +02:00
|
|
|
if (do_edit(fname, query_buf, lineno, NULL))
|
|
|
|
status = PSQL_CMD_NEWEDIT;
|
|
|
|
else
|
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
if (fname)
|
|
|
|
free(fname);
|
|
|
|
if (ln)
|
|
|
|
free(ln);
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-09-06 23:32:40 +02:00
|
|
|
* \ef/\ev -- edit the named function/view, or
|
|
|
|
* present a blank CREATE FUNCTION/VIEW template if no argument is given
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
*/
|
|
|
|
static backslashResult
|
2017-09-06 23:32:40 +02:00
|
|
|
exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
|
|
|
|
PQExpBuffer query_buf, bool is_func)
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
2008-09-06 02:01:25 +02:00
|
|
|
{
|
2017-09-06 23:32:40 +02:00
|
|
|
char *obj_desc = psql_scan_slash_option(scan_state,
|
|
|
|
OT_WHOLE_LINE,
|
|
|
|
NULL, true);
|
2010-08-12 02:40:59 +02:00
|
|
|
int lineno = -1;
|
|
|
|
|
2017-09-06 23:32:40 +02:00
|
|
|
if (pset.sversion < (is_func ? 80400 : 70400))
|
2011-11-11 00:36:49 +01:00
|
|
|
{
|
Fix assorted places in psql to print version numbers >= 10 in new style.
This is somewhat cosmetic, since as long as you know what you are looking
at, "10.0" is a serviceable substitute for "10". But there is a potential
for confusion between version numbers with minor numbers and those without
--- we don't want people asking "why is psql saying 10.0 when my server is
10.2". Therefore, back-patch as far as practical, which turns out to be
9.3. I could have redone the patch to use fprintf(stderr) in place of
psql_error(), but it seems more work than is warranted for branches that
will be EOL or nearly so by the time v10 comes out.
Although only psql seems to contain any code that needs this, I chose
to put the support function into fe_utils, since it seems likely we'll
need it in other client programs in future. (In 9.3-9.5, use dumputils.c,
the predecessor of fe_utils/string_utils.c.)
In HEAD, also fix the backend code that whines about loadable-library
version mismatch. I don't see much need to back-patch that.
2016-08-16 21:58:30 +02:00
|
|
|
char sverbuf[32];
|
|
|
|
|
2017-09-06 23:32:40 +02:00
|
|
|
formatPGVersionNumber(pset.sversion, false,
|
|
|
|
sverbuf, sizeof(sverbuf));
|
|
|
|
if (is_func)
|
|
|
|
psql_error("The server (version %s) does not support editing function source.\n",
|
|
|
|
sverbuf);
|
|
|
|
else
|
|
|
|
psql_error("The server (version %s) does not support editing view definitions.\n",
|
|
|
|
sverbuf);
|
2011-11-11 00:36:49 +01:00
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
else if (!query_buf)
|
2008-09-06 02:01:25 +02:00
|
|
|
{
|
|
|
|
psql_error("no query buffer\n");
|
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-09-06 23:32:40 +02:00
|
|
|
Oid obj_oid = InvalidOid;
|
|
|
|
EditableObjectType eot = is_func ? EditableFunction : EditableView;
|
2008-09-06 02:01:25 +02:00
|
|
|
|
2017-09-06 23:32:40 +02:00
|
|
|
lineno = strip_lineno_from_objdesc(obj_desc);
|
2010-08-12 02:40:59 +02:00
|
|
|
if (lineno == 0)
|
|
|
|
{
|
|
|
|
/* error already reported */
|
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
2017-09-06 23:32:40 +02:00
|
|
|
else if (!obj_desc)
|
2008-09-06 02:01:25 +02:00
|
|
|
{
|
2008-09-06 22:18:08 +02:00
|
|
|
/* set up an empty command to fill in */
|
2017-09-06 23:32:40 +02:00
|
|
|
resetPQExpBuffer(query_buf);
|
|
|
|
if (is_func)
|
|
|
|
appendPQExpBufferStr(query_buf,
|
|
|
|
"CREATE FUNCTION ( )\n"
|
|
|
|
" RETURNS \n"
|
|
|
|
" LANGUAGE \n"
|
|
|
|
" -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n"
|
|
|
|
"AS $function$\n"
|
|
|
|
"\n$function$\n");
|
|
|
|
else
|
|
|
|
appendPQExpBufferStr(query_buf,
|
|
|
|
"CREATE VIEW AS\n"
|
|
|
|
" SELECT \n"
|
|
|
|
" -- something...\n");
|
2008-09-06 22:18:08 +02:00
|
|
|
}
|
2017-09-06 23:32:40 +02:00
|
|
|
else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
|
2008-09-06 22:18:08 +02:00
|
|
|
{
|
|
|
|
/* error already reported */
|
2008-09-06 02:01:25 +02:00
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
2017-09-06 23:32:40 +02:00
|
|
|
else if (!get_create_object_cmd(eot, obj_oid, query_buf))
|
2008-09-06 02:01:25 +02:00
|
|
|
{
|
2008-09-06 22:18:08 +02:00
|
|
|
/* error already reported */
|
|
|
|
status = PSQL_CMD_ERROR;
|
2008-09-06 02:01:25 +02:00
|
|
|
}
|
2017-09-06 23:32:40 +02:00
|
|
|
else if (is_func && lineno > 0)
|
2010-08-12 02:40:59 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* lineno "1" should correspond to the first line of the
|
|
|
|
* function body. We expect that pg_get_functiondef() will
|
2010-08-14 16:20:35 +02:00
|
|
|
* emit that on a line beginning with "AS ", and that there
|
|
|
|
* can be no such line before the real start of the function
|
|
|
|
* body. Increment lineno by the number of lines before that
|
|
|
|
* line, so that it becomes relative to the first line of the
|
|
|
|
* function definition.
|
2010-08-12 02:40:59 +02:00
|
|
|
*/
|
|
|
|
const char *lines = query_buf->data;
|
|
|
|
|
|
|
|
while (*lines != '\0')
|
|
|
|
{
|
2010-08-14 16:20:35 +02:00
|
|
|
if (strncmp(lines, "AS ", 3) == 0)
|
2010-08-12 02:40:59 +02:00
|
|
|
break;
|
|
|
|
lineno++;
|
|
|
|
/* find start of next line */
|
|
|
|
lines = strchr(lines, '\n');
|
|
|
|
if (!lines)
|
|
|
|
break;
|
|
|
|
lines++;
|
|
|
|
}
|
|
|
|
}
|
2008-09-06 22:18:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (status != PSQL_CMD_ERROR)
|
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
bool edited = false;
|
2008-09-06 22:18:08 +02:00
|
|
|
|
2010-08-12 02:40:59 +02:00
|
|
|
if (!do_edit(NULL, query_buf, lineno, &edited))
|
2008-09-06 22:18:08 +02:00
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
else if (!edited)
|
2009-03-25 14:07:26 +01:00
|
|
|
puts(_("No changes"));
|
2008-09-06 02:01:25 +02:00
|
|
|
else
|
|
|
|
status = PSQL_CMD_NEWEDIT;
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
|
2017-09-06 23:32:40 +02:00
|
|
|
if (obj_desc)
|
|
|
|
free(obj_desc);
|
2015-07-03 21:48:18 +02:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_whole_line(scan_state);
|
2015-07-03 21:48:18 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \echo and \qecho -- echo arguments to stdout or query output
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_echo(PsqlScanState scan_state, bool active_branch, const char *cmd)
|
|
|
|
{
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
char *value;
|
|
|
|
char quoted;
|
|
|
|
bool no_newline = false;
|
|
|
|
bool first = true;
|
|
|
|
FILE *fout;
|
|
|
|
|
|
|
|
if (strcmp(cmd, "qecho") == 0)
|
|
|
|
fout = pset.queryFout;
|
|
|
|
else
|
|
|
|
fout = stdout;
|
2001-10-25 07:50:21 +02:00
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
while ((value = psql_scan_slash_option(scan_state,
|
2005-10-15 04:49:52 +02:00
|
|
|
OT_NORMAL, "ed, false)))
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
|
|
|
if (!quoted && strcmp(value, "-n") == 0)
|
|
|
|
no_newline = true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = false;
|
|
|
|
else
|
|
|
|
fputc(' ', fout);
|
|
|
|
fputs(value, fout);
|
|
|
|
}
|
|
|
|
free(value);
|
|
|
|
}
|
|
|
|
if (!no_newline)
|
|
|
|
fputs("\n", fout);
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \encoding -- set/show client side encoding
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_encoding(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
if (active_branch)
|
2000-02-19 06:01:16 +01:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *encoding = psql_scan_slash_option(scan_state,
|
2005-10-15 04:49:52 +02:00
|
|
|
OT_NORMAL, NULL, false);
|
2000-02-20 15:28:28 +01:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
if (!encoding)
|
2003-06-28 02:12:40 +02:00
|
|
|
{
|
2003-09-16 19:59:02 +02:00
|
|
|
/* show encoding */
|
2000-02-21 03:05:12 +01:00
|
|
|
puts(pg_encoding_to_char(pset.encoding));
|
2003-06-28 02:12:40 +02:00
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
else
|
2000-02-21 03:05:12 +01:00
|
|
|
{
|
|
|
|
/* set encoding */
|
|
|
|
if (PQsetClientEncoding(pset.db, encoding) == -1)
|
2002-09-22 22:57:21 +02:00
|
|
|
psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
|
2000-02-21 03:05:12 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* save encoding info into psql internal data */
|
|
|
|
pset.encoding = PQclientEncoding(pset.db);
|
2003-06-28 02:12:40 +02:00
|
|
|
pset.popt.topt.encoding = pset.encoding;
|
|
|
|
SetVariable(pset.vars, "ENCODING",
|
|
|
|
pg_encoding_to_char(pset.encoding));
|
2000-02-21 03:05:12 +01:00
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
free(encoding);
|
|
|
|
}
|
2000-02-20 15:28:28 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2000-02-20 15:28:28 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \errverbose -- display verbose message from last failed query
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_errverbose(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
if (active_branch)
|
2016-04-03 18:29:55 +02:00
|
|
|
{
|
|
|
|
if (pset.last_error_result)
|
|
|
|
{
|
|
|
|
char *msg;
|
|
|
|
|
|
|
|
msg = PQresultVerboseErrorMessage(pset.last_error_result,
|
|
|
|
PQERRORS_VERBOSE,
|
|
|
|
PQSHOW_CONTEXT_ALWAYS);
|
|
|
|
if (msg)
|
|
|
|
{
|
|
|
|
psql_error("%s", msg);
|
|
|
|
PQfreemem(msg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
puts(_("out of memory"));
|
|
|
|
}
|
|
|
|
else
|
2016-05-22 04:17:00 +02:00
|
|
|
puts(_("There is no previous error."));
|
2016-04-03 18:29:55 +02:00
|
|
|
}
|
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/*
|
|
|
|
* \f -- change field separator
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_f(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
|
|
|
{
|
|
|
|
char *fname = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false);
|
|
|
|
|
|
|
|
success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
|
2000-04-12 19:17:23 +02:00
|
|
|
free(fname);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \g [filename] -- send query, optionally with output to file/pipe
|
|
|
|
* \gx [filename] -- same as \g, with expanded mode forced
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *fname = psql_scan_slash_option(scan_state,
|
2005-10-15 04:49:52 +02:00
|
|
|
OT_FILEPIPE, NULL, false);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2000-02-08 00:10:11 +01:00
|
|
|
if (!fname)
|
2000-01-14 23:18:03 +01:00
|
|
|
pset.gfname = NULL;
|
1999-11-05 00:14:30 +01:00
|
|
|
else
|
2004-01-09 22:12:20 +01:00
|
|
|
{
|
|
|
|
expand_tilde(&fname);
|
2004-01-25 04:07:22 +01:00
|
|
|
pset.gfname = pg_strdup(fname);
|
2004-01-09 22:12:20 +01:00
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
free(fname);
|
2017-03-07 15:31:52 +01:00
|
|
|
if (strcmp(cmd, "gx") == 0)
|
|
|
|
pset.g_expanded = true;
|
2005-12-18 03:17:16 +01:00
|
|
|
status = PSQL_CMD_SEND;
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_filepipe(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2017-09-06 00:17:47 +02:00
|
|
|
/*
|
|
|
|
* \gdesc -- describe query result
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_gdesc(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
|
|
|
{
|
|
|
|
pset.gdesc_flag = true;
|
|
|
|
status = PSQL_CMD_SEND;
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/*
|
|
|
|
* \gexec -- send query and execute each field of result
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_gexec(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
Add a \gexec command to psql for evaluation of computed queries.
\gexec executes the just-entered query, like \g, but instead of printing
the results it takes each field as a SQL command to send to the server.
Computing a series of queries to be executed is a fairly common thing,
but up to now you always had to resort to kluges like writing the queries
to a file and then inputting the file. Now it can be done with no
intermediate step.
The implementation is fairly straightforward except for its interaction
with FETCH_COUNT. ExecQueryUsingCursor isn't capable of being called
recursively, and even if it were, its need to create a transaction
block interferes unpleasantly with the desired behavior of \gexec after
a failure of a generated query (i.e., that it can continue). Therefore,
disable use of ExecQueryUsingCursor when doing the master \gexec query.
We can still apply it to individual generated queries, however, and there
might be some value in doing so.
While testing this feature's interaction with single-step mode, I (tgl) was
led to conclude that SendQuery needs to recognize SIGINT (cancel_pressed)
as a negative response to the single-step prompt. Perhaps that's a
back-patchable bug fix, but for now I just included it here.
Corey Huinker, reviewed by Jim Nasby, Daniel Vérité, and myself
2016-04-04 21:25:16 +02:00
|
|
|
{
|
|
|
|
pset.gexec_flag = true;
|
|
|
|
status = PSQL_CMD_SEND;
|
|
|
|
}
|
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \gset [prefix] -- send query and store result into variables
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_gset(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
2013-02-02 23:06:38 +01:00
|
|
|
{
|
|
|
|
char *prefix = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false);
|
|
|
|
|
|
|
|
if (prefix)
|
|
|
|
pset.gset_prefix = prefix;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* we must set a non-NULL prefix to trigger storing */
|
|
|
|
pset.gset_prefix = pg_strdup("");
|
|
|
|
}
|
2014-02-15 06:09:24 +01:00
|
|
|
/* gset_prefix is freed later */
|
2013-02-02 23:06:38 +01:00
|
|
|
status = PSQL_CMD_SEND;
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2013-02-02 23:06:38 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \help [topic] -- print help about SQL commands
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_help(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
2005-10-15 04:49:52 +02:00
|
|
|
OT_WHOLE_LINE, NULL, false);
|
2010-05-08 18:39:53 +02:00
|
|
|
size_t len;
|
|
|
|
|
|
|
|
/* strip any trailing spaces and semicolons */
|
2010-05-21 19:37:44 +02:00
|
|
|
if (opt)
|
|
|
|
{
|
|
|
|
len = strlen(opt);
|
|
|
|
while (len > 0 &&
|
|
|
|
(isspace((unsigned char) opt[len - 1])
|
2010-07-06 21:19:02 +02:00
|
|
|
|| opt[len - 1] == ';'))
|
2010-05-21 19:37:44 +02:00
|
|
|
opt[--len] = '\0';
|
|
|
|
}
|
2004-02-19 20:40:09 +01:00
|
|
|
|
|
|
|
helpSQL(opt, pset.popt.topt.pager);
|
|
|
|
free(opt);
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_whole_line(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \H and \html -- toggle HTML formatting
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_html(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2000-01-14 23:18:03 +01:00
|
|
|
if (pset.popt.topt.format != PRINT_HTML)
|
2006-08-29 17:19:51 +02:00
|
|
|
success = do_pset("format", "html", &pset.popt, pset.quiet);
|
* Includes tab completion. It's not magic, but it's very cool. At any
rate
it's better than what used to be there.
* Does proper SQL "host variable" substitution as pointed out by Andreas
Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
and ';' are treated (escape with \ to send to backend). This does
_not_
affect the '::' cast operator, but perhaps others that contain : or ;
(but there are none right now).
* To show description with a <something> listing, append '?' to command
name, e.g., \df?. This seemed to be the convenient and logical
solution.
Or append a '+' to see more useless information, e.g., \df+.
* Fixed fflush()'ing bug pointed out by Jan during the regression test
discussion.
* Added LastOid variable. This ought to take care of TODO item "Add a
function to return the last inserted oid, for use in psql scripts"
(under CLIENTS)
E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid
* \d command shows constraints, rules, and triggers defined on the table
(in addition to indices)
* Various fixes, optimizations, corrections
* Documentation update as well
Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.
Enjoy.
--
Peter Eisentraut Sernanders väg 10:115
1999-11-26 05:24:17 +01:00
|
|
|
else
|
2006-08-29 17:19:51 +02:00
|
|
|
success = do_pset("format", "aligned", &pset.popt, pset.quiet);
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/*
|
|
|
|
* \i and \ir -- include a file
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_include(PsqlScanState scan_state, bool active_branch, const char *cmd)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *fname = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2000-02-08 00:10:11 +01:00
|
|
|
if (!fname)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
|
|
|
psql_error("\\%s: missing required argument\n", cmd);
|
1999-11-05 00:14:30 +01:00
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
else
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2012-06-10 21:20:04 +02:00
|
|
|
bool include_relative;
|
2011-07-06 17:45:13 +02:00
|
|
|
|
|
|
|
include_relative = (strcmp(cmd, "ir") == 0
|
|
|
|
|| strcmp(cmd, "include_relative") == 0);
|
2004-01-09 22:12:20 +01:00
|
|
|
expand_tilde(&fname);
|
2015-12-08 20:04:08 +01:00
|
|
|
success = (process_file(fname, include_relative) == EXIT_SUCCESS);
|
2000-04-12 19:17:23 +02:00
|
|
|
free(fname);
|
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \if <expr> -- beginning of an \if..\endif block
|
|
|
|
*
|
|
|
|
* <expr> is parsed as a boolean expression. Invalid expressions will emit a
|
|
|
|
* warning and be treated as false. Statements that follow a false expression
|
|
|
|
* will be parsed but ignored. Note that in the case where an \if statement
|
|
|
|
* is itself within an inactive section of a block, then the entire inner
|
|
|
|
* \if..\endif block will be parsed but ignored.
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf)
|
|
|
|
{
|
|
|
|
if (conditional_active(cstack))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* First, push a new active stack entry; this ensures that the lexer
|
|
|
|
* will perform variable substitution and backtick evaluation while
|
|
|
|
* scanning the expression. (That should happen anyway, since we know
|
|
|
|
* we're in an active outer branch, but let's be sure.)
|
|
|
|
*/
|
|
|
|
conditional_stack_push(cstack, IFSTATE_TRUE);
|
|
|
|
|
|
|
|
/* Remember current query state in case we need to restore later */
|
|
|
|
save_query_text_state(scan_state, cstack, query_buf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Evaluate the expression; if it's false, change to inactive state.
|
|
|
|
*/
|
|
|
|
if (!is_true_boolean_expression(scan_state, "\\if expression"))
|
|
|
|
conditional_stack_poke(cstack, IFSTATE_FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We're within an inactive outer branch, so this entire \if block
|
|
|
|
* will be ignored. We don't want to evaluate the expression, so push
|
|
|
|
* the "ignored" stack state before scanning it.
|
|
|
|
*/
|
|
|
|
conditional_stack_push(cstack, IFSTATE_IGNORED);
|
|
|
|
|
|
|
|
/* Remember current query state in case we need to restore later */
|
|
|
|
save_query_text_state(scan_state, cstack, query_buf);
|
|
|
|
|
|
|
|
ignore_boolean_expression(scan_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \elif <expr> -- alternative branch in an \if..\endif block
|
|
|
|
*
|
|
|
|
* <expr> is evaluated the same as in \if <expr>.
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
switch (conditional_stack_peek(cstack))
|
|
|
|
{
|
|
|
|
case IFSTATE_TRUE:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Just finished active branch of this \if block. Update saved
|
|
|
|
* state so we will keep whatever data was put in query_buf by the
|
|
|
|
* active branch.
|
|
|
|
*/
|
|
|
|
save_query_text_state(scan_state, cstack, query_buf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Discard \elif expression and ignore the rest until \endif.
|
|
|
|
* Switch state before reading expression to ensure proper lexer
|
|
|
|
* behavior.
|
|
|
|
*/
|
|
|
|
conditional_stack_poke(cstack, IFSTATE_IGNORED);
|
|
|
|
ignore_boolean_expression(scan_state);
|
|
|
|
break;
|
|
|
|
case IFSTATE_FALSE:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Discard any query text added by the just-skipped branch.
|
|
|
|
*/
|
|
|
|
discard_query_text(scan_state, cstack, query_buf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Have not yet found a true expression in this \if block, so this
|
|
|
|
* might be the first. We have to change state before examining
|
|
|
|
* the expression, or the lexer won't do the right thing.
|
|
|
|
*/
|
|
|
|
conditional_stack_poke(cstack, IFSTATE_TRUE);
|
|
|
|
if (!is_true_boolean_expression(scan_state, "\\elif expression"))
|
|
|
|
conditional_stack_poke(cstack, IFSTATE_FALSE);
|
|
|
|
break;
|
|
|
|
case IFSTATE_IGNORED:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Discard any query text added by the just-skipped branch.
|
|
|
|
*/
|
|
|
|
discard_query_text(scan_state, cstack, query_buf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip expression and move on. Either the \if block already had
|
|
|
|
* an active section, or whole block is being skipped.
|
|
|
|
*/
|
|
|
|
ignore_boolean_expression(scan_state);
|
|
|
|
break;
|
|
|
|
case IFSTATE_ELSE_TRUE:
|
|
|
|
case IFSTATE_ELSE_FALSE:
|
|
|
|
psql_error("\\elif: cannot occur after \\else\n");
|
|
|
|
success = false;
|
|
|
|
break;
|
|
|
|
case IFSTATE_NONE:
|
|
|
|
/* no \if to elif from */
|
|
|
|
psql_error("\\elif: no matching \\if\n");
|
|
|
|
success = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \else -- final alternative in an \if..\endif block
|
|
|
|
*
|
|
|
|
* Statements within an \else branch will only be executed if
|
|
|
|
* all previous \if and \elif expressions evaluated to false
|
|
|
|
* and the block was not itself being ignored.
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
switch (conditional_stack_peek(cstack))
|
|
|
|
{
|
|
|
|
case IFSTATE_TRUE:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Just finished active branch of this \if block. Update saved
|
|
|
|
* state so we will keep whatever data was put in query_buf by the
|
|
|
|
* active branch.
|
|
|
|
*/
|
|
|
|
save_query_text_state(scan_state, cstack, query_buf);
|
|
|
|
|
|
|
|
/* Now skip the \else branch */
|
|
|
|
conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
|
|
|
|
break;
|
|
|
|
case IFSTATE_FALSE:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Discard any query text added by the just-skipped branch.
|
|
|
|
*/
|
|
|
|
discard_query_text(scan_state, cstack, query_buf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We've not found any true \if or \elif expression, so execute
|
|
|
|
* the \else branch.
|
|
|
|
*/
|
|
|
|
conditional_stack_poke(cstack, IFSTATE_ELSE_TRUE);
|
|
|
|
break;
|
|
|
|
case IFSTATE_IGNORED:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Discard any query text added by the just-skipped branch.
|
|
|
|
*/
|
|
|
|
discard_query_text(scan_state, cstack, query_buf);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Either we previously processed the active branch of this \if,
|
|
|
|
* or the whole \if block is being skipped. Either way, skip the
|
|
|
|
* \else branch.
|
|
|
|
*/
|
|
|
|
conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
|
|
|
|
break;
|
|
|
|
case IFSTATE_ELSE_TRUE:
|
|
|
|
case IFSTATE_ELSE_FALSE:
|
|
|
|
psql_error("\\else: cannot occur after \\else\n");
|
|
|
|
success = false;
|
|
|
|
break;
|
|
|
|
case IFSTATE_NONE:
|
|
|
|
/* no \if to else from */
|
|
|
|
psql_error("\\else: no matching \\if\n");
|
|
|
|
success = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \endif -- ends an \if...\endif block
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
switch (conditional_stack_peek(cstack))
|
|
|
|
{
|
|
|
|
case IFSTATE_TRUE:
|
|
|
|
case IFSTATE_ELSE_TRUE:
|
|
|
|
/* Close the \if block, keeping the query text */
|
|
|
|
success = conditional_stack_pop(cstack);
|
|
|
|
Assert(success);
|
|
|
|
break;
|
|
|
|
case IFSTATE_FALSE:
|
|
|
|
case IFSTATE_IGNORED:
|
|
|
|
case IFSTATE_ELSE_FALSE:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Discard any query text added by the just-skipped branch.
|
|
|
|
*/
|
|
|
|
discard_query_text(scan_state, cstack, query_buf);
|
|
|
|
|
|
|
|
/* Close the \if block */
|
|
|
|
success = conditional_stack_pop(cstack);
|
|
|
|
Assert(success);
|
|
|
|
break;
|
|
|
|
case IFSTATE_NONE:
|
|
|
|
/* no \if to end */
|
|
|
|
psql_error("\\endif: no matching \\if\n");
|
|
|
|
success = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \l -- list databases
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2013-03-04 04:17:08 +01:00
|
|
|
{
|
|
|
|
char *pattern;
|
|
|
|
bool show_verbose;
|
|
|
|
|
|
|
|
pattern = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
|
|
|
|
|
|
|
show_verbose = strchr(cmd, '+') ? true : false;
|
|
|
|
|
|
|
|
success = listAllDbs(pattern, show_verbose);
|
|
|
|
|
|
|
|
if (pattern)
|
|
|
|
free(pattern);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \lo_* -- large object operations
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
char *opt1,
|
|
|
|
*opt2;
|
2000-02-08 00:10:11 +01:00
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
opt1 = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
|
|
|
opt2 = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
2000-02-08 00:10:11 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (strcmp(cmd + 3, "export") == 0)
|
|
|
|
{
|
2000-02-08 00:10:11 +01:00
|
|
|
if (!opt2)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
psql_error("\\%s: missing required argument\n", cmd);
|
1999-11-05 00:14:30 +01:00
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
else
|
2004-01-09 22:12:20 +01:00
|
|
|
{
|
|
|
|
expand_tilde(&opt2);
|
2000-02-08 00:10:11 +01:00
|
|
|
success = do_lo_export(opt1, opt2);
|
2004-01-09 22:12:20 +01:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (strcmp(cmd + 3, "import") == 0)
|
|
|
|
{
|
2000-02-08 00:10:11 +01:00
|
|
|
if (!opt1)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
psql_error("\\%s: missing required argument\n", cmd);
|
1999-11-05 00:14:30 +01:00
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
else
|
2004-01-09 22:12:20 +01:00
|
|
|
{
|
|
|
|
expand_tilde(&opt1);
|
2001-03-22 05:01:46 +01:00
|
|
|
success = do_lo_import(opt1, opt2);
|
2004-01-09 22:12:20 +01:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (strcmp(cmd + 3, "list") == 0)
|
2000-01-14 23:18:03 +01:00
|
|
|
success = do_lo_list();
|
1999-11-05 00:14:30 +01:00
|
|
|
|
|
|
|
else if (strcmp(cmd + 3, "unlink") == 0)
|
|
|
|
{
|
2000-02-08 00:10:11 +01:00
|
|
|
if (!opt1)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
psql_error("\\%s: missing required argument\n", cmd);
|
1999-11-05 00:14:30 +01:00
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
else
|
2000-02-08 00:10:11 +01:00
|
|
|
success = do_lo_unlink(opt1);
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
else
|
2005-12-18 03:17:16 +01:00
|
|
|
status = PSQL_CMD_UNKNOWN;
|
2000-02-08 00:10:11 +01:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
free(opt1);
|
|
|
|
free(opt2);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
if (!success)
|
|
|
|
status = PSQL_CMD_ERROR;
|
2000-02-08 00:10:11 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \o -- set query output
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_out(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *fname = psql_scan_slash_option(scan_state,
|
2005-10-15 04:49:52 +02:00
|
|
|
OT_FILEPIPE, NULL, true);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2004-01-09 22:12:20 +01:00
|
|
|
expand_tilde(&fname);
|
2000-02-08 00:10:11 +01:00
|
|
|
success = setQFout(fname);
|
2000-04-12 19:17:23 +02:00
|
|
|
free(fname);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_filepipe(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \p -- print the current query buffer
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_print(PsqlScanState scan_state, bool active_branch,
|
2017-04-02 22:50:25 +02:00
|
|
|
PQExpBuffer query_buf, PQExpBuffer previous_buf)
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
{
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2017-04-02 22:50:25 +02:00
|
|
|
/*
|
|
|
|
* We want to print the same thing \g would execute, but not to change
|
|
|
|
* the query buffer state; so we can't use copy_previous_query().
|
|
|
|
* Also, beware of possibility that buffer pointers are NULL.
|
|
|
|
*/
|
1999-11-05 00:14:30 +01:00
|
|
|
if (query_buf && query_buf->len > 0)
|
|
|
|
puts(query_buf->data);
|
2017-04-02 22:50:25 +02:00
|
|
|
else if (previous_buf && previous_buf->len > 0)
|
|
|
|
puts(previous_buf->data);
|
2006-08-29 17:19:51 +02:00
|
|
|
else if (!pset.quiet)
|
2005-02-22 05:43:23 +01:00
|
|
|
puts(_("Query buffer is empty."));
|
1999-12-10 01:26:35 +01:00
|
|
|
fflush(stdout);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \password -- set user password
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_password(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2005-12-18 03:17:16 +01:00
|
|
|
{
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
char *opt0 = psql_scan_slash_option(scan_state,
|
|
|
|
OT_SQLID, NULL, true);
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
char pw1[100];
|
|
|
|
char pw2[100];
|
2005-12-18 03:17:16 +01:00
|
|
|
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
simple_prompt("Enter new password: ", pw1, sizeof(pw1), false);
|
|
|
|
simple_prompt("Enter it again: ", pw2, sizeof(pw2), false);
|
2005-12-18 03:17:16 +01:00
|
|
|
|
|
|
|
if (strcmp(pw1, pw2) != 0)
|
|
|
|
{
|
2012-08-26 04:58:42 +02:00
|
|
|
psql_error("Passwords didn't match.\n");
|
2005-12-18 03:17:16 +01:00
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *user;
|
2005-12-23 02:16:38 +01:00
|
|
|
char *encrypted_password;
|
2005-12-18 03:17:16 +01:00
|
|
|
|
|
|
|
if (opt0)
|
|
|
|
user = opt0;
|
|
|
|
else
|
|
|
|
user = PQuser(pset.db);
|
|
|
|
|
2017-05-03 10:19:07 +02:00
|
|
|
encrypted_password = PQencryptPasswordConn(pset.db, pw1, user, NULL);
|
2005-12-23 02:16:38 +01:00
|
|
|
|
|
|
|
if (!encrypted_password)
|
2005-12-18 03:17:16 +01:00
|
|
|
{
|
2017-05-03 10:19:07 +02:00
|
|
|
psql_error("%s", PQerrorMessage(pset.db));
|
2005-12-18 03:17:16 +01:00
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PQExpBufferData buf;
|
|
|
|
PGresult *res;
|
|
|
|
|
|
|
|
initPQExpBuffer(&buf);
|
2006-06-01 02:15:36 +02:00
|
|
|
printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
|
|
|
|
fmtId(user));
|
|
|
|
appendStringLiteralConn(&buf, encrypted_password, pset.db);
|
2014-10-23 15:33:56 +02:00
|
|
|
res = PSQLexec(buf.data);
|
2005-12-18 03:17:16 +01:00
|
|
|
termPQExpBuffer(&buf);
|
|
|
|
if (!res)
|
|
|
|
success = false;
|
|
|
|
else
|
|
|
|
PQclear(res);
|
2005-12-23 02:16:38 +01:00
|
|
|
PQfreemem(encrypted_password);
|
2005-12-18 03:17:16 +01:00
|
|
|
}
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
|
|
|
|
if (opt0)
|
|
|
|
free(opt0);
|
2005-12-18 03:17:16 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2005-12-18 03:17:16 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \prompt -- prompt and set variable
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_prompt(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2007-02-23 19:20:59 +01:00
|
|
|
{
|
2007-11-15 22:14:46 +01:00
|
|
|
char *opt,
|
|
|
|
*prompt_text = NULL;
|
|
|
|
char *arg1,
|
|
|
|
*arg2;
|
2007-02-23 19:20:59 +01:00
|
|
|
|
|
|
|
arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
|
|
|
|
arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
|
|
|
|
|
|
|
|
if (!arg1)
|
|
|
|
{
|
|
|
|
psql_error("\\%s: missing required argument\n", cmd);
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-11-15 22:14:46 +01:00
|
|
|
char *result;
|
2007-02-23 19:20:59 +01:00
|
|
|
|
|
|
|
if (arg2)
|
|
|
|
{
|
|
|
|
prompt_text = arg1;
|
|
|
|
opt = arg2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
opt = arg1;
|
|
|
|
|
|
|
|
if (!pset.inputfile)
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
{
|
|
|
|
result = (char *) pg_malloc(4096);
|
|
|
|
simple_prompt(prompt_text, result, 4096, true);
|
|
|
|
}
|
2007-02-23 19:20:59 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (prompt_text)
|
|
|
|
{
|
|
|
|
fputs(prompt_text, stdout);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
result = gets_fromFile(stdin);
|
2016-08-31 00:22:43 +02:00
|
|
|
if (!result)
|
|
|
|
{
|
|
|
|
psql_error("\\%s: could not read value for variable\n",
|
|
|
|
cmd);
|
|
|
|
success = false;
|
|
|
|
}
|
2007-02-23 19:20:59 +01:00
|
|
|
}
|
|
|
|
|
2016-08-31 00:22:43 +02:00
|
|
|
if (result &&
|
|
|
|
!SetVariable(pset.vars, opt, result))
|
2007-02-23 19:20:59 +01:00
|
|
|
success = false;
|
|
|
|
|
2016-08-31 00:22:43 +02:00
|
|
|
if (result)
|
|
|
|
free(result);
|
2007-02-23 19:20:59 +01:00
|
|
|
if (prompt_text)
|
|
|
|
free(prompt_text);
|
|
|
|
free(opt);
|
|
|
|
}
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2007-02-23 19:20:59 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \pset -- set printing parameters
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_pset(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *opt0 = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false);
|
|
|
|
char *opt1 = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2000-02-08 00:10:11 +01:00
|
|
|
if (!opt0)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2013-11-10 15:20:52 +01:00
|
|
|
/* list all variables */
|
|
|
|
|
2014-05-06 18:12:18 +02:00
|
|
|
int i;
|
2013-11-10 15:20:52 +01:00
|
|
|
static const char *const my_list[] = {
|
2018-11-26 21:18:55 +01:00
|
|
|
"border", "columns", "csv_fieldsep", "expanded", "fieldsep",
|
|
|
|
"fieldsep_zero", "footer", "format", "linestyle", "null",
|
2015-03-28 16:07:41 +01:00
|
|
|
"numericlocale", "pager", "pager_min_lines",
|
|
|
|
"recordsep", "recordsep_zero",
|
2013-10-03 21:18:02 +02:00
|
|
|
"tableattr", "title", "tuples_only",
|
2014-09-12 18:04:37 +02:00
|
|
|
"unicode_border_linestyle",
|
|
|
|
"unicode_column_linestyle",
|
|
|
|
"unicode_header_linestyle",
|
2013-11-10 15:20:52 +01:00
|
|
|
NULL
|
|
|
|
};
|
2013-10-03 21:18:02 +02:00
|
|
|
|
2013-11-10 15:20:52 +01:00
|
|
|
for (i = 0; my_list[i] != NULL; i++)
|
2014-10-19 03:58:17 +02:00
|
|
|
{
|
2015-05-24 03:35:49 +02:00
|
|
|
char *val = pset_value_string(my_list[i], &pset.popt);
|
|
|
|
|
2014-10-19 03:58:17 +02:00
|
|
|
printf("%-24s %s\n", my_list[i], val);
|
|
|
|
free(val);
|
|
|
|
}
|
2013-10-03 21:18:02 +02:00
|
|
|
|
2013-11-10 15:20:52 +01:00
|
|
|
success = true;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
|
|
|
else
|
2006-08-29 17:19:51 +02:00
|
|
|
success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
|
2000-02-08 00:10:11 +01:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
free(opt0);
|
|
|
|
free(opt1);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \q or \quit -- exit psql
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_quit(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
2005-12-18 03:17:16 +01:00
|
|
|
status = PSQL_CMD_TERMINATE;
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \r -- reset (clear) the query buffer
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_reset(PsqlScanState scan_state, bool active_branch,
|
|
|
|
PQExpBuffer query_buf)
|
|
|
|
{
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
|
|
|
resetPQExpBuffer(query_buf);
|
2004-02-19 20:40:09 +01:00
|
|
|
psql_scan_reset(scan_state);
|
2006-08-29 17:19:51 +02:00
|
|
|
if (!pset.quiet)
|
2005-02-22 05:43:23 +01:00
|
|
|
puts(_("Query buffer reset (cleared)."));
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \s -- save history in a file or show it on the screen
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_s(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *fname = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
2004-01-09 22:12:20 +01:00
|
|
|
expand_tilde(&fname);
|
Fix psql \s to work with recent libedit, and add pager support.
psql's \s (print command history) doesn't work at all with recent libedit
versions when printing to the terminal, because libedit tries to do an
fchmod() on the target file which will fail if the target is /dev/tty.
(We'd already noted this in the context of the target being /dev/null.)
Even before that, it didn't work pleasantly, because libedit likes to
encode the command history file (to ensure successful reloading), which
renders it nigh unreadable, not to mention significantly different-looking
depending on exactly which libedit version you have. So let's forget using
write_history() for this purpose, and instead print the data ourselves,
using logic similar to that used to iterate over the history for newline
encoding/decoding purposes.
While we're at it, insert the ability to use the pager when \s is printing
to the terminal. This has been an acknowledged shortcoming of \s for many
years, so while you could argue it's not exactly a back-patchable bug fix
it still seems like a good improvement. Anyone who's seriously annoyed
at this can use "\s /dev/tty" or local equivalent to get the old behavior.
Experimentation with this showed that the history iteration logic was
actually rather broken when used with libedit. It turns out that with
libedit you have to use previous_history() not next_history() to advance
to more recent history entries. The easiest and most robust fix for this
seems to be to make a run-time test to verify which function to call.
We had not noticed this because libedit doesn't really need the newline
encoding logic: its own encoding ensures that command entries containing
newlines are reloaded correctly (unlike libreadline). So the effective
behavior with recent libedits was that only the oldest history entry got
newline-encoded or newline-decoded. However, because of yet other bugs in
history_set_pos(), some old versions of libedit allowed the existing loop
logic to reach entries besides the oldest, which means there may be libedit
~/.psql_history files out there containing encoded newlines in more than
just the oldest entry. To ensure we can reload such files, it seems
appropriate to back-patch this fix, even though that will result in some
incompatibility with older psql versions (ie, multiline history entries
written by a psql with this fix will look corrupted to a psql without it,
if its libedit is reasonably up to date).
Stepan Rutz and Tom Lane
2014-09-08 22:09:45 +02:00
|
|
|
success = printHistory(fname, pset.popt.topt.pager);
|
2006-08-29 17:19:51 +02:00
|
|
|
if (success && !pset.quiet && fname)
|
2013-11-05 23:51:58 +01:00
|
|
|
printf(_("Wrote history to file \"%s\".\n"), fname);
|
2004-11-30 21:00:34 +01:00
|
|
|
if (!fname)
|
|
|
|
putchar('\n');
|
2000-04-12 19:17:23 +02:00
|
|
|
free(fname);
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
|
|
|
|
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/*
|
|
|
|
* \set -- set variable
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_set(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *opt0 = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false);
|
2000-02-08 00:10:11 +01:00
|
|
|
|
|
|
|
if (!opt0)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
|
|
|
/* list all variables */
|
2003-03-20 07:43:35 +01:00
|
|
|
PrintVariables(pset.vars);
|
1999-11-05 00:14:30 +01:00
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
/*
|
|
|
|
* Set variable to the concatenation of the arguments.
|
|
|
|
*/
|
2004-02-19 20:40:09 +01:00
|
|
|
char *newval;
|
2000-04-12 19:17:23 +02:00
|
|
|
char *opt;
|
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
opt = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false);
|
2004-01-25 04:07:22 +01:00
|
|
|
newval = pg_strdup(opt ? opt : "");
|
2000-04-12 19:17:23 +02:00
|
|
|
free(opt);
|
|
|
|
|
2004-02-19 20:40:09 +01:00
|
|
|
while ((opt = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false)))
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2014-11-18 19:28:06 +01:00
|
|
|
newval = pg_realloc(newval, strlen(newval) + strlen(opt) + 1);
|
2000-04-12 19:17:23 +02:00
|
|
|
strcat(newval, opt);
|
|
|
|
free(opt);
|
|
|
|
}
|
2000-02-08 00:10:11 +01:00
|
|
|
|
2006-08-29 17:19:51 +02:00
|
|
|
if (!SetVariable(pset.vars, opt0, newval))
|
1999-11-05 00:14:30 +01:00
|
|
|
success = false;
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
free(newval);
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
free(opt0);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
2011-12-04 17:43:38 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/*
|
|
|
|
* \setenv -- set environment variable
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_setenv(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2011-12-04 17:43:38 +01:00
|
|
|
{
|
|
|
|
char *envvar = psql_scan_slash_option(scan_state,
|
2012-06-10 21:20:04 +02:00
|
|
|
OT_NORMAL, NULL, false);
|
2011-12-04 17:43:38 +01:00
|
|
|
char *envval = psql_scan_slash_option(scan_state,
|
2012-06-10 21:20:04 +02:00
|
|
|
OT_NORMAL, NULL, false);
|
2011-12-04 17:43:38 +01:00
|
|
|
|
|
|
|
if (!envvar)
|
|
|
|
{
|
|
|
|
psql_error("\\%s: missing required argument\n", cmd);
|
|
|
|
success = false;
|
|
|
|
}
|
2012-06-10 21:20:04 +02:00
|
|
|
else if (strchr(envvar, '=') != NULL)
|
2011-12-04 17:43:38 +01:00
|
|
|
{
|
2012-06-07 22:35:33 +02:00
|
|
|
psql_error("\\%s: environment variable name must not contain \"=\"\n",
|
2011-12-04 17:43:38 +01:00
|
|
|
cmd);
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
else if (!envval)
|
|
|
|
{
|
|
|
|
/* No argument - unset the environment variable */
|
|
|
|
unsetenv(envvar);
|
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set variable to the value of the next argument */
|
2013-10-13 06:09:18 +02:00
|
|
|
char *newval;
|
2011-12-04 17:43:38 +01:00
|
|
|
|
2013-10-23 01:40:26 +02:00
|
|
|
newval = psprintf("%s=%s", envvar, envval);
|
2011-12-04 17:43:38 +01:00
|
|
|
putenv(newval);
|
|
|
|
success = true;
|
2012-06-10 21:20:04 +02:00
|
|
|
|
2011-12-04 17:43:38 +01:00
|
|
|
/*
|
2012-06-10 21:20:04 +02:00
|
|
|
* Do not free newval here, it will screw up the environment if
|
|
|
|
* you do. See putenv man page for details. That means we leak a
|
|
|
|
* bit of memory here, but not enough to worry about.
|
2011-12-04 17:43:38 +01:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
free(envvar);
|
|
|
|
free(envval);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2011-12-04 17:43:38 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-09-06 23:32:40 +02:00
|
|
|
* \sf/\sv -- show a function/view's source code
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
*/
|
|
|
|
static backslashResult
|
2017-09-06 23:32:40 +02:00
|
|
|
exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd, bool is_func)
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
2010-08-14 15:59:49 +02:00
|
|
|
{
|
2017-09-06 23:32:40 +02:00
|
|
|
bool show_linenumbers = (strchr(cmd, '+') != NULL);
|
|
|
|
PQExpBuffer buf;
|
|
|
|
char *obj_desc;
|
|
|
|
Oid obj_oid = InvalidOid;
|
|
|
|
EditableObjectType eot = is_func ? EditableFunction : EditableView;
|
|
|
|
|
|
|
|
buf = createPQExpBuffer();
|
|
|
|
obj_desc = psql_scan_slash_option(scan_state,
|
|
|
|
OT_WHOLE_LINE, NULL, true);
|
|
|
|
if (pset.sversion < (is_func ? 80400 : 70400))
|
2011-11-11 00:36:49 +01:00
|
|
|
{
|
Fix assorted places in psql to print version numbers >= 10 in new style.
This is somewhat cosmetic, since as long as you know what you are looking
at, "10.0" is a serviceable substitute for "10". But there is a potential
for confusion between version numbers with minor numbers and those without
--- we don't want people asking "why is psql saying 10.0 when my server is
10.2". Therefore, back-patch as far as practical, which turns out to be
9.3. I could have redone the patch to use fprintf(stderr) in place of
psql_error(), but it seems more work than is warranted for branches that
will be EOL or nearly so by the time v10 comes out.
Although only psql seems to contain any code that needs this, I chose
to put the support function into fe_utils, since it seems likely we'll
need it in other client programs in future. (In 9.3-9.5, use dumputils.c,
the predecessor of fe_utils/string_utils.c.)
In HEAD, also fix the backend code that whines about loadable-library
version mismatch. I don't see much need to back-patch that.
2016-08-16 21:58:30 +02:00
|
|
|
char sverbuf[32];
|
|
|
|
|
2017-09-06 23:32:40 +02:00
|
|
|
formatPGVersionNumber(pset.sversion, false,
|
|
|
|
sverbuf, sizeof(sverbuf));
|
|
|
|
if (is_func)
|
|
|
|
psql_error("The server (version %s) does not support showing function source.\n",
|
|
|
|
sverbuf);
|
|
|
|
else
|
|
|
|
psql_error("The server (version %s) does not support showing view definitions.\n",
|
|
|
|
sverbuf);
|
2011-11-11 00:36:49 +01:00
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
2017-09-06 23:32:40 +02:00
|
|
|
else if (!obj_desc)
|
2010-08-14 15:59:49 +02:00
|
|
|
{
|
2017-09-06 23:32:40 +02:00
|
|
|
if (is_func)
|
|
|
|
psql_error("function name is required\n");
|
|
|
|
else
|
|
|
|
psql_error("view name is required\n");
|
2010-08-14 15:59:49 +02:00
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
2017-09-06 23:32:40 +02:00
|
|
|
else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
|
2010-08-14 15:59:49 +02:00
|
|
|
{
|
|
|
|
/* error already reported */
|
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
2017-09-06 23:32:40 +02:00
|
|
|
else if (!get_create_object_cmd(eot, obj_oid, buf))
|
2010-08-14 15:59:49 +02:00
|
|
|
{
|
|
|
|
/* error already reported */
|
|
|
|
status = PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-04-10 17:42:00 +02:00
|
|
|
FILE *output;
|
|
|
|
bool is_pager;
|
2010-08-14 15:59:49 +02:00
|
|
|
|
|
|
|
/* Select output stream: stdout, pager, or file */
|
|
|
|
if (pset.queryFout == stdout)
|
|
|
|
{
|
|
|
|
/* count lines in function to see if pager is needed */
|
2017-09-06 23:32:40 +02:00
|
|
|
int lineno = count_lines_in_buf(buf);
|
2010-08-14 15:59:49 +02:00
|
|
|
|
2015-03-28 16:07:41 +01:00
|
|
|
output = PageOutput(lineno, &(pset.popt.topt));
|
2010-08-14 15:59:49 +02:00
|
|
|
is_pager = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* use previously set output file, without pager */
|
|
|
|
output = pset.queryFout;
|
|
|
|
is_pager = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (show_linenumbers)
|
|
|
|
{
|
|
|
|
/*
|
2017-09-06 23:32:40 +02:00
|
|
|
* For functions, lineno "1" should correspond to the first
|
|
|
|
* line of the function body. We expect that
|
|
|
|
* pg_get_functiondef() will emit that on a line beginning
|
|
|
|
* with "AS ", and that there can be no such line before the
|
|
|
|
* real start of the function body.
|
2010-08-14 15:59:49 +02:00
|
|
|
*/
|
2017-09-06 23:32:40 +02:00
|
|
|
print_with_linenumbers(output, buf->data,
|
|
|
|
is_func ? "AS " : NULL);
|
2015-07-03 21:48:18 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-09-06 23:32:40 +02:00
|
|
|
/* just send the definition to output */
|
|
|
|
fputs(buf->data, output);
|
2015-07-03 21:48:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (is_pager)
|
|
|
|
ClosePager(output);
|
|
|
|
}
|
|
|
|
|
2017-09-06 23:32:40 +02:00
|
|
|
if (obj_desc)
|
|
|
|
free(obj_desc);
|
|
|
|
destroyPQExpBuffer(buf);
|
2015-07-03 21:48:18 +02:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_whole_line(scan_state);
|
2015-07-03 21:48:18 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \t -- turn off table headers and row count
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_t(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2007-03-03 18:19:11 +01:00
|
|
|
{
|
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
|
|
|
|
|
|
|
success = do_pset("tuples_only", opt, &pset.popt, pset.quiet);
|
|
|
|
free(opt);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \T -- define html <table ...> attributes
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_T(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *value = psql_scan_slash_option(scan_state,
|
2005-10-15 04:49:52 +02:00
|
|
|
OT_NORMAL, NULL, false);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2006-08-29 17:19:51 +02:00
|
|
|
success = do_pset("tableattr", value, &pset.popt, pset.quiet);
|
2000-04-12 19:17:23 +02:00
|
|
|
free(value);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \timing -- enable/disable timing of queries
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_timing(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2002-03-05 01:01:03 +01:00
|
|
|
{
|
2008-06-11 12:48:17 +02:00
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
2009-06-11 16:49:15 +02:00
|
|
|
OT_NORMAL, NULL, false);
|
|
|
|
|
2008-06-11 12:48:17 +02:00
|
|
|
if (opt)
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
success = ParseVariableBool(opt, "\\timing", &pset.timing);
|
2008-06-11 12:48:17 +02:00
|
|
|
else
|
|
|
|
pset.timing = !pset.timing;
|
2006-08-29 17:19:51 +02:00
|
|
|
if (!pset.quiet)
|
2002-03-05 01:01:03 +01:00
|
|
|
{
|
|
|
|
if (pset.timing)
|
2005-02-22 05:43:23 +01:00
|
|
|
puts(_("Timing is on."));
|
2002-03-05 01:01:03 +01:00
|
|
|
else
|
2005-02-22 05:43:23 +01:00
|
|
|
puts(_("Timing is off."));
|
2002-03-05 01:01:03 +01:00
|
|
|
}
|
2008-06-11 12:48:17 +02:00
|
|
|
free(opt);
|
2002-03-05 01:01:03 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2002-09-04 22:31:48 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \unset -- unset variable
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_unset(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
|
|
|
if (!opt)
|
|
|
|
{
|
|
|
|
psql_error("\\%s: missing required argument\n", cmd);
|
|
|
|
success = false;
|
|
|
|
}
|
2002-01-18 17:14:54 +01:00
|
|
|
else if (!SetVariable(pset.vars, opt, NULL))
|
2000-04-12 19:17:23 +02:00
|
|
|
success = false;
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
free(opt);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \w -- write query buffer to file
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_write(PsqlScanState scan_state, bool active_branch,
|
|
|
|
const char *cmd,
|
|
|
|
PQExpBuffer query_buf, PQExpBuffer previous_buf)
|
|
|
|
{
|
|
|
|
backslashResult status = PSQL_CMD_SKIP_LINE;
|
|
|
|
|
|
|
|
if (active_branch)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
char *fname = psql_scan_slash_option(scan_state,
|
|
|
|
OT_FILEPIPE, NULL, true);
|
1999-11-05 00:14:30 +01:00
|
|
|
FILE *fd = NULL;
|
2000-02-08 00:10:11 +01:00
|
|
|
bool is_pipe = false;
|
2000-04-12 19:17:23 +02:00
|
|
|
|
|
|
|
if (!query_buf)
|
|
|
|
{
|
|
|
|
psql_error("no query buffer\n");
|
2005-12-18 03:17:16 +01:00
|
|
|
status = PSQL_CMD_ERROR;
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!fname)
|
|
|
|
{
|
|
|
|
psql_error("\\%s: missing required argument\n", cmd);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
status = PSQL_CMD_ERROR;
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
expand_tilde(&fname);
|
2000-04-12 19:17:23 +02:00
|
|
|
if (fname[0] == '|')
|
|
|
|
{
|
|
|
|
is_pipe = true;
|
2015-12-03 20:28:58 +01:00
|
|
|
disable_sigpipe_trap();
|
2000-04-12 19:17:23 +02:00
|
|
|
fd = popen(&fname[1], "w");
|
|
|
|
}
|
|
|
|
else
|
2004-07-11 23:34:04 +02:00
|
|
|
{
|
|
|
|
canonicalize_path(fname);
|
2000-04-12 19:17:23 +02:00
|
|
|
fd = fopen(fname, "w");
|
2004-07-11 23:34:04 +02:00
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
if (!fd)
|
|
|
|
{
|
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
status = PSQL_CMD_ERROR;
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (fd)
|
|
|
|
{
|
|
|
|
int result;
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2017-04-02 22:50:25 +02:00
|
|
|
/*
|
|
|
|
* We want to print the same thing \g would execute, but not to
|
|
|
|
* change the query buffer state; so we can't use
|
|
|
|
* copy_previous_query(). Also, beware of possibility that buffer
|
|
|
|
* pointers are NULL.
|
|
|
|
*/
|
1999-11-05 00:14:30 +01:00
|
|
|
if (query_buf && query_buf->len > 0)
|
|
|
|
fprintf(fd, "%s\n", query_buf->data);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else if (previous_buf && previous_buf->len > 0)
|
|
|
|
fprintf(fd, "%s\n", previous_buf->data);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2000-02-08 00:10:11 +01:00
|
|
|
if (is_pipe)
|
1999-11-05 00:14:30 +01:00
|
|
|
result = pclose(fd);
|
|
|
|
else
|
|
|
|
result = fclose(fd);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (result == EOF)
|
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
status = PSQL_CMD_ERROR;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
|
|
|
}
|
2000-02-08 00:10:11 +01:00
|
|
|
|
2015-12-03 20:28:58 +01:00
|
|
|
if (is_pipe)
|
|
|
|
restore_sigpipe_trap();
|
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
free(fname);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_filepipe(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \watch -- execute a query every N seconds
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_watch(PsqlScanState scan_state, bool active_branch,
|
|
|
|
PQExpBuffer query_buf, PQExpBuffer previous_buf)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2013-04-05 01:56:33 +02:00
|
|
|
{
|
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
2016-03-21 23:34:18 +01:00
|
|
|
double sleep = 2;
|
2013-04-05 01:56:33 +02:00
|
|
|
|
|
|
|
/* Convert optional sleep-length argument */
|
|
|
|
if (opt)
|
|
|
|
{
|
2016-03-21 23:34:18 +01:00
|
|
|
sleep = strtod(opt, NULL);
|
2013-04-05 01:56:33 +02:00
|
|
|
if (sleep <= 0)
|
|
|
|
sleep = 1;
|
|
|
|
free(opt);
|
|
|
|
}
|
|
|
|
|
2017-04-02 22:50:25 +02:00
|
|
|
/* If query_buf is empty, recall and execute previous query */
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
copy_previous_query(query_buf, previous_buf);
|
|
|
|
|
2013-04-05 01:56:33 +02:00
|
|
|
success = do_watch(query_buf, sleep);
|
|
|
|
|
|
|
|
/* Reset the query buffer as though for \r */
|
|
|
|
resetPQExpBuffer(query_buf);
|
|
|
|
psql_scan_reset(scan_state);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
2013-04-05 01:56:33 +02:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \x -- set or toggle expanded table representation
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_x(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2007-03-03 18:19:11 +01:00
|
|
|
{
|
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, true);
|
|
|
|
|
|
|
|
success = do_pset("expanded", opt, &pset.popt, pset.quiet);
|
|
|
|
free(opt);
|
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \z -- list table privileges (equivalent to \dp)
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_z(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *pattern = psql_scan_slash_option(scan_state,
|
2005-10-15 04:49:52 +02:00
|
|
|
OT_NORMAL, NULL, true);
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2002-08-10 05:56:24 +02:00
|
|
|
success = permissionsList(pattern);
|
|
|
|
if (pattern)
|
|
|
|
free(pattern);
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \! -- execute shell command
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_shell_escape(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if (active_branch)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
2004-02-19 20:40:09 +01:00
|
|
|
char *opt = psql_scan_slash_option(scan_state,
|
2005-10-15 04:49:52 +02:00
|
|
|
OT_WHOLE_LINE, NULL, false);
|
2004-02-19 20:40:09 +01:00
|
|
|
|
|
|
|
success = do_shell(opt);
|
|
|
|
free(opt);
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_whole_line(scan_state);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* \? -- print help about backslash commands
|
|
|
|
*/
|
|
|
|
static backslashResult
|
|
|
|
exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch)
|
|
|
|
{
|
|
|
|
if (active_branch)
|
Add new psql help topics, accessible to both --help and \?.
Add --help=<topic> for the commandline, and \? <topic> as a backslash
command, to show more help than the invocations without parameters
do. "commands", "variables" and "options" currently exist as help
topics describing, respectively, backslash commands, psql variables,
and commandline switches. Without parameters the help commands show
their previous topic.
Some further wordsmithing or extending of the added help content might
be needed; but there seems little benefit delaying the overall feature
further.
Author: Pavel Stehule, editorialized by many
Reviewed-By: Andres Freund, Petr Jelinek, Fujii Masao, MauMau, Abhijit
Menon-Sen and Erik Rijkers.
Discussion: CAFj8pRDVGuC-nXBfe2CK8vpyzd2Dsr9GVpbrATAnZO=2YQ0s2Q@mail.gmail.com,
CAFj8pRA54AbTv2RXDTRxiAd8hy8wxmoVLqhJDRCwEnhdd7OUkw@mail.gmail.com
2014-09-09 22:19:14 +02:00
|
|
|
{
|
|
|
|
char *opt0 = psql_scan_slash_option(scan_state,
|
2015-05-24 03:35:49 +02:00
|
|
|
OT_NORMAL, NULL, false);
|
Add new psql help topics, accessible to both --help and \?.
Add --help=<topic> for the commandline, and \? <topic> as a backslash
command, to show more help than the invocations without parameters
do. "commands", "variables" and "options" currently exist as help
topics describing, respectively, backslash commands, psql variables,
and commandline switches. Without parameters the help commands show
their previous topic.
Some further wordsmithing or extending of the added help content might
be needed; but there seems little benefit delaying the overall feature
further.
Author: Pavel Stehule, editorialized by many
Reviewed-By: Andres Freund, Petr Jelinek, Fujii Masao, MauMau, Abhijit
Menon-Sen and Erik Rijkers.
Discussion: CAFj8pRDVGuC-nXBfe2CK8vpyzd2Dsr9GVpbrATAnZO=2YQ0s2Q@mail.gmail.com,
CAFj8pRA54AbTv2RXDTRxiAd8hy8wxmoVLqhJDRCwEnhdd7OUkw@mail.gmail.com
2014-09-09 22:19:14 +02:00
|
|
|
|
|
|
|
if (!opt0 || strcmp(opt0, "commands") == 0)
|
|
|
|
slashUsage(pset.popt.topt.pager);
|
|
|
|
else if (strcmp(opt0, "options") == 0)
|
|
|
|
usage(pset.popt.topt.pager);
|
|
|
|
else if (strcmp(opt0, "variables") == 0)
|
|
|
|
helpVariables(pset.popt.topt.pager);
|
|
|
|
else
|
|
|
|
slashUsage(pset.popt.topt.pager);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
|
|
|
|
if (opt0)
|
|
|
|
free(opt0);
|
Add new psql help topics, accessible to both --help and \?.
Add --help=<topic> for the commandline, and \? <topic> as a backslash
command, to show more help than the invocations without parameters
do. "commands", "variables" and "options" currently exist as help
topics describing, respectively, backslash commands, psql variables,
and commandline switches. Without parameters the help commands show
their previous topic.
Some further wordsmithing or extending of the added help content might
be needed; but there seems little benefit delaying the overall feature
further.
Author: Pavel Stehule, editorialized by many
Reviewed-By: Andres Freund, Petr Jelinek, Fujii Masao, MauMau, Abhijit
Menon-Sen and Erik Rijkers.
Discussion: CAFj8pRDVGuC-nXBfe2CK8vpyzd2Dsr9GVpbrATAnZO=2YQ0s2Q@mail.gmail.com,
CAFj8pRA54AbTv2RXDTRxiAd8hy8wxmoVLqhJDRCwEnhdd7OUkw@mail.gmail.com
2014-09-09 22:19:14 +02:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
else
|
|
|
|
ignore_slash_options(scan_state);
|
|
|
|
|
|
|
|
return PSQL_CMD_SKIP_LINE;
|
|
|
|
}
|
|
|
|
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/*
|
|
|
|
* Read and interpret an argument to the \connect slash command.
|
2017-07-27 17:10:38 +02:00
|
|
|
*
|
|
|
|
* Returns a malloc'd string, or NULL if no/empty argument.
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
read_connect_arg(PsqlScanState scan_state)
|
|
|
|
{
|
|
|
|
char *result;
|
|
|
|
char quote;
|
2000-04-12 19:17:23 +02:00
|
|
|
|
|
|
|
/*
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
* Ideally we should treat the arguments as SQL identifiers. But for
|
|
|
|
* backwards compatibility with 7.2 and older pg_dump files, we have to
|
|
|
|
* take unquoted arguments verbatim (don't downcase them). For now,
|
|
|
|
* double-quoted arguments may be stripped of double quotes (as if SQL
|
|
|
|
* identifiers). By 7.4 or so, pg_dump files can be expected to
|
|
|
|
* double-quote all mixed-case \connect arguments, and then we can get rid
|
|
|
|
* of OT_SQLIDHACK.
|
1999-11-05 00:14:30 +01:00
|
|
|
*/
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, "e, true);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
if (!result)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (quote)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if (*result == '\0' || strcmp(result, "-") == 0)
|
2017-07-27 17:10:38 +02:00
|
|
|
{
|
|
|
|
free(result);
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return NULL;
|
2017-07-27 17:10:38 +02:00
|
|
|
}
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read a boolean expression, return it as a PQExpBuffer string.
|
|
|
|
*
|
|
|
|
* Note: anything more or less than one token will certainly fail to be
|
|
|
|
* parsed by ParseVariableBool, so we don't worry about complaining here.
|
|
|
|
* This routine's return data structure will need to be rethought anyway
|
|
|
|
* to support likely future extensions such as "\if defined VARNAME".
|
|
|
|
*/
|
|
|
|
static PQExpBuffer
|
|
|
|
gather_boolean_expression(PsqlScanState scan_state)
|
|
|
|
{
|
|
|
|
PQExpBuffer exp_buf = createPQExpBuffer();
|
|
|
|
int num_options = 0;
|
|
|
|
char *value;
|
|
|
|
|
|
|
|
/* collect all arguments for the conditional command into exp_buf */
|
|
|
|
while ((value = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false)) != NULL)
|
|
|
|
{
|
|
|
|
/* add spaces between tokens */
|
|
|
|
if (num_options > 0)
|
|
|
|
appendPQExpBufferChar(exp_buf, ' ');
|
|
|
|
appendPQExpBufferStr(exp_buf, value);
|
|
|
|
num_options++;
|
|
|
|
free(value);
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
return exp_buf;
|
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
/*
|
|
|
|
* Read a boolean expression, return true if the expression
|
|
|
|
* was a valid boolean expression that evaluated to true.
|
|
|
|
* Otherwise return false.
|
|
|
|
*
|
|
|
|
* Note: conditional stack's top state must be active, else lexer will
|
|
|
|
* fail to expand variables and backticks.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
is_true_boolean_expression(PsqlScanState scan_state, const char *name)
|
|
|
|
{
|
|
|
|
PQExpBuffer buf = gather_boolean_expression(scan_state);
|
|
|
|
bool value = false;
|
|
|
|
bool success = ParseVariableBool(buf->data, name, &value);
|
2000-02-08 00:10:11 +01:00
|
|
|
|
Support \if ... \elif ... \else ... \endif in psql scripting.
This patch adds nestable conditional blocks to psql. The control
structure feature per se is complete, but the boolean expressions
understood by \if and \elif are pretty primitive; basically, after
variable substitution and backtick expansion, the result has to be
"true" or "false" or one of the other standard spellings of a boolean
value. But that's enough for many purposes, since you can always
do the heavy lifting on the server side; and we can extend it later.
Along the way, pay down some of the technical debt that had built up
around psql/command.c:
* Refactor exec_command() into a function per command, instead of
being a 1500-line monstrosity. This makes the file noticeably longer
because of repetitive function header/trailer overhead, but it seems
much more readable.
* Teach psql_get_variable() and psqlscanslash.l to suppress variable
substitution and backtick expansion on the basis of the conditional
stack state, thereby allowing removal of the OT_NO_EVAL kluge.
* Fix the no-doubt-once-expedient hack of sometimes silently substituting
mainloop.c's previous_buf for query_buf when calling HandleSlashCmds.
(It's a bit remarkable that commands like \r worked at all with that.)
Recall of a previous query is now done explicitly in the slash commands
where that should happen.
Corey Huinker, reviewed by Fabien Coelho, further hacking by me
Discussion: https://postgr.es/m/CADkLM=c94OSRTnat=LX0ivNq4pxDNeoomFfYvBKM5N_xfmLtAA@mail.gmail.com
2017-03-30 18:59:11 +02:00
|
|
|
destroyPQExpBuffer(buf);
|
|
|
|
return success && value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read a boolean expression, but do nothing with it.
|
|
|
|
*
|
|
|
|
* Note: conditional stack's top state must be INACTIVE, else lexer will
|
|
|
|
* expand variables and backticks, which we do not want here.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ignore_boolean_expression(PsqlScanState scan_state)
|
|
|
|
{
|
|
|
|
PQExpBuffer buf = gather_boolean_expression(scan_state);
|
|
|
|
|
|
|
|
destroyPQExpBuffer(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read and discard "normal" slash command options.
|
|
|
|
*
|
|
|
|
* This should be used for inactive-branch processing of any slash command
|
|
|
|
* that eats one or more OT_NORMAL, OT_SQLID, or OT_SQLIDHACK parameters.
|
|
|
|
* We don't need to worry about exactly how many it would eat, since the
|
|
|
|
* cleanup logic in HandleSlashCmds would silently discard any extras anyway.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ignore_slash_options(PsqlScanState scan_state)
|
|
|
|
{
|
|
|
|
char *arg;
|
|
|
|
|
|
|
|
while ((arg = psql_scan_slash_option(scan_state,
|
|
|
|
OT_NORMAL, NULL, false)) != NULL)
|
|
|
|
free(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read and discard FILEPIPE slash command argument.
|
|
|
|
*
|
|
|
|
* This *MUST* be used for inactive-branch processing of any slash command
|
|
|
|
* that takes an OT_FILEPIPE option. Otherwise we might consume a different
|
|
|
|
* amount of option text in active and inactive cases.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ignore_slash_filepipe(PsqlScanState scan_state)
|
|
|
|
{
|
|
|
|
char *arg = psql_scan_slash_option(scan_state,
|
|
|
|
OT_FILEPIPE, NULL, false);
|
|
|
|
|
|
|
|
if (arg)
|
|
|
|
free(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read and discard whole-line slash command argument.
|
|
|
|
*
|
|
|
|
* This *MUST* be used for inactive-branch processing of any slash command
|
|
|
|
* that takes an OT_WHOLE_LINE option. Otherwise we might consume a different
|
|
|
|
* amount of option text in active and inactive cases.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ignore_slash_whole_line(PsqlScanState scan_state)
|
|
|
|
{
|
|
|
|
char *arg = psql_scan_slash_option(scan_state,
|
|
|
|
OT_WHOLE_LINE, NULL, false);
|
|
|
|
|
|
|
|
if (arg)
|
|
|
|
free(arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return true if the command given is a branching command.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
is_branching_command(const char *cmd)
|
|
|
|
{
|
|
|
|
return (strcmp(cmd, "if") == 0 ||
|
|
|
|
strcmp(cmd, "elif") == 0 ||
|
|
|
|
strcmp(cmd, "else") == 0 ||
|
|
|
|
strcmp(cmd, "endif") == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prepare to possibly restore query buffer to its current state
|
|
|
|
* (cf. discard_query_text).
|
|
|
|
*
|
|
|
|
* We need to remember the length of the query buffer, and the lexer's
|
|
|
|
* notion of the parenthesis nesting depth.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf)
|
|
|
|
{
|
|
|
|
if (query_buf)
|
|
|
|
conditional_stack_set_query_len(cstack, query_buf->len);
|
|
|
|
conditional_stack_set_paren_depth(cstack,
|
|
|
|
psql_scan_get_paren_depth(scan_state));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Discard any query text absorbed during an inactive conditional branch.
|
|
|
|
*
|
|
|
|
* We must discard data that was appended to query_buf during an inactive
|
|
|
|
* \if branch. We don't have to do anything there if there's no query_buf.
|
|
|
|
*
|
|
|
|
* Also, reset the lexer state to the same paren depth there was before.
|
|
|
|
* (The rest of its state doesn't need attention, since we could not be
|
|
|
|
* inside a comment or literal or partial token.)
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
|
|
|
|
PQExpBuffer query_buf)
|
|
|
|
{
|
|
|
|
if (query_buf)
|
|
|
|
{
|
|
|
|
int new_len = conditional_stack_get_query_len(cstack);
|
|
|
|
|
|
|
|
Assert(new_len >= 0 && new_len <= query_buf->len);
|
|
|
|
query_buf->len = new_len;
|
|
|
|
query_buf->data[new_len] = '\0';
|
|
|
|
}
|
|
|
|
psql_scan_set_paren_depth(scan_state,
|
|
|
|
conditional_stack_get_paren_depth(cstack));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If query_buf is empty, copy previous_buf into it.
|
|
|
|
*
|
|
|
|
* This is used by various slash commands for which re-execution of a
|
|
|
|
* previous query is a common usage. For convenience, we allow the
|
|
|
|
* case of query_buf == NULL (and do nothing).
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf)
|
|
|
|
{
|
|
|
|
if (query_buf && query_buf->len == 0)
|
|
|
|
appendPQExpBufferStr(query_buf, previous_buf->data);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
/*
|
|
|
|
* Ask the user for a password; 'username' is the username the
|
|
|
|
* password is for, if one has been explicitly specified. Returns a
|
|
|
|
* malloc'd string.
|
1999-11-04 22:56:02 +01:00
|
|
|
*/
|
2006-04-02 22:08:22 +02:00
|
|
|
static char *
|
|
|
|
prompt_for_password(const char *username)
|
1999-11-04 22:56:02 +01:00
|
|
|
{
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
char buf[100];
|
1999-11-05 00:14:30 +01:00
|
|
|
|
Avoid misleading psql password prompt when username is multiply specified.
When a password is needed, cases such as
psql -d "postgresql://alice@localhost/testdb" -U bob
would incorrectly prompt for "Password for user bob: ", when actually the
connection will be attempted with username alice. The priority order of
which name to use isn't that important here, but the misleading prompt is.
When we are prompting for a password after initial connection failure,
we can fix this reliably by looking at PQuser(conn) to see how libpq
interpreted the connection arguments. But when we're doing a forced
password prompt because of a -W switch, we can't use that solution.
Fortunately, because the main use of -W is for noninteractive situations,
it's less critical to produce a helpful prompt in such cases. I made
the startup prompt for -W just say "Password: " all the time, rather
than expending extra code on trying to identify which username to use.
In the case of a \c command (after -W has been given), there's already
logic in do_connect that determines whether the "dbname" is a connstring
or URI, so we can avoid lobotomizing the prompt except in cases that
are actually dubious. (We could do similarly in startup.c if anyone
complains, but for now it seems not worthwhile, especially since that
would still be only a partial solution.)
Per bug #15025 from Akos Vandra. Although this is arguably a bug fix,
it doesn't seem worth back-patching. The case where it matters seems
like a very corner-case usage, and someone might complain that we'd
changed the behavior of -W in a minor release.
Discussion: https://postgr.es/m/20180123130013.7407.24749@wrigleys.postgresql.org
2018-01-29 18:57:09 +01:00
|
|
|
if (username == NULL || username[0] == '\0')
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
simple_prompt("Password: ", buf, sizeof(buf), false);
|
1999-11-05 00:14:30 +01:00
|
|
|
else
|
2006-04-02 22:08:22 +02:00
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
char *prompt_text;
|
1999-11-05 00:14:30 +01:00
|
|
|
|
2013-10-23 01:40:26 +02:00
|
|
|
prompt_text = psprintf(_("Password for user %s: "), username);
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
simple_prompt(prompt_text, buf, sizeof(buf), false);
|
2006-04-02 22:08:22 +02:00
|
|
|
free(prompt_text);
|
|
|
|
}
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
return pg_strdup(buf);
|
2006-04-02 22:08:22 +02:00
|
|
|
}
|
2006-02-12 03:54:30 +01:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
static bool
|
|
|
|
param_is_newly_set(const char *old_val, const char *new_val)
|
|
|
|
{
|
|
|
|
if (new_val == NULL)
|
|
|
|
return false;
|
2005-07-25 19:17:41 +02:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
if (old_val == NULL || strcmp(old_val, new_val) != 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* do_connect -- handler for \connect
|
|
|
|
*
|
2016-08-08 16:07:46 +02:00
|
|
|
* Connects to a database with given parameters. Absent an established
|
|
|
|
* connection, all parameters are required. Given -reuse-previous=off or a
|
|
|
|
* connection string without -reuse-previous=on, NULL values will pass through
|
|
|
|
* to PQconnectdbParams(), so the libpq defaults will be used. Otherwise, NULL
|
|
|
|
* values will be replaced with the ones in the current connection.
|
2006-04-02 22:08:22 +02:00
|
|
|
*
|
|
|
|
* In interactive mode, if connection fails with the given parameters,
|
|
|
|
* the old connection will be kept.
|
|
|
|
*/
|
|
|
|
static bool
|
2016-08-08 16:07:46 +02:00
|
|
|
do_connect(enum trivalue reuse_previous_specification,
|
|
|
|
char *dbname, char *user, char *host, char *port)
|
2006-04-02 22:08:22 +02:00
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
PGconn *o_conn = pset.db,
|
|
|
|
*n_conn;
|
|
|
|
char *password = NULL;
|
2018-11-19 18:34:12 +01:00
|
|
|
char *hostaddr = NULL;
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
bool keep_password;
|
|
|
|
bool has_connection_string;
|
2016-08-08 16:07:46 +02:00
|
|
|
bool reuse_previous;
|
2016-08-08 16:07:46 +02:00
|
|
|
PQExpBufferData connstr;
|
2006-04-02 22:08:22 +02:00
|
|
|
|
2012-08-16 01:04:52 +02:00
|
|
|
if (!o_conn && (!dbname || !user || !host || !port))
|
|
|
|
{
|
2012-08-16 01:17:26 +02:00
|
|
|
/*
|
2013-05-29 22:58:43 +02:00
|
|
|
* We don't know the supplied connection parameters and don't want to
|
|
|
|
* connect to the wrong database by using defaults, so require all
|
|
|
|
* parameters to be specified.
|
2012-08-16 01:17:26 +02:00
|
|
|
*/
|
2012-08-26 04:58:42 +02:00
|
|
|
psql_error("All connection parameters must be supplied because no "
|
|
|
|
"database connection exists\n");
|
2012-08-16 01:04:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-08-08 16:07:46 +02:00
|
|
|
has_connection_string = dbname ?
|
|
|
|
recognized_connection_string(dbname) : false;
|
|
|
|
switch (reuse_previous_specification)
|
|
|
|
{
|
|
|
|
case TRI_YES:
|
|
|
|
reuse_previous = true;
|
|
|
|
break;
|
|
|
|
case TRI_NO:
|
|
|
|
reuse_previous = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
reuse_previous = !has_connection_string;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Silently ignore arguments subsequent to a connection string. */
|
|
|
|
if (has_connection_string)
|
|
|
|
{
|
|
|
|
user = NULL;
|
|
|
|
host = NULL;
|
|
|
|
port = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* grab missing values from the old connection */
|
2018-11-19 18:34:12 +01:00
|
|
|
if (reuse_previous)
|
|
|
|
{
|
|
|
|
if (!user)
|
|
|
|
user = PQuser(o_conn);
|
|
|
|
if (host && strcmp(host, PQhost(o_conn)) == 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* if we are targetting the same host, reuse its hostaddr for
|
|
|
|
* consistency
|
|
|
|
*/
|
|
|
|
hostaddr = PQhostaddr(o_conn);
|
|
|
|
}
|
|
|
|
if (!host)
|
|
|
|
{
|
|
|
|
host = PQhost(o_conn);
|
|
|
|
/* also set hostaddr for consistency */
|
|
|
|
hostaddr = PQhostaddr(o_conn);
|
|
|
|
}
|
|
|
|
if (!port)
|
|
|
|
port = PQport(o_conn);
|
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
/*
|
|
|
|
* Any change in the parameters read above makes us discard the password.
|
2015-05-24 03:35:49 +02:00
|
|
|
* We also discard it if we're to use a conninfo rather than the
|
Improve PQhost() to return useful data for default Unix-socket connections.
Previously, if no host information had been specified at connection time,
PQhost() would return NULL (unless you are on Windows, in which case you
got "localhost"). This is an unhelpful definition for a couple of reasons:
it can cause corner-case crashes in applications (cf commit c5ef8ce53d),
and there's no well-defined way for applications to find out the socket
directory path that's actually in use. As an example of the latter
problem, psql substituted DEFAULT_PGSOCKET_DIR for NULL in a couple of
places, but this is subtly wrong because it's conceivable that psql is
using a libpq shared library that was built with a different setting.
Hence, change PQhost() to return DEFAULT_PGSOCKET_DIR when appropriate,
and strip out the now-dead substitutions in psql. (There is still one
remaining reference to DEFAULT_PGSOCKET_DIR in psql, in prompt.c, which
I don't see a nice way to get rid of. But it only controls a prompt
abbreviation decision, so it seems noncritical.)
Also update the docs for PQhost, which had never previously mentioned
the possibility of a socket directory path being returned. In passing
fix the outright-incorrect code comment about PGconn.pgunixsocket.
2015-11-27 20:13:53 +01:00
|
|
|
* positional syntax.
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
*/
|
2015-11-25 23:31:53 +01:00
|
|
|
if (has_connection_string)
|
|
|
|
keep_password = false;
|
|
|
|
else
|
|
|
|
keep_password =
|
|
|
|
(user && PQuser(o_conn) && strcmp(user, PQuser(o_conn)) == 0) &&
|
Improve PQhost() to return useful data for default Unix-socket connections.
Previously, if no host information had been specified at connection time,
PQhost() would return NULL (unless you are on Windows, in which case you
got "localhost"). This is an unhelpful definition for a couple of reasons:
it can cause corner-case crashes in applications (cf commit c5ef8ce53d),
and there's no well-defined way for applications to find out the socket
directory path that's actually in use. As an example of the latter
problem, psql substituted DEFAULT_PGSOCKET_DIR for NULL in a couple of
places, but this is subtly wrong because it's conceivable that psql is
using a libpq shared library that was built with a different setting.
Hence, change PQhost() to return DEFAULT_PGSOCKET_DIR when appropriate,
and strip out the now-dead substitutions in psql. (There is still one
remaining reference to DEFAULT_PGSOCKET_DIR in psql, in prompt.c, which
I don't see a nice way to get rid of. But it only controls a prompt
abbreviation decision, so it seems noncritical.)
Also update the docs for PQhost, which had never previously mentioned
the possibility of a socket directory path being returned. In passing
fix the outright-incorrect code comment about PGconn.pgunixsocket.
2015-11-27 20:13:53 +01:00
|
|
|
(host && PQhost(o_conn) && strcmp(host, PQhost(o_conn)) == 0) &&
|
2015-11-25 23:31:53 +01:00
|
|
|
(port && PQport(o_conn) && strcmp(port, PQport(o_conn)) == 0);
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
|
|
|
|
/*
|
2016-08-08 16:07:46 +02:00
|
|
|
* Grab missing dbname from old connection. No password discard if this
|
|
|
|
* changes: passwords aren't (usually) database-specific.
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
*/
|
2016-08-08 16:07:46 +02:00
|
|
|
if (!dbname && reuse_previous)
|
2016-08-08 16:07:46 +02:00
|
|
|
{
|
|
|
|
initPQExpBuffer(&connstr);
|
|
|
|
appendPQExpBuffer(&connstr, "dbname=");
|
|
|
|
appendConnStrVal(&connstr, PQdb(o_conn));
|
|
|
|
dbname = connstr.data;
|
|
|
|
/* has_connection_string=true would be a dead store */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
connstr.data = NULL;
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* If the user asked to be prompted for a password, ask for one now. If
|
|
|
|
* not, use the password from the old connection, provided the username
|
2015-11-25 23:31:53 +01:00
|
|
|
* etc have not changed. Otherwise, try to connect without a password
|
|
|
|
* first, and then ask for a password if needed.
|
2006-04-02 22:08:22 +02:00
|
|
|
*
|
2007-11-15 22:14:46 +01:00
|
|
|
* XXX: this behavior leads to spurious connection attempts recorded in
|
|
|
|
* the postmaster's log. But libpq offers no API that would let us obtain
|
|
|
|
* a password and then continue with the first connection attempt.
|
1999-11-05 00:14:30 +01:00
|
|
|
*/
|
2009-02-26 17:02:39 +01:00
|
|
|
if (pset.getPassword == TRI_YES)
|
2006-04-02 22:08:22 +02:00
|
|
|
{
|
Avoid misleading psql password prompt when username is multiply specified.
When a password is needed, cases such as
psql -d "postgresql://alice@localhost/testdb" -U bob
would incorrectly prompt for "Password for user bob: ", when actually the
connection will be attempted with username alice. The priority order of
which name to use isn't that important here, but the misleading prompt is.
When we are prompting for a password after initial connection failure,
we can fix this reliably by looking at PQuser(conn) to see how libpq
interpreted the connection arguments. But when we're doing a forced
password prompt because of a -W switch, we can't use that solution.
Fortunately, because the main use of -W is for noninteractive situations,
it's less critical to produce a helpful prompt in such cases. I made
the startup prompt for -W just say "Password: " all the time, rather
than expending extra code on trying to identify which username to use.
In the case of a \c command (after -W has been given), there's already
logic in do_connect that determines whether the "dbname" is a connstring
or URI, so we can avoid lobotomizing the prompt except in cases that
are actually dubious. (We could do similarly in startup.c if anyone
complains, but for now it seems not worthwhile, especially since that
would still be only a partial solution.)
Per bug #15025 from Akos Vandra. Although this is arguably a bug fix,
it doesn't seem worth back-patching. The case where it matters seems
like a very corner-case usage, and someone might complain that we'd
changed the behavior of -W in a minor release.
Discussion: https://postgr.es/m/20180123130013.7407.24749@wrigleys.postgresql.org
2018-01-29 18:57:09 +01:00
|
|
|
/*
|
|
|
|
* If a connstring or URI is provided, we can't be sure we know which
|
|
|
|
* username will be used, since we haven't parsed that argument yet.
|
|
|
|
* Don't risk issuing a misleading prompt. As in startup.c, it does
|
|
|
|
* not seem worth working harder, since this getPassword option is
|
|
|
|
* normally only used in noninteractive cases.
|
|
|
|
*/
|
|
|
|
password = prompt_for_password(has_connection_string ? NULL : user);
|
2006-04-02 22:08:22 +02:00
|
|
|
}
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
else if (o_conn && keep_password)
|
2006-04-02 22:08:22 +02:00
|
|
|
{
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
password = PQpass(o_conn);
|
|
|
|
if (password && *password)
|
|
|
|
password = pg_strdup(password);
|
|
|
|
else
|
|
|
|
password = NULL;
|
2006-04-02 22:08:22 +02:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
while (true)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2018-11-19 18:34:12 +01:00
|
|
|
#define PARAMS_ARRAY_SIZE 9
|
2010-02-05 04:09:05 +01:00
|
|
|
const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
|
|
|
|
const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
|
2016-08-08 16:07:46 +02:00
|
|
|
int paramnum = -1;
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
|
2016-08-08 16:07:46 +02:00
|
|
|
keywords[++paramnum] = "host";
|
|
|
|
values[paramnum] = host;
|
2018-11-19 18:34:12 +01:00
|
|
|
if (hostaddr && *hostaddr)
|
|
|
|
{
|
|
|
|
keywords[++paramnum] = "hostaddr";
|
|
|
|
values[paramnum] = hostaddr;
|
|
|
|
}
|
2016-08-08 16:07:46 +02:00
|
|
|
keywords[++paramnum] = "port";
|
|
|
|
values[paramnum] = port;
|
|
|
|
keywords[++paramnum] = "user";
|
|
|
|
values[paramnum] = user;
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
|
2016-08-08 16:07:46 +02:00
|
|
|
/*
|
|
|
|
* Position in the array matters when the dbname is a connection
|
|
|
|
* string, because settings in a connection string override earlier
|
|
|
|
* array entries only. Thus, user= in the connection string always
|
|
|
|
* takes effect, but client_encoding= often will not.
|
|
|
|
*
|
|
|
|
* If you change this code, also change the initial-connection code in
|
|
|
|
* main(). For no good reason, a connection string password= takes
|
|
|
|
* precedence in main() but not here.
|
|
|
|
*/
|
|
|
|
keywords[++paramnum] = "dbname";
|
|
|
|
values[paramnum] = dbname;
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
keywords[++paramnum] = "password";
|
|
|
|
values[paramnum] = password;
|
|
|
|
keywords[++paramnum] = "fallback_application_name";
|
|
|
|
values[paramnum] = pset.progname;
|
|
|
|
keywords[++paramnum] = "client_encoding";
|
|
|
|
values[paramnum] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
|
2010-02-05 04:09:05 +01:00
|
|
|
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
/* add array terminator */
|
|
|
|
keywords[++paramnum] = NULL;
|
|
|
|
values[paramnum] = NULL;
|
2010-02-05 04:09:05 +01:00
|
|
|
|
|
|
|
n_conn = PQconnectdbParams(keywords, values, true);
|
|
|
|
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
pg_free(keywords);
|
|
|
|
pg_free(values);
|
2006-04-02 22:08:22 +02:00
|
|
|
|
|
|
|
/* We can immediately discard the password -- no longer needed */
|
|
|
|
if (password)
|
psql: fix \connect with URIs and conninfo strings
This is the second try at this, after fcef1617295 failed miserably and
had to be reverted: as it turns out, libpq cannot depend on libpgcommon
after all. Instead of shuffling code in the master branch, make that one
just like 9.4 and accept the duplication. (This was all my own mistake,
not the patch submitter's).
psql was already accepting conninfo strings as the first parameter in
\connect, but the way it worked wasn't sane; some of the other
parameters would get the previous connection's values, causing it to
connect to a completely unexpected server or, more likely, not finding
any server at all because of completely wrong combinations of
parameters.
Fix by explicitely checking for a conninfo-looking parameter in the
dbname position; if one is found, use its complete specification rather
than mix with the other arguments. Also, change tab-completion to not
try to complete conninfo/URI-looking "dbnames" and document that
conninfos are accepted as first argument.
There was a weak consensus to backpatch this, because while the behavior
of using the dbname as a conninfo is nowhere documented for \connect, it
is reasonable to expect that it works because it does work in many other
contexts. Therefore this is backpatched all the way back to 9.0.
Author: David Fetter, Andrew Dunstan. Some editorialization by me
(probably earning a Gierth's "Sloppy" badge in the process.)
Reviewers: Andrew Gierth, Erik Rijkers, Pavel Stěhule, Stephen Frost,
Robert Haas, Andrew Dunstan.
2015-04-02 17:30:57 +02:00
|
|
|
pg_free(password);
|
1999-11-05 00:14:30 +01:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
if (PQstatus(n_conn) == CONNECTION_OK)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* Connection attempt failed; either retry the connection attempt with
|
|
|
|
* a new password, or give up.
|
2006-04-02 22:08:22 +02:00
|
|
|
*/
|
2009-02-26 17:02:39 +01:00
|
|
|
if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
Avoid misleading psql password prompt when username is multiply specified.
When a password is needed, cases such as
psql -d "postgresql://alice@localhost/testdb" -U bob
would incorrectly prompt for "Password for user bob: ", when actually the
connection will be attempted with username alice. The priority order of
which name to use isn't that important here, but the misleading prompt is.
When we are prompting for a password after initial connection failure,
we can fix this reliably by looking at PQuser(conn) to see how libpq
interpreted the connection arguments. But when we're doing a forced
password prompt because of a -W switch, we can't use that solution.
Fortunately, because the main use of -W is for noninteractive situations,
it's less critical to produce a helpful prompt in such cases. I made
the startup prompt for -W just say "Password: " all the time, rather
than expending extra code on trying to identify which username to use.
In the case of a \c command (after -W has been given), there's already
logic in do_connect that determines whether the "dbname" is a connstring
or URI, so we can avoid lobotomizing the prompt except in cases that
are actually dubious. (We could do similarly in startup.c if anyone
complains, but for now it seems not worthwhile, especially since that
would still be only a partial solution.)
Per bug #15025 from Akos Vandra. Although this is arguably a bug fix,
it doesn't seem worth back-patching. The case where it matters seems
like a very corner-case usage, and someone might complain that we'd
changed the behavior of -W in a minor release.
Discussion: https://postgr.es/m/20180123130013.7407.24749@wrigleys.postgresql.org
2018-01-29 18:57:09 +01:00
|
|
|
/*
|
|
|
|
* Prompt for password using the username we actually connected
|
|
|
|
* with --- it might've come out of "dbname" rather than "user".
|
|
|
|
*/
|
|
|
|
password = prompt_for_password(PQuser(n_conn));
|
2006-04-02 22:08:22 +02:00
|
|
|
PQfinish(n_conn);
|
|
|
|
continue;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* Failed to connect to the database. In interactive mode, keep the
|
|
|
|
* previous connection to the DB; in scripting mode, close our
|
|
|
|
* previous connection as well.
|
2006-04-02 22:08:22 +02:00
|
|
|
*/
|
2000-04-12 19:17:23 +02:00
|
|
|
if (pset.cur_cmd_interactive)
|
|
|
|
{
|
2006-04-02 22:08:22 +02:00
|
|
|
psql_error("%s", PQerrorMessage(n_conn));
|
|
|
|
|
|
|
|
/* pset.db is left unmodified */
|
|
|
|
if (o_conn)
|
2012-08-26 04:58:42 +02:00
|
|
|
psql_error("Previous connection kept\n");
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-02 22:08:22 +02:00
|
|
|
psql_error("\\connect: %s", PQerrorMessage(n_conn));
|
|
|
|
if (o_conn)
|
2006-02-12 03:54:30 +01:00
|
|
|
{
|
2006-04-02 22:08:22 +02:00
|
|
|
PQfinish(o_conn);
|
|
|
|
pset.db = NULL;
|
2006-02-12 03:54:30 +01:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
PQfinish(n_conn);
|
2016-08-08 16:07:46 +02:00
|
|
|
if (connstr.data)
|
|
|
|
termPQExpBuffer(&connstr);
|
2006-04-02 22:08:22 +02:00
|
|
|
return false;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
2016-08-08 16:07:46 +02:00
|
|
|
if (connstr.data)
|
|
|
|
termPQExpBuffer(&connstr);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
/*
|
|
|
|
* Replace the old connection with the new one, and update
|
|
|
|
* connection-dependent variables.
|
|
|
|
*/
|
|
|
|
PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
|
|
|
|
pset.db = n_conn;
|
2003-06-28 02:12:40 +02:00
|
|
|
SyncVariables();
|
2010-02-26 03:01:40 +01:00
|
|
|
connection_warnings(false); /* Must be after SyncVariables */
|
2003-06-28 02:12:40 +02:00
|
|
|
|
2006-04-02 22:08:22 +02:00
|
|
|
/* Tell the user about the new connection */
|
2006-08-29 17:19:51 +02:00
|
|
|
if (!pset.quiet)
|
2006-04-02 22:08:22 +02:00
|
|
|
{
|
2015-07-09 02:44:21 +02:00
|
|
|
if (!o_conn ||
|
|
|
|
param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
|
2010-08-03 20:33:09 +02:00
|
|
|
param_is_newly_set(PQport(o_conn), PQport(pset.db)))
|
2010-07-23 16:56:54 +02:00
|
|
|
{
|
2011-04-10 17:42:00 +02:00
|
|
|
char *host = PQhost(pset.db);
|
2018-11-19 18:34:12 +01:00
|
|
|
char *hostaddr = PQhostaddr(pset.db);
|
2010-07-23 16:56:54 +02:00
|
|
|
|
2010-08-03 20:33:09 +02:00
|
|
|
/* If the host is an absolute path, the connection is via socket */
|
2010-07-23 16:56:54 +02:00
|
|
|
if (is_absolute_path(host))
|
2018-11-19 18:34:12 +01:00
|
|
|
{
|
|
|
|
if (hostaddr && *hostaddr)
|
|
|
|
printf(_("You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"),
|
|
|
|
PQdb(pset.db), PQuser(pset.db), hostaddr, PQport(pset.db));
|
|
|
|
else
|
|
|
|
printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
|
|
|
|
PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
|
|
|
|
}
|
2010-07-23 16:56:54 +02:00
|
|
|
else
|
2018-11-19 18:34:12 +01:00
|
|
|
{
|
|
|
|
if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0)
|
|
|
|
printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"),
|
|
|
|
PQdb(pset.db), PQuser(pset.db), host, hostaddr, PQport(pset.db));
|
|
|
|
else
|
|
|
|
printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
|
|
|
|
PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
|
|
|
|
}
|
2010-07-23 16:56:54 +02:00
|
|
|
}
|
2010-08-03 20:33:09 +02:00
|
|
|
else
|
|
|
|
printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
|
|
|
|
PQdb(pset.db), PQuser(pset.db));
|
2006-04-02 22:08:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (o_conn)
|
|
|
|
PQfinish(o_conn);
|
|
|
|
return true;
|
2003-06-28 02:12:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-07-01 02:08:18 +02:00
|
|
|
void
|
2010-02-16 22:07:01 +01:00
|
|
|
connection_warnings(bool in_startup)
|
2008-07-01 02:08:18 +02:00
|
|
|
{
|
|
|
|
if (!pset.quiet && !pset.notty)
|
|
|
|
{
|
2013-03-26 14:21:57 +01:00
|
|
|
int client_ver = PG_VERSION_NUM;
|
Fix assorted places in psql to print version numbers >= 10 in new style.
This is somewhat cosmetic, since as long as you know what you are looking
at, "10.0" is a serviceable substitute for "10". But there is a potential
for confusion between version numbers with minor numbers and those without
--- we don't want people asking "why is psql saying 10.0 when my server is
10.2". Therefore, back-patch as far as practical, which turns out to be
9.3. I could have redone the patch to use fprintf(stderr) in place of
psql_error(), but it seems more work than is warranted for branches that
will be EOL or nearly so by the time v10 comes out.
Although only psql seems to contain any code that needs this, I chose
to put the support function into fe_utils, since it seems likely we'll
need it in other client programs in future. (In 9.3-9.5, use dumputils.c,
the predecessor of fe_utils/string_utils.c.)
In HEAD, also fix the backend code that whines about loadable-library
version mismatch. I don't see much need to back-patch that.
2016-08-16 21:58:30 +02:00
|
|
|
char cverbuf[32];
|
|
|
|
char sverbuf[32];
|
2008-07-01 02:08:18 +02:00
|
|
|
|
|
|
|
if (pset.sversion != client_ver)
|
|
|
|
{
|
|
|
|
const char *server_version;
|
|
|
|
|
|
|
|
/* Try to get full text form, might include "devel" etc */
|
|
|
|
server_version = PQparameterStatus(pset.db, "server_version");
|
Fix assorted places in psql to print version numbers >= 10 in new style.
This is somewhat cosmetic, since as long as you know what you are looking
at, "10.0" is a serviceable substitute for "10". But there is a potential
for confusion between version numbers with minor numbers and those without
--- we don't want people asking "why is psql saying 10.0 when my server is
10.2". Therefore, back-patch as far as practical, which turns out to be
9.3. I could have redone the patch to use fprintf(stderr) in place of
psql_error(), but it seems more work than is warranted for branches that
will be EOL or nearly so by the time v10 comes out.
Although only psql seems to contain any code that needs this, I chose
to put the support function into fe_utils, since it seems likely we'll
need it in other client programs in future. (In 9.3-9.5, use dumputils.c,
the predecessor of fe_utils/string_utils.c.)
In HEAD, also fix the backend code that whines about loadable-library
version mismatch. I don't see much need to back-patch that.
2016-08-16 21:58:30 +02:00
|
|
|
/* Otherwise fall back on pset.sversion */
|
2008-07-01 02:08:18 +02:00
|
|
|
if (!server_version)
|
|
|
|
{
|
Fix assorted places in psql to print version numbers >= 10 in new style.
This is somewhat cosmetic, since as long as you know what you are looking
at, "10.0" is a serviceable substitute for "10". But there is a potential
for confusion between version numbers with minor numbers and those without
--- we don't want people asking "why is psql saying 10.0 when my server is
10.2". Therefore, back-patch as far as practical, which turns out to be
9.3. I could have redone the patch to use fprintf(stderr) in place of
psql_error(), but it seems more work than is warranted for branches that
will be EOL or nearly so by the time v10 comes out.
Although only psql seems to contain any code that needs this, I chose
to put the support function into fe_utils, since it seems likely we'll
need it in other client programs in future. (In 9.3-9.5, use dumputils.c,
the predecessor of fe_utils/string_utils.c.)
In HEAD, also fix the backend code that whines about loadable-library
version mismatch. I don't see much need to back-patch that.
2016-08-16 21:58:30 +02:00
|
|
|
formatPGVersionNumber(pset.sversion, true,
|
|
|
|
sverbuf, sizeof(sverbuf));
|
|
|
|
server_version = sverbuf;
|
2008-07-01 02:08:18 +02:00
|
|
|
}
|
|
|
|
|
2009-06-11 16:49:15 +02:00
|
|
|
printf(_("%s (%s, server %s)\n"),
|
|
|
|
pset.progname, PG_VERSION, server_version);
|
2008-07-01 02:08:18 +02:00
|
|
|
}
|
2010-02-16 22:07:01 +01:00
|
|
|
/* For version match, only print psql banner on startup. */
|
|
|
|
else if (in_startup)
|
2008-07-01 02:08:18 +02:00
|
|
|
printf("%s (%s)\n", pset.progname, PG_VERSION);
|
|
|
|
|
2012-09-01 05:28:14 +02:00
|
|
|
if (pset.sversion / 100 > client_ver / 100)
|
Fix assorted places in psql to print version numbers >= 10 in new style.
This is somewhat cosmetic, since as long as you know what you are looking
at, "10.0" is a serviceable substitute for "10". But there is a potential
for confusion between version numbers with minor numbers and those without
--- we don't want people asking "why is psql saying 10.0 when my server is
10.2". Therefore, back-patch as far as practical, which turns out to be
9.3. I could have redone the patch to use fprintf(stderr) in place of
psql_error(), but it seems more work than is warranted for branches that
will be EOL or nearly so by the time v10 comes out.
Although only psql seems to contain any code that needs this, I chose
to put the support function into fe_utils, since it seems likely we'll
need it in other client programs in future. (In 9.3-9.5, use dumputils.c,
the predecessor of fe_utils/string_utils.c.)
In HEAD, also fix the backend code that whines about loadable-library
version mismatch. I don't see much need to back-patch that.
2016-08-16 21:58:30 +02:00
|
|
|
printf(_("WARNING: %s major version %s, server major version %s.\n"
|
2009-06-11 16:49:15 +02:00
|
|
|
" Some psql features might not work.\n"),
|
Fix assorted places in psql to print version numbers >= 10 in new style.
This is somewhat cosmetic, since as long as you know what you are looking
at, "10.0" is a serviceable substitute for "10". But there is a potential
for confusion between version numbers with minor numbers and those without
--- we don't want people asking "why is psql saying 10.0 when my server is
10.2". Therefore, back-patch as far as practical, which turns out to be
9.3. I could have redone the patch to use fprintf(stderr) in place of
psql_error(), but it seems more work than is warranted for branches that
will be EOL or nearly so by the time v10 comes out.
Although only psql seems to contain any code that needs this, I chose
to put the support function into fe_utils, since it seems likely we'll
need it in other client programs in future. (In 9.3-9.5, use dumputils.c,
the predecessor of fe_utils/string_utils.c.)
In HEAD, also fix the backend code that whines about loadable-library
version mismatch. I don't see much need to back-patch that.
2016-08-16 21:58:30 +02:00
|
|
|
pset.progname,
|
|
|
|
formatPGVersionNumber(client_ver, false,
|
|
|
|
cverbuf, sizeof(cverbuf)),
|
|
|
|
formatPGVersionNumber(pset.sversion, false,
|
|
|
|
sverbuf, sizeof(sverbuf)));
|
2008-07-01 02:08:18 +02:00
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
checkWin32Codepage();
|
|
|
|
#endif
|
|
|
|
printSSLInfo();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* printSSLInfo
|
|
|
|
*
|
|
|
|
* Prints information about the current SSL connection, if SSL is in use
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
printSSLInfo(void)
|
|
|
|
{
|
2015-02-03 18:57:52 +01:00
|
|
|
const char *protocol;
|
|
|
|
const char *cipher;
|
|
|
|
const char *bits;
|
|
|
|
const char *compression;
|
2008-07-01 02:08:18 +02:00
|
|
|
|
2015-02-03 18:57:52 +01:00
|
|
|
if (!PQsslInUse(pset.db))
|
2008-07-01 02:08:18 +02:00
|
|
|
return; /* no SSL */
|
|
|
|
|
2015-02-03 18:57:52 +01:00
|
|
|
protocol = PQsslAttribute(pset.db, "protocol");
|
|
|
|
cipher = PQsslAttribute(pset.db, "cipher");
|
|
|
|
bits = PQsslAttribute(pset.db, "key_bits");
|
|
|
|
compression = PQsslAttribute(pset.db, "compression");
|
2009-06-11 16:49:15 +02:00
|
|
|
|
2015-02-03 18:57:52 +01:00
|
|
|
printf(_("SSL connection (protocol: %s, cipher: %s, bits: %s, compression: %s)\n"),
|
|
|
|
protocol ? protocol : _("unknown"),
|
|
|
|
cipher ? cipher : _("unknown"),
|
|
|
|
bits ? bits : _("unknown"),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
(compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
|
2008-11-11 16:01:53 +01:00
|
|
|
}
|
2008-07-01 02:08:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* checkWin32Codepage
|
|
|
|
*
|
|
|
|
* Prints a warning when win32 console codepage differs from Windows codepage
|
|
|
|
*/
|
|
|
|
#ifdef WIN32
|
|
|
|
static void
|
|
|
|
checkWin32Codepage(void)
|
|
|
|
{
|
|
|
|
unsigned int wincp,
|
|
|
|
concp;
|
|
|
|
|
|
|
|
wincp = GetACP();
|
|
|
|
concp = GetConsoleCP();
|
|
|
|
if (wincp != concp)
|
|
|
|
{
|
|
|
|
printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n"
|
|
|
|
" 8-bit characters might not work correctly. See psql reference\n"
|
2009-06-11 16:49:15 +02:00
|
|
|
" page \"Notes for Windows users\" for details.\n"),
|
2008-07-01 02:08:18 +02:00
|
|
|
concp, wincp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2003-06-28 02:12:40 +02:00
|
|
|
/*
|
|
|
|
* SyncVariables
|
|
|
|
*
|
|
|
|
* Make psql's internal variables agree with connection state upon
|
|
|
|
* establishing a new connection.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SyncVariables(void)
|
|
|
|
{
|
2017-09-05 16:51:36 +02:00
|
|
|
char vbuf[32];
|
|
|
|
const char *server_version;
|
|
|
|
|
2003-06-28 02:12:40 +02:00
|
|
|
/* get stuff from connection */
|
|
|
|
pset.encoding = PQclientEncoding(pset.db);
|
|
|
|
pset.popt.topt.encoding = pset.encoding;
|
2006-08-29 17:19:51 +02:00
|
|
|
pset.sversion = PQserverVersion(pset.db);
|
2003-06-28 02:12:40 +02:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
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));
|
2000-01-14 23:18:03 +01:00
|
|
|
|
2017-09-05 16:51:36 +02:00
|
|
|
/* this bit should match connection_warnings(): */
|
|
|
|
/* Try to get full text form of version, might include "devel" etc */
|
|
|
|
server_version = PQparameterStatus(pset.db, "server_version");
|
|
|
|
/* Otherwise fall back on pset.sversion */
|
|
|
|
if (!server_version)
|
|
|
|
{
|
|
|
|
formatPGVersionNumber(pset.sversion, true, vbuf, sizeof(vbuf));
|
|
|
|
server_version = vbuf;
|
|
|
|
}
|
|
|
|
SetVariable(pset.vars, "SERVER_VERSION_NAME", server_version);
|
|
|
|
|
|
|
|
snprintf(vbuf, sizeof(vbuf), "%d", pset.sversion);
|
|
|
|
SetVariable(pset.vars, "SERVER_VERSION_NUM", vbuf);
|
|
|
|
|
2003-06-28 02:12:40 +02:00
|
|
|
/* send stuff to it, too */
|
2006-08-29 17:19:51 +02:00
|
|
|
PQsetErrorVerbosity(pset.db, pset.verbosity);
|
2015-09-05 17:58:20 +02:00
|
|
|
PQsetErrorContextVisibility(pset.db, pset.show_context);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
2000-01-29 17:58:54 +01:00
|
|
|
/*
|
2003-06-28 02:12:40 +02:00
|
|
|
* UnsyncVariables
|
|
|
|
*
|
|
|
|
* Clear variables that should be not be set when there is no connection.
|
2000-01-29 17:58:54 +01:00
|
|
|
*/
|
2003-06-28 02:12:40 +02:00
|
|
|
void
|
|
|
|
UnsyncVariables(void)
|
2000-01-29 17:58:54 +01:00
|
|
|
{
|
2003-06-28 02:12:40 +02:00
|
|
|
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);
|
2017-09-05 16:51:36 +02:00
|
|
|
SetVariable(pset.vars, "SERVER_VERSION_NAME", NULL);
|
|
|
|
SetVariable(pset.vars, "SERVER_VERSION_NUM", NULL);
|
2000-01-29 17:58:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-11-04 22:56:02 +01:00
|
|
|
/*
|
|
|
|
* do_edit -- handler for \e
|
|
|
|
*
|
|
|
|
* If you do not specify a filename, the current query buffer will be copied
|
|
|
|
* into a temporary one.
|
|
|
|
*/
|
|
|
|
static bool
|
2010-08-12 02:40:59 +02:00
|
|
|
editFile(const char *fname, int lineno)
|
1999-11-04 22:56:02 +01:00
|
|
|
{
|
2000-02-08 00:10:11 +01:00
|
|
|
const char *editorName;
|
2011-07-23 23:25:29 +02:00
|
|
|
const char *editor_lineno_arg = NULL;
|
1999-11-05 00:14:30 +01:00
|
|
|
char *sys;
|
|
|
|
int result;
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2012-12-15 00:03:07 +01:00
|
|
|
Assert(fname != NULL);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
/* Find an editor to use */
|
|
|
|
editorName = getenv("PSQL_EDITOR");
|
|
|
|
if (!editorName)
|
|
|
|
editorName = getenv("EDITOR");
|
|
|
|
if (!editorName)
|
|
|
|
editorName = getenv("VISUAL");
|
|
|
|
if (!editorName)
|
|
|
|
editorName = DEFAULT_EDITOR;
|
|
|
|
|
2011-07-23 23:25:29 +02:00
|
|
|
/* Get line number argument, if we need it. */
|
2010-08-12 02:40:59 +02:00
|
|
|
if (lineno > 0)
|
|
|
|
{
|
2011-07-23 23:25:29 +02:00
|
|
|
editor_lineno_arg = getenv("PSQL_EDITOR_LINENUMBER_ARG");
|
|
|
|
#ifdef DEFAULT_EDITOR_LINENUMBER_ARG
|
|
|
|
if (!editor_lineno_arg)
|
|
|
|
editor_lineno_arg = DEFAULT_EDITOR_LINENUMBER_ARG;
|
|
|
|
#endif
|
|
|
|
if (!editor_lineno_arg)
|
2010-08-12 02:40:59 +02:00
|
|
|
{
|
2011-07-23 23:25:29 +02:00
|
|
|
psql_error("environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number\n");
|
2010-08-12 02:40:59 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-16 00:15:12 +01:00
|
|
|
/*
|
|
|
|
* On Unix the EDITOR value should *not* be quoted, since it might include
|
|
|
|
* switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
|
|
|
|
* if necessary. But this policy is not very workable on Windows, due to
|
|
|
|
* severe brain damage in their command shell plus the fact that standard
|
|
|
|
* program paths include spaces.
|
|
|
|
*/
|
2003-04-04 22:40:45 +02:00
|
|
|
#ifndef WIN32
|
2010-08-12 02:40:59 +02:00
|
|
|
if (lineno > 0)
|
2013-10-23 01:40:26 +02:00
|
|
|
sys = psprintf("exec %s %s%d '%s'",
|
2014-05-06 18:12:18 +02:00
|
|
|
editorName, editor_lineno_arg, lineno, fname);
|
2010-08-12 02:40:59 +02:00
|
|
|
else
|
2013-10-23 01:40:26 +02:00
|
|
|
sys = psprintf("exec %s '%s'",
|
2014-05-06 18:12:18 +02:00
|
|
|
editorName, fname);
|
2004-11-16 00:15:12 +01:00
|
|
|
#else
|
2010-08-12 02:40:59 +02:00
|
|
|
if (lineno > 0)
|
Replace SYSTEMQUOTEs with Windows-specific wrapper functions.
It's easy to forget using SYSTEMQUOTEs when constructing command strings
for system() or popen(). Even if we fix all the places missing it now, it is
bound to be forgotten again in the future. Introduce wrapper functions that
do the the extra quoting for you, and get rid of SYSTEMQUOTEs in all the
callers.
We previosly used SYSTEMQUOTEs in all the hard-coded command strings, and
this doesn't change the behavior of those. But user-supplied commands, like
archive_command, restore_command, COPY TO/FROM PROGRAM calls, as well as
pgbench's \shell, will now gain an extra pair of quotes. That is desirable,
but if you have existing scripts or config files that include an extra
pair of quotes, those might need to be adjusted.
Reviewed by Amit Kapila and Tom Lane
2014-05-05 15:07:40 +02:00
|
|
|
sys = psprintf("\"%s\" %s%d \"%s\"",
|
2014-05-06 18:12:18 +02:00
|
|
|
editorName, editor_lineno_arg, lineno, fname);
|
2010-08-12 02:40:59 +02:00
|
|
|
else
|
Replace SYSTEMQUOTEs with Windows-specific wrapper functions.
It's easy to forget using SYSTEMQUOTEs when constructing command strings
for system() or popen(). Even if we fix all the places missing it now, it is
bound to be forgotten again in the future. Introduce wrapper functions that
do the the extra quoting for you, and get rid of SYSTEMQUOTEs in all the
callers.
We previosly used SYSTEMQUOTEs in all the hard-coded command strings, and
this doesn't change the behavior of those. But user-supplied commands, like
archive_command, restore_command, COPY TO/FROM PROGRAM calls, as well as
pgbench's \shell, will now gain an extra pair of quotes. That is desirable,
but if you have existing scripts or config files that include an extra
pair of quotes, those might need to be adjusted.
Reviewed by Amit Kapila and Tom Lane
2014-05-05 15:07:40 +02:00
|
|
|
sys = psprintf("\"%s\" \"%s\"",
|
2014-05-06 18:12:18 +02:00
|
|
|
editorName, fname);
|
2003-04-04 22:40:45 +02:00
|
|
|
#endif
|
1999-11-05 00:14:30 +01:00
|
|
|
result = system(sys);
|
2000-01-19 00:30:24 +01:00
|
|
|
if (result == -1)
|
2003-07-23 10:47:41 +02:00
|
|
|
psql_error("could not start editor \"%s\"\n", editorName);
|
2000-04-12 19:17:23 +02:00
|
|
|
else if (result == 127)
|
2000-01-19 00:30:24 +01:00
|
|
|
psql_error("could not start /bin/sh\n");
|
1999-11-05 00:14:30 +01:00
|
|
|
free(sys);
|
|
|
|
|
|
|
|
return result == 0;
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* call this one */
|
|
|
|
static bool
|
2010-08-12 02:40:59 +02:00
|
|
|
do_edit(const char *filename_arg, PQExpBuffer query_buf,
|
|
|
|
int lineno, bool *edited)
|
1999-11-04 22:56:02 +01:00
|
|
|
{
|
2000-01-12 20:36:36 +01:00
|
|
|
char fnametmp[MAXPGPATH];
|
2000-11-26 12:09:32 +01:00
|
|
|
FILE *stream = NULL;
|
1999-11-05 00:14:30 +01:00
|
|
|
const char *fname;
|
|
|
|
bool error = false;
|
2000-11-25 07:21:54 +01:00
|
|
|
int fd;
|
2001-03-22 05:01:46 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
struct stat before,
|
|
|
|
after;
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (filename_arg)
|
|
|
|
fname = filename_arg;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* make a temp file to edit */
|
1999-11-04 22:56:02 +01:00
|
|
|
#ifndef WIN32
|
2004-11-04 23:25:14 +01:00
|
|
|
const char *tmpdir = getenv("TMPDIR");
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2004-11-04 23:25:14 +01:00
|
|
|
if (!tmpdir)
|
|
|
|
tmpdir = "/tmp";
|
|
|
|
#else
|
2005-10-15 04:49:52 +02:00
|
|
|
char tmpdir[MAXPGPATH];
|
|
|
|
int ret;
|
2004-11-04 23:25:14 +01:00
|
|
|
|
|
|
|
ret = GetTempPath(MAXPGPATH, tmpdir);
|
|
|
|
if (ret == 0 || ret > MAXPGPATH)
|
|
|
|
{
|
2011-07-26 22:23:18 +02:00
|
|
|
psql_error("could not locate temporary directory: %s\n",
|
2005-10-15 04:49:52 +02:00
|
|
|
!ret ? strerror(errno) : "");
|
2004-11-04 23:25:14 +01:00
|
|
|
return false;
|
|
|
|
}
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2004-11-04 23:25:14 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
|
|
|
|
* current directory to the supplied path unless we use only
|
|
|
|
* backslashes, so we do that.
|
2004-11-04 23:25:14 +01:00
|
|
|
*/
|
|
|
|
#endif
|
|
|
|
#ifndef WIN32
|
2011-12-02 22:38:33 +01:00
|
|
|
snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
|
2005-10-15 04:49:52 +02:00
|
|
|
"/", (int) getpid());
|
1999-11-04 22:56:02 +01:00
|
|
|
#else
|
2011-12-02 22:38:33 +01:00
|
|
|
snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
"" /* trailing separator already present */ , (int) getpid());
|
1999-11-04 22:56:02 +01:00
|
|
|
#endif
|
2004-11-04 23:25:14 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
fname = (const char *) fnametmp;
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
2000-11-25 07:21:54 +01:00
|
|
|
if (fd != -1)
|
|
|
|
stream = fdopen(fd, "w");
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2000-11-25 07:21:54 +01:00
|
|
|
if (fd == -1 || !stream)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2003-07-23 10:47:41 +02:00
|
|
|
psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno));
|
1999-11-05 00:14:30 +01:00
|
|
|
error = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned int ql = query_buf->len;
|
|
|
|
|
|
|
|
if (ql == 0 || query_buf->data[ql - 1] != '\n')
|
|
|
|
{
|
|
|
|
appendPQExpBufferChar(query_buf, '\n');
|
|
|
|
ql++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fwrite(query_buf->data, 1, ql, stream) != ql)
|
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
2014-03-02 04:14:14 +01:00
|
|
|
|
|
|
|
if (fclose(stream) != 0)
|
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
|
|
|
|
|
|
|
if (remove(fname) != 0)
|
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
error = true;
|
|
|
|
}
|
2004-01-26 23:35:32 +01:00
|
|
|
else if (fclose(stream) != 0)
|
|
|
|
{
|
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
2014-03-02 04:14:14 +01:00
|
|
|
if (remove(fname) != 0)
|
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
2004-01-26 23:35:32 +01:00
|
|
|
error = true;
|
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
|
|
|
|
if (!error && stat(fname, &before) != 0)
|
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
1999-11-04 22:56:02 +01:00
|
|
|
error = true;
|
|
|
|
}
|
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
/* call editor */
|
|
|
|
if (!error)
|
2010-08-12 02:40:59 +02:00
|
|
|
error = !editFile(fname, lineno);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (!error && stat(fname, &after) != 0)
|
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
1999-11-05 00:14:30 +01:00
|
|
|
error = true;
|
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (!error && before.st_mtime != after.st_mtime)
|
|
|
|
{
|
2004-07-11 15:29:16 +02:00
|
|
|
stream = fopen(fname, PG_BINARY_R);
|
1999-11-05 00:14:30 +01:00
|
|
|
if (!stream)
|
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
1999-11-05 00:14:30 +01:00
|
|
|
error = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-06-12 01:06:00 +02:00
|
|
|
/* read file back into query_buf */
|
1999-11-05 00:14:30 +01:00
|
|
|
char line[1024];
|
|
|
|
|
|
|
|
resetPQExpBuffer(query_buf);
|
2000-11-27 03:20:36 +01:00
|
|
|
while (fgets(line, sizeof(line), stream) != NULL)
|
2000-03-27 23:11:37 +02:00
|
|
|
appendPQExpBufferStr(query_buf, line);
|
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
if (ferror(stream))
|
|
|
|
{
|
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
|
|
|
error = true;
|
|
|
|
}
|
2008-09-06 02:01:25 +02:00
|
|
|
else if (edited)
|
|
|
|
{
|
|
|
|
*edited = true;
|
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
|
|
|
|
fclose(stream);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
}
|
2000-04-11 19:35:50 +02:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
/* remove temp file */
|
2000-04-11 19:35:50 +02:00
|
|
|
if (!filename_arg)
|
2000-04-12 19:17:23 +02:00
|
|
|
{
|
|
|
|
if (remove(fname) == -1)
|
|
|
|
{
|
|
|
|
psql_error("%s: %s\n", fname, strerror(errno));
|
|
|
|
error = true;
|
|
|
|
}
|
|
|
|
}
|
2000-03-27 23:11:37 +02:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
return !error;
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* process_file
|
|
|
|
*
|
2013-09-18 18:58:32 +02:00
|
|
|
* Reads commands from filename and passes them to the main processing loop.
|
2011-07-06 17:45:13 +02:00
|
|
|
* Handler for \i and \ir, but can be used for other things as well. Returns
|
2005-09-20 20:59:02 +02:00
|
|
|
* MainLoop() error code.
|
2011-07-06 17:45:13 +02:00
|
|
|
*
|
|
|
|
* If use_relative_path is true and filename is not an absolute path, then open
|
|
|
|
* the file from where the currently processed file (if any) is located.
|
1999-11-04 22:56:02 +01:00
|
|
|
*/
|
2000-02-20 15:28:28 +01:00
|
|
|
int
|
2015-12-08 20:04:08 +01:00
|
|
|
process_file(char *filename, bool use_relative_path)
|
1999-11-04 22:56:02 +01:00
|
|
|
{
|
1999-11-05 00:14:30 +01:00
|
|
|
FILE *fd;
|
|
|
|
int result;
|
2000-04-12 19:17:23 +02:00
|
|
|
char *oldfilename;
|
2011-07-06 17:45:13 +02:00
|
|
|
char relpath[MAXPGPATH];
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (!filename)
|
2012-08-09 15:59:45 +02:00
|
|
|
{
|
|
|
|
fd = stdin;
|
|
|
|
filename = NULL;
|
|
|
|
}
|
|
|
|
else if (strcmp(filename, "-") != 0)
|
2009-12-01 23:34:33 +01:00
|
|
|
{
|
|
|
|
canonicalize_path(filename);
|
2011-07-06 17:45:13 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we were asked to resolve the pathname relative to the location
|
2012-06-10 21:20:04 +02:00
|
|
|
* of the currently executing script, and there is one, and this is a
|
|
|
|
* relative pathname, then prepend all but the last pathname component
|
|
|
|
* of the current script to this pathname.
|
2011-07-06 17:45:13 +02:00
|
|
|
*/
|
2012-07-05 23:15:05 +02:00
|
|
|
if (use_relative_path && pset.inputfile &&
|
|
|
|
!is_absolute_path(filename) && !has_drive_prefix(filename))
|
2011-07-06 17:45:13 +02:00
|
|
|
{
|
2012-07-05 23:15:05 +02:00
|
|
|
strlcpy(relpath, pset.inputfile, sizeof(relpath));
|
2011-07-06 17:45:13 +02:00
|
|
|
get_parent_directory(relpath);
|
|
|
|
join_path_components(relpath, relpath, filename);
|
|
|
|
canonicalize_path(relpath);
|
|
|
|
|
|
|
|
filename = relpath;
|
|
|
|
}
|
|
|
|
|
2009-12-01 23:34:33 +01:00
|
|
|
fd = fopen(filename, PG_BINARY_R);
|
2012-03-01 18:58:10 +01:00
|
|
|
|
|
|
|
if (!fd)
|
|
|
|
{
|
|
|
|
psql_error("%s: %s\n", filename, strerror(errno));
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2009-12-01 23:34:33 +01:00
|
|
|
}
|
|
|
|
else
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2012-03-01 18:58:10 +01:00
|
|
|
fd = stdin;
|
|
|
|
filename = "<stdin>"; /* for future error messages */
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
oldfilename = pset.inputfile;
|
|
|
|
pset.inputfile = filename;
|
2006-02-12 05:04:32 +01:00
|
|
|
|
2000-01-19 00:30:24 +01:00
|
|
|
result = MainLoop(fd);
|
2010-03-09 00:03:00 +01:00
|
|
|
|
2010-10-27 01:28:18 +02:00
|
|
|
if (fd != stdin)
|
|
|
|
fclose(fd);
|
|
|
|
|
2000-01-23 02:27:39 +01:00
|
|
|
pset.inputfile = oldfilename;
|
2000-02-20 15:28:28 +01:00
|
|
|
return result;
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
_align2string(enum printFormat in)
|
|
|
|
{
|
1999-11-05 00:14:30 +01:00
|
|
|
switch (in)
|
|
|
|
{
|
2001-10-25 07:50:21 +02:00
|
|
|
case PRINT_NOTHING:
|
1999-11-05 00:14:30 +01:00
|
|
|
return "nothing";
|
|
|
|
break;
|
|
|
|
case PRINT_ALIGNED:
|
|
|
|
return "aligned";
|
|
|
|
break;
|
2018-11-06 07:04:40 +01:00
|
|
|
case PRINT_ASCIIDOC:
|
|
|
|
return "asciidoc";
|
2008-05-08 19:04:26 +02:00
|
|
|
break;
|
2018-11-26 21:18:55 +01:00
|
|
|
case PRINT_CSV:
|
|
|
|
return "csv";
|
|
|
|
break;
|
1999-11-05 00:14:30 +01:00
|
|
|
case PRINT_HTML:
|
|
|
|
return "html";
|
|
|
|
break;
|
|
|
|
case PRINT_LATEX:
|
|
|
|
return "latex";
|
|
|
|
break;
|
2013-01-17 17:39:38 +01:00
|
|
|
case PRINT_LATEX_LONGTABLE:
|
|
|
|
return "latex-longtable";
|
|
|
|
break;
|
2005-06-09 17:27:27 +02:00
|
|
|
case PRINT_TROFF_MS:
|
|
|
|
return "troff-ms";
|
|
|
|
break;
|
2018-11-06 07:04:40 +01:00
|
|
|
case PRINT_UNALIGNED:
|
|
|
|
return "unaligned";
|
|
|
|
break;
|
|
|
|
case PRINT_WRAPPED:
|
|
|
|
return "wrapped";
|
|
|
|
break;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
|
|
|
return "unknown";
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
2014-09-12 18:04:37 +02:00
|
|
|
/*
|
2015-12-03 16:23:59 +01:00
|
|
|
* Parse entered Unicode linestyle. If ok, update *linestyle and return
|
2015-11-03 17:49:21 +01:00
|
|
|
* true, else return false.
|
2014-09-12 18:04:37 +02:00
|
|
|
*/
|
|
|
|
static bool
|
2015-11-03 17:49:21 +01:00
|
|
|
set_unicode_line_style(const char *value, size_t vallen,
|
2014-09-12 18:04:37 +02:00
|
|
|
unicode_linestyle *linestyle)
|
|
|
|
{
|
|
|
|
if (pg_strncasecmp("single", value, vallen) == 0)
|
|
|
|
*linestyle = UNICODE_LINESTYLE_SINGLE;
|
|
|
|
else if (pg_strncasecmp("double", value, vallen) == 0)
|
|
|
|
*linestyle = UNICODE_LINESTYLE_DOUBLE;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
_unicode_linestyle2string(int linestyle)
|
|
|
|
{
|
|
|
|
switch (linestyle)
|
|
|
|
{
|
|
|
|
case UNICODE_LINESTYLE_SINGLE:
|
|
|
|
return "single";
|
|
|
|
break;
|
|
|
|
case UNICODE_LINESTYLE_DOUBLE:
|
|
|
|
return "double";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return "unknown";
|
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2014-10-19 03:58:17 +02:00
|
|
|
/*
|
|
|
|
* do_pset
|
|
|
|
*
|
|
|
|
*/
|
1999-11-04 22:56:02 +01:00
|
|
|
bool
|
2000-04-12 19:17:23 +02:00
|
|
|
do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
|
1999-11-04 22:56:02 +01:00
|
|
|
{
|
1999-11-05 00:14:30 +01:00
|
|
|
size_t vallen = 0;
|
|
|
|
|
2012-12-15 00:03:07 +01:00
|
|
|
Assert(param != NULL);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (value)
|
|
|
|
vallen = strlen(value);
|
|
|
|
|
|
|
|
/* set format */
|
|
|
|
if (strcmp(param, "format") == 0)
|
|
|
|
{
|
2018-11-14 22:39:59 +01:00
|
|
|
static const struct fmt
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
enum printFormat number;
|
|
|
|
} formats[] =
|
|
|
|
{
|
|
|
|
/* remember to update error message below when adding more */
|
|
|
|
{"aligned", PRINT_ALIGNED},
|
|
|
|
{"asciidoc", PRINT_ASCIIDOC},
|
2018-11-26 21:18:55 +01:00
|
|
|
{"csv", PRINT_CSV},
|
2018-11-14 22:39:59 +01:00
|
|
|
{"html", PRINT_HTML},
|
|
|
|
{"latex", PRINT_LATEX},
|
|
|
|
{"troff-ms", PRINT_TROFF_MS},
|
|
|
|
{"unaligned", PRINT_UNALIGNED},
|
|
|
|
{"wrapped", PRINT_WRAPPED}
|
|
|
|
};
|
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (!value)
|
|
|
|
;
|
|
|
|
else
|
|
|
|
{
|
2018-11-14 22:39:59 +01:00
|
|
|
int match_pos = -1;
|
|
|
|
|
|
|
|
for (int i = 0; i < lengthof(formats); i++)
|
|
|
|
{
|
|
|
|
if (pg_strncasecmp(formats[i].name, value, vallen) == 0)
|
|
|
|
{
|
|
|
|
if (match_pos < 0)
|
|
|
|
match_pos = i;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
psql_error("\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"\n",
|
|
|
|
value,
|
|
|
|
formats[match_pos].name, formats[i].name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-26 18:31:20 +01:00
|
|
|
if (match_pos >= 0)
|
|
|
|
popt->topt.format = formats[match_pos].number;
|
|
|
|
else if (pg_strncasecmp("latex-longtable", value, vallen) == 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We must treat latex-longtable specially because latex is a
|
|
|
|
* prefix of it; if both were in the table above, we'd think
|
|
|
|
* "latex" is ambiguous.
|
|
|
|
*/
|
|
|
|
popt->topt.format = PRINT_LATEX_LONGTABLE;
|
|
|
|
}
|
|
|
|
else
|
2018-11-14 22:39:59 +01:00
|
|
|
{
|
2018-11-26 21:18:55 +01:00
|
|
|
psql_error("\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped\n");
|
2018-11-14 22:39:59 +01:00
|
|
|
return false;
|
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
2009-10-13 23:04:01 +02:00
|
|
|
/* set table line style */
|
|
|
|
else if (strcmp(param, "linestyle") == 0)
|
|
|
|
{
|
|
|
|
if (!value)
|
|
|
|
;
|
|
|
|
else if (pg_strncasecmp("ascii", value, vallen) == 0)
|
|
|
|
popt->topt.line_style = &pg_asciiformat;
|
2009-11-22 06:20:41 +01:00
|
|
|
else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
|
|
|
|
popt->topt.line_style = &pg_asciiformat_old;
|
2009-10-13 23:04:01 +02:00
|
|
|
else if (pg_strncasecmp("unicode", value, vallen) == 0)
|
|
|
|
popt->topt.line_style = &pg_utf8format;
|
|
|
|
else
|
|
|
|
{
|
2009-11-22 06:20:41 +01:00
|
|
|
psql_error("\\pset: allowed line styles are ascii, old-ascii, unicode\n");
|
2009-10-13 23:04:01 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-12 18:04:37 +02:00
|
|
|
/* set unicode border line style */
|
|
|
|
else if (strcmp(param, "unicode_border_linestyle") == 0)
|
|
|
|
{
|
|
|
|
if (!value)
|
|
|
|
;
|
2015-11-03 17:49:21 +01:00
|
|
|
else if (set_unicode_line_style(value, vallen,
|
|
|
|
&popt->topt.unicode_border_linestyle))
|
|
|
|
refresh_utf8format(&(popt->topt));
|
|
|
|
else
|
2014-09-12 18:04:37 +02:00
|
|
|
{
|
2015-12-03 16:23:59 +01:00
|
|
|
psql_error("\\pset: allowed Unicode border line styles are single, double\n");
|
2014-09-12 18:04:37 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set unicode column line style */
|
|
|
|
else if (strcmp(param, "unicode_column_linestyle") == 0)
|
|
|
|
{
|
|
|
|
if (!value)
|
|
|
|
;
|
2015-11-03 17:49:21 +01:00
|
|
|
else if (set_unicode_line_style(value, vallen,
|
|
|
|
&popt->topt.unicode_column_linestyle))
|
|
|
|
refresh_utf8format(&(popt->topt));
|
|
|
|
else
|
2014-09-12 18:04:37 +02:00
|
|
|
{
|
2015-12-03 16:23:59 +01:00
|
|
|
psql_error("\\pset: allowed Unicode column line styles are single, double\n");
|
2014-09-12 18:04:37 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set unicode header line style */
|
|
|
|
else if (strcmp(param, "unicode_header_linestyle") == 0)
|
|
|
|
{
|
|
|
|
if (!value)
|
|
|
|
;
|
2015-11-03 17:49:21 +01:00
|
|
|
else if (set_unicode_line_style(value, vallen,
|
|
|
|
&popt->topt.unicode_header_linestyle))
|
|
|
|
refresh_utf8format(&(popt->topt));
|
|
|
|
else
|
2014-09-12 18:04:37 +02:00
|
|
|
{
|
2015-12-03 16:23:59 +01:00
|
|
|
psql_error("\\pset: allowed Unicode header line styles are single, double\n");
|
2014-09-12 18:04:37 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
/* set border style/width */
|
|
|
|
else if (strcmp(param, "border") == 0)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
popt->topt.border = atoi(value);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
|
|
|
|
/* set expanded/vertical mode */
|
Improve consistency of parsing of psql's magic variables.
For simple boolean variables such as ON_ERROR_STOP, psql has for a long
time recognized variant spellings of "on" and "off" (such as "1"/"0"),
and it also made a point of warning you if you'd misspelled the setting.
But these conveniences did not exist for other keyword-valued variables.
In particular, though ECHO_HIDDEN and ON_ERROR_ROLLBACK include "on" and
"off" as possible values, none of the alternative spellings for those were
recognized; and to make matters worse the code would just silently assume
"on" was meant for any unrecognized spelling. Several people have reported
getting bitten by this, so let's fix it. In detail, this patch:
* Allows all spellings recognized by ParseVariableBool() for ECHO_HIDDEN
and ON_ERROR_ROLLBACK.
* Reports a warning for unrecognized values for COMP_KEYWORD_CASE, ECHO,
ECHO_HIDDEN, HISTCONTROL, ON_ERROR_ROLLBACK, and VERBOSITY.
* Recognizes all values for all these variables case-insensitively;
previously there was a mishmash of case-sensitive and case-insensitive
behaviors.
Back-patch to all supported branches. There is a small risk of breaking
existing scripts that were accidentally failing to malfunction; but the
consensus is that the chance of detecting real problems and preventing
future mistakes outweighs this.
2014-12-31 18:16:53 +01:00
|
|
|
else if (strcmp(param, "x") == 0 ||
|
|
|
|
strcmp(param, "expanded") == 0 ||
|
|
|
|
strcmp(param, "vertical") == 0)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
2011-11-12 16:03:10 +01:00
|
|
|
if (value && pg_strcasecmp(value, "auto") == 0)
|
|
|
|
popt->topt.expanded = 2;
|
|
|
|
else if (value)
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
{
|
|
|
|
bool on_off;
|
|
|
|
|
|
|
|
if (ParseVariableBool(value, NULL, &on_off))
|
|
|
|
popt->topt.expanded = on_off ? 1 : 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PsqlVarEnumError(param, value, "on, off, auto");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2007-03-03 18:19:11 +01:00
|
|
|
else
|
|
|
|
popt->topt.expanded = !popt->topt.expanded;
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
2018-11-26 21:18:55 +01:00
|
|
|
/* field separator for CSV format */
|
|
|
|
else if (strcmp(param, "csv_fieldsep") == 0)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
{
|
|
|
|
/* CSV separator has to be a one-byte character */
|
|
|
|
if (strlen(value) != 1)
|
|
|
|
{
|
|
|
|
psql_error("\\pset: csv_fieldsep must be a single one-byte character\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (value[0] == '"' || value[0] == '\n' || value[0] == '\r')
|
|
|
|
{
|
|
|
|
psql_error("\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
popt->topt.csvFieldSep[0] = value[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-18 22:57:53 +02:00
|
|
|
/* locale-aware numeric output */
|
|
|
|
else if (strcmp(param, "numericlocale") == 0)
|
2005-07-10 05:46:13 +02:00
|
|
|
{
|
2007-03-03 18:19:11 +01:00
|
|
|
if (value)
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
return ParseVariableBool(value, param, &popt->topt.numericLocale);
|
2007-03-03 18:19:11 +01:00
|
|
|
else
|
|
|
|
popt->topt.numericLocale = !popt->topt.numericLocale;
|
2005-07-10 05:46:13 +02:00
|
|
|
}
|
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
/* null display */
|
|
|
|
else if (strcmp(param, "null") == 0)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
{
|
|
|
|
free(popt->nullPrint);
|
2004-01-25 04:07:22 +01:00
|
|
|
popt->nullPrint = pg_strdup(value);
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
/* field separator for unaligned text */
|
|
|
|
else if (strcmp(param, "fieldsep") == 0)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
{
|
2012-02-09 19:15:48 +01:00
|
|
|
free(popt->topt.fieldSep.separator);
|
|
|
|
popt->topt.fieldSep.separator = pg_strdup(value);
|
|
|
|
popt->topt.fieldSep.separator_zero = false;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
2012-02-09 19:15:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (strcmp(param, "fieldsep_zero") == 0)
|
|
|
|
{
|
|
|
|
free(popt->topt.fieldSep.separator);
|
|
|
|
popt->topt.fieldSep.separator = NULL;
|
|
|
|
popt->topt.fieldSep.separator_zero = true;
|
2000-01-19 00:30:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* record separator for unaligned text */
|
|
|
|
else if (strcmp(param, "recordsep") == 0)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
{
|
2012-02-09 19:15:48 +01:00
|
|
|
free(popt->topt.recordSep.separator);
|
|
|
|
popt->topt.recordSep.separator = pg_strdup(value);
|
|
|
|
popt->topt.recordSep.separator_zero = false;
|
2000-01-19 00:30:24 +01:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2012-02-09 19:15:48 +01:00
|
|
|
else if (strcmp(param, "recordsep_zero") == 0)
|
|
|
|
{
|
|
|
|
free(popt->topt.recordSep.separator);
|
|
|
|
popt->topt.recordSep.separator = NULL;
|
|
|
|
popt->topt.recordSep.separator_zero = true;
|
|
|
|
}
|
|
|
|
|
2005-07-14 08:49:58 +02:00
|
|
|
/* toggle between full and tuples-only format */
|
1999-11-05 00:14:30 +01:00
|
|
|
else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
|
|
|
|
{
|
2007-03-03 18:19:11 +01:00
|
|
|
if (value)
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
return ParseVariableBool(value, param, &popt->topt.tuples_only);
|
2007-03-03 18:19:11 +01:00
|
|
|
else
|
|
|
|
popt->topt.tuples_only = !popt->topt.tuples_only;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* set title override */
|
2015-10-06 02:56:38 +02:00
|
|
|
else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
|
1999-11-05 00:14:30 +01:00
|
|
|
{
|
|
|
|
free(popt->title);
|
|
|
|
if (!value)
|
|
|
|
popt->title = NULL;
|
|
|
|
else
|
2004-01-25 04:07:22 +01:00
|
|
|
popt->title = pg_strdup(value);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
|
|
|
|
/* set HTML table tag options */
|
|
|
|
else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
|
|
|
|
{
|
|
|
|
free(popt->topt.tableAttr);
|
|
|
|
if (!value)
|
|
|
|
popt->topt.tableAttr = NULL;
|
|
|
|
else
|
2004-01-25 04:07:22 +01:00
|
|
|
popt->topt.tableAttr = pg_strdup(value);
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
/* toggle use of pager */
|
|
|
|
else if (strcmp(param, "pager") == 0)
|
|
|
|
{
|
2004-05-07 02:24:59 +02:00
|
|
|
if (value && pg_strcasecmp(value, "always") == 0)
|
2003-08-04 02:43:34 +02:00
|
|
|
popt->topt.pager = 2;
|
2007-03-03 18:19:11 +01:00
|
|
|
else if (value)
|
Improve consistency of parsing of psql's magic variables.
For simple boolean variables such as ON_ERROR_STOP, psql has for a long
time recognized variant spellings of "on" and "off" (such as "1"/"0"),
and it also made a point of warning you if you'd misspelled the setting.
But these conveniences did not exist for other keyword-valued variables.
In particular, though ECHO_HIDDEN and ON_ERROR_ROLLBACK include "on" and
"off" as possible values, none of the alternative spellings for those were
recognized; and to make matters worse the code would just silently assume
"on" was meant for any unrecognized spelling. Several people have reported
getting bitten by this, so let's fix it. In detail, this patch:
* Allows all spellings recognized by ParseVariableBool() for ECHO_HIDDEN
and ON_ERROR_ROLLBACK.
* Reports a warning for unrecognized values for COMP_KEYWORD_CASE, ECHO,
ECHO_HIDDEN, HISTCONTROL, ON_ERROR_ROLLBACK, and VERBOSITY.
* Recognizes all values for all these variables case-insensitively;
previously there was a mishmash of case-sensitive and case-insensitive
behaviors.
Back-patch to all supported branches. There is a small risk of breaking
existing scripts that were accidentally failing to malfunction; but the
consensus is that the chance of detecting real problems and preventing
future mistakes outweighs this.
2014-12-31 18:16:53 +01:00
|
|
|
{
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
bool on_off;
|
|
|
|
|
|
|
|
if (!ParseVariableBool(value, NULL, &on_off))
|
|
|
|
{
|
|
|
|
PsqlVarEnumError(param, value, "on, off, always");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
popt->topt.pager = on_off ? 1 : 0;
|
Improve consistency of parsing of psql's magic variables.
For simple boolean variables such as ON_ERROR_STOP, psql has for a long
time recognized variant spellings of "on" and "off" (such as "1"/"0"),
and it also made a point of warning you if you'd misspelled the setting.
But these conveniences did not exist for other keyword-valued variables.
In particular, though ECHO_HIDDEN and ON_ERROR_ROLLBACK include "on" and
"off" as possible values, none of the alternative spellings for those were
recognized; and to make matters worse the code would just silently assume
"on" was meant for any unrecognized spelling. Several people have reported
getting bitten by this, so let's fix it. In detail, this patch:
* Allows all spellings recognized by ParseVariableBool() for ECHO_HIDDEN
and ON_ERROR_ROLLBACK.
* Reports a warning for unrecognized values for COMP_KEYWORD_CASE, ECHO,
ECHO_HIDDEN, HISTCONTROL, ON_ERROR_ROLLBACK, and VERBOSITY.
* Recognizes all values for all these variables case-insensitively;
previously there was a mishmash of case-sensitive and case-insensitive
behaviors.
Back-patch to all supported branches. There is a small risk of breaking
existing scripts that were accidentally failing to malfunction; but the
consensus is that the chance of detecting real problems and preventing
future mistakes outweighs this.
2014-12-31 18:16:53 +01:00
|
|
|
}
|
2002-11-08 20:12:21 +01:00
|
|
|
else if (popt->topt.pager == 1)
|
2003-08-04 02:43:34 +02:00
|
|
|
popt->topt.pager = 0;
|
2002-11-08 20:12:21 +01:00
|
|
|
else
|
2003-08-04 02:43:34 +02:00
|
|
|
popt->topt.pager = 1;
|
1999-11-05 00:14:30 +01:00
|
|
|
}
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2015-03-28 16:07:41 +01:00
|
|
|
/* set minimum lines for pager use */
|
|
|
|
else if (strcmp(param, "pager_min_lines") == 0)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
popt->topt.pager_min_lines = atoi(value);
|
|
|
|
}
|
|
|
|
|
2001-05-12 21:44:46 +02:00
|
|
|
/* disable "(x rows)" footer */
|
|
|
|
else if (strcmp(param, "footer") == 0)
|
|
|
|
{
|
2007-03-03 18:19:11 +01:00
|
|
|
if (value)
|
Make psql reject attempts to set special variables to invalid values.
Previously, if the user set a special variable such as ECHO to an
unrecognized value, psql would bleat but store the new value anyway, and
then fall back to a default setting for the behavior controlled by the
variable. This was agreed to be a not particularly good idea. With
this patch, invalid values result in an error message and no change in
state.
(But this applies only to variables that affect psql's behavior; purely
informational variables such as ENCODING can still be set to random
values.)
To do this, modify the API for psql's assign-hook functions so that they
can return an OK/not OK result, and give them the responsibility for
printing error messages when they reject a value. Adjust the APIs for
ParseVariableBool and ParseVariableNum to support the new behavior
conveniently.
In passing, document the variable VERSION, which had somehow escaped that.
And improve the quite-inadequate commenting in psql/variables.c.
Daniel Vérité, reviewed by Rahila Syed, some further tweaking by me
Discussion: https://postgr.es/m/7356e741-fa59-4146-a8eb-cf95fd6b21fb@mm
2017-01-30 22:37:15 +01:00
|
|
|
return ParseVariableBool(value, param, &popt->topt.default_footer);
|
2007-03-03 18:19:11 +01:00
|
|
|
else
|
2012-05-01 22:03:45 +02:00
|
|
|
popt->topt.default_footer = !popt->topt.default_footer;
|
2001-05-12 21:44:46 +02:00
|
|
|
}
|
1999-11-05 00:14:30 +01:00
|
|
|
|
2008-05-08 19:04:26 +02:00
|
|
|
/* set border style/width */
|
|
|
|
else if (strcmp(param, "columns") == 0)
|
|
|
|
{
|
|
|
|
if (value)
|
|
|
|
popt->topt.columns = atoi(value);
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
psql_error("\\pset: unknown option: %s\n", param);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-10 15:20:52 +01:00
|
|
|
if (!quiet)
|
|
|
|
printPsetInfo(param, &pset.popt);
|
2013-10-03 21:18:02 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
printPsetInfo(const char *param, struct printQueryOpt *popt)
|
|
|
|
{
|
|
|
|
Assert(param != NULL);
|
|
|
|
|
|
|
|
/* show border style/width */
|
|
|
|
if (strcmp(param, "border") == 0)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Border style is %d.\n"), popt->topt.border);
|
2013-10-03 21:18:02 +02:00
|
|
|
|
|
|
|
/* show the target width for the wrapped format */
|
|
|
|
else if (strcmp(param, "columns") == 0)
|
|
|
|
{
|
|
|
|
if (!popt->topt.columns)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Target width is unset.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Target width is %d.\n"), popt->topt.columns);
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* show expanded/vertical mode */
|
|
|
|
else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
|
|
|
|
{
|
|
|
|
if (popt->topt.expanded == 1)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Expanded display is on.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else if (popt->topt.expanded == 2)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Expanded display is used automatically.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Expanded display is off.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
2018-11-26 21:18:55 +01:00
|
|
|
/* show field separator for CSV format */
|
|
|
|
else if (strcmp(param, "csv_fieldsep") == 0)
|
|
|
|
{
|
|
|
|
printf(_("Field separator for CSV is \"%s\".\n"),
|
|
|
|
popt->topt.csvFieldSep);
|
|
|
|
}
|
|
|
|
|
2013-10-03 21:18:02 +02:00
|
|
|
/* show field separator for unaligned text */
|
|
|
|
else if (strcmp(param, "fieldsep") == 0)
|
|
|
|
{
|
|
|
|
if (popt->topt.fieldSep.separator_zero)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Field separator is zero byte.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Field separator is \"%s\".\n"),
|
2014-05-06 18:12:18 +02:00
|
|
|
popt->topt.fieldSep.separator);
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (strcmp(param, "fieldsep_zero") == 0)
|
|
|
|
{
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Field separator is zero byte.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* show disable "(x rows)" footer */
|
|
|
|
else if (strcmp(param, "footer") == 0)
|
|
|
|
{
|
|
|
|
if (popt->topt.default_footer)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Default footer is on.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Default footer is off.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* show format */
|
|
|
|
else if (strcmp(param, "format") == 0)
|
|
|
|
{
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* show table line style */
|
|
|
|
else if (strcmp(param, "linestyle") == 0)
|
|
|
|
{
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Line style is %s.\n"),
|
2014-05-06 18:12:18 +02:00
|
|
|
get_line_style(&popt->topt)->name);
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* show null display */
|
|
|
|
else if (strcmp(param, "null") == 0)
|
|
|
|
{
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Null display is \"%s\".\n"),
|
2014-05-06 18:12:18 +02:00
|
|
|
popt->nullPrint ? popt->nullPrint : "");
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* show locale-aware numeric output */
|
|
|
|
else if (strcmp(param, "numericlocale") == 0)
|
|
|
|
{
|
|
|
|
if (popt->topt.numericLocale)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Locale-adjusted numeric output is on.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Locale-adjusted numeric output is off.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* show toggle use of pager */
|
|
|
|
else if (strcmp(param, "pager") == 0)
|
|
|
|
{
|
|
|
|
if (popt->topt.pager == 1)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Pager is used for long output.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else if (popt->topt.pager == 2)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Pager is always used.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Pager usage is off.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
2015-03-28 16:07:41 +01:00
|
|
|
/* show minimum lines for pager use */
|
|
|
|
else if (strcmp(param, "pager_min_lines") == 0)
|
|
|
|
{
|
2015-10-29 01:23:53 +01:00
|
|
|
printf(ngettext("Pager won't be used for less than %d line.\n",
|
|
|
|
"Pager won't be used for less than %d lines.\n",
|
|
|
|
popt->topt.pager_min_lines),
|
2015-03-28 16:07:41 +01:00
|
|
|
popt->topt.pager_min_lines);
|
|
|
|
}
|
|
|
|
|
2013-10-03 21:18:02 +02:00
|
|
|
/* show record separator for unaligned text */
|
|
|
|
else if (strcmp(param, "recordsep") == 0)
|
|
|
|
{
|
|
|
|
if (popt->topt.recordSep.separator_zero)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Record separator is zero byte.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else if (strcmp(popt->topt.recordSep.separator, "\n") == 0)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Record separator is <newline>.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Record separator is \"%s\".\n"),
|
2014-05-06 18:12:18 +02:00
|
|
|
popt->topt.recordSep.separator);
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (strcmp(param, "recordsep_zero") == 0)
|
|
|
|
{
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Record separator is zero byte.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* show HTML table tag options */
|
|
|
|
else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
|
|
|
|
{
|
|
|
|
if (popt->topt.tableAttr)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Table attributes are \"%s\".\n"),
|
2014-05-06 18:12:18 +02:00
|
|
|
popt->topt.tableAttr);
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Table attributes unset.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
2008-05-08 19:04:26 +02:00
|
|
|
|
2013-10-03 21:18:02 +02:00
|
|
|
/* show title override */
|
2015-10-06 02:56:38 +02:00
|
|
|
else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
|
2013-10-03 21:18:02 +02:00
|
|
|
{
|
|
|
|
if (popt->title)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Title is \"%s\".\n"), popt->title);
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Title is unset.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* show toggle between full and tuples-only format */
|
|
|
|
else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
|
|
|
|
{
|
|
|
|
if (popt->topt.tuples_only)
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Tuples only is on.\n"));
|
2013-10-03 21:18:02 +02:00
|
|
|
else
|
2014-10-19 03:58:17 +02:00
|
|
|
printf(_("Tuples only is off.\n"));
|
2008-05-08 19:04:26 +02:00
|
|
|
}
|
|
|
|
|
2015-12-03 16:23:59 +01:00
|
|
|
/* Unicode style formatting */
|
2014-09-12 18:04:37 +02:00
|
|
|
else if (strcmp(param, "unicode_border_linestyle") == 0)
|
|
|
|
{
|
2015-12-03 16:23:59 +01:00
|
|
|
printf(_("Unicode border line style is \"%s\".\n"),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
_unicode_linestyle2string(popt->topt.unicode_border_linestyle));
|
2014-09-12 18:04:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (strcmp(param, "unicode_column_linestyle") == 0)
|
|
|
|
{
|
2015-12-03 16:23:59 +01:00
|
|
|
printf(_("Unicode column line style is \"%s\".\n"),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
_unicode_linestyle2string(popt->topt.unicode_column_linestyle));
|
2014-09-12 18:04:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (strcmp(param, "unicode_header_linestyle") == 0)
|
|
|
|
{
|
2015-12-03 16:23:59 +01:00
|
|
|
printf(_("Unicode header line style is \"%s\".\n"),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
_unicode_linestyle2string(popt->topt.unicode_header_linestyle));
|
2014-09-12 18:04:37 +02:00
|
|
|
}
|
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
else
|
|
|
|
{
|
2000-01-19 00:30:24 +01:00
|
|
|
psql_error("\\pset: unknown option: %s\n", param);
|
1999-11-05 00:14:30 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-19 03:58:17 +02:00
|
|
|
static const char *
|
|
|
|
pset_bool_string(bool val)
|
|
|
|
{
|
|
|
|
return val ? "on" : "off";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
pset_quoted_string(const char *str)
|
|
|
|
{
|
2014-10-27 00:17:55 +01:00
|
|
|
char *ret = pg_malloc(strlen(str) * 2 + 3);
|
2014-10-19 03:58:17 +02:00
|
|
|
char *r = ret;
|
|
|
|
|
|
|
|
*r++ = '\'';
|
|
|
|
|
|
|
|
for (; *str; str++)
|
|
|
|
{
|
|
|
|
if (*str == '\n')
|
|
|
|
{
|
|
|
|
*r++ = '\\';
|
|
|
|
*r++ = 'n';
|
|
|
|
}
|
|
|
|
else if (*str == '\'')
|
|
|
|
{
|
|
|
|
*r++ = '\\';
|
|
|
|
*r++ = '\'';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*r++ = *str;
|
|
|
|
}
|
|
|
|
|
|
|
|
*r++ = '\'';
|
|
|
|
*r = '\0';
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return a malloc'ed string for the \pset value.
|
|
|
|
*
|
|
|
|
* Note that for some string parameters, print.c distinguishes between unset
|
|
|
|
* and empty string, but for others it doesn't. This function should produce
|
|
|
|
* output that produces the correct setting when fed back into \pset.
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
pset_value_string(const char *param, struct printQueryOpt *popt)
|
|
|
|
{
|
|
|
|
Assert(param != NULL);
|
|
|
|
|
|
|
|
if (strcmp(param, "border") == 0)
|
|
|
|
return psprintf("%d", popt->topt.border);
|
|
|
|
else if (strcmp(param, "columns") == 0)
|
|
|
|
return psprintf("%d", popt->topt.columns);
|
2018-11-26 21:18:55 +01:00
|
|
|
else if (strcmp(param, "csv_fieldsep") == 0)
|
|
|
|
return pset_quoted_string(popt->topt.csvFieldSep);
|
2014-10-19 03:58:17 +02:00
|
|
|
else if (strcmp(param, "expanded") == 0)
|
|
|
|
return pstrdup(popt->topt.expanded == 2
|
|
|
|
? "auto"
|
|
|
|
: pset_bool_string(popt->topt.expanded));
|
|
|
|
else if (strcmp(param, "fieldsep") == 0)
|
|
|
|
return pset_quoted_string(popt->topt.fieldSep.separator
|
|
|
|
? popt->topt.fieldSep.separator
|
|
|
|
: "");
|
|
|
|
else if (strcmp(param, "fieldsep_zero") == 0)
|
|
|
|
return pstrdup(pset_bool_string(popt->topt.fieldSep.separator_zero));
|
|
|
|
else if (strcmp(param, "footer") == 0)
|
|
|
|
return pstrdup(pset_bool_string(popt->topt.default_footer));
|
|
|
|
else if (strcmp(param, "format") == 0)
|
|
|
|
return psprintf("%s", _align2string(popt->topt.format));
|
|
|
|
else if (strcmp(param, "linestyle") == 0)
|
|
|
|
return psprintf("%s", get_line_style(&popt->topt)->name);
|
|
|
|
else if (strcmp(param, "null") == 0)
|
|
|
|
return pset_quoted_string(popt->nullPrint
|
|
|
|
? popt->nullPrint
|
|
|
|
: "");
|
|
|
|
else if (strcmp(param, "numericlocale") == 0)
|
|
|
|
return pstrdup(pset_bool_string(popt->topt.numericLocale));
|
|
|
|
else if (strcmp(param, "pager") == 0)
|
|
|
|
return psprintf("%d", popt->topt.pager);
|
2015-03-28 16:07:41 +01:00
|
|
|
else if (strcmp(param, "pager_min_lines") == 0)
|
|
|
|
return psprintf("%d", popt->topt.pager_min_lines);
|
2014-10-19 03:58:17 +02:00
|
|
|
else if (strcmp(param, "recordsep") == 0)
|
|
|
|
return pset_quoted_string(popt->topt.recordSep.separator
|
|
|
|
? popt->topt.recordSep.separator
|
|
|
|
: "");
|
|
|
|
else if (strcmp(param, "recordsep_zero") == 0)
|
|
|
|
return pstrdup(pset_bool_string(popt->topt.recordSep.separator_zero));
|
|
|
|
else if (strcmp(param, "tableattr") == 0)
|
|
|
|
return popt->topt.tableAttr ? pset_quoted_string(popt->topt.tableAttr) : pstrdup("");
|
|
|
|
else if (strcmp(param, "title") == 0)
|
|
|
|
return popt->title ? pset_quoted_string(popt->title) : pstrdup("");
|
|
|
|
else if (strcmp(param, "tuples_only") == 0)
|
|
|
|
return pstrdup(pset_bool_string(popt->topt.tuples_only));
|
|
|
|
else if (strcmp(param, "unicode_border_linestyle") == 0)
|
|
|
|
return pstrdup(_unicode_linestyle2string(popt->topt.unicode_border_linestyle));
|
|
|
|
else if (strcmp(param, "unicode_column_linestyle") == 0)
|
|
|
|
return pstrdup(_unicode_linestyle2string(popt->topt.unicode_column_linestyle));
|
|
|
|
else if (strcmp(param, "unicode_header_linestyle") == 0)
|
|
|
|
return pstrdup(_unicode_linestyle2string(popt->topt.unicode_header_linestyle));
|
|
|
|
else
|
|
|
|
return pstrdup("ERROR");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-11-04 22:56:02 +01:00
|
|
|
|
2004-11-06 05:29:40 +01:00
|
|
|
#ifndef WIN32
|
2000-02-08 00:10:11 +01:00
|
|
|
#define DEFAULT_SHELL "/bin/sh"
|
2004-11-06 05:29:40 +01:00
|
|
|
#else
|
2004-11-06 18:56:40 +01:00
|
|
|
/*
|
|
|
|
* CMD.EXE is in different places in different Win32 releases so we
|
|
|
|
* have to rely on the path to find it.
|
|
|
|
*/
|
|
|
|
#define DEFAULT_SHELL "cmd.exe"
|
2004-11-06 05:29:40 +01:00
|
|
|
#endif
|
1999-11-04 22:56:02 +01:00
|
|
|
|
|
|
|
static bool
|
|
|
|
do_shell(const char *command)
|
|
|
|
{
|
1999-11-05 00:14:30 +01:00
|
|
|
int result;
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (!command)
|
|
|
|
{
|
|
|
|
char *sys;
|
2004-11-06 06:20:41 +01:00
|
|
|
const char *shellName;
|
1999-11-05 00:14:30 +01:00
|
|
|
|
2004-11-06 05:29:40 +01:00
|
|
|
shellName = getenv("SHELL");
|
2004-11-04 23:25:14 +01:00
|
|
|
#ifdef WIN32
|
|
|
|
if (shellName == NULL)
|
2004-11-06 05:29:40 +01:00
|
|
|
shellName = getenv("COMSPEC");
|
|
|
|
#endif
|
1999-11-05 00:14:30 +01:00
|
|
|
if (shellName == NULL)
|
|
|
|
shellName = DEFAULT_SHELL;
|
|
|
|
|
2012-04-24 04:43:09 +02:00
|
|
|
/* See EDITOR handling comment for an explanation */
|
2013-10-13 06:09:18 +02:00
|
|
|
#ifndef WIN32
|
2013-10-23 01:40:26 +02:00
|
|
|
sys = psprintf("exec %s", shellName);
|
2004-11-30 20:01:28 +01:00
|
|
|
#else
|
Replace SYSTEMQUOTEs with Windows-specific wrapper functions.
It's easy to forget using SYSTEMQUOTEs when constructing command strings
for system() or popen(). Even if we fix all the places missing it now, it is
bound to be forgotten again in the future. Introduce wrapper functions that
do the the extra quoting for you, and get rid of SYSTEMQUOTEs in all the
callers.
We previosly used SYSTEMQUOTEs in all the hard-coded command strings, and
this doesn't change the behavior of those. But user-supplied commands, like
archive_command, restore_command, COPY TO/FROM PROGRAM calls, as well as
pgbench's \shell, will now gain an extra pair of quotes. That is desirable,
but if you have existing scripts or config files that include an extra
pair of quotes, those might need to be adjusted.
Reviewed by Amit Kapila and Tom Lane
2014-05-05 15:07:40 +02:00
|
|
|
sys = psprintf("\"%s\"", shellName);
|
2004-11-30 20:01:28 +01:00
|
|
|
#endif
|
1999-11-05 00:14:30 +01:00
|
|
|
result = system(sys);
|
|
|
|
free(sys);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
result = system(command);
|
1999-11-04 22:56:02 +01:00
|
|
|
|
1999-11-05 00:14:30 +01:00
|
|
|
if (result == 127 || result == -1)
|
|
|
|
{
|
2000-04-12 19:17:23 +02:00
|
|
|
psql_error("\\!: failed\n");
|
1999-11-05 00:14:30 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
1999-11-04 22:56:02 +01:00
|
|
|
}
|
2008-09-06 02:01:25 +02:00
|
|
|
|
2013-04-05 01:56:33 +02:00
|
|
|
/*
|
|
|
|
* do_watch -- handler for \watch
|
|
|
|
*
|
|
|
|
* We break this out of exec_command to avoid having to plaster "volatile"
|
|
|
|
* onto a bunch of exec_command's variables to silence stupider compilers.
|
|
|
|
*/
|
|
|
|
static bool
|
2016-03-21 23:34:18 +01:00
|
|
|
do_watch(PQExpBuffer query_buf, double sleep)
|
2013-04-05 01:56:33 +02:00
|
|
|
{
|
2016-03-21 23:34:18 +01:00
|
|
|
long sleep_ms = (long) (sleep * 1000);
|
2013-04-05 01:56:33 +02:00
|
|
|
printQueryOpt myopt = pset.popt;
|
2016-06-16 01:31:08 +02:00
|
|
|
const char *strftime_fmt;
|
2016-03-21 23:18:13 +01:00
|
|
|
const char *user_title;
|
|
|
|
char *title;
|
|
|
|
int title_len;
|
|
|
|
int res = 0;
|
2013-04-05 01:56:33 +02:00
|
|
|
|
|
|
|
if (!query_buf || query_buf->len <= 0)
|
|
|
|
{
|
|
|
|
psql_error(_("\\watch cannot be used with an empty query\n"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-06-16 01:31:08 +02:00
|
|
|
/*
|
|
|
|
* Choose format for timestamps. We might eventually make this a \pset
|
|
|
|
* option. In the meantime, using a variable for the format suppresses
|
|
|
|
* overly-anal-retentive gcc warnings about %c being Y2K sensitive.
|
|
|
|
*/
|
|
|
|
strftime_fmt = "%c";
|
|
|
|
|
2013-04-05 01:56:33 +02:00
|
|
|
/*
|
|
|
|
* Set up rendering options, in particular, disable the pager, because
|
|
|
|
* nobody wants to be prompted while watching the output of 'watch'.
|
|
|
|
*/
|
|
|
|
myopt.topt.pager = 0;
|
|
|
|
|
2016-03-21 23:18:13 +01:00
|
|
|
/*
|
|
|
|
* If there's a title in the user configuration, make sure we have room
|
2016-06-16 01:31:08 +02:00
|
|
|
* for it in the title buffer. Allow 128 bytes for the timestamp plus 128
|
|
|
|
* bytes for the rest.
|
2016-03-21 23:18:13 +01:00
|
|
|
*/
|
|
|
|
user_title = myopt.title;
|
2016-06-16 01:31:08 +02:00
|
|
|
title_len = (user_title ? strlen(user_title) : 0) + 256;
|
2016-03-21 23:18:13 +01:00
|
|
|
title = pg_malloc(title_len);
|
|
|
|
|
2013-04-05 01:56:33 +02:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
time_t timer;
|
2016-06-16 01:31:08 +02:00
|
|
|
char timebuf[128];
|
2013-04-05 01:56:33 +02:00
|
|
|
long i;
|
|
|
|
|
|
|
|
/*
|
2016-03-21 23:18:13 +01:00
|
|
|
* Prepare title for output. Note that we intentionally include a
|
|
|
|
* newline at the end of the title; this is somewhat historical but it
|
|
|
|
* makes for reasonably nicely formatted output in simple cases.
|
2013-04-05 01:56:33 +02:00
|
|
|
*/
|
|
|
|
timer = time(NULL);
|
2016-06-16 01:31:08 +02:00
|
|
|
strftime(timebuf, sizeof(timebuf), strftime_fmt, localtime(&timer));
|
2016-03-21 23:18:13 +01:00
|
|
|
|
|
|
|
if (user_title)
|
2016-03-21 23:34:18 +01:00
|
|
|
snprintf(title, title_len, _("%s\t%s (every %gs)\n"),
|
2016-06-16 01:31:08 +02:00
|
|
|
user_title, timebuf, sleep);
|
2016-03-21 23:18:13 +01:00
|
|
|
else
|
2016-03-21 23:34:18 +01:00
|
|
|
snprintf(title, title_len, _("%s (every %gs)\n"),
|
2016-06-16 01:31:08 +02:00
|
|
|
timebuf, sleep);
|
2013-04-05 01:56:33 +02:00
|
|
|
myopt.title = title;
|
|
|
|
|
2014-09-04 05:31:48 +02:00
|
|
|
/* Run the query and print out the results */
|
|
|
|
res = PSQLexecWatch(query_buf->data, &myopt);
|
2013-04-05 01:56:33 +02:00
|
|
|
|
|
|
|
/*
|
2015-05-24 03:35:49 +02:00
|
|
|
* PSQLexecWatch handles the case where we can no longer repeat the
|
|
|
|
* query, and returns 0 or -1.
|
2013-04-05 01:56:33 +02:00
|
|
|
*/
|
2016-03-21 23:18:13 +01:00
|
|
|
if (res <= 0)
|
2013-04-05 01:56:33 +02:00
|
|
|
break;
|
2013-05-04 22:41:22 +02:00
|
|
|
|
2013-04-05 01:56:33 +02:00
|
|
|
/*
|
|
|
|
* Set up cancellation of 'watch' via SIGINT. We redo this each time
|
2014-09-04 05:31:48 +02:00
|
|
|
* through the loop since it's conceivable something inside
|
|
|
|
* PSQLexecWatch could change sigint_interrupt_jmp.
|
2013-04-05 01:56:33 +02:00
|
|
|
*/
|
|
|
|
if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable 'watch' cancellations and wait a while before running the
|
2016-03-21 23:34:18 +01:00
|
|
|
* query again. Break the sleep into short intervals (at most 1s)
|
|
|
|
* since pg_usleep isn't interruptible on some platforms.
|
2013-04-05 01:56:33 +02:00
|
|
|
*/
|
|
|
|
sigint_interrupt_enabled = true;
|
2016-03-21 23:34:18 +01:00
|
|
|
i = sleep_ms;
|
|
|
|
while (i > 0)
|
2013-04-05 01:56:33 +02:00
|
|
|
{
|
2016-03-21 23:34:18 +01:00
|
|
|
long s = Min(i, 1000L);
|
|
|
|
|
|
|
|
pg_usleep(s * 1000L);
|
2013-04-05 01:56:33 +02:00
|
|
|
if (cancel_pressed)
|
|
|
|
break;
|
2016-03-21 23:34:18 +01:00
|
|
|
i -= s;
|
2013-04-05 01:56:33 +02:00
|
|
|
}
|
|
|
|
sigint_interrupt_enabled = false;
|
|
|
|
}
|
|
|
|
|
2016-03-21 23:18:13 +01:00
|
|
|
pg_free(title);
|
|
|
|
return (res >= 0);
|
2013-04-05 01:56:33 +02:00
|
|
|
}
|
|
|
|
|
2014-11-22 15:39:01 +01:00
|
|
|
/*
|
|
|
|
* a little code borrowed from PSQLexec() to manage ECHO_HIDDEN output.
|
|
|
|
* returns true unless we have ECHO_HIDDEN_NOEXEC.
|
|
|
|
*/
|
|
|
|
static bool
|
2015-07-03 21:48:18 +02:00
|
|
|
echo_hidden_command(const char *query)
|
2014-11-22 15:39:01 +01:00
|
|
|
{
|
|
|
|
if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
|
|
|
|
{
|
|
|
|
printf(_("********* QUERY **********\n"
|
|
|
|
"%s\n"
|
|
|
|
"**************************\n\n"), query);
|
|
|
|
fflush(stdout);
|
|
|
|
if (pset.logfile)
|
|
|
|
{
|
|
|
|
fprintf(pset.logfile,
|
|
|
|
_("********* QUERY **********\n"
|
|
|
|
"%s\n"
|
|
|
|
"**************************\n\n"), query);
|
|
|
|
fflush(pset.logfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-09-06 02:01:25 +02:00
|
|
|
/*
|
2015-07-03 21:48:18 +02:00
|
|
|
* Look up the object identified by obj_type and desc. If successful,
|
2017-08-16 06:22:32 +02:00
|
|
|
* store its OID in *obj_oid and return true, else return false.
|
2015-07-03 21:48:18 +02:00
|
|
|
*
|
|
|
|
* Note that we'll fail if the object doesn't exist OR if there are multiple
|
|
|
|
* matching candidates OR if there's something syntactically wrong with the
|
|
|
|
* object description; unfortunately it can be hard to tell the difference.
|
2008-09-06 02:01:25 +02:00
|
|
|
*/
|
|
|
|
static bool
|
2015-07-03 21:48:18 +02:00
|
|
|
lookup_object_oid(EditableObjectType obj_type, const char *desc,
|
|
|
|
Oid *obj_oid)
|
2008-09-06 02:01:25 +02:00
|
|
|
{
|
|
|
|
bool result = true;
|
2015-07-03 21:48:18 +02:00
|
|
|
PQExpBuffer query = createPQExpBuffer();
|
2009-06-11 16:49:15 +02:00
|
|
|
PGresult *res;
|
2008-09-06 02:01:25 +02:00
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
switch (obj_type)
|
|
|
|
{
|
|
|
|
case EditableFunction:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have a function description, e.g. "x" or "x(int)". Issue a
|
|
|
|
* query to retrieve the function's OID using a cast to regproc or
|
|
|
|
* regprocedure (as appropriate).
|
|
|
|
*/
|
|
|
|
appendPQExpBufferStr(query, "SELECT ");
|
|
|
|
appendStringLiteralConn(query, desc, pset.db);
|
|
|
|
appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
|
|
|
|
strchr(desc, '(') ? "regprocedure" : "regproc");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EditableView:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert view name (possibly schema-qualified) to OID. Note:
|
|
|
|
* this code doesn't check if the relation is actually a view.
|
|
|
|
* We'll detect that in get_create_object_cmd().
|
|
|
|
*/
|
|
|
|
appendPQExpBufferStr(query, "SELECT ");
|
|
|
|
appendStringLiteralConn(query, desc, pset.db);
|
|
|
|
appendPQExpBuffer(query, "::pg_catalog.regclass::pg_catalog.oid");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!echo_hidden_command(query->data))
|
2014-11-23 19:47:08 +01:00
|
|
|
{
|
|
|
|
destroyPQExpBuffer(query);
|
2014-11-22 15:39:01 +01:00
|
|
|
return false;
|
2014-11-23 19:47:08 +01:00
|
|
|
}
|
2014-11-22 15:39:01 +01:00
|
|
|
res = PQexec(pset.db, query->data);
|
2008-09-06 02:01:25 +02:00
|
|
|
if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
|
2015-07-03 21:48:18 +02:00
|
|
|
*obj_oid = atooid(PQgetvalue(res, 0, 0));
|
2008-09-06 02:01:25 +02:00
|
|
|
else
|
2008-09-06 22:18:08 +02:00
|
|
|
{
|
|
|
|
minimal_error_message(res);
|
2008-09-06 02:01:25 +02:00
|
|
|
result = false;
|
2008-09-06 22:18:08 +02:00
|
|
|
}
|
2008-09-06 02:01:25 +02:00
|
|
|
|
|
|
|
PQclear(res);
|
|
|
|
destroyPQExpBuffer(query);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-07-03 21:48:18 +02:00
|
|
|
* Construct a "CREATE OR REPLACE ..." command that describes the specified
|
|
|
|
* database object. If successful, the result is stored in buf.
|
2008-09-06 02:01:25 +02:00
|
|
|
*/
|
|
|
|
static bool
|
2015-07-03 21:48:18 +02:00
|
|
|
get_create_object_cmd(EditableObjectType obj_type, Oid oid,
|
|
|
|
PQExpBuffer buf)
|
2008-09-06 02:01:25 +02:00
|
|
|
{
|
|
|
|
bool result = true;
|
2015-07-03 21:48:18 +02:00
|
|
|
PQExpBuffer query = createPQExpBuffer();
|
2009-06-11 16:49:15 +02:00
|
|
|
PGresult *res;
|
2008-09-06 02:01:25 +02:00
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
switch (obj_type)
|
|
|
|
{
|
|
|
|
case EditableFunction:
|
|
|
|
printfPQExpBuffer(query,
|
|
|
|
"SELECT pg_catalog.pg_get_functiondef(%u)",
|
|
|
|
oid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EditableView:
|
2008-09-06 02:01:25 +02:00
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
/*
|
|
|
|
* pg_get_viewdef() just prints the query, so we must prepend
|
|
|
|
* CREATE for ourselves. We must fully qualify the view name to
|
|
|
|
* ensure the right view gets replaced. Also, check relation kind
|
|
|
|
* to be sure it's a view.
|
2016-05-06 13:48:27 +02:00
|
|
|
*
|
|
|
|
* Starting with 9.2, views may have reloptions (security_barrier)
|
|
|
|
* and from 9.4 onwards they may also have WITH [LOCAL|CASCADED]
|
|
|
|
* CHECK OPTION. These are not part of the view definition
|
|
|
|
* returned by pg_get_viewdef() and so need to be retrieved
|
|
|
|
* separately. Materialized views (introduced in 9.3) may have
|
|
|
|
* arbitrary storage parameter reloptions.
|
2015-07-03 21:48:18 +02:00
|
|
|
*/
|
2016-05-06 13:48:27 +02:00
|
|
|
if (pset.sversion >= 90400)
|
|
|
|
{
|
|
|
|
printfPQExpBuffer(query,
|
|
|
|
"SELECT nspname, relname, relkind, "
|
|
|
|
"pg_catalog.pg_get_viewdef(c.oid, true), "
|
2018-12-03 06:21:52 +01:00
|
|
|
"pg_catalog.array_remove(pg_catalog.array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
|
2016-05-06 13:48:27 +02:00
|
|
|
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
|
|
|
|
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption "
|
|
|
|
"FROM pg_catalog.pg_class c "
|
|
|
|
"LEFT JOIN pg_catalog.pg_namespace n "
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
"ON c.relnamespace = n.oid WHERE c.oid = %u",
|
2016-05-06 13:48:27 +02:00
|
|
|
oid);
|
|
|
|
}
|
|
|
|
else if (pset.sversion >= 90200)
|
|
|
|
{
|
|
|
|
printfPQExpBuffer(query,
|
|
|
|
"SELECT nspname, relname, relkind, "
|
|
|
|
"pg_catalog.pg_get_viewdef(c.oid, true), "
|
|
|
|
"c.reloptions AS reloptions, "
|
|
|
|
"NULL AS checkoption "
|
|
|
|
"FROM pg_catalog.pg_class c "
|
|
|
|
"LEFT JOIN pg_catalog.pg_namespace n "
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
"ON c.relnamespace = n.oid WHERE c.oid = %u",
|
2016-05-06 13:48:27 +02:00
|
|
|
oid);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printfPQExpBuffer(query,
|
|
|
|
"SELECT nspname, relname, relkind, "
|
|
|
|
"pg_catalog.pg_get_viewdef(c.oid, true), "
|
|
|
|
"NULL AS reloptions, "
|
|
|
|
"NULL AS checkoption "
|
|
|
|
"FROM pg_catalog.pg_class c "
|
|
|
|
"LEFT JOIN pg_catalog.pg_namespace n "
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 21:35:54 +02:00
|
|
|
"ON c.relnamespace = n.oid WHERE c.oid = %u",
|
2016-05-06 13:48:27 +02:00
|
|
|
oid);
|
|
|
|
}
|
2015-07-03 21:48:18 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!echo_hidden_command(query->data))
|
2014-11-23 19:47:08 +01:00
|
|
|
{
|
|
|
|
destroyPQExpBuffer(query);
|
2014-11-22 15:39:01 +01:00
|
|
|
return false;
|
2014-11-23 19:47:08 +01:00
|
|
|
}
|
2014-11-22 15:39:01 +01:00
|
|
|
res = PQexec(pset.db, query->data);
|
2008-09-06 02:01:25 +02:00
|
|
|
if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
|
|
|
|
{
|
|
|
|
resetPQExpBuffer(buf);
|
2015-07-03 21:48:18 +02:00
|
|
|
switch (obj_type)
|
|
|
|
{
|
|
|
|
case EditableFunction:
|
|
|
|
appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EditableView:
|
|
|
|
{
|
|
|
|
char *nspname = PQgetvalue(res, 0, 0);
|
|
|
|
char *relname = PQgetvalue(res, 0, 1);
|
|
|
|
char *relkind = PQgetvalue(res, 0, 2);
|
|
|
|
char *viewdef = PQgetvalue(res, 0, 3);
|
2016-05-06 13:48:27 +02:00
|
|
|
char *reloptions = PQgetvalue(res, 0, 4);
|
|
|
|
char *checkoption = PQgetvalue(res, 0, 5);
|
2015-07-03 21:48:18 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the backend ever supports CREATE OR REPLACE
|
|
|
|
* MATERIALIZED VIEW, allow that here; but as of today it
|
|
|
|
* does not, so editing a matview definition in this way
|
|
|
|
* is impossible.
|
|
|
|
*/
|
|
|
|
switch (relkind[0])
|
|
|
|
{
|
|
|
|
#ifdef NOT_USED
|
2017-03-10 04:42:16 +01:00
|
|
|
case RELKIND_MATVIEW:
|
2015-07-03 21:48:18 +02:00
|
|
|
appendPQExpBufferStr(buf, "CREATE OR REPLACE MATERIALIZED VIEW ");
|
|
|
|
break;
|
|
|
|
#endif
|
2017-03-10 04:42:16 +01:00
|
|
|
case RELKIND_VIEW:
|
2015-07-03 21:48:18 +02:00
|
|
|
appendPQExpBufferStr(buf, "CREATE OR REPLACE VIEW ");
|
|
|
|
break;
|
|
|
|
default:
|
2016-05-22 04:17:00 +02:00
|
|
|
psql_error("\"%s.%s\" is not a view\n",
|
2015-07-03 21:48:18 +02:00
|
|
|
nspname, relname);
|
|
|
|
result = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
appendPQExpBuffer(buf, "%s.", fmtId(nspname));
|
2016-05-06 13:48:27 +02:00
|
|
|
appendPQExpBufferStr(buf, fmtId(relname));
|
|
|
|
|
|
|
|
/* reloptions, if not an empty array "{}" */
|
|
|
|
if (reloptions != NULL && strlen(reloptions) > 2)
|
|
|
|
{
|
|
|
|
appendPQExpBufferStr(buf, "\n WITH (");
|
|
|
|
if (!appendReloptionsArray(buf, reloptions, "",
|
|
|
|
pset.encoding,
|
|
|
|
standard_strings()))
|
|
|
|
{
|
2016-05-22 04:17:00 +02:00
|
|
|
psql_error("could not parse reloptions array\n");
|
2016-05-06 13:48:27 +02:00
|
|
|
result = false;
|
|
|
|
}
|
2017-08-16 05:34:39 +02:00
|
|
|
appendPQExpBufferChar(buf, ')');
|
2016-05-06 13:48:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* View definition from pg_get_viewdef (a SELECT query) */
|
|
|
|
appendPQExpBuffer(buf, " AS\n%s", viewdef);
|
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
/* Get rid of the semicolon that pg_get_viewdef appends */
|
|
|
|
if (buf->len > 0 && buf->data[buf->len - 1] == ';')
|
|
|
|
buf->data[--(buf->len)] = '\0';
|
2016-05-06 13:48:27 +02:00
|
|
|
|
|
|
|
/* WITH [LOCAL|CASCADED] CHECK OPTION */
|
|
|
|
if (checkoption && checkoption[0] != '\0')
|
|
|
|
appendPQExpBuffer(buf, "\n WITH %s CHECK OPTION",
|
|
|
|
checkoption);
|
2015-07-03 21:48:18 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Make sure result ends with a newline */
|
|
|
|
if (buf->len > 0 && buf->data[buf->len - 1] != '\n')
|
|
|
|
appendPQExpBufferChar(buf, '\n');
|
2008-09-06 02:01:25 +02:00
|
|
|
}
|
|
|
|
else
|
2008-09-06 22:18:08 +02:00
|
|
|
{
|
|
|
|
minimal_error_message(res);
|
2008-09-06 02:01:25 +02:00
|
|
|
result = false;
|
2008-09-06 22:18:08 +02:00
|
|
|
}
|
2008-09-06 02:01:25 +02:00
|
|
|
|
|
|
|
PQclear(res);
|
|
|
|
destroyPQExpBuffer(query);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2008-09-06 22:18:08 +02:00
|
|
|
|
2010-08-12 02:40:59 +02:00
|
|
|
/*
|
2015-07-03 21:48:18 +02:00
|
|
|
* If the given argument of \ef or \ev ends with a line number, delete the line
|
2010-08-12 02:40:59 +02:00
|
|
|
* number from the argument string and return it as an integer. (We need
|
2015-07-03 21:48:18 +02:00
|
|
|
* this kluge because we're too lazy to parse \ef's function or \ev's view
|
|
|
|
* argument carefully --- we just slop it up in OT_WHOLE_LINE mode.)
|
2010-08-12 02:40:59 +02:00
|
|
|
*
|
|
|
|
* Returns -1 if no line number is present, 0 on error, or a positive value
|
|
|
|
* on success.
|
|
|
|
*/
|
|
|
|
static int
|
2015-07-03 21:48:18 +02:00
|
|
|
strip_lineno_from_objdesc(char *obj)
|
2010-08-12 02:40:59 +02:00
|
|
|
{
|
|
|
|
char *c;
|
|
|
|
int lineno;
|
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
if (!obj || obj[0] == '\0')
|
2010-08-12 02:40:59 +02:00
|
|
|
return -1;
|
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
c = obj + strlen(obj) - 1;
|
2010-08-12 02:40:59 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This business of parsing backwards is dangerous as can be in a
|
|
|
|
* multibyte environment: there is no reason to believe that we are
|
|
|
|
* looking at the first byte of a character, nor are we necessarily
|
|
|
|
* working in a "safe" encoding. Fortunately the bitpatterns we are
|
2011-04-10 17:42:00 +02:00
|
|
|
* looking for are unlikely to occur as non-first bytes, but beware of
|
|
|
|
* trying to expand the set of cases that can be recognized. We must
|
2010-08-12 02:40:59 +02:00
|
|
|
* guard the <ctype.h> macros by using isascii() first, too.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* skip trailing whitespace */
|
2015-07-03 21:48:18 +02:00
|
|
|
while (c > obj && isascii((unsigned char) *c) && isspace((unsigned char) *c))
|
2010-08-12 02:40:59 +02:00
|
|
|
c--;
|
|
|
|
|
|
|
|
/* must have a digit as last non-space char */
|
2015-07-03 21:48:18 +02:00
|
|
|
if (c == obj || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c))
|
2010-08-12 02:40:59 +02:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* find start of digit string */
|
2015-07-03 21:48:18 +02:00
|
|
|
while (c > obj && isascii((unsigned char) *c) && isdigit((unsigned char) *c))
|
2010-08-12 02:40:59 +02:00
|
|
|
c--;
|
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
/* digits must be separated from object name by space or closing paren */
|
|
|
|
/* notice also that we are not allowing an empty object name ... */
|
|
|
|
if (c == obj || !isascii((unsigned char) *c) ||
|
2010-08-25 02:53:37 +02:00
|
|
|
!(isspace((unsigned char) *c) || *c == ')'))
|
2010-08-12 02:40:59 +02:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* parse digit string */
|
|
|
|
c++;
|
|
|
|
lineno = atoi(c);
|
|
|
|
if (lineno < 1)
|
|
|
|
{
|
|
|
|
psql_error("invalid line number: %s\n", c);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
/* strip digit string from object name */
|
2010-08-12 02:40:59 +02:00
|
|
|
*c = '\0';
|
|
|
|
|
|
|
|
return lineno;
|
|
|
|
}
|
|
|
|
|
2015-07-03 21:48:18 +02:00
|
|
|
/*
|
|
|
|
* Count number of lines in the buffer.
|
|
|
|
* This is used to test if pager is needed or not.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
count_lines_in_buf(PQExpBuffer buf)
|
|
|
|
{
|
|
|
|
int lineno = 0;
|
|
|
|
const char *lines = buf->data;
|
|
|
|
|
|
|
|
while (*lines != '\0')
|
|
|
|
{
|
|
|
|
lineno++;
|
|
|
|
/* find start of next line */
|
|
|
|
lines = strchr(lines, '\n');
|
|
|
|
if (!lines)
|
|
|
|
break;
|
|
|
|
lines++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return lineno;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write text at *lines to output with line numbers.
|
|
|
|
*
|
|
|
|
* If header_keyword isn't NULL, then line 1 should be the first line beginning
|
|
|
|
* with header_keyword; lines before that are unnumbered.
|
|
|
|
*
|
|
|
|
* Caution: this scribbles on *lines.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
print_with_linenumbers(FILE *output, char *lines,
|
|
|
|
const char *header_keyword)
|
|
|
|
{
|
|
|
|
bool in_header = (header_keyword != NULL);
|
|
|
|
size_t header_sz = in_header ? strlen(header_keyword) : 0;
|
|
|
|
int lineno = 0;
|
|
|
|
|
|
|
|
while (*lines != '\0')
|
|
|
|
{
|
|
|
|
char *eol;
|
|
|
|
|
|
|
|
if (in_header && strncmp(lines, header_keyword, header_sz) == 0)
|
|
|
|
in_header = false;
|
|
|
|
|
|
|
|
/* increment lineno only for body's lines */
|
|
|
|
if (!in_header)
|
|
|
|
lineno++;
|
|
|
|
|
|
|
|
/* find and mark end of current line */
|
|
|
|
eol = strchr(lines, '\n');
|
|
|
|
if (eol != NULL)
|
|
|
|
*eol = '\0';
|
|
|
|
|
|
|
|
/* show current line as appropriate */
|
|
|
|
if (in_header)
|
|
|
|
fprintf(output, " %s\n", lines);
|
|
|
|
else
|
|
|
|
fprintf(output, "%-7d %s\n", lineno, lines);
|
|
|
|
|
|
|
|
/* advance to next line, if any */
|
|
|
|
if (eol == NULL)
|
|
|
|
break;
|
|
|
|
lines = ++eol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-06 22:18:08 +02:00
|
|
|
/*
|
|
|
|
* Report just the primary error; this is to avoid cluttering the output
|
|
|
|
* with, for instance, a redisplay of the internally generated query
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
minimal_error_message(PGresult *res)
|
|
|
|
{
|
|
|
|
PQExpBuffer msg;
|
|
|
|
const char *fld;
|
|
|
|
|
|
|
|
msg = createPQExpBuffer();
|
|
|
|
|
|
|
|
fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
|
|
|
|
if (fld)
|
|
|
|
printfPQExpBuffer(msg, "%s: ", fld);
|
|
|
|
else
|
|
|
|
printfPQExpBuffer(msg, "ERROR: ");
|
|
|
|
fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
|
|
|
|
if (fld)
|
|
|
|
appendPQExpBufferStr(msg, fld);
|
|
|
|
else
|
|
|
|
appendPQExpBufferStr(msg, "(not available)");
|
2017-08-16 05:34:39 +02:00
|
|
|
appendPQExpBufferChar(msg, '\n');
|
2008-09-06 22:18:08 +02:00
|
|
|
|
2008-11-21 21:14:27 +01:00
|
|
|
psql_error("%s", msg->data);
|
2008-09-06 22:18:08 +02:00
|
|
|
|
|
|
|
destroyPQExpBuffer(msg);
|
|
|
|
}
|