aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/runtime.sgml23
-rw-r--r--src/backend/tcop/postgres.c56
-rw-r--r--src/backend/utils/misc/guc.c112
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample2
-rw-r--r--src/include/tcop/tcopprot.h15
-rw-r--r--src/include/utils/guc.h3
6 files changed, 161 insertions, 50 deletions
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index f23772b8da7..bf9caac2aee 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
<!--
-$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.257 2004/04/05 03:02:03 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.258 2004/04/07 05:05:49 momjian Exp $
-->
<Chapter Id="runtime">
@@ -2121,12 +2121,21 @@ SET ENABLE_SEQSCAN TO OFF;
</varlistentry>
<varlistentry id="guc-log-statement" xreflabel="log_statement">
- <term><varname>log_statement</varname> (<type>boolean</type>)</term>
- <listitem>
- <para>
- Causes each SQL statement to be logged. The default is
- off. Only superusers can disable this option if it has been
- enabled by an administrator.
+ <term><varname>log_statement</varname> (<type>string</type>)</term>
+ <listitem>
+ <para>
+ Controls which SQL statement are logged. Valid values are
+ <literal>all</>, <literal>ddl</>, <literal>mod</>, and
+ <literal>none</>. <literal>ddl</> logs all data definition
+ commands like <literal>CREATE</>, <literal>ALTER</>, and
+ <literal>DROP</> commands. <literal>mod</> logs all
+ <literal>ddl</> statements, plus <literal>INSERT</>,
+ <literal>UPDATE</>, <literal>DELETE</>, <literal>TRUNCATE</>,
+ and <literal>COPY FROM</>. <literal>PREPARE</> and
+ <literal>EXPLAIN ANALYZE</> statements are also considered for
+ appropriate commands. The default is <literal>none</>. Only
+ superusers can reduce the detail of this option if it has been
+ set by an administrator.
</para>
<note>
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index ff0ac6aa64a..6cece54b30b 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.397 2004/03/24 22:40:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.398 2004/04/07 05:05:49 momjian Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -87,6 +87,8 @@ bool InError = false;
/* flag for logging end of session */
bool Log_disconnections = false;
+LogStmtLevel log_statement = LOGSTMT_NONE;
+
/*
* Flags for expensive function optimization -- JMH 3/9/92
*/
@@ -471,9 +473,10 @@ pg_parse_and_rewrite(const char *query_string, /* string to execute */
List *
pg_parse_query(const char *query_string)
{
- List *raw_parsetree_list;
+ List *raw_parsetree_list,
+ *parsetree_item;
- if (log_statement)
+ if (log_statement == LOGSTMT_ALL)
ereport(LOG,
(errmsg("statement: %s", query_string)));
@@ -482,6 +485,51 @@ pg_parse_query(const char *query_string)
raw_parsetree_list = raw_parser(query_string);
+ /* do log_statement tests for mod and ddl */
+ if (log_statement == LOGSTMT_MOD ||
+ log_statement == LOGSTMT_DDL)
+ {
+ foreach(parsetree_item, raw_parsetree_list)
+ {
+ Node *parsetree = (Node *) lfirst(parsetree_item);
+ const char *commandTag;
+
+ if (IsA(parsetree, ExplainStmt) &&
+ ((ExplainStmt *)parsetree)->analyze)
+ parsetree = (Node *)(((ExplainStmt *)parsetree)->query);
+
+ if (IsA(parsetree, PrepareStmt))
+ parsetree = (Node *)(((PrepareStmt *)parsetree)->query);
+
+ if (IsA(parsetree, SelectStmt))
+ continue; /* optimization for frequent command */
+
+ if (log_statement == LOGSTMT_MOD &&
+ (IsA(parsetree, InsertStmt) ||
+ IsA(parsetree, UpdateStmt) ||
+ IsA(parsetree, DeleteStmt) ||
+ IsA(parsetree, TruncateStmt) ||
+ (IsA(parsetree, CopyStmt) &&
+ ((CopyStmt *)parsetree)->is_from))) /* COPY FROM */
+ {
+ ereport(LOG,
+ (errmsg("statement: %s", query_string)));
+ break;
+ }
+ commandTag = CreateCommandTag(parsetree);
+ if (strncmp(commandTag, "CREATE ", strlen("CREATE ")) == 0 ||
+ strncmp(commandTag, "ALTER ", strlen("ALTER ")) == 0 ||
+ strncmp(commandTag, "DROP ", strlen("DROP ")) == 0 ||
+ IsA(parsetree, GrantStmt) || /* GRANT or REVOKE */
+ IsA(parsetree, CommentStmt))
+ {
+ ereport(LOG,
+ (errmsg("statement: %s", query_string)));
+ break;
+ }
+ }
+ }
+
if (log_parser_stats)
ShowUsage("PARSER STATISTICS");
@@ -2488,7 +2536,7 @@ PostgresMain(int argc, char *argv[], const char *username)
SetConfigOption("log_disconnections", "true", debug_context, gucsource);
}
if (debug_flag >= 2)
- SetConfigOption("log_statement", "true", debug_context, gucsource);
+ SetConfigOption("log_statement", "all", debug_context, gucsource);
if (debug_flag >= 3)
SetConfigOption("debug_print_parse", "true", debug_context, gucsource);
if (debug_flag >= 4)
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 215378749b6..adbbda25d48 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.197 2004/04/05 03:02:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.198 2004/04/07 05:05:50 momjian Exp $
*
*--------------------------------------------------------------------
*/
@@ -86,18 +86,22 @@ static const char *assign_facility(const char *facility,
bool doit, GucSource source);
#endif
-static const char *assign_defaultxactisolevel(const char *newval,
- bool doit, GucSource source);
-static const char *assign_log_min_messages(const char *newval,
- bool doit, GucSource source);
+static const char *assign_defaultxactisolevel(const char *newval, bool doit,
+ GucSource source);
+static const char *assign_log_min_messages(const char *newval, bool doit,
+ GucSource source);
static const char *assign_client_min_messages(const char *newval,
bool doit, GucSource source);
static const char *assign_min_error_statement(const char *newval, bool doit,
GucSource source);
-static const char *assign_msglvl(int *var, const char *newval,
- bool doit, GucSource source);
+static const char *assign_msglvl(int *var, const char *newval, bool doit,
+ GucSource source);
static const char *assign_log_error_verbosity(const char *newval, bool doit,
GucSource source);
+static const char *assign_log_statement(const char *newval, bool doit,
+ GucSource source);
+static const char *assign_log_stmtlvl(int *var, const char *newval,
+ bool doit, GucSource source);
static bool assign_phony_autocommit(bool newval, bool doit, GucSource source);
@@ -107,7 +111,6 @@ static bool assign_phony_autocommit(bool newval, bool doit, GucSource source);
#ifdef USE_ASSERT_CHECKING
bool assert_enabled = true;
#endif
-bool log_statement = false;
bool log_duration = false;
bool Debug_print_plan = false;
bool Debug_print_parse = false;
@@ -145,6 +148,7 @@ int log_min_duration_statement = -1;
static char *client_min_messages_str;
static char *log_min_messages_str;
static char *log_error_verbosity_str;
+static char *log_statement_str;
static char *log_min_error_statement_str;
static char *log_destination_string;
static bool phony_autocommit;
@@ -528,14 +532,6 @@ static struct config_bool ConfigureNamesBool[] =
false, NULL, NULL
},
{
- {"log_statement", PGC_USERLIMIT, LOGGING_WHAT,
- gettext_noop("Logs each SQL statement."),
- NULL
- },
- &log_statement,
- false, NULL, NULL
- },
- {
{"log_duration", PGC_USERLIMIT, LOGGING_WHAT,
gettext_noop("Logs the duration each completed SQL statement."),
NULL
@@ -1442,6 +1438,14 @@ static struct config_string ConfigureNamesString[] =
&log_error_verbosity_str,
"default", assign_log_error_verbosity, NULL
},
+ {
+ {"log_statement", PGC_USERLIMIT, LOGGING_WHAT,
+ gettext_noop("Sets the type of statements logged."),
+ gettext_noop("Valid values are \"none\", \"mod\", \"ddl\", and \"all\".")
+ },
+ &log_statement_str,
+ "none", assign_log_statement, NULL
+ },
{
{"log_min_error_statement", PGC_USERLIMIT, LOGGING_WHEN,
@@ -2007,14 +2011,11 @@ InitializeGUCOptions(void)
struct config_string *conf = (struct config_string *) gconf;
char *str;
- /*
- * Check to make sure we only have valid
- * PGC_USERLIMITs
- */
+ /* Check to make sure we only have valid PGC_USERLIMITs */
Assert(conf->gen.context != PGC_USERLIMIT ||
conf->assign_hook == assign_log_min_messages ||
- conf->assign_hook == assign_client_min_messages ||
- conf->assign_hook == assign_min_error_statement);
+ conf->assign_hook == assign_min_error_statement ||
+ conf->assign_hook == assign_log_statement);
*conf->variable = NULL;
conf->reset_val = NULL;
conf->session_val = NULL;
@@ -3025,15 +3026,23 @@ set_config_option(const char *name, const char *value,
if (record->context == PGC_USERLIMIT &&
IsUnderPostmaster && !superuser())
{
- int old_int_value,
- new_int_value;
-
- /* all USERLIMIT strings are message levels */
- assign_msglvl(&new_int_value, newval,
- true, source);
- assign_msglvl(&old_int_value, conf->reset_val,
- true, source);
- if (new_int_value > old_int_value)
+ int var_value, reset_value, new_value;
+ const char * (*var_hook) (int *var, const char *newval,
+ bool doit, GucSource source);
+
+ if (conf->assign_hook == assign_log_statement)
+ var_hook = assign_log_stmtlvl;
+ else
+ var_hook = assign_msglvl;
+
+ (*var_hook) (&new_value, newval, true, source);
+ (*var_hook) (&reset_value, conf->reset_val, true,
+ source);
+ (*var_hook) (&var_value, *conf->variable, true,
+ source);
+
+ /* Limit non-superuser changes */
+ if (new_value > reset_value)
{
/* Limit non-superuser changes */
if (source > PGC_S_UNPRIVILEGED)
@@ -3046,10 +3055,9 @@ set_config_option(const char *name, const char *value,
return false;
}
}
- /* Allow change if admin should override */
- assign_msglvl(&old_int_value, *conf->variable,
- true, source);
- if (new_int_value < old_int_value)
+
+ /* Allow change if admin should override */
+ if (new_value < var_value)
{
if (source < PGC_S_UNPRIVILEGED &&
record->source > PGC_S_UNPRIVILEGED)
@@ -4652,6 +4660,40 @@ assign_log_error_verbosity(const char *newval, bool doit, GucSource source)
return newval; /* OK */
}
+static const char *
+assign_log_statement(const char *newval, bool doit, GucSource source)
+{
+ return (assign_log_stmtlvl((int *)&log_statement, newval, doit, source));
+}
+
+static const char *
+assign_log_stmtlvl(int *var, const char *newval, bool doit, GucSource source)
+{
+ if (strcasecmp(newval, "none") == 0)
+ {
+ if (doit)
+ (*var) = LOGSTMT_NONE;
+ }
+ else if (strcasecmp(newval, "mod") == 0)
+ {
+ if (doit)
+ (*var) = LOGSTMT_MOD;
+ }
+ else if (strcasecmp(newval, "ddl") == 0)
+ {
+ if (doit)
+ (*var) = LOGSTMT_DDL;
+ }
+ else if (strcasecmp(newval, "all") == 0)
+ {
+ if (doit)
+ (*var) = LOGSTMT_ALL;
+ }
+ else
+ return NULL; /* fail */
+ return newval; /* OK */
+}
+
static bool
assign_phony_autocommit(bool newval, bool doit, GucSource source)
{
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 536e3de0c06..7983abbf7f0 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -191,7 +191,7 @@
# %s=session start timestamp
# %x=stop here in non-session processes
# %%='%'
-#log_statement = false
+#log_statement = 'none' # none, mod, ddl, all
#log_hostname = false
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index b2520b210e6..046fe3e810e 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.63 2004/03/24 22:40:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.64 2004/04/07 05:05:50 momjian Exp $
*
* OLD COMMENTS
* This file was created so that other c files could get the two
@@ -35,6 +35,19 @@ extern DLLIMPORT const char *debug_query_string;
extern char *rendezvous_name;
extern int max_stack_depth;
+/* GUC-configurable parameters */
+
+typedef enum
+{
+ /* Reverse order so GUC USERLIMIT is easier */
+ LOGSTMT_ALL, /* log all statements */
+ LOGSTMT_DDL, /* log data definition statements */
+ LOGSTMT_MOD, /* log modification statements, plus DDL */
+ LOGSTMT_NONE /* log no statements */
+} LogStmtLevel;
+
+extern LogStmtLevel log_statement;
+
#ifndef BOOTSTRAP_INCLUDE
extern List *pg_parse_and_rewrite(const char *query_string,
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 597f10069fd..ca1f87b1fe1 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -7,7 +7,7 @@
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
- * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.44 2004/01/19 19:04:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.45 2004/04/07 05:05:50 momjian Exp $
*--------------------------------------------------------------------
*/
#ifndef GUC_H
@@ -103,7 +103,6 @@ typedef enum
} GucSource;
/* GUC vars that are actually declared in guc.c, rather than elsewhere */
-extern bool log_statement;
extern bool log_duration;
extern bool Debug_print_plan;
extern bool Debug_print_parse;