On 2024/3/11 09:25, Quan Zongliang wrote:


On 2024/3/4 15:48, jian he wrote:

Maybe we can tolerate LOG, first output the query plan then statement.

It is more appropriate to let the extension solve its own problems.
Of course, this change is not easy to implement.
Due to the way XID is assigned, there seems to be no good solution at the moment.


According to the discussion with Jian He. Use the guc hook to check if the xid needs to be output. If needed, the statement log can be delayed to be output.
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 76f48b13d2..217910c9de 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -1068,11 +1068,14 @@ exec_simple_query(const char *query_string)
        /* Log immediately if dictated by log_statement */
        if (check_log_statement(parsetree_list))
        {
-               ereport(LOG,
-                               (errmsg("statement: %s", query_string),
-                                errhidestmt(true),
-                                errdetail_execute(parsetree_list)));
-               was_logged = true;
+               if (!Log_has_xid || 
TransactionIdIsValid(GetTopTransactionIdIfAny()))
+               {
+                       ereport(LOG,
+                                       (errmsg("statement: %s", query_string),
+                                       errhidestmt(true),
+                                       errdetail_execute(parsetree_list)));
+                       was_logged = true;
+               }
        }
 
        /*
@@ -1283,6 +1286,16 @@ exec_simple_query(const char *query_string)
 
                PortalDrop(portal, false);
 
+               /* Log if dictated by log_statement and has not been logged. */
+               if (!was_logged && check_log_statement(parsetree_list))
+               {
+                       ereport(LOG,
+                                       (errmsg("statement: %s", query_string),
+                                       errhidestmt(true),
+                                       errdetail_execute(parsetree_list)));
+                       was_logged = true;
+               }
+
                if (lnext(parsetree_list, parsetree_item) == NULL)
                {
                        /*
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 605ff3b045..e7dd9f5027 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -79,6 +79,7 @@
 #include "storage/ipc.h"
 #include "storage/proc.h"
 #include "tcop/tcopprot.h"
+#include "utils/guc.h"
 #include "utils/guc_hooks.h"
 #include "utils/memutils.h"
 #include "utils/ps_status.h"
@@ -114,6 +115,9 @@ char           *Log_destination_string = NULL;
 bool           syslog_sequence_numbers = true;
 bool           syslog_split_messages = true;
 
+/* Whether the transaction id will appear in the log messages. */
+bool           Log_has_xid = false;
+
 /* Processed form of backtrace_functions GUC */
 static char *backtrace_function_list;
 
@@ -286,6 +290,50 @@ message_level_is_interesting(int elevel)
 }
 
 
+/*
+ * check_log_line_prefix: GUC check_hook for Log_line_prefix
+ */
+bool check_log_line_prefix(char **newval, void **extra, GucSource source)
+{
+       const char *p;
+
+       if ((*newval) == NULL)
+       {
+               Log_has_xid = false;
+               return true;
+       }
+
+       Log_has_xid = false;
+
+       for (p = (*newval); *p != '\0'; p++)
+       {
+               if (*p != '%')
+               {
+                       /* literal char, just skip */
+                       continue;
+               }
+
+               /* must be a '%', so skip to the next char */
+               p++;
+               if (*p == '\0')
+                       break;                          /* format error - 
ignore it */
+               else if (*p == '%')
+               {
+                       /* string contains %% */
+                       continue;
+               }
+
+               /* process the option */
+               if (*p == 'x')
+               {
+                       Log_has_xid = true;
+                       break;
+               }
+       }
+
+       return true;
+}
+
 /*
  * in_error_recursion_trouble --- are we at risk of infinite error recursion?
  *
diff --git a/src/backend/utils/misc/guc_tables.c 
b/src/backend/utils/misc/guc_tables.c
index c68fdc008b..96948e5005 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4103,7 +4103,7 @@ struct config_string ConfigureNamesString[] =
                },
                &Log_line_prefix,
                "%m [%p] ",
-               NULL, NULL, NULL
+               check_log_line_prefix, NULL, NULL
        },
 
        {
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 054dd2bf62..9536146ce3 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -502,6 +502,8 @@ extern PGDLLIMPORT char *Log_destination_string;
 extern PGDLLIMPORT bool syslog_sequence_numbers;
 extern PGDLLIMPORT bool syslog_split_messages;
 
+extern PGDLLIMPORT bool        Log_has_xid;
+
 /* Log destination bitmap */
 #define LOG_DESTINATION_STDERR  1
 #define LOG_DESTINATION_SYSLOG  2
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index d64dc5fcdb..41f8ba3f16 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -78,6 +78,7 @@ extern bool check_log_destination(char **newval, void **extra,
 extern void assign_log_destination(const char *newval, void *extra);
 extern const char *show_log_file_mode(void);
 extern bool check_log_stats(bool *newval, void **extra, GucSource source);
+extern bool check_log_line_prefix(char **newval, void **extra, GucSource 
source);
 extern bool check_log_timezone(char **newval, void **extra, GucSource source);
 extern void assign_log_timezone(const char *newval, void *extra);
 extern const char *show_log_timezone(void);

Reply via email to