From a9a36905f22a64c18d4cc7774afbd31b1ab22de5 Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Mon, 18 Oct 2021 11:41:37 -0300 Subject: [PATCH 1/2] PG-262: Fix comment extraction on queries. The regular expression was updated to properly capture comments in SQL in the form /* */. The previous regex was capturing everything from /* until the last */ because regex are greedy, this was presenting problems if a input query has something like: SELECT /* comment 1 */ field /* comment 2 */ from FOO; As such, the previous regex would capture anytying between /* comment 1 and comment 2 */, the result would be: /* comment 1 field comment 2*/. Multiline comments are also captured. Multiple comments in one query are now stored in the pg_stat_monitor comments field in the form: /* Comment 1 */, ... , /* Comment N */. --- pg_stat_monitor.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/pg_stat_monitor.c b/pg_stat_monitor.c index a045cc4..4f9a504 100644 --- a/pg_stat_monitor.c +++ b/pg_stat_monitor.c @@ -251,7 +251,7 @@ _PG_init(void) /* * Compile regular expression for extracting out query comments only once. */ - rc = regcomp(&preg_query_comments, "/\\*.*\\*/", 0); + rc = regcomp(&preg_query_comments, "/\\*([^*]|[\r\n]|(\\*+([^*/]|[\r\n])))*\\*+/", REG_EXTENDED); if (rc != 0) { elog(ERROR, "pg_stat_monitor: query comments regcomp() failed, return code=(%d)\n", rc); @@ -3461,12 +3461,37 @@ extract_query_comments(const char *query, char *comments, size_t max_len) int rc; size_t nmatch = 1; regmatch_t pmatch; + regoff_t comment_len, total_len = 0; + const char *s = query; - rc = regexec(&preg_query_comments, query, nmatch, &pmatch, 0); - if (rc != 0) - return; + while (total_len < max_len) + { + rc = regexec(&preg_query_comments, s, nmatch, &pmatch, 0); + if (rc != 0) + break; - snprintf(comments, max_len, "%.*s", pmatch.rm_eo - pmatch.rm_so -4, &query[pmatch.rm_so + 2]); + comment_len = pmatch.rm_eo - pmatch.rm_so; + + if (total_len + comment_len > max_len) + break; /* TODO: log error in error view, insufficient space for comment. */ + + total_len += comment_len; + + /* Not 1st iteration, append ", " before next comment. */ + if (s != query) + { + if (total_len + 2 > max_len) + break; /* TODO: log error in error view, insufficient space for ", " + comment. */ + + memcpy(comments, ", ", 2); + comments += 2; + total_len += 2; + } + + memcpy(comments, s + pmatch.rm_so, comment_len); + comments += comment_len; + s += pmatch.rm_eo; + } } #if PG_VERSION_NUM < 140000 From c390f24f5cb7c648a7b5c7a78889b980512aadbe Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Mon, 18 Oct 2021 11:51:49 -0300 Subject: [PATCH 2/2] PG-262: Fix tags regression test. The test was updated to reflect the new output format for query comments. --- regression/expected/tags.out | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/regression/expected/tags.out b/regression/expected/tags.out index dffe468..b2cda90 100644 --- a/regression/expected/tags.out +++ b/regression/expected/tags.out @@ -12,9 +12,9 @@ SELECT 1 AS num /* { "application", psql_app, "real_ip", 192.168.1.3) */; (1 row) SELECT query, comments FROM pg_stat_monitor ORDER BY query COLLATE "C"; - query | comments ----------------------------------------------------------------------------+------------------------------------------------------ - SELECT $1 AS num /* { "application", psql_app, "real_ip", 192.168.1.3) */ | { "application", psql_app, "real_ip", 192.168.1.3) + query | comments +---------------------------------------------------------------------------+---------------------------------------------------------- + SELECT $1 AS num /* { "application", psql_app, "real_ip", 192.168.1.3) */ | /* { "application", psql_app, "real_ip", 192.168.1.3) */ SELECT pg_stat_monitor_reset(); | SELECT query, comments FROM pg_stat_monitor ORDER BY query COLLATE "C"; | (3 rows)