aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/ref/psql-ref.sgml10
-rw-r--r--src/bin/psql/command.c2
-rw-r--r--src/bin/psql/common.c32
3 files changed, 27 insertions, 17 deletions
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 4c87d8ad7fe..eb5e3b19048 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1608,9 +1608,13 @@ Tue Oct 26 21:40:57 CEST 1999
optionally stores the query's output in <replaceable
class="parameter">filename</replaceable> or pipes the output
into a separate Unix shell executing <replaceable
- class="parameter">command</replaceable>. A bare
- <literal>\g</literal> is virtually equivalent to a semicolon. A
- <literal>\g</literal> with argument is a <quote>one-shot</quote>
+ class="parameter">command</replaceable>. The file or command is
+ written to only if the query successfully returns zero or more tuples,
+ not if the query fails or is a non-data-returning SQL command.
+ </para>
+ <para>
+ A bare <literal>\g</literal> is essentially equivalent to a semicolon.
+ A <literal>\g</literal> with argument is a <quote>one-shot</quote>
alternative to the <command>\o</command> command.
</para>
</listitem>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 20c45e2d0a5..1e9aa89089e 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -731,7 +731,7 @@ exec_command(const char *cmd,
free(fname);
}
- /* \g means send query */
+ /* \g [filename] means send query, optionally with output to file/pipe */
else if (strcmp(cmd, "g") == 0)
{
char *fname = psql_scan_slash_option(scan_state,
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 5fb031650e3..ab517906fca 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -607,9 +607,6 @@ PrintQueryTuples(const PGresult *results)
pset.queryFout = queryFout_copy;
pset.queryFoutPipe = queryFoutPipe_copy;
-
- free(pset.gfname);
- pset.gfname = NULL;
}
else
printQuery(results, &my_popt, pset.queryFout, pset.logfile);
@@ -835,14 +832,14 @@ SendQuery(const char *query)
PGresult *results;
PGTransactionStatusType transaction_status;
double elapsed_msec = 0;
- bool OK,
- on_error_rollback_savepoint = false;
+ bool OK = false;
+ bool on_error_rollback_savepoint = false;
static bool on_error_rollback_warning = false;
if (!pset.db)
{
psql_error("You are currently not connected to a database.\n");
- return false;
+ goto sendquery_cleanup;
}
if (pset.singlestep)
@@ -856,7 +853,7 @@ SendQuery(const char *query)
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) != NULL)
if (buf[0] == 'x')
- return false;
+ goto sendquery_cleanup;
}
else if (pset.echo == PSQL_ECHO_QUERIES)
{
@@ -887,7 +884,7 @@ SendQuery(const char *query)
psql_error("%s", PQerrorMessage(pset.db));
PQclear(results);
ResetCancelConn();
- return false;
+ goto sendquery_cleanup;
}
PQclear(results);
transaction_status = PQtransactionStatus(pset.db);
@@ -912,7 +909,7 @@ SendQuery(const char *query)
psql_error("%s", PQerrorMessage(pset.db));
PQclear(results);
ResetCancelConn();
- return false;
+ goto sendquery_cleanup;
}
PQclear(results);
on_error_rollback_savepoint = true;
@@ -1008,10 +1005,11 @@ SendQuery(const char *query)
{
psql_error("%s", PQerrorMessage(pset.db));
PQclear(svptres);
+ OK = false;
PQclear(results);
ResetCancelConn();
- return false;
+ goto sendquery_cleanup;
}
PQclear(svptres);
}
@@ -1037,6 +1035,17 @@ SendQuery(const char *query)
PrintNotifications();
+ /* perform cleanup that should occur after any attempted query */
+
+sendquery_cleanup:
+
+ /* reset \g's output-to-filename trigger */
+ if (pset.gfname)
+ {
+ free(pset.gfname);
+ pset.gfname = NULL;
+ }
+
return OK;
}
@@ -1218,9 +1227,6 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
pset.queryFout = queryFout_copy;
pset.queryFoutPipe = queryFoutPipe_copy;
-
- free(pset.gfname);
- pset.gfname = NULL;
}
else if (did_pager)
{