From e6a67acd0866e2b14fc716ef8a17cc7ac870e50f Mon Sep 17 00:00:00 2001 From: MasaoFujii Date: Fri, 20 Jun 2014 20:39:08 +0900 Subject: [PATCH] Redefine log_statement as a list. --- doc/src/sgml/config.sgml | 14 +++++- src/backend/tcop/fastpath.c | 2 +- src/backend/tcop/postgres.c | 3 +- src/backend/tcop/utility.c | 60 +++++++++++++------------- src/backend/utils/misc/guc.c | 97 ++++++++++++++++++++++++++++++++++-------- src/include/tcop/tcopprot.h | 15 +++--- src/include/tcop/utility.h | 2 +- 7 files changed, 132 insertions(+), 61 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 8f0ca4c..e93dd37 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -4490,7 +4490,7 @@ FROM pg_stat_activity; - log_statement (enum) + log_statement (string) log_statement configuration parameter @@ -4498,14 +4498,16 @@ FROM pg_stat_activity; Controls which SQL statements are logged. Valid values are - none (off), ddl, mod, and - all (all statements). ddl logs all data definition + none (off), ddl, mod, dml, + and all (all statements). ddl logs all data definition statements, such as CREATE, ALTER, and DROP statements. mod logs all ddl statements, plus data-modifying statements such as INSERT, UPDATE, DELETE, TRUNCATE, and COPY FROM. + dml logs all data-modifying statements, plus query access + statements such as SELECT and COPY TO. PREPARE, EXECUTE, and EXPLAIN ANALYZE statements are also logged if their contained command is of an appropriate type. For clients using @@ -4515,6 +4517,12 @@ FROM pg_stat_activity; + This parameter can be set to a list of desired SQL statements separated by + commas. Note that if none is specified in the list, other settings + are ignored and then no SQL statements are logged. + + + The default is none. Only superusers can change this setting. diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c index 9f50c5a..c170e54 100644 --- a/src/backend/tcop/fastpath.c +++ b/src/backend/tcop/fastpath.c @@ -340,7 +340,7 @@ HandleFunctionRequest(StringInfo msgBuf) fetch_fp_info(fid, fip); /* Log as soon as we have the function OID and name */ - if (log_statement == LOGSTMT_ALL) + if (log_statement & LOGSTMT_OTHER) { ereport(LOG, (errmsg("fastpath function call: \"%s\" (OID %u)", diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 6b4221a..8a78989 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -89,6 +89,7 @@ CommandDest whereToSendOutput = DestDebug; bool Log_disconnections = false; int log_statement = LOGSTMT_NONE; +char *log_statement_string = NULL; /* GUC variable for maximum stack depth (measured in kilobytes) */ int max_stack_depth = 100; @@ -2017,7 +2018,7 @@ check_log_statement(List *stmt_list) { Node *stmt = (Node *) lfirst(stmt_item); - if (GetCommandLogLevel(stmt) <= log_statement) + if (GetCommandLogLevel(stmt) & log_statement) return true; } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 3423898..8498e30 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -2448,10 +2448,10 @@ CreateCommandTag(Node *parsetree) * This must handle all command types, but since the vast majority * of 'em are utility commands, it seems sensible to keep it here. */ -LogStmtLevel +int GetCommandLogLevel(Node *parsetree) { - LogStmtLevel lev; + int lev; switch (nodeTag(parsetree)) { @@ -2466,24 +2466,24 @@ GetCommandLogLevel(Node *parsetree) if (((SelectStmt *) parsetree)->intoClause) lev = LOGSTMT_DDL; /* SELECT INTO */ else - lev = LOGSTMT_ALL; + lev = LOGSTMT_QUERY; break; /* utility statements --- same whether raw or cooked */ case T_TransactionStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_DeclareCursorStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_ClosePortalStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_FetchStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; /* should this be QUERY? */ break; case T_CreateSchemaStmt: @@ -2541,7 +2541,7 @@ GetCommandLogLevel(Node *parsetree) if (((CopyStmt *) parsetree)->is_from) lev = LOGSTMT_MOD; else - lev = LOGSTMT_ALL; + lev = LOGSTMT_QUERY; break; case T_PrepareStmt: @@ -2563,12 +2563,12 @@ GetCommandLogLevel(Node *parsetree) if (ps) lev = GetCommandLogLevel(ps->plansource->raw_parse_tree); else - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; } break; case T_DeallocateStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_RenameStmt: @@ -2652,7 +2652,7 @@ GetCommandLogLevel(Node *parsetree) break; case T_DoStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_CreatedbStmt: @@ -2672,19 +2672,19 @@ GetCommandLogLevel(Node *parsetree) break; case T_NotifyStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_ListenStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_UnlistenStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_LoadStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_ClusterStmt: @@ -2692,7 +2692,7 @@ GetCommandLogLevel(Node *parsetree) break; case T_VacuumStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_ExplainStmt: @@ -2714,7 +2714,7 @@ GetCommandLogLevel(Node *parsetree) return GetCommandLogLevel(stmt->query); /* Plain EXPLAIN isn't so interesting */ - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; } break; @@ -2727,19 +2727,19 @@ GetCommandLogLevel(Node *parsetree) break; case T_AlterSystemStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_VariableSetStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_VariableShowStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_DiscardStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_CreateTrigStmt: @@ -2787,19 +2787,19 @@ GetCommandLogLevel(Node *parsetree) break; case T_LockStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_ConstraintsSetStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_CheckPointStmt: - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; case T_ReindexStmt: - lev = LOGSTMT_ALL; /* should this be DDL? */ + lev = LOGSTMT_OTHER; /* should this be DDL? */ break; case T_CreateConversionStmt: @@ -2838,7 +2838,7 @@ GetCommandLogLevel(Node *parsetree) switch (stmt->commandType) { case CMD_SELECT: - lev = LOGSTMT_ALL; + lev = LOGSTMT_QUERY; break; case CMD_UPDATE: @@ -2850,7 +2850,7 @@ GetCommandLogLevel(Node *parsetree) default: elog(WARNING, "unrecognized commandType: %d", (int) stmt->commandType); - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; } } @@ -2864,7 +2864,7 @@ GetCommandLogLevel(Node *parsetree) switch (stmt->commandType) { case CMD_SELECT: - lev = LOGSTMT_ALL; + lev = LOGSTMT_QUERY; break; case CMD_UPDATE: @@ -2880,7 +2880,7 @@ GetCommandLogLevel(Node *parsetree) default: elog(WARNING, "unrecognized commandType: %d", (int) stmt->commandType); - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; } @@ -2890,7 +2890,7 @@ GetCommandLogLevel(Node *parsetree) default: elog(WARNING, "unrecognized node type: %d", (int) nodeTag(parsetree)); - lev = LOGSTMT_ALL; + lev = LOGSTMT_OTHER; break; } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 6902c23..67c3552 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -160,6 +160,8 @@ static bool call_string_check_hook(struct config_string * conf, char **newval, static bool call_enum_check_hook(struct config_enum * conf, int *newval, void **extra, GucSource source, int elevel); +static bool check_logstmt(char **newval, void **extra, GucSource source); +static void assign_logstmt(const char *newval, void *extra); static bool check_log_destination(char **newval, void **extra, GucSource source); static void assign_log_destination(const char *newval, void *extra); @@ -275,14 +277,6 @@ static const struct config_enum_entry log_error_verbosity_options[] = { {NULL, 0, false} }; -static const struct config_enum_entry log_statement_options[] = { - {"none", LOGSTMT_NONE, false}, - {"ddl", LOGSTMT_DDL, false}, - {"mod", LOGSTMT_MOD, false}, - {"all", LOGSTMT_ALL, false}, - {NULL, 0, false} -}; - static const struct config_enum_entry isolation_level_options[] = { {"serializable", XACT_SERIALIZABLE, false}, {"repeatable read", XACT_REPEATABLE_READ, false}, @@ -2966,6 +2960,17 @@ static struct config_string ConfigureNamesString[] = }, { + {"log_statement", PGC_SUSET, LOGGING_WHAT, + gettext_noop("Sets the type of statements logged."), + NULL, + GUC_LIST_INPUT + }, + &log_statement_string, + "none", + check_logstmt, assign_logstmt, NULL + }, + + { {"log_destination", PGC_SIGHUP, LOGGING_WHERE, gettext_noop("Sets the destination for server log output."), gettext_noop("Valid values are combinations of \"stderr\", " @@ -3366,16 +3371,6 @@ static struct config_enum ConfigureNamesEnum[] = }, { - {"log_statement", PGC_SUSET, LOGGING_WHAT, - gettext_noop("Sets the type of statements logged."), - NULL - }, - &log_statement, - LOGSTMT_NONE, log_statement_options, - NULL, NULL, NULL - }, - - { {"syslog_facility", PGC_SIGHUP, LOGGING_WHERE, gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."), NULL @@ -8993,6 +8988,72 @@ call_enum_check_hook(struct config_enum * conf, int *newval, void **extra, */ static bool +check_logstmt(char **newval, void **extra, GucSource source) +{ + char *rawstring; + List *elemlist; + ListCell *l; + int newlogstmt = 0; + int *myextra; + bool nolog = false; + + /* Need a modifiable copy of string */ + rawstring = pstrdup(*newval); + + /* Parse string into list of identifiers */ + if (!SplitIdentifierString(rawstring, ',', &elemlist)) + { + /* syntax error in list */ + GUC_check_errdetail("List syntax is invalid."); + pfree(rawstring); + list_free(elemlist); + return false; + } + + foreach(l, elemlist) + { + char *tok = (char *) lfirst(l); + + if (pg_strcasecmp(tok, "none") == 0) + nolog = true; + else if (pg_strcasecmp(tok, "ddl") == 0) + newlogstmt |= LOGSTMT_DDL; + else if (pg_strcasecmp(tok, "mod") == 0) + newlogstmt |= (LOGSTMT_DDL | LOGSTMT_MOD); + else if (pg_strcasecmp(tok, "dml") == 0) + newlogstmt |= (LOGSTMT_MOD | LOGSTMT_QUERY); + else if (pg_strcasecmp(tok, "all") == 0) + newlogstmt = LOGSTMT_ALL; + else + { + GUC_check_errdetail("Unrecognized key word: \"%s\".", tok); + pfree(rawstring); + list_free(elemlist); + return false; + } + } + + /* If "none" is set, ignore other settings and don't log any statements */ + if (nolog) + newlogstmt = LOGSTMT_NONE; + + pfree(rawstring); + list_free(elemlist); + + myextra = (int *) guc_malloc(ERROR, sizeof(int)); + *myextra = newlogstmt; + *extra = (void *) myextra; + + return true; +} + +static void +assign_logstmt(const char *newval, void *extra) +{ + log_statement = *((int *) extra); +} + +static bool check_log_destination(char **newval, void **extra, GucSource source) { char *rawstring; diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index 60f7532..837111c 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -36,15 +36,16 @@ extern int PostAuthDelay; /* GUC-configurable parameters */ -typedef enum -{ - LOGSTMT_NONE, /* log no statements */ - LOGSTMT_DDL, /* log data definition statements */ - LOGSTMT_MOD, /* log modification statements, plus DDL */ - LOGSTMT_ALL /* log all statements */ -} LogStmtLevel; +/* Log statement bigmap */ +#define LOGSTMT_NONE 0 /* log no statements */ +#define LOGSTMT_DDL 1 /* log data definition statements */ +#define LOGSTMT_MOD 2 /* log modification statements */ +#define LOGSTMT_QUERY 4 /* log query access statements */ +#define LOGSTMT_OTHER 8 /* log other statements */ +#define LOGSTMT_ALL 15 /* log all statements */ extern int log_statement; +extern char *log_statement_string; extern List *pg_parse_query(const char *query_string); extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string, diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h index 3ecf931..a3852da 100644 --- a/src/include/tcop/utility.h +++ b/src/include/tcop/utility.h @@ -45,7 +45,7 @@ extern Query *UtilityContainsQuery(Node *parsetree); extern const char *CreateCommandTag(Node *parsetree); -extern LogStmtLevel GetCommandLogLevel(Node *parsetree); +extern int GetCommandLogLevel(Node *parsetree); extern bool CommandIsReadOnly(Node *parsetree); -- 1.7.1