On Mon, Sep 1, 2014 at 11:56 PM, Tom Lane <t...@sss.pgh.pa.us> wrote: > Michael Paquier <michael.paqu...@gmail.com> writes: >> I just tested the patch and this feature works as expected if timing >> is on and it displays the individual run time of each query kicked by >> \watch. Note that --echo-hidden does not display the query run during >> each loop and that this is contrary to the behavior in HEAD so it >> breaks backward compatibility, but are there really people relying in >> the existing behavior? > > ISTM that's an anti-feature anyway, and changing that behavior is a > good thing. OK, then as all the comments are basically addressed, here is an updated patch correcting the comment problems mentioned by Heikki. This is ready for a committer. Regards, -- Michael
*** a/src/bin/psql/command.c --- b/src/bin/psql/command.c *************** *** 2687,2693 **** do_watch(PQExpBuffer query_buf, long sleep) for (;;) { ! PGresult *res; time_t timer; long i; --- 2687,2693 ---- for (;;) { ! int res; time_t timer; long i; *************** *** 2700,2764 **** do_watch(PQExpBuffer query_buf, long sleep) 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; /* ! * 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. */ ! if (cancel_pressed) ! { ! PQclear(res); 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); /* * 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. */ if (sigsetjmp(sigint_interrupt_jmp, 1) != 0) break; --- 2700,2721 ---- sleep, asctime(localtime(&timer))); myopt.title = title; ! /* Run the query and print out the results */ ! res = PSQLexecWatch(query_buf->data, &myopt); /* ! * PSQLexecWatch handles the case where we can no longer ! * repeat the query, and returns 0 or -1. */ ! if (res == 0) break; ! 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 ! * PSQLexecWatch could change sigint_interrupt_jmp. */ if (sigsetjmp(sigint_interrupt_jmp, 1) != 0) break; *** a/src/bin/psql/common.c --- b/src/bin/psql/common.c *************** *** 497,502 **** PSQLexec(const char *query, bool start_xact) --- 497,598 ---- } + /* + * 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 *** a/src/bin/psql/common.h --- b/src/bin/psql/common.h *************** *** 12,17 **** --- 12,19 ---- #include <setjmp.h> #include "libpq-fe.h" + #include "print.h" + #define atooid(x) ((Oid) strtoul((x), NULL, 10)) extern bool setQFout(const char *fname); *************** *** 37,42 **** extern void SetCancelConn(void); --- 39,45 ---- 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);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers