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

Reply via email to