@@ -60,6 +60,7 @@ static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
6060int lineno ,bool * edited );
6161static bool do_connect (char * dbname ,char * user ,char * host ,char * port );
6262static bool do_shell (const char * command );
63+ static bool do_watch (PQExpBuffer query_buf ,long sleep );
6364static bool lookup_function_oid (PGconn * conn ,const char * desc ,Oid * foid );
6465static bool get_create_function_cmd (PGconn * conn ,Oid oid ,PQExpBuffer buf );
6566static int strip_lineno_from_funcdesc (char * func );
@@ -1433,6 +1434,29 @@ exec_command(const char *cmd,
14331434free (fname );
14341435}
14351436
1437+ /* \watch -- execute a query every N seconds */
1438+ else if (strcmp (cmd ,"watch" )== 0 )
1439+ {
1440+ char * opt = psql_scan_slash_option (scan_state ,
1441+ OT_NORMAL ,NULL , true);
1442+ long sleep = 2 ;
1443+
1444+ /* Convert optional sleep-length argument */
1445+ if (opt )
1446+ {
1447+ sleep = strtol (opt ,NULL ,10 );
1448+ if (sleep <=0 )
1449+ sleep = 1 ;
1450+ free (opt );
1451+ }
1452+
1453+ success = do_watch (query_buf ,sleep );
1454+
1455+ /* Reset the query buffer as though for \r */
1456+ resetPQExpBuffer (query_buf );
1457+ psql_scan_reset (scan_state );
1458+ }
1459+
14361460/* \x -- set or toggle expanded table representation */
14371461else if (strcmp (cmd ,"x" )== 0 )
14381462{
@@ -2555,6 +2579,112 @@ do_shell(const char *command)
25552579return true;
25562580}
25572581
2582+ /*
2583+ * do_watch -- handler for \watch
2584+ *
2585+ * We break this out of exec_command to avoid having to plaster "volatile"
2586+ * onto a bunch of exec_command's variables to silence stupider compilers.
2587+ */
2588+ static bool
2589+ do_watch (PQExpBuffer query_buf ,long sleep )
2590+ {
2591+ printQueryOpt myopt = pset .popt ;
2592+ char title [50 ];
2593+
2594+ if (!query_buf || query_buf -> len <=0 )
2595+ {
2596+ psql_error (_ ("\\watch cannot be used with an empty query\n" ));
2597+ return false;
2598+ }
2599+
2600+ /*
2601+ * Set up rendering options, in particular, disable the pager, because
2602+ * nobody wants to be prompted while watching the output of 'watch'.
2603+ */
2604+ myopt .nullPrint = NULL ;
2605+ myopt .topt .pager = 0 ;
2606+
2607+ for (;;)
2608+ {
2609+ PGresult * res ;
2610+ time_t timer ;
2611+ long i ;
2612+
2613+ /*
2614+ * Prepare title for output. XXX would it be better to use the time
2615+ * of completion of the command?
2616+ */
2617+ timer = time (NULL );
2618+ snprintf (title ,sizeof (title ),_ ("Watch every %lds\t%s" ),
2619+ sleep ,asctime (localtime (& timer )));
2620+ myopt .title = title ;
2621+
2622+ /*
2623+ * Run the query. We use PSQLexec, which is kind of cheating, but
2624+ * SendQuery doesn't let us suppress autocommit behavior.
2625+ */
2626+ res = PSQLexec (query_buf -> data , false);
2627+
2628+ /* PSQLexec handles failure results and returns NULL */
2629+ if (res == NULL )
2630+ break ;
2631+
2632+ /*
2633+ * If SIGINT is sent while the query is processing, PSQLexec will
2634+ * consume the interrupt. The user's intention, though, is to cancel
2635+ * the entire watch process, so detect a sent cancellation request and
2636+ * exit in this case.
2637+ */
2638+ if (cancel_pressed )
2639+ {
2640+ PQclear (res );
2641+ break ;
2642+ }
2643+
2644+ switch (PQresultStatus (res ))
2645+ {
2646+ case PGRES_TUPLES_OK :
2647+ printQuery (res ,& myopt ,pset .queryFout ,pset .logfile );
2648+ break ;
2649+
2650+ case PGRES_EMPTY_QUERY :
2651+ psql_error (_ ("\\watch cannot be used with an empty query\n" ));
2652+ PQclear (res );
2653+ return false;
2654+
2655+ default :
2656+ /* should we fail for non-tuple-result commands? */
2657+ break ;
2658+ }
2659+
2660+ PQclear (res );
2661+
2662+ /*
2663+ * Set up cancellation of 'watch' via SIGINT. We redo this each time
2664+ * through the loop since it's conceivable something inside PSQLexec
2665+ * could change sigint_interrupt_jmp.
2666+ */
2667+ if (sigsetjmp (sigint_interrupt_jmp ,1 )!= 0 )
2668+ break ;
2669+
2670+ /*
2671+ * Enable 'watch' cancellations and wait a while before running the
2672+ * query again. Break the sleep into short intervals since pg_usleep
2673+ * isn't interruptible on some platforms.
2674+ */
2675+ sigint_interrupt_enabled = true;
2676+ for (i = 0 ;i < sleep ;i ++ )
2677+ {
2678+ pg_usleep (1000000L );
2679+ if (cancel_pressed )
2680+ break ;
2681+ }
2682+ sigint_interrupt_enabled = false;
2683+ }
2684+
2685+ return true;
2686+ }
2687+
25582688/*
25592689 * This function takes a function description, e.g. "x" or "x(int)", and
25602690 * issues a query on the given connection to retrieve the function's OID