Skip to content

Commit 24b4252

Browse files
author
Commitfest Bot
committed
[PATCH]: ./psql-copy-var-3.patch
1 parent e8ca9ed commit 24b4252

File tree

10 files changed

+359
-166
lines changed

10 files changed

+359
-166
lines changed

doc/src/sgml/ref/psql-ref.sgml

+30-5
Original file line numberDiff line numberDiff line change
@@ -1172,10 +1172,13 @@ SELECT $1 \parse stmt1
11721172
<tip>
11731173
<para>
11741174
Another way to obtain the same result as <literal>\copy
1175-
... to</literal> is to use the <acronym>SQL</acronym> <literal>COPY
1176-
... TO STDOUT</literal> command and terminate it
1177-
with <literal>\g <replaceable>filename</replaceable></literal>
1178-
or <literal>\g |<replaceable>program</replaceable></literal>.
1175+
... to</literal> or <literal>from</literal> is to use the <acronym>SQL</acronym>
1176+
<literal>COPY ... TO STDOUT</literal> or <literal>FROM STDIN</literal>
1177+
command and terminate it with either
1178+
<literal>\g <replaceable>filename</replaceable></literal>
1179+
or <literal>\g |<replaceable>program</replaceable></literal> for output
1180+
and <literal>\gi <replaceable>filename</replaceable></literal>
1181+
or <literal>\gi <replaceable>program</replaceable>|</literal> for input.
11791182
Unlike <literal>\copy</literal>, this method allows the command to
11801183
span multiple lines; also, variable interpolation and backquote
11811184
expansion can be used.
@@ -1188,7 +1191,7 @@ SELECT $1 \parse stmt1
11881191
<command>COPY</command> command with a file or program data source or
11891192
destination, because all data must pass through the client/server
11901193
connection. For large amounts of data the <acronym>SQL</acronym>
1191-
command might be preferable.
1194+
command might be preferable if data are available on the server.
11921195
</para>
11931196
</tip>
11941197

@@ -2558,6 +2561,28 @@ CREATE INDEX
25582561
</varlistentry>
25592562

25602563

2564+
<varlistentry id="app-psql-meta-command-gi">
2565+
<term><literal>\gi <replaceable class="parameter">file</replaceable></literal></term>
2566+
<term><literal>\gi <replaceable class="parameter">command</replaceable>|</literal></term>
2567+
<listitem>
2568+
<para>
2569+
Sends the current query buffer to the server and uses the provided
2570+
<replaceable>file</replaceable> contents or <replaceable>command</replaceable>
2571+
output as input.
2572+
This should only apply to <acronym>SQL</acronym>
2573+
<link linkend="sql-copy"><command>COPY</command></link>
2574+
which seeks an input when used with <literal>FROM STDIN</literal>, and
2575+
will simply result in the command simple execution for other commands
2576+
which do not need an input stream.
2577+
</para>
2578+
<para>
2579+
This approach should be prefered to using <literal>\copy</literal>
2580+
as it achieves the same result but can span several lines and
2581+
is subject to variable interpolation and backquote expansion.
2582+
</para>
2583+
</listitem>
2584+
</varlistentry>
2585+
25612586
<varlistentry id="app-psql-meta-command-gset">
25622587
<term><literal>\gset [ <replaceable class="parameter">prefix</replaceable> ]</literal></term>
25632588

src/bin/psql/command.c

+57-2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ static backslashResult exec_command_getenv(PsqlScanState scan_state, bool active
107107
const char *cmd);
108108
static backslashResult exec_command_gexec(PsqlScanState scan_state, bool active_branch);
109109
static backslashResult exec_command_getresults(PsqlScanState scan_state, bool active_branch);
110+
static backslashResult exec_command_gi(PsqlScanState scan_state, bool active_branch);
110111
static backslashResult exec_command_gset(PsqlScanState scan_state, bool active_branch);
111112
static backslashResult exec_command_help(PsqlScanState scan_state, bool active_branch);
112113
static backslashResult exec_command_html(PsqlScanState scan_state, bool active_branch);
@@ -380,6 +381,8 @@ exec_command(const char *cmd,
380381
status = exec_command_getresults(scan_state, active_branch);
381382
else if (strcmp(cmd, "gexec") == 0)
382383
status = exec_command_gexec(scan_state, active_branch);
384+
else if (strcmp(cmd, "gi") == 0)
385+
status = exec_command_gi(scan_state, active_branch);
383386
else if (strcmp(cmd, "gset") == 0)
384387
status = exec_command_gset(scan_state, active_branch);
385388
else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
@@ -1750,7 +1753,8 @@ exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
17501753
else
17511754
{
17521755
expand_tilde(&fname);
1753-
pset.gfname = pg_strdup(fname);
1756+
pset.g_pipe = fname[0] == '|';
1757+
pset.gfname = pg_strdup(fname + (pset.g_pipe ? 1 : 0));
17541758
}
17551759
if (strcmp(cmd, "gx") == 0)
17561760
{
@@ -1957,6 +1961,56 @@ exec_command_gexec(PsqlScanState scan_state, bool active_branch)
19571961
return status;
19581962
}
19591963

1964+
/*
1965+
* \gi filename/shell-command
1966+
*
1967+
* Send the current query with a query input from the filename or pipe
1968+
* command.
1969+
*/
1970+
static backslashResult
1971+
exec_command_gi(PsqlScanState scan_state, bool active_branch)
1972+
{
1973+
backslashResult status = PSQL_CMD_SKIP_LINE;
1974+
1975+
if (active_branch)
1976+
{
1977+
char *fname;
1978+
int last;
1979+
1980+
fname = psql_scan_slash_option(scan_state, OT_FILEPIPE, NULL, false);
1981+
1982+
if (fname == NULL)
1983+
{
1984+
pg_log_error("\\gi expects a filename or pipe command");
1985+
clean_extended_state();
1986+
free(fname);
1987+
return PSQL_CMD_ERROR;
1988+
}
1989+
1990+
/* check and truncate final pipe character */
1991+
last = strlen(fname) - 1;
1992+
pset.gi_pipe = last >= 0 && fname[last] == '|';
1993+
if (pset.gi_pipe)
1994+
fname[last] = '\0';
1995+
1996+
if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF)
1997+
{
1998+
pg_log_error("\\gi not allowed in pipeline mode");
1999+
clean_extended_state();
2000+
free(fname);
2001+
return PSQL_CMD_ERROR;
2002+
}
2003+
2004+
expand_tilde(&fname);
2005+
pset.gi_fname = pg_strdup(fname);
2006+
2007+
status = PSQL_CMD_SEND;
2008+
free(fname);
2009+
}
2010+
2011+
return status;
2012+
}
2013+
19602014
/*
19612015
* \gset [prefix] -- send query and store result into variables
19622016
*/
@@ -2440,9 +2494,10 @@ exec_command_out(PsqlScanState scan_state, bool active_branch)
24402494
{
24412495
char *fname = psql_scan_slash_option(scan_state,
24422496
OT_FILEPIPE, NULL, true);
2497+
bool is_pipe = *fname == '|';
24432498

24442499
expand_tilde(&fname);
2445-
success = setQFout(fname);
2500+
success = setQFout(fname + (is_pipe ? 1 : 0), is_pipe);
24462501
free(fname);
24472502
}
24482503
else

0 commit comments

Comments
 (0)