From a9a36905f22a64c18d4cc7774afbd31b1ab22de5 Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Mon, 18 Oct 2021 11:41:37 -0300 Subject: [PATCH] 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