agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH] Introduce timeout capability for ConditionVariableSleep 9+ messages / 4 participants [nested] [flat]
* [PATCH] Introduce timeout capability for ConditionVariableSleep @ 2019-03-12 23:21 Shawn Debnath <[email protected]> 0 siblings, 0 replies; 9+ messages in thread From: Shawn Debnath @ 2019-03-12 23:21 UTC (permalink / raw) This patch introduces ConditionVariableTimedSleep to enable timing out of waiting for a condition variable to get signalled. --- src/backend/storage/lmgr/condition_variable.c | 63 ++++++++++++++++++++++++--- src/include/storage/condition_variable.h | 2 + 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/backend/storage/lmgr/condition_variable.c b/src/backend/storage/lmgr/condition_variable.c index 58b7b51472..390072451c 100644 --- a/src/backend/storage/lmgr/condition_variable.c +++ b/src/backend/storage/lmgr/condition_variable.c @@ -19,6 +19,7 @@ #include "postgres.h" #include "miscadmin.h" +#include "portability/instr_time.h" #include "storage/condition_variable.h" #include "storage/ipc.h" #include "storage/proc.h" @@ -122,8 +123,23 @@ ConditionVariablePrepareToSleep(ConditionVariable *cv) void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) { - WaitEvent event; - bool done = false; + (void) ConditionVariableTimedSleep(cv, -1 /* no timeout */, wait_event_info); +} + +/* + * Wait for the given condition variable to be signaled or till timeout. + * + * Returns true when timeout expires, otherwise returns false. + * + * See ConditionVariableSleep() for general usage. + */ +bool +ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, + uint32 wait_event_info) +{ + long cur_timeout = -1; + instr_time start_time; + instr_time cur_time; /* * If the caller didn't prepare to sleep explicitly, then do so now and @@ -143,23 +159,42 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) if (cv_sleep_target != cv) { ConditionVariablePrepareToSleep(cv); - return; + return false; } - do + /* + * Record the current time so that we can calculate the remaining timeout + * if we are woken up spuriously. + */ + if (timeout >= 0) { + INSTR_TIME_SET_CURRENT(start_time); + Assert(timeout >= 0 && timeout <= INT_MAX); + cur_timeout = timeout; + } + + while (true) + { + WaitEvent event; + bool done = false; + int rc; + CHECK_FOR_INTERRUPTS(); /* * Wait for latch to be set. (If we're awakened for some other * reason, the code below will cope anyway.) */ - (void) WaitEventSetWait(cv_wait_event_set, -1, &event, 1, + rc = WaitEventSetWait(cv_wait_event_set, cur_timeout, &event, 1, wait_event_info); /* Reset latch before examining the state of the wait list. */ ResetLatch(MyLatch); + /* Timed out */ + if (rc == 0) + return true; + /* * If this process has been taken out of the wait list, then we know * that it has been signaled by ConditionVariableSignal (or @@ -182,7 +217,23 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) proclist_push_tail(&cv->wakeup, MyProc->pgprocno, cvWaitLink); } SpinLockRelease(&cv->mutex); - } while (!done); + + /* We were signaled, so return */ + if (done) + return false; + + /* If we're not done, update cur_timeout for next iteration */ + if (timeout >= 0) + { + INSTR_TIME_SET_CURRENT(cur_time); + INSTR_TIME_SUBTRACT(cur_time, start_time); + cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time); + + /* Have we crossed the timeout threshold? */ + if (cur_timeout <= 0) + return true; + } + } } /* diff --git a/src/include/storage/condition_variable.h b/src/include/storage/condition_variable.h index 2a0249392c..ee06e051ce 100644 --- a/src/include/storage/condition_variable.h +++ b/src/include/storage/condition_variable.h @@ -43,6 +43,8 @@ extern void ConditionVariableInit(ConditionVariable *cv); * the condition variable. */ extern void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info); +extern bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, + uint32 wait_event_info); extern void ConditionVariableCancelSleep(void); /* -- 2.16.5 --HlL+5n6rz5pIUxbD-- ^ permalink raw reply [nested|flat] 9+ messages in thread
* [PATCH] Introduce timeout capability for ConditionVariableSleep @ 2019-03-12 23:21 Shawn Debnath <[email protected]> 0 siblings, 0 replies; 9+ messages in thread From: Shawn Debnath @ 2019-03-12 23:21 UTC (permalink / raw) This patch introduces ConditionVariableTimedSleep to enable timing out of waiting for a condition variable to get signalled. --- src/backend/storage/lmgr/condition_variable.c | 41 +++++++++++++++++++++++++-- src/include/storage/condition_variable.h | 2 ++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/backend/storage/lmgr/condition_variable.c b/src/backend/storage/lmgr/condition_variable.c index 58b7b51472..a0e14a5efa 100644 --- a/src/backend/storage/lmgr/condition_variable.c +++ b/src/backend/storage/lmgr/condition_variable.c @@ -121,9 +121,33 @@ ConditionVariablePrepareToSleep(ConditionVariable *cv) */ void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) +{ + (void) ConditionVariableTimedSleep(cv, -1 /* no timeout */, wait_event_info); +} + +/* + * Wait for the given condition variable to be signaled or till timeout. + * This should be called in a predicate loop that tests for a specific exit + * condition and otherwise sleeps, like so: + * + * ConditionVariablePrepareToSleep(cv); // optional + * while (condition for which we are waiting is not true) + * ConditionVariableSleep(cv, wait_event_info); + * ConditionVariableCancelSleep(); + * + * wait_event_info should be a value from one of the WaitEventXXX enums + * defined in pgstat.h. This controls the contents of pg_stat_activity's + * wait_event_type and wait_event columns while waiting. + * + * Returns 0 or -1 if timed out. + */ +int +ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, + uint32 wait_event_info) { WaitEvent event; bool done = false; + int ret; /* * If the caller didn't prepare to sleep explicitly, then do so now and @@ -143,7 +167,7 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) if (cv_sleep_target != cv) { ConditionVariablePrepareToSleep(cv); - return; + return 0; } do @@ -154,12 +178,23 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) * Wait for latch to be set. (If we're awakened for some other * reason, the code below will cope anyway.) */ - (void) WaitEventSetWait(cv_wait_event_set, -1, &event, 1, + ret = WaitEventSetWait(cv_wait_event_set, timeout, &event, 1, wait_event_info); /* Reset latch before examining the state of the wait list. */ ResetLatch(MyLatch); + /* Timeout */ + if (ret == 0 && timeout >= 0) + { + /* + * In the event of a timeout, we simply return and the caller + * calls ConditionVariableCancelSleep to remove themselves from the + * wait queue + */ + return -1; + } + /* * If this process has been taken out of the wait list, then we know * that it has been signaled by ConditionVariableSignal (or @@ -183,6 +218,8 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) } SpinLockRelease(&cv->mutex); } while (!done); + + return 0; } /* diff --git a/src/include/storage/condition_variable.h b/src/include/storage/condition_variable.h index 2a0249392c..f62164e483 100644 --- a/src/include/storage/condition_variable.h +++ b/src/include/storage/condition_variable.h @@ -43,6 +43,8 @@ extern void ConditionVariableInit(ConditionVariable *cv); * the condition variable. */ extern void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info); +extern int ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, + uint32 wait_event_info); extern void ConditionVariableCancelSleep(void); /* -- 2.16.5 --wRRV7LY7NUeQGEoC-- ^ permalink raw reply [nested|flat] 9+ messages in thread
* [PATCH] Introduce timeout capability for ConditionVariableSleep @ 2019-03-12 23:21 Shawn Debnath <[email protected]> 0 siblings, 0 replies; 9+ messages in thread From: Shawn Debnath @ 2019-03-12 23:21 UTC (permalink / raw) This patch introduces ConditionVariableTimedSleep to enable timing out of waiting for a condition variable to get signalled. --- src/backend/storage/lmgr/condition_variable.c | 66 ++++++++++++++++++++++++++- src/include/storage/condition_variable.h | 2 + 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/backend/storage/lmgr/condition_variable.c b/src/backend/storage/lmgr/condition_variable.c index 58b7b51472..3afb726131 100644 --- a/src/backend/storage/lmgr/condition_variable.c +++ b/src/backend/storage/lmgr/condition_variable.c @@ -19,6 +19,7 @@ #include "postgres.h" #include "miscadmin.h" +#include "portability/instr_time.h" #include "storage/condition_variable.h" #include "storage/ipc.h" #include "storage/proc.h" @@ -121,9 +122,31 @@ ConditionVariablePrepareToSleep(ConditionVariable *cv) */ void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) +{ + (void) ConditionVariableTimedSleep(cv, -1 /* no timeout */, wait_event_info); +} + +/* + * Wait for the given condition variable to be signaled or till timeout. + * + * In the event of a timeout, we simply return and the caller + * calls ConditionVariableCancelSleep to remove themselves from the + * wait queue. See ConditionVariableSleep() for notes on how to correctly check + * for the exit condition. + * + * Returns 0, or -1 if timed out. + */ +int +ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, + uint32 wait_event_info) { WaitEvent event; bool done = false; + int rc; + int ret = 0; + long rem_timeout = -1; + instr_time start_time; + instr_time cur_time; /* * If the caller didn't prepare to sleep explicitly, then do so now and @@ -143,7 +166,18 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) if (cv_sleep_target != cv) { ConditionVariablePrepareToSleep(cv); - return; + return ret; + } + + /* + * Track the current time so that we can calculate the remaining timeout + * if we are woken up spuriously. + */ + if (timeout >= 0) + { + INSTR_TIME_SET_CURRENT(start_time); + Assert(timeout >= 0 && timeout <= INT_MAX); + rem_timeout = timeout; } do @@ -154,12 +188,19 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) * Wait for latch to be set. (If we're awakened for some other * reason, the code below will cope anyway.) */ - (void) WaitEventSetWait(cv_wait_event_set, -1, &event, 1, + rc = WaitEventSetWait(cv_wait_event_set, rem_timeout, &event, 1, wait_event_info); /* Reset latch before examining the state of the wait list. */ ResetLatch(MyLatch); + /* Timed out */ + if (rc == 0 && timeout >= 0) + { + ret = -1; /* timeout */ + break; + } + /* * If this process has been taken out of the wait list, then we know * that it has been signaled by ConditionVariableSignal (or @@ -179,10 +220,31 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) if (!proclist_contains(&cv->wakeup, MyProc->pgprocno, cvWaitLink)) { done = true; + Assert(ret == 0); proclist_push_tail(&cv->wakeup, MyProc->pgprocno, cvWaitLink); } SpinLockRelease(&cv->mutex); + + /* If we're not done, update rem_timeout for next iteration */ + if (!done && timeout >= 0) + { + INSTR_TIME_SET_CURRENT(cur_time); + INSTR_TIME_SUBTRACT(cur_time, start_time); + rem_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time); + + /* + * Check if we have reached the timeout threshold after calculating + * the remaining timeout value. + */ + if (rem_timeout <= 0) + { + ret = -1; /* timeout */ + break; + } + } } while (!done); + + return ret; } /* diff --git a/src/include/storage/condition_variable.h b/src/include/storage/condition_variable.h index 2a0249392c..f62164e483 100644 --- a/src/include/storage/condition_variable.h +++ b/src/include/storage/condition_variable.h @@ -43,6 +43,8 @@ extern void ConditionVariableInit(ConditionVariable *cv); * the condition variable. */ extern void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info); +extern int ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, + uint32 wait_event_info); extern void ConditionVariableCancelSleep(void); /* -- 2.16.5 --mxv5cy4qt+RJ9ypb-- ^ permalink raw reply [nested|flat] 9+ messages in thread
* [PATCH] Introduce timeout capability for ConditionVariableSleep @ 2019-03-12 23:21 Shawn Debnath <[email protected]> 0 siblings, 0 replies; 9+ messages in thread From: Shawn Debnath @ 2019-03-12 23:21 UTC (permalink / raw) This patch introduces ConditionVariableTimedSleep to enable timing out of waiting for a condition variable to get signalled. --- src/backend/storage/lmgr/condition_variable.c | 63 ++++++++++++++++++++++++--- src/include/storage/condition_variable.h | 2 + 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/backend/storage/lmgr/condition_variable.c b/src/backend/storage/lmgr/condition_variable.c index 58b7b51472..57a8098d90 100644 --- a/src/backend/storage/lmgr/condition_variable.c +++ b/src/backend/storage/lmgr/condition_variable.c @@ -19,6 +19,7 @@ #include "postgres.h" #include "miscadmin.h" +#include "portability/instr_time.h" #include "storage/condition_variable.h" #include "storage/ipc.h" #include "storage/proc.h" @@ -122,8 +123,23 @@ ConditionVariablePrepareToSleep(ConditionVariable *cv) void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) { - WaitEvent event; - bool done = false; + (void) ConditionVariableTimedSleep(cv, -1 /* no timeout */, wait_event_info); +} + +/* + * Wait for the given condition variable to be signaled or till timeout. + * + * Returns true when timeout expires, otherwise returns false. + * + * See ConditionVariableSleep() for general usage. + */ +bool +ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, + uint32 wait_event_info) +{ + long rem_timeout = -1; + instr_time start_time; + instr_time cur_time; /* * If the caller didn't prepare to sleep explicitly, then do so now and @@ -143,23 +159,42 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) if (cv_sleep_target != cv) { ConditionVariablePrepareToSleep(cv); - return; + return false; } - do + /* + * Track the current time so that we can calculate the remaining timeout + * if we are woken up spuriously. + */ + if (timeout >= 0) { + INSTR_TIME_SET_CURRENT(start_time); + Assert(timeout >= 0 && timeout <= INT_MAX); + rem_timeout = timeout; + } + + while (true) + { + WaitEvent event; + bool done = false; + int rc; + CHECK_FOR_INTERRUPTS(); /* * Wait for latch to be set. (If we're awakened for some other * reason, the code below will cope anyway.) */ - (void) WaitEventSetWait(cv_wait_event_set, -1, &event, 1, + rc = WaitEventSetWait(cv_wait_event_set, rem_timeout, &event, 1, wait_event_info); /* Reset latch before examining the state of the wait list. */ ResetLatch(MyLatch); + /* Timed out */ + if (rc == 0) + return true; + /* * If this process has been taken out of the wait list, then we know * that it has been signaled by ConditionVariableSignal (or @@ -182,7 +217,23 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info) proclist_push_tail(&cv->wakeup, MyProc->pgprocno, cvWaitLink); } SpinLockRelease(&cv->mutex); - } while (!done); + + /* We were signaled, so return */ + if (done) + return false; + + /* If we're not done, update rem_timeout for next iteration */ + if (timeout >= 0) + { + INSTR_TIME_SET_CURRENT(cur_time); + INSTR_TIME_SUBTRACT(cur_time, start_time); + rem_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time); + + /* Have we crossed the timeout threshold? */ + if (rem_timeout <= 0) + return true; + } + } } /* diff --git a/src/include/storage/condition_variable.h b/src/include/storage/condition_variable.h index 2a0249392c..ee06e051ce 100644 --- a/src/include/storage/condition_variable.h +++ b/src/include/storage/condition_variable.h @@ -43,6 +43,8 @@ extern void ConditionVariableInit(ConditionVariable *cv); * the condition variable. */ extern void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info); +extern bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, + uint32 wait_event_info); extern void ConditionVariableCancelSleep(void); /* -- 2.16.5 --C7zPtVaVf+AK4Oqc-- ^ permalink raw reply [nested|flat] 9+ messages in thread
* [PATCH v19 3/8] Row pattern recognition patch (rewriter). @ 2024-05-14 23:26 Tatsuo Ishii <[email protected]> 0 siblings, 0 replies; 9+ messages in thread From: Tatsuo Ishii @ 2024-05-14 23:26 UTC (permalink / raw) --- src/backend/utils/adt/ruleutils.c | 103 ++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 9a6d372414..f4dc60a7d2 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -426,6 +426,10 @@ static void get_rule_groupingset(GroupingSet *gset, List *targetlist, bool omit_parens, deparse_context *context); static void get_rule_orderby(List *orderList, List *targetList, bool force_colno, deparse_context *context); +static void get_rule_pattern(List *patternVariable, List *patternRegexp, + bool force_colno, deparse_context *context); +static void get_rule_define(List *defineClause, List *patternVariables, + bool force_colno, deparse_context *context); static void get_rule_windowclause(Query *query, deparse_context *context); static void get_rule_windowspec(WindowClause *wc, List *targetList, deparse_context *context); @@ -6465,6 +6469,67 @@ get_rule_orderby(List *orderList, List *targetList, } } +/* + * Display a PATTERN clause. + */ +static void +get_rule_pattern(List *patternVariable, List *patternRegexp, + bool force_colno, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *lc_var, + *lc_reg = list_head(patternRegexp); + + sep = ""; + appendStringInfoChar(buf, '('); + foreach(lc_var, patternVariable) + { + char *variable = strVal((String *) lfirst(lc_var)); + char *regexp = NULL; + + if (lc_reg != NULL) + { + regexp = strVal((String *) lfirst(lc_reg)); + + lc_reg = lnext(patternRegexp, lc_reg); + } + + appendStringInfo(buf, "%s%s", sep, variable); + if (regexp !=NULL) + appendStringInfoString(buf, regexp); + + sep = " "; + } + appendStringInfoChar(buf, ')'); +} + +/* + * Display a DEFINE clause. + */ +static void +get_rule_define(List *defineClause, List *patternVariables, + bool force_colno, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *lc_var, + *lc_def; + + sep = " "; + Assert(list_length(patternVariables) == list_length(defineClause)); + + forboth(lc_var, patternVariables, lc_def, defineClause) + { + char *varName = strVal(lfirst(lc_var)); + TargetEntry *te = (TargetEntry *) lfirst(lc_def); + + appendStringInfo(buf, "%s%s AS ", sep, varName); + get_rule_expr((Node *) te->expr, context, false); + sep = ",\n "; + } +} + /* * Display a WINDOW clause. * @@ -6602,6 +6667,44 @@ get_rule_windowspec(WindowClause *wc, List *targetList, appendStringInfoString(buf, "EXCLUDE GROUP "); else if (wc->frameOptions & FRAMEOPTION_EXCLUDE_TIES) appendStringInfoString(buf, "EXCLUDE TIES "); + /* RPR */ + if (wc->rpSkipTo == ST_NEXT_ROW) + appendStringInfoString(buf, + "\n AFTER MATCH SKIP TO NEXT ROW "); + else if (wc->rpSkipTo == ST_PAST_LAST_ROW) + appendStringInfoString(buf, + "\n AFTER MATCH SKIP PAST LAST ROW "); + else if (wc->rpSkipTo == ST_FIRST_VARIABLE) + appendStringInfo(buf, + "\n AFTER MATCH SKIP TO FIRST %s ", + wc->rpSkipVariable); + else if (wc->rpSkipTo == ST_LAST_VARIABLE) + appendStringInfo(buf, + "\n AFTER MATCH SKIP TO LAST %s ", + wc->rpSkipVariable); + else if (wc->rpSkipTo == ST_VARIABLE) + appendStringInfo(buf, + "\n AFTER MATCH SKIP TO %s ", + wc->rpSkipVariable); + + if (wc->initial) + appendStringInfoString(buf, "\n INITIAL"); + + if (wc->patternVariable) + { + appendStringInfoString(buf, "\n PATTERN "); + get_rule_pattern(wc->patternVariable, wc->patternRegexp, + false, context); + } + + if (wc->defineClause) + { + appendStringInfoString(buf, "\n DEFINE\n"); + get_rule_define(wc->defineClause, wc->patternVariable, + false, context); + appendStringInfoChar(buf, ' '); + } + /* we will now have a trailing space; remove it */ buf->len--; } -- 2.25.1 ----Next_Part(Wed_May_15_09_02_03_2024_008)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="v19-0004-Row-pattern-recognition-patch-planner.patch" ^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: PoC - psql - emphases line with table name in verbose output @ 2026-04-14 03:42 Pavel Stehule <[email protected]> 0 siblings, 1 reply; 9+ messages in thread From: Pavel Stehule @ 2026-04-14 03:42 UTC (permalink / raw) To: PostgreSQL Hackers <[email protected]> Hi rebase, new commit message and minor cleaning Regards Pavel Attachments: [text/x-patch] v20260414-1-0001-Print-opening-INFO-lines-with-coulours.patch (2.3K, ../../CAFj8pRDarWO-OsR+u0dWs=Y6aVOc+ebb_PJH8CdUuwmdOmR4tA@mail.gmail.com/3-v20260414-1-0001-Print-opening-INFO-lines-with-coulours.patch) download | inline diff: From 37bd1aa00fea7c7d88c81bea15694212e99b4e52 Mon Sep 17 00:00:00 2001 From: "[email protected]" <[email protected]> Date: Sun, 29 Mar 2026 18:01:16 +0200 Subject: [PATCH] Print opening INFO lines with coulours By default it use inverse printing for lines: INFO: vacuuming tablename INFO: repacking tablename INFO: analyzing tablename It helps with orientation inside verbose output of REINDEX, VACUUM and ANALYZE commands. --- src/common/logging.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/common/logging.c b/src/common/logging.c index 4a69d96281b..3e5e9eea6e8 100644 --- a/src/common/logging.c +++ b/src/common/logging.c @@ -32,11 +32,13 @@ static const char *sgr_error = NULL; static const char *sgr_warning = NULL; static const char *sgr_note = NULL; static const char *sgr_locus = NULL; +static const char *sgr_info_command = NULL; #define SGR_ERROR_DEFAULT "01;31" #define SGR_WARNING_DEFAULT "01;35" #define SGR_NOTE_DEFAULT "01;36" #define SGR_LOCUS_DEFAULT "01" +#define SGR_INFO_COMMAND_DEFAULT "07" #define ANSI_ESCAPE_FMT "\x1b[%sm" #define ANSI_ESCAPE_RESET "\x1b[0m" @@ -145,6 +147,8 @@ pg_logging_init(const char *argv0) sgr_note = strdup(value); if (strcmp(name, "locus") == 0) sgr_locus = strdup(value); + if (strcmp(name, "info_command") == 0) + sgr_info_command = strdup(value); } } @@ -157,6 +161,7 @@ pg_logging_init(const char *argv0) sgr_warning = SGR_WARNING_DEFAULT; sgr_note = SGR_NOTE_DEFAULT; sgr_locus = SGR_LOCUS_DEFAULT; + sgr_info_command = SGR_INFO_COMMAND_DEFAULT; } } } @@ -353,7 +358,17 @@ pg_log_generic_v(enum pg_log_level level, enum pg_log_part part, if (required_len >= 2 && buf[required_len - 2] == '\n') buf[required_len - 2] = '\0'; - fprintf(stderr, "%s\n", buf); + if (level == PG_LOG_INFO && sgr_info_command && + (strncmp(buf, "INFO: vacuuming", strlen("INFO: vacuuming")) == 0 || + strncmp(buf, "INFO: repacking", strlen("INFO: repacking")) == 0 || + strncmp(buf, "INFO: analyzing", strlen("INFO: analyzing")) == 0)) + { + fprintf(stderr, ANSI_ESCAPE_FMT, sgr_info_command); + fprintf(stderr, "%s\n", buf); + fprintf(stderr, ANSI_ESCAPE_RESET); + } + else + fprintf(stderr, "%s\n", buf); if (log_logfile) { fprintf(log_logfile, "%s\n", buf); -- 2.53.0 ^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: PoC - psql - emphases line with table name in verbose output @ 2026-04-23 15:17 Jim Jones <[email protected]> parent: Pavel Stehule <[email protected]> 0 siblings, 1 reply; 9+ messages in thread From: Jim Jones @ 2026-04-23 15:17 UTC (permalink / raw) To: Pavel Stehule <[email protected]>; PostgreSQL Hackers <[email protected]> Hi Pavel On 14/04/2026 05:42, Pavel Stehule wrote: > rebase, new commit message and minor cleaning Thanks for the patch! I tested the patch and setting PG_COLOR highlights the INFO messages. A few observations: == string matching is locale-fragile == Since the code relies on these fixed strings ... if (level == PG_LOG_INFO && sgr_info_command && (strncmp(buf, "INFO: vacuuming", strlen("INFO: vacuuming")) == 0 || strncmp(buf, "INFO: repacking", strlen("INFO: repacking")) == 0 || strncmp(buf, "INFO: analyzing", strlen("INFO: analyzing")) == 0)) .. the conditions only work if lc_messages is set to English. For instance, in German you get a different string, which means that highlighting won't work: $ psql postgres -c "VACUUM VERBOSE pg_class;" 2>&1 | grep INFO INFO: Vacuum von »postgres.pg_catalog.pg_class« INFO: beende Vacuum der Tabelle »postgres.pg_catalog.pg_class«: Index-Scans: 0 $ psql postgres -c "ANALYSE VERBOSE pg_class;" 2>&1 | grep INFO INFO: analysiere »pg_catalog.pg_class« INFO: »pg_class«: 15 von 15 Seiten gelesen, enthalten 452 lebende Zeilen und 0 tote Zeilen; 452 Zeilen in Stichprobe, schätzungsweise 452 Zeilen insgesamt INFO: finished analyzing table "postgres.pg_catalog.pg_class" == fixed command list == Future verbose operations, if not added to this list, would silently get no highlighting. I'm wondering if it is possible to achieve it (locale-agnostic) only for certain commands without touching the code on the server side. Only by checking strings it'll be difficult to identify which INFO messages to highlight. Thanks! Best, Jim ^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: PoC - psql - emphases line with table name in verbose output @ 2026-04-24 06:56 Pavel Stehule <[email protected]> parent: Jim Jones <[email protected]> 0 siblings, 1 reply; 9+ messages in thread From: Pavel Stehule @ 2026-04-24 06:56 UTC (permalink / raw) To: Jim Jones <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> Hi čt 23. 4. 2026 v 17:17 odesílatel Jim Jones <[email protected]> napsal: > Hi Pavel > > On 14/04/2026 05:42, Pavel Stehule wrote: > > rebase, new commit message and minor cleaning > Thanks for the patch! > > I tested the patch and setting PG_COLOR highlights the INFO messages. > > A few observations: > > == string matching is locale-fragile == > > Since the code relies on these fixed strings ... > > if (level == PG_LOG_INFO && sgr_info_command && > (strncmp(buf, "INFO: vacuuming", strlen("INFO: vacuuming")) == 0 || > strncmp(buf, "INFO: repacking", strlen("INFO: repacking")) == 0 || > strncmp(buf, "INFO: analyzing", strlen("INFO: analyzing")) == 0)) > > .. the conditions only work if lc_messages is set to English. For > instance, in German you get a different string, which means that > highlighting won't work: > > $ psql postgres -c "VACUUM VERBOSE pg_class;" 2>&1 | grep INFO > INFO: Vacuum von »postgres.pg_catalog.pg_class« > INFO: beende Vacuum der Tabelle »postgres.pg_catalog.pg_class«: > Index-Scans: 0 > > $ psql postgres -c "ANALYSE VERBOSE pg_class;" 2>&1 | grep INFO > INFO: analysiere »pg_catalog.pg_class« > INFO: »pg_class«: 15 von 15 Seiten gelesen, enthalten 452 lebende > Zeilen und 0 tote Zeilen; 452 Zeilen in Stichprobe, schätzungsweise 452 > Zeilen insgesamt > INFO: finished analyzing table "postgres.pg_catalog.pg_class" > > == fixed command list == > > Future verbose operations, if not added to this list, would silently get > no highlighting. > > I'm wondering if it is possible to achieve it (locale-agnostic) only for > certain commands without touching the code on the server side. Only by > checking strings it'll be difficult to identify which INFO messages to > highlight. > I am afraid this is the end of this direction. :-/ Please, can you check the functionality (only in english). I am interested if this is just helpful and if it makes sense to continue in this feature. Unfortunately, there are not too many possibilities about possible formats, colors in terminals (that can work mostly everywhere). I don't think it is possible to implement this without communication protocol enhancement. And if we will do this, the next question is if we cannot use this for some more complex information about the executed command. For example - I thought about the possibility of teaching psql to read progress stat tables - so can be nice, if the server can send some information to client - maybe pgstat_progres_update can send INFO like - "emphasize: nextinfo, pid: xxxx, progress table: pg_stat_vacuum, commandtype: vacuum, .... Maybe a different approach - instead of a plain text message, we can send messages of this type in client side parsable format - if I am not wrong, we are able to parse json on client side. json is still readable for humans for old clients. On the client side we decide what and how we will display. This can be more generic than just for VERBOSE mode of ANALYZE, VACUUM or REINDEX. some like elog(INFO_CLIENT, '{ "cmdtag": "VACUUM", "state":"started", "progress_tab": "pg_stat_progress_vacuum", "table_name": "yyy", "schema_name":"xxx", ...) elog(INFO_CLIENT, '{"cmdatag": "VACUUM", "state":"finished", "pages_removed": 0, "pages_ ... I don't see some simple and nice solution at this moment. Maybe just using new line after INFO with details so results can looks like INFO: vacuuming "postgres.pg_catalog.pg_class" INFO: finished vacuuming "postgres.pg_catalog.pg_class": index scans: 0 pages: 0 removed, 15 remain, 15 scanned (100.00% of total), 0 eagerly scanned tuples: 0 removed, 452 remain, 0 are dead but not yet removable removable cutoff: 701, which was 0 XIDs old when operation ended frozen: 0 pages from table (0.00% of total) had 0 tuples frozen visibility map: 0 pages set all-visible, 0 pages set all-frozen (0 were all-visible) index scan not needed: 0 pages from table (0.00% of total) had 0 dead item identifiers removed avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s buffer usage: 75 hits, 0 reads, 0 dirtied WAL usage: 0 records, 0 full page images, 0 bytes, 0 full page image bytes, 0 buffers full memory usage: dead item storage 0.02 MB accumulated across 0 resets (limit 64.00 MB each) system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: vacuuming "postgres.pg_catalog.pg_proc" INFO: finished vacuuming "postgres.pg_catalog.pg_proc": index scans: 0 pages: 0 removed, 101 remain, 1 scanned (0.99% of total), 0 eagerly scanned tuples: 0 removed, 3437 remain, 0 are dead but not yet removable removable cutoff: 701, which was 0 XIDs old when operation ended new relfrozenxid: 701, which is 17 XIDs ahead of previous value frozen: 0 pages from table (0.00% of total) had 0 tuples frozen visibility map: 0 pages set all-visible, 0 pages set all-frozen (0 were all-visible) index scan not needed: 0 pages from table (0.00% of total) had 0 dead item identifiers removed avg read rate: 4.534 MB/s, avg write rate: 1.133 MB/s buffer usage: 15 hits, 4 reads, 1 dirtied WAL usage: 1 records, 1 full page images, 5871 bytes, 5752 full page image bytes, 0 buffers full memory usage: dead item storage 0.02 MB accumulated across 0 resets (limit 64.00 MB each) system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: vacuuming "postgres.pg_toast.pg_toast_1255" INFO: finished vacuuming "postgres.pg_toast.pg_toast_1255": index scans: 0 pages: 0 removed, 2 remain, 2 scanned (100.00% of total), 0 eagerly scanned tuples: 0 removed, 7 remain, 0 are dead but not yet removable removable cutoff: 701, which was 0 XIDs old when operation ended new relfrozenxid: 701, which is 17 XIDs ahead of previous value frozen: 0 pages from table (0.00% of total) had 0 tuples frozen visibility map: 0 pages set all-visible, 0 pages set all-frozen (0 were all-visible) index scan not needed: 0 pages from table (0.00% of total) had 0 dead item identifiers removed avg read rate: 19.462 MB/s, avg write rate: 2.780 MB/s buffer usage: 36 hits, 7 reads, 1 dirtied WAL usage: 1 records, 1 full page images, 4255 bytes, 4136 full page image bytes, 0 buffers full memory usage: dead item storage 0.02 MB accumulated across 0 resets (limit 64.00 MB each) system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s This is small change and maybe it can be enough Regards Pavel > Thanks! > > Best, Jim > > ^ permalink raw reply [nested|flat] 9+ messages in thread
* Re: PoC - psql - emphases line with table name in verbose output @ 2026-04-24 10:41 Jim Jones <[email protected]> parent: Pavel Stehule <[email protected]> 0 siblings, 0 replies; 9+ messages in thread From: Jim Jones @ 2026-04-24 10:41 UTC (permalink / raw) To: Pavel Stehule <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]> On 24/04/2026 08:56, Pavel Stehule wrote: > Please, can you check the functionality (only in english). I am > interested if this is just helpful and if it makes sense to continue in > this feature. Unfortunately, there are not too many possibilities about > possible formats, colors in terminals (that can work mostly everywhere). I tested it yesterday with lc_messages = 'en_GB.UTF-8' and it worked just fine. And I also agree that it is currently hard to spot tables in the verbose output. > I don't think it is possible to implement this without communication > protocol enhancement. And if we will do this, the next question is if we > cannot use this for some more complex information about the executed > command. > > For example - I thought about the possibility of teaching psql to read > progress stat tables - so can be nice, if the server can send some > information to client - maybe pgstat_progres_update can send INFO > > like - "emphasize: nextinfo, pid: xxxx, progress table: pg_stat_vacuum, > commandtype: vacuum, .... > > Maybe a different approach - instead of a plain text message, we can > send messages of this type in client side parsable format - if I am not > wrong, we are able to parse json on client side. json is still readable > for humans for old clients. On the client side we decide what and how we > will display. This can be more generic than just for VERBOSE mode of > ANALYZE, VACUUM or REINDEX. > > some like > > elog(INFO_CLIENT, '{ "cmdtag": "VACUUM", "state":"started", > "progress_tab": "pg_stat_progress_vacuum", "table_name": "yyy", > "schema_name":"xxx", ...) > > elog(INFO_CLIENT, '{"cmdatag": "VACUUM", "state":"finished", > "pages_removed": 0, "pages_ ... I think it is feasible. The question is now is rather, is it worth the trouble just to highlight an output? I also don't see an easy way to implement this feature. It's virtually impossible to do that without some change in the server side. I took a look at the code and perhaps NoticeProcessor() at common.c would be better than pg_log_generic_v() for that, but still the problem of identifying the INFO messages remains. One option would be to create a new SQLSTATE and add it to the ereport calls, e.g. ERRCODE_VERBOSE_PROGRESS_INFO if (verbose) { if (vacrel->aggressive) ereport(INFO, errcode(ERRCODE_VERBOSE_PROGRESS_INFO), (errmsg("aggressively vacuuming \"%s.%s.%s\"", vacrel->dbname, vacrel->relnamespace, vacrel->relname))); else ereport(INFO, errcode(ERRCODE_VERBOSE_PROGRESS_INFO), (errmsg("vacuuming \"%s.%s.%s\"", vacrel->dbname, vacrel->relnamespace, vacrel->relname))); } Then in NoticeProcessor() check for it and act accordingly: const char *state = PQresultErrorField(result, PG_DIAG_SQLSTATE); if (state && strcmp(state, "00001") == 0) ... apply color / blank line / bold / whatever But it also looks like we'd be using SQLSTATES incorrectly. That would certainly require a bit more research. > I don't see some simple and nice solution at this moment. Maybe just > using new line after INFO with details It's much less invasive with more or less the same effect. However, the Error Message Style Guide explicitly says "Don't put any specific assumptions about formatting into the message texts" and "Don't end a message with a newline"[1]. So I'm afraid it's not an option either :\ Of course, it could also disturb external tools that parse the verbose output, but that alone wouldn't be a blocker IMHO. Thanks! Best, Jim 1 - https://www.postgresql.org/docs/current/error-style-guide.html#ERROR-STYLE-GUIDE-FORMATTING ^ permalink raw reply [nested|flat] 9+ messages in thread
end of thread, other threads:[~2026-04-24 10:41 UTC | newest] Thread overview: 9+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2019-03-12 23:21 [PATCH] Introduce timeout capability for ConditionVariableSleep Shawn Debnath <[email protected]> 2019-03-12 23:21 [PATCH] Introduce timeout capability for ConditionVariableSleep Shawn Debnath <[email protected]> 2019-03-12 23:21 [PATCH] Introduce timeout capability for ConditionVariableSleep Shawn Debnath <[email protected]> 2019-03-12 23:21 [PATCH] Introduce timeout capability for ConditionVariableSleep Shawn Debnath <[email protected]> 2024-05-14 23:26 [PATCH v19 3/8] Row pattern recognition patch (rewriter). Tatsuo Ishii <[email protected]> 2026-04-14 03:42 Re: PoC - psql - emphases line with table name in verbose output Pavel Stehule <[email protected]> 2026-04-23 15:17 ` Re: PoC - psql - emphases line with table name in verbose output Jim Jones <[email protected]> 2026-04-24 06:56 ` Re: PoC - psql - emphases line with table name in verbose output Pavel Stehule <[email protected]> 2026-04-24 10:41 ` Re: PoC - psql - emphases line with table name in verbose output Jim Jones <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox