aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/psql/common.c')
-rw-r--r--src/bin/psql/common.c90
1 files changed, 86 insertions, 4 deletions
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index a2a07fb538e..df3441cc750 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -798,6 +798,76 @@ StoreQueryTuple(const PGresult *result)
/*
+ * ExecQueryTuples: assuming query result is OK, execute each query
+ * result field as a SQL statement
+ *
+ * Returns true if successful, false otherwise.
+ */
+static bool
+ExecQueryTuples(const PGresult *result)
+{
+ bool success = true;
+ int nrows = PQntuples(result);
+ int ncolumns = PQnfields(result);
+ int r,
+ c;
+
+ /*
+ * We must turn off gexec_flag to avoid infinite recursion. Note that
+ * this allows ExecQueryUsingCursor to be applied to the individual query
+ * results. SendQuery prevents it from being applied when fetching the
+ * queries-to-execute, because it can't handle recursion either.
+ */
+ pset.gexec_flag = false;
+
+ for (r = 0; r < nrows; r++)
+ {
+ for (c = 0; c < ncolumns; c++)
+ {
+ if (!PQgetisnull(result, r, c))
+ {
+ const char *query = PQgetvalue(result, r, c);
+
+ /* Abandon execution if cancel_pressed */
+ if (cancel_pressed)
+ goto loop_exit;
+
+ /*
+ * ECHO_ALL mode should echo these queries, but SendQuery
+ * assumes that MainLoop did that, so we have to do it here.
+ */
+ if (pset.echo == PSQL_ECHO_ALL && !pset.singlestep)
+ {
+ puts(query);
+ fflush(stdout);
+ }
+
+ if (!SendQuery(query))
+ {
+ /* Error - abandon execution if ON_ERROR_STOP */
+ success = false;
+ if (pset.on_error_stop)
+ goto loop_exit;
+ }
+ }
+ }
+ }
+
+loop_exit:
+
+ /*
+ * Restore state. We know gexec_flag was on, else we'd not be here. (We
+ * also know it'll get turned off at end of command, but that's not ours
+ * to do here.)
+ */
+ pset.gexec_flag = true;
+
+ /* Return true if all queries were successful */
+ return success;
+}
+
+
+/*
* ProcessResult: utility function for use by SendQuery() only
*
* When our command string contained a COPY FROM STDIN or COPY TO STDOUT,
@@ -971,7 +1041,7 @@ PrintQueryStatus(PGresult *results)
/*
- * PrintQueryResults: print out (or store) query results as required
+ * PrintQueryResults: print out (or store or execute) query results as required
*
* Note: Utility function for use by SendQuery() only.
*
@@ -989,9 +1059,11 @@ PrintQueryResults(PGresult *results)
switch (PQresultStatus(results))
{
case PGRES_TUPLES_OK:
- /* store or print the data ... */
+ /* store or execute or print the data ... */
if (pset.gset_prefix)
success = StoreQueryTuple(results);
+ else if (pset.gexec_flag)
+ success = ExecQueryTuples(results);
else
success = PrintQueryTuples(results);
/* if it's INSERT/UPDATE/DELETE RETURNING, also print status */
@@ -1068,6 +1140,7 @@ SendQuery(const char *query)
{
char buf[3];
+ fflush(stderr);
printf(_("***(Single step mode: verify command)*******************************************\n"
"%s\n"
"***(press return to proceed or enter x and return to cancel)********************\n"),
@@ -1076,6 +1149,8 @@ SendQuery(const char *query)
if (fgets(buf, sizeof(buf), stdin) != NULL)
if (buf[0] == 'x')
goto sendquery_cleanup;
+ if (cancel_pressed)
+ goto sendquery_cleanup;
}
else if (pset.echo == PSQL_ECHO_QUERIES)
{
@@ -1138,7 +1213,7 @@ SendQuery(const char *query)
}
}
- if (pset.fetch_count <= 0 || !is_select_command(query))
+ if (pset.fetch_count <= 0 || pset.gexec_flag || !is_select_command(query))
{
/* Default fetch-it-all-and-print mode */
instr_time before,
@@ -1278,6 +1353,9 @@ sendquery_cleanup:
pset.gset_prefix = NULL;
}
+ /* reset \gexec trigger */
+ pset.gexec_flag = false;
+
return OK;
}
@@ -1423,6 +1501,8 @@ ExecQueryUsingCursor(const char *query, double *elapsed_msec)
break;
}
+ /* Note we do not deal with \gexec mode here */
+
ntuples = PQntuples(results);
if (ntuples < fetch_count)
@@ -1499,8 +1579,10 @@ cleanup:
{
OK = AcceptResult(results) &&
(PQresultStatus(results) == PGRES_COMMAND_OK);
+ ClearOrSaveResult(results);
}
- ClearOrSaveResult(results);
+ else
+ PQclear(results);
if (started_txn)
{