for (;;)
{
- PGresult *res;
+ int res;
time_t timer;
long i;
sleep, asctime(localtime(&timer)));
myopt.title = title;
- /*
- * Run the query. We use PSQLexec, which is kind of cheating, but
- * SendQuery doesn't let us suppress autocommit behavior.
- */
- res = PSQLexec(query_buf->data, false);
-
- /* PSQLexec handles failure results and returns NULL */
- if (res == NULL)
- break;
+ /* Run the query and print out the results */
+ res = PSQLexecWatch(query_buf->data, &myopt);
/*
- * If SIGINT is sent while the query is processing, PSQLexec will
- * consume the interrupt. The user's intention, though, is to cancel
- * the entire watch process, so detect a sent cancellation request and
- * exit in this case.
+ * PSQLexecWatch handles the case where we can no longer
+ * repeat the query, and returns 0 or -1.
*/
- if (cancel_pressed)
- {
- PQclear(res);
+ if (res == 0)
break;
- }
-
- switch (PQresultStatus(res))
- {
- case PGRES_TUPLES_OK:
- printQuery(res, &myopt, pset.queryFout, pset.logfile);
- break;
-
- case PGRES_COMMAND_OK:
- fprintf(pset.queryFout, "%s\n%s\n\n", title, PQcmdStatus(res));
- break;
-
- case PGRES_EMPTY_QUERY:
- psql_error(_("\\watch cannot be used with an empty query\n"));
- PQclear(res);
- return false;
-
- case PGRES_COPY_OUT:
- case PGRES_COPY_IN:
- case PGRES_COPY_BOTH:
- psql_error(_("\\watch cannot be used with COPY\n"));
- PQclear(res);
- return false;
-
- default:
- /* other cases should have been handled by PSQLexec */
- psql_error(_("unexpected result status for \\watch\n"));
- PQclear(res);
- return false;
- }
-
- PQclear(res);
-
- fflush(pset.queryFout);
+ if (res == -1)
+ return false;
/*
* Set up cancellation of 'watch' via SIGINT. We redo this each time
- * through the loop since it's conceivable something inside PSQLexec
- * could change sigint_interrupt_jmp.
+ * through the loop since it's conceivable something inside
+ * PSQLexecWatch could change sigint_interrupt_jmp.
*/
if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
break;
}
+/*
+ * PSQLexecWatch
+ *
+ * This function is used for \watch command to send the query to
+ * the server and print out the results.
+ *
+ * Returns 1 if the query executed successfully, 0 if it cannot be repeated,
+ * e.g., because of the interrupt, -1 on error.
+ */
+int
+PSQLexecWatch(const char *query, const printQueryOpt *opt)
+{
+ PGresult *res;
+ double elapsed_msec = 0;
+ instr_time before;
+ instr_time after;
+
+ if (!pset.db)
+ {
+ psql_error("You are currently not connected to a database.\n");
+ return 0;
+ }
+
+ SetCancelConn();
+
+ if (pset.timing)
+ INSTR_TIME_SET_CURRENT(before);
+
+ res = PQexec(pset.db, query);
+
+ ResetCancelConn();
+
+ if (!AcceptResult(res))
+ {
+ PQclear(res);
+ return 0;
+ }
+
+ if (pset.timing)
+ {
+ INSTR_TIME_SET_CURRENT(after);
+ INSTR_TIME_SUBTRACT(after, before);
+ elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
+ }
+
+ /*
+ * If SIGINT is sent while the query is processing, the interrupt
+ * will be consumed. The user's intention, though, is to cancel
+ * the entire watch process, so detect a sent cancellation request and
+ * exit in this case.
+ */
+ if (cancel_pressed)
+ {
+ PQclear(res);
+ return 0;
+ }
+
+ switch (PQresultStatus(res))
+ {
+ case PGRES_TUPLES_OK:
+ printQuery(res, opt, pset.queryFout, pset.logfile);
+ break;
+
+ case PGRES_COMMAND_OK:
+ fprintf(pset.queryFout, "%s\n%s\n\n", opt->title, PQcmdStatus(res));
+ break;
+
+ case PGRES_EMPTY_QUERY:
+ psql_error(_("\\watch cannot be used with an empty query\n"));
+ PQclear(res);
+ return -1;
+
+ case PGRES_COPY_OUT:
+ case PGRES_COPY_IN:
+ case PGRES_COPY_BOTH:
+ psql_error(_("\\watch cannot be used with COPY\n"));
+ PQclear(res);
+ return -1;
+
+ default:
+ psql_error(_("unexpected result status for \\watch\n"));
+ PQclear(res);
+ return -1;
+ }
+
+ PQclear(res);
+
+ fflush(pset.queryFout);
+
+ /* Possible microtiming output */
+ if (pset.timing)
+ printf(_("Time: %.3f ms\n"), elapsed_msec);
+
+ return 1;
+}
+
/*
* PrintNotifications: check for asynchronous notifications, and print them out
#include <setjmp.h>
#include "libpq-fe.h"
+#include "print.h"
+
#define atooid(x) ((Oid) strtoul((x), NULL, 10))
extern bool setQFout(const char *fname);
extern void ResetCancelConn(void);
extern PGresult *PSQLexec(const char *query, bool start_xact);
+extern int PSQLexecWatch(const char *query, const printQueryOpt *opt);
extern bool SendQuery(const char *query);