diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 8a16c77a7ddb5c61ddfdd64880faaac32a645279..4c92c2c77a5d90bdf4b73ee04868268af1946bcb 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.162 2008/03/06 18:49:32 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.163 2008/03/10 12:55:13 mha Exp $ -->
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
  -->
@@ -6260,8 +6260,8 @@
      <row>
       <entry><structfield>vartype</structfield></entry>
       <entry><type>text</type></entry>
-      <entry>Parameter type (<literal>bool</>, <literal>integer</>,
-       <literal>real</>, or <literal>string</>)
+      <entry>Parameter type (<literal>bool</>, <literal>enum</>,
+       <literal>integer</>, <literal>real</>, or <literal>string</>)
       </entry>
      </row>
      <row>
@@ -6281,6 +6281,12 @@
       <entry>Maximum allowed value of the parameter (NULL for non-numeric
       values)</entry>
      </row>
+     <row>
+      <entry><structfield>enumvals</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry>Allowed values in enum parameters (NULL for non-enum
+      values)</entry>
+     </row>
     </tbody>
    </tgroup>
   </table>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 0c2740890da5ef27468c60976194f02cc9c766d3..38f996ec0ba850ea752dcbb04ef78543e6b31ee0 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.169 2008/03/10 03:22:29 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.170 2008/03/10 12:55:13 mha Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -162,7 +162,8 @@ SET ENABLE_SEQSCAN TO OFF;
     displaying and updating session run-time parameters.  It is equivalent
     to <command>SHOW</> and <command>SET</>, but can be more convenient
     to use because it can be joined with other tables, or selected from using
-    any desired selection condition.
+    any desired selection condition. It also contains more information about
+    what values are allowed for the parameters.
    </para>
   </sect1>
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 52fbc91ed7fce4f9646991902462e977727e2a42..0bbf48ac0740984cd7a2c5a16157a8861c938c0c 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1996-2008, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.48 2008/01/01 19:45:48 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.49 2008/03/10 12:55:13 mha Exp $
  */
 
 CREATE VIEW pg_roles AS 
@@ -173,7 +173,7 @@ CREATE VIEW pg_settings AS
     SELECT * 
     FROM pg_show_all_settings() AS A 
     (name text, setting text, unit text, category text, short_desc text, extra_desc text,
-     context text, vartype text, source text, min_val text, max_val text);
+     context text, vartype text, source text, min_val text, max_val text, enumvals text);
 
 CREATE RULE pg_settings_u AS 
     ON UPDATE TO pg_settings 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index c95695b7f9a0cea1eb5d4813b9859e5601188344..9fc0389d96bcf12f4118946a93cb59cf2316c4e0 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.543 2008/02/17 04:21:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.544 2008/03/10 12:55:13 mha Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -85,7 +85,7 @@ CommandDest whereToSendOutput = DestDebug;
 /* flag for logging end of session */
 bool		Log_disconnections = false;
 
-LogStmtLevel log_statement = LOGSTMT_NONE;
+int			log_statement = LOGSTMT_NONE;
 
 /* GUC variable for maximum stack depth (measured in kilobytes) */
 int			max_stack_depth = 100;
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index cdb40bb13ebfacd9afd6b6166e5f8bac3d41f19a..8ff4c2fb67850a24a2a72cb562fac8a125038215 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -42,7 +42,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.201 2008/01/01 19:45:53 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.202 2008/03/10 12:55:13 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -80,7 +80,7 @@ sigjmp_buf *PG_exception_stack = NULL;
 extern bool redirection_done;
 
 /* GUC parameters */
-PGErrorVerbosity Log_error_verbosity = PGERROR_VERBOSE;
+int			Log_error_verbosity = PGERROR_VERBOSE;
 char	   *Log_line_prefix = NULL;		/* format for extra log line info */
 int			Log_destination = LOG_DESTINATION_STDERR;
 
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 49958cb4e7f3ab74c62a82ecf89b6fb80294fe11..9f7e87037ff440ffc2a6c5b42d961816f07d0f3f 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.436 2008/03/10 12:39:23 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.437 2008/03/10 12:55:13 mha Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -144,18 +144,6 @@ static const char *assign_defaultxactisolevel(const char *newval, bool doit,
 						   GucSource source);
 static const char *assign_session_replication_role(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_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 *show_num_temp_buffers(void);
 static bool assign_phony_autocommit(bool newval, bool doit, GucSource source);
 static const char *assign_custom_variable_classes(const char *newval, bool doit,
@@ -180,6 +168,41 @@ static const char *show_tcp_keepalives_count(void);
 static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source);
 static bool assign_maxconnections(int newval, bool doit, GucSource source);
 
+/*
+ * Options for enum values defined in this module.
+ */
+static const struct config_enum_entry message_level_options[] = {
+	{"debug", DEBUG2},
+	{"debug5", DEBUG5},
+	{"debug4", DEBUG4},
+	{"debug3", DEBUG3},
+	{"debug2", DEBUG2},
+	{"debug1", DEBUG1},
+	{"log", LOG},
+	{"info", INFO},
+	{"notice", NOTICE},
+	{"warning", WARNING},
+	{"error", ERROR},
+	{"fatal", FATAL},
+	{"panic", PANIC},
+	{NULL, 0}
+};
+
+static const struct config_enum_entry log_error_verbosity_options[] = {
+	{"default", PGERROR_DEFAULT},
+	{"terse", PGERROR_TERSE},
+	{"verbose", PGERROR_VERBOSE},
+	{NULL, 0}
+};
+
+static const struct config_enum_entry log_statement_options[] = {
+	{"none", LOGSTMT_NONE},
+	{"ddl", LOGSTMT_DDL},
+	{"mod", LOGSTMT_MOD},
+	{"all", LOGSTMT_ALL},
+	{NULL, 0}
+};
+
 /*
  * GUC option variables that are exported from this module
  */
@@ -230,11 +253,6 @@ int			tcp_keepalives_count;
  * cases provide the value for SHOW to display.  The real state is elsewhere
  * and is kept in sync by assign_hooks.
  */
-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;
 
 #ifdef HAVE_SYSLOG
@@ -400,7 +418,8 @@ const char *const config_type_names[] =
 	 /* PGC_BOOL */ "bool",
 	 /* PGC_INT */ "integer",
 	 /* PGC_REAL */ "real",
-	 /* PGC_STRING */ "string"
+	 /* PGC_STRING */ "string",
+	 /* PGC_ENUM */ "enum"
 };
 
 
@@ -1915,56 +1934,6 @@ static struct config_string ConfigureNamesString[] =
 		"SQL_ASCII", assign_client_encoding, NULL
 	},
 
-	{
-		{"client_min_messages", PGC_USERSET, LOGGING_WHEN,
-			gettext_noop("Sets the message levels that are sent to the client."),
-			gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, "
-						 "DEBUG1, LOG, NOTICE, WARNING, and ERROR. Each level includes all the "
-						 "levels that follow it. The later the level, the fewer messages are "
-						 "sent.")
-		},
-		&client_min_messages_str,
-		"notice", assign_client_min_messages, NULL
-	},
-
-	{
-		{"log_min_messages", PGC_SUSET, LOGGING_WHEN,
-			gettext_noop("Sets the message levels that are logged."),
-			gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, "
-			"INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. Each level "
-						 "includes all the levels that follow it.")
-		},
-		&log_min_messages_str,
-		"warning", assign_log_min_messages, NULL
-	},
-
-	{
-		{"log_error_verbosity", PGC_SUSET, LOGGING_WHEN,
-			gettext_noop("Sets the verbosity of logged messages."),
-			gettext_noop("Valid values are \"terse\", \"default\", and \"verbose\".")
-		},
-		&log_error_verbosity_str,
-		"default", assign_log_error_verbosity, NULL
-	},
-	{
-		{"log_statement", PGC_SUSET, LOGGING_WHAT,
-			gettext_noop("Sets the type of statements logged."),
-			gettext_noop("Valid values are \"none\", \"ddl\", \"mod\", and \"all\".")
-		},
-		&log_statement_str,
-		"none", assign_log_statement, NULL
-	},
-
-	{
-		{"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
-			gettext_noop("Causes all statements generating error at or above this level to be logged."),
-			gettext_noop("All SQL statements that cause an error of the "
-						 "specified level or a higher level are logged.")
-		},
-		&log_min_error_statement_str,
-		"error", assign_min_error_statement, NULL
-	},
-
 	{
 		{"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Controls information prefixed to each log line."),
@@ -2461,6 +2430,68 @@ static struct config_string ConfigureNamesString[] =
 };
 
 
+static struct config_enum ConfigureNamesEnum[] =
+{
+	{
+		{"client_min_messages", PGC_USERSET, LOGGING_WHEN,
+			gettext_noop("Sets the message levels that are sent to the client."),
+			gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, "
+						 "DEBUG1, LOG, NOTICE, WARNING, and ERROR. Each level includes all the "
+						 "levels that follow it. The later the level, the fewer messages are "
+						 "sent.")
+		},
+		&client_min_messages,
+		NOTICE, message_level_options,NULL, NULL
+	},
+
+	{
+		{"log_error_verbosity", PGC_SUSET, LOGGING_WHEN,
+			gettext_noop("Sets the verbosity of logged messages."),
+			gettext_noop("Valid values are \"terse\", \"default\", and \"verbose\".")
+		},
+		&Log_error_verbosity,
+		PGERROR_DEFAULT, log_error_verbosity_options, NULL, NULL
+	},
+
+	{
+		{"log_min_messages", PGC_SUSET, LOGGING_WHEN,
+			gettext_noop("Sets the message levels that are logged."),
+			gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, "
+			"INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. Each level "
+						 "includes all the levels that follow it.")
+		},
+		&log_min_messages,
+		WARNING, message_level_options, NULL, NULL
+	},
+
+	{
+		{"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
+			gettext_noop("Causes all statements generating error at or above this level to be logged."),
+			gettext_noop("All SQL statements that cause an error of the "
+						 "specified level or a higher level are logged.")
+		},
+		&log_min_error_statement,
+		ERROR, message_level_options, NULL, NULL
+	},
+
+	{
+		{"log_statement", PGC_SUSET, LOGGING_WHAT,
+			gettext_noop("Sets the type of statements logged."),
+			gettext_noop("Valid values are \"none\", \"ddl\", \"mod\", and \"all\".")
+		},
+		&log_statement,
+		LOGSTMT_NONE, log_statement_options, NULL, NULL
+	},
+
+
+
+
+	/* End-of-list marker */
+	{
+		{NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL
+	}
+};
+
 /******** end of options list ********/
 
 
@@ -2627,6 +2658,10 @@ set_stack_value(struct config_generic * gconf, union config_var_value * val)
 							 &(val->stringval),
 							 *((struct config_string *) gconf)->variable);
 			break;
+		case PGC_ENUM:
+			val->enumval = 
+				*((struct config_enum *) gconf)->variable;
+			break;
 	}
 }
 
@@ -2641,6 +2676,7 @@ discard_stack_value(struct config_generic * gconf, union config_var_value * val)
 		case PGC_BOOL:
 		case PGC_INT:
 		case PGC_REAL:
+		case PGC_ENUM:
 			/* no need to do anything */
 			break;
 		case PGC_STRING:
@@ -2708,6 +2744,14 @@ build_guc_variables(void)
 		num_vars++;
 	}
 
+	for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
+	{
+		struct config_enum *conf = &ConfigureNamesEnum[i];
+
+		conf->gen.vartype = PGC_ENUM;
+		num_vars++;
+	}
+
 	/*
 	 * Create table with 20% slack
 	 */
@@ -2730,6 +2774,9 @@ build_guc_variables(void)
 	for (i = 0; ConfigureNamesString[i].gen.name; i++)
 		guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
 
+	for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
+		guc_vars[num_vars++] = &ConfigureNamesEnum[i].gen;
+
 	if (guc_variables)
 		free(guc_variables);
 	guc_variables = guc_vars;
@@ -3080,6 +3127,18 @@ InitializeGUCOptions(void)
 					*conf->variable = str;
 					break;
 				}
+			case PGC_ENUM:
+				{
+					struct config_enum *conf = (struct config_enum *) gconf;
+
+					if (conf->assign_hook)
+						if (!(*conf->assign_hook) (conf->boot_val, true,
+												   PGC_S_DEFAULT))
+							elog(FATAL, "failed to initialize %s to %d",
+								 conf->gen.name, conf->boot_val);
+					*conf->variable = conf->reset_val = conf->boot_val;
+					break;
+				}
 		}
 	}
 
@@ -3379,6 +3438,18 @@ ResetAllOptions(void)
 					conf->gen.source = conf->gen.reset_source;
 					break;
 				}
+			case PGC_ENUM:
+				{
+					struct config_enum *conf = (struct config_enum *) gconf;
+
+					if (conf->assign_hook)
+						if (!(*conf->assign_hook) (conf->reset_val, true,
+												   PGC_S_SESSION))
+							elog(ERROR, "failed to reset %s", conf->gen.name);
+					*conf->variable = conf->reset_val;
+					conf->gen.source = conf->gen.reset_source;
+					break;
+				}
 		}
 
 		if (gconf->flags & GUC_REPORT)
@@ -3728,6 +3799,23 @@ AtEOXact_GUC(bool isCommit, int nestLevel)
 							set_string_field(conf, &stack->masked.stringval, NULL);
 							break;
 						}
+					case PGC_ENUM:
+						{
+							struct config_enum *conf = (struct config_enum *) gconf;
+							int newval = newvalue.enumval;
+
+							if (*conf->variable != newval)
+							{
+								if (conf->assign_hook)
+									if (!(*conf->assign_hook) (newval,
+															   true, PGC_S_OVERRIDE))
+										elog(LOG, "failed to commit %s",
+											 conf->gen.name);
+								*conf->variable = newval;
+								changed = true;
+							}
+							break;
+						}
 				}
 
 				gconf->source = newsource;
@@ -4114,6 +4202,100 @@ parse_real(const char *value, double *result)
 }
 
 
+/*
+ * Lookup the name for an enum option with the selected value.
+ * Should only ever be called with known-valid values, so throws
+ * an elog(ERROR) if the enum option is not found.
+ *
+ * The returned string is a pointer to static data and not
+ * allocated for modification.
+ */
+static const char *
+config_enum_lookup_value(struct config_enum *record, int val)
+{
+	const struct config_enum_entry *entry = record->options;
+	while (entry && entry->name)
+	{
+		if (entry->val == val)
+			return entry->name;
+		entry++;
+	}
+	elog(ERROR, "could not find enum option %d for %s",
+		 val, record->gen.name);
+	return NULL; /* silence compiler */
+}
+
+
+/*
+ * Lookup the value for an enum option with the selected name
+ * (case-insensitive).
+ * If the enum option is found, sets the retval value and returns
+ * true. If it's not found, return FALSE and don't touch retval.
+ *
+ */
+static bool
+config_enum_lookup_name(struct config_enum *record, const char *value, int *retval)
+{
+	const struct config_enum_entry *entry = record->options;
+	
+	if (retval)
+		*retval = 0;			/* suppress compiler warning */
+	
+	while (entry && entry->name)
+	{
+		if (!pg_strcasecmp(value, entry->name))
+		{
+			*retval = entry->val;
+			return TRUE;
+		}
+		entry++;
+	}
+	return FALSE;
+}
+
+
+/*
+ * Returna list of all available options for an enum, separated
+ * by ", " (comma-space).
+ * If prefix is gievn, it is added before the first enum value.
+ * If suffix is given, it is added to the end of the string.
+ */
+static char *
+config_enum_get_options(struct config_enum *record, const char *prefix, const char *suffix)
+{
+	const struct config_enum_entry *entry = record->options;
+	int		len = 0;
+	char   *hintmsg;
+
+	if (!entry || !entry->name)
+		return NULL;					/* Should not happen */
+	
+	while (entry && entry->name)
+	{
+		len += strlen(entry->name) + 2; /* string and ", " */
+		entry++;
+	}
+
+	hintmsg = palloc(len + strlen(prefix) + strlen(suffix) + 2);
+
+	strcpy(hintmsg, prefix);
+	
+	entry = record->options;
+	while (entry && entry->name)
+	{
+		strcat(hintmsg, entry->name);
+		strcat(hintmsg, ", ");
+		entry++;
+	}
+
+	/* Replace final comma/space */
+	hintmsg[strlen(hintmsg)-2] = '\0';
+	strcat(hintmsg, suffix);
+
+	return hintmsg;
+}
+
+
 /*
  * Call a GucStringAssignHook function, being careful to free the
  * "newval" string if the hook ereports.
@@ -4678,6 +4860,77 @@ set_config_option(const char *name, const char *value,
 					free(newval);
 				break;
 			}
+		case PGC_ENUM:
+			{
+				struct config_enum *conf = (struct config_enum *) record;
+				int			newval;
+
+				if (value)
+				{
+					if (!config_enum_lookup_name(conf, value, &newval))
+					{
+						char *hintmsg = config_enum_get_options(conf, "Available values: ", ".");
+
+						ereport(elevel,
+								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								 errmsg("invalid value for parameter \"%s\": \"%s\"",
+										name, value),
+								 hintmsg ? errhint(hintmsg) : 0));
+
+						if (hintmsg)
+							pfree(hintmsg);
+						return false;
+					}
+				}
+				else if (source == PGC_S_DEFAULT)
+					newval = conf->boot_val;
+				else
+				{
+					newval = conf->reset_val;
+					source = conf->gen.reset_source;
+				}
+
+				if (conf->assign_hook)
+					if (!(*conf->assign_hook) (newval, changeVal, source))
+					{
+						ereport(elevel,
+								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+								 errmsg("invalid value for parameter \"%s\": \"%d\"",
+										name, newval)));
+						return false;
+					}
+
+				if (changeVal || makeDefault)
+				{
+					/* Save old value to support transaction abort */
+					if (!makeDefault)
+						push_old_value(&conf->gen, action);
+					if (changeVal)
+					{
+						*conf->variable = newval;
+						conf->gen.source = source;
+					}
+					if (makeDefault)
+					{
+						GucStack   *stack;
+
+						if (conf->gen.reset_source <= source)
+						{
+							conf->reset_val = newval;
+							conf->gen.reset_source = source;
+						}
+						for (stack = conf->gen.stack; stack; stack = stack->prev)
+						{
+							if (stack->source <= source)
+							{
+								stack->prior.enumval = newval;
+								stack->source = source;
+							}
+						}
+					}
+				}
+				break;
+			}
 	}
 
 	if (changeVal && (record->flags & GUC_REPORT))
@@ -4742,6 +4995,10 @@ GetConfigOption(const char *name)
 
 		case PGC_STRING:
 			return *((struct config_string *) record)->variable;
+
+		case PGC_ENUM:
+			return config_enum_lookup_value((struct config_enum *) record,
+											*((struct config_enum *) record)->variable);
 	}
 	return NULL;
 }
@@ -4786,6 +5043,10 @@ GetConfigOptionResetString(const char *name)
 
 		case PGC_STRING:
 			return ((struct config_string *) record)->reset_val;
+
+		case PGC_ENUM:
+			return config_enum_lookup_value((struct config_enum *) record,
+										    ((struct config_enum *) record)->reset_val);
 	}
 	return NULL;
 }
@@ -5597,6 +5858,9 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
 
 				/* max_val */
 				values[10] = NULL;
+
+				/* enumvals */
+				values[11] = NULL;
 			}
 			break;
 
@@ -5611,6 +5875,9 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
 				/* max_val */
 				snprintf(buffer, sizeof(buffer), "%d", lconf->max);
 				values[10] = pstrdup(buffer);
+
+				/* enumvals */
+				values[11] = NULL;
 			}
 			break;
 
@@ -5625,6 +5892,9 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
 				/* max_val */
 				snprintf(buffer, sizeof(buffer), "%g", lconf->max);
 				values[10] = pstrdup(buffer);
+
+				/* enumvals */
+				values[11] = NULL;
 			}
 			break;
 
@@ -5635,6 +5905,22 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
 
 				/* max_val */
 				values[10] = NULL;
+
+				/* enumvals */
+				values[11] = NULL;
+			}
+			break;
+
+		case PGC_ENUM:
+			{
+				/* min_val */
+				values[9] = NULL;
+
+				/* max_val */
+				values[10] = NULL;
+
+				/* enumvals */
+				values[11] = config_enum_get_options((struct config_enum *) conf, "", "");
 			}
 			break;
 
@@ -5649,6 +5935,9 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
 
 				/* max_val */
 				values[10] = NULL;
+
+				/* enumvals */
+				values[11] = NULL;
 			}
 			break;
 	}
@@ -5691,7 +5980,7 @@ show_config_by_name(PG_FUNCTION_ARGS)
  * show_all_settings - equiv to SHOW ALL command but implemented as
  * a Table Function.
  */
-#define NUM_PG_SETTINGS_ATTS	11
+#define NUM_PG_SETTINGS_ATTS	12
 
 Datum
 show_all_settings(PG_FUNCTION_ARGS)
@@ -5741,6 +6030,8 @@ show_all_settings(PG_FUNCTION_ARGS)
 						   TEXTOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
 						   TEXTOID, -1, 0);
+		TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals",
+						   TEXTOID, -1, 0);
 
 		/*
 		 * Generate attribute metadata needed later to produce tuples from raw
@@ -5933,6 +6224,17 @@ _ShowOption(struct config_generic * record, bool use_units)
 			}
 			break;
 
+		case PGC_ENUM:
+			{
+				struct config_enum *conf = (struct config_enum *) record;
+
+				if(conf->show_hook)
+					val = (*conf->show_hook) ();
+				else
+					val = config_enum_lookup_value(conf, *conf->variable);
+			}
+			break;
+
 		default:
 			/* just to keep compiler quiet */
 			val = "???";
@@ -5989,6 +6291,15 @@ is_newvalue_equal(struct config_generic * record, const char *newvalue)
 				return *conf->variable != NULL &&
 					strcmp(*conf->variable, newvalue) == 0;
 			}
+
+		case PGC_ENUM:
+			{
+				struct config_enum *conf = (struct config_enum *) record;
+				int			newval;
+
+				return config_enum_lookup_name(conf, newvalue, &newval)
+					&& *conf->variable == newval;
+			}
 	}
 
 	return false;
@@ -6075,6 +6386,14 @@ write_nondefault_variables(GucContext context)
 						fprintf(fp, "%s", *conf->variable);
 					}
 					break;
+
+				case PGC_ENUM:
+					{
+						struct config_enum *conf = (struct config_enum *) gconf;
+						
+						fprintf(fp, "%s", config_enum_lookup_value(conf, *conf->variable));
+					}
+					break;
 			}
 
 			fputc(0, fp);
@@ -6600,154 +6919,6 @@ assign_session_replication_role(const char *newval, bool doit, GucSource source)
 	return newval;
 }
 
-static const char *
-assign_log_min_messages(const char *newval, bool doit, GucSource source)
-{
-	return (assign_msglvl(&log_min_messages, newval, doit, source));
-}
-
-static const char *
-assign_client_min_messages(const char *newval, bool doit, GucSource source)
-{
-	return (assign_msglvl(&client_min_messages, newval, doit, source));
-}
-
-static const char *
-assign_min_error_statement(const char *newval, bool doit, GucSource source)
-{
-	return (assign_msglvl(&log_min_error_statement, newval, doit, source));
-}
-
-static const char *
-assign_msglvl(int *var, const char *newval, bool doit, GucSource source)
-{
-	if (pg_strcasecmp(newval, "debug") == 0)
-	{
-		if (doit)
-			(*var) = DEBUG2;
-	}
-	else if (pg_strcasecmp(newval, "debug5") == 0)
-	{
-		if (doit)
-			(*var) = DEBUG5;
-	}
-	else if (pg_strcasecmp(newval, "debug4") == 0)
-	{
-		if (doit)
-			(*var) = DEBUG4;
-	}
-	else if (pg_strcasecmp(newval, "debug3") == 0)
-	{
-		if (doit)
-			(*var) = DEBUG3;
-	}
-	else if (pg_strcasecmp(newval, "debug2") == 0)
-	{
-		if (doit)
-			(*var) = DEBUG2;
-	}
-	else if (pg_strcasecmp(newval, "debug1") == 0)
-	{
-		if (doit)
-			(*var) = DEBUG1;
-	}
-	else if (pg_strcasecmp(newval, "log") == 0)
-	{
-		if (doit)
-			(*var) = LOG;
-	}
-
-	/*
-	 * Client_min_messages always prints 'info', but we allow it as a value
-	 * anyway.
-	 */
-	else if (pg_strcasecmp(newval, "info") == 0)
-	{
-		if (doit)
-			(*var) = INFO;
-	}
-	else if (pg_strcasecmp(newval, "notice") == 0)
-	{
-		if (doit)
-			(*var) = NOTICE;
-	}
-	else if (pg_strcasecmp(newval, "warning") == 0)
-	{
-		if (doit)
-			(*var) = WARNING;
-	}
-	else if (pg_strcasecmp(newval, "error") == 0)
-	{
-		if (doit)
-			(*var) = ERROR;
-	}
-	/* We allow FATAL/PANIC for client-side messages too. */
-	else if (pg_strcasecmp(newval, "fatal") == 0)
-	{
-		if (doit)
-			(*var) = FATAL;
-	}
-	else if (pg_strcasecmp(newval, "panic") == 0)
-	{
-		if (doit)
-			(*var) = PANIC;
-	}
-	else
-		return NULL;			/* fail */
-	return newval;				/* OK */
-}
-
-static const char *
-assign_log_error_verbosity(const char *newval, bool doit, GucSource source)
-{
-	if (pg_strcasecmp(newval, "terse") == 0)
-	{
-		if (doit)
-			Log_error_verbosity = PGERROR_TERSE;
-	}
-	else if (pg_strcasecmp(newval, "default") == 0)
-	{
-		if (doit)
-			Log_error_verbosity = PGERROR_DEFAULT;
-	}
-	else if (pg_strcasecmp(newval, "verbose") == 0)
-	{
-		if (doit)
-			Log_error_verbosity = PGERROR_VERBOSE;
-	}
-	else
-		return NULL;			/* fail */
-	return newval;				/* OK */
-}
-
-static const char *
-assign_log_statement(const char *newval, bool doit, GucSource source)
-{
-	if (pg_strcasecmp(newval, "none") == 0)
-	{
-		if (doit)
-			log_statement = LOGSTMT_NONE;
-	}
-	else if (pg_strcasecmp(newval, "ddl") == 0)
-	{
-		if (doit)
-			log_statement = LOGSTMT_DDL;
-	}
-	else if (pg_strcasecmp(newval, "mod") == 0)
-	{
-		if (doit)
-			log_statement = LOGSTMT_MOD;
-	}
-	else if (pg_strcasecmp(newval, "all") == 0)
-	{
-		if (doit)
-			log_statement = LOGSTMT_ALL;
-	}
-	else
-		return NULL;			/* fail */
-	return newval;				/* OK */
-}
-
 static const char *
 show_num_temp_buffers(void)
 {
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 251d9ec92df55c3c0c19bb5fff4b6305284c7298..ef87e1ee0525349be0a3536633a741fbddbc4987 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.92 2008/01/01 19:45:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.93 2008/03/10 12:55:13 mha Exp $
  *
  * OLD COMMENTS
  *	  This file was created so that other c files could get the two
@@ -42,7 +42,7 @@ typedef enum
 	LOGSTMT_ALL					/* log all statements */
 } LogStmtLevel;
 
-extern LogStmtLevel log_statement;
+extern int log_statement;
 
 extern List *pg_parse_and_rewrite(const char *query_string,
 					 Oid *paramTypes, int numParams);
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 57ca1533928715b705af83c9ecbbbe29320d7df1..78939baa8987fbc7f5be4d862a4b8ae634b02a2b 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.90 2008/01/01 19:45:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.91 2008/03/10 12:55:13 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -283,7 +283,7 @@ typedef enum
 	PGERROR_VERBOSE				/* all the facts, ma'am */
 } PGErrorVerbosity;
 
-extern PGErrorVerbosity Log_error_verbosity;
+extern int	Log_error_verbosity;
 extern char *Log_line_prefix;
 extern int	Log_destination;
 
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 75dd42aaf918b9e7de1d66162821902fc5392f2f..43c37eb4ff06853dc2df7ec015ed4a52f61c0a81 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -7,7 +7,7 @@
  * Copyright (c) 2000-2008, PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
- * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.90 2008/01/01 19:45:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.91 2008/03/10 12:55:13 mha Exp $
  *--------------------------------------------------------------------
  */
 #ifndef GUC_H
@@ -97,6 +97,7 @@ typedef const char *(*GucStringAssignHook) (const char *newval, bool doit, GucSo
 typedef bool (*GucBoolAssignHook) (bool newval, bool doit, GucSource source);
 typedef bool (*GucIntAssignHook) (int newval, bool doit, GucSource source);
 typedef bool (*GucRealAssignHook) (double newval, bool doit, GucSource source);
+typedef bool (*GucEnumAssignHook) (int newval, bool doit, GucSource source);
 
 typedef const char *(*GucShowHook) (void);
 
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
index 3d389acb2f72c04c0ea0db6385690171e7d152a9..2b8d8e6e3e339928deb526003bf0ed18607b343d 100644
--- a/src/include/utils/guc_tables.h
+++ b/src/include/utils/guc_tables.h
@@ -7,7 +7,7 @@
  *
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  *
- *	  $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.38 2008/01/01 19:45:59 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.39 2008/03/10 12:55:13 mha Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,7 +24,8 @@ enum config_type
 	PGC_BOOL,
 	PGC_INT,
 	PGC_REAL,
-	PGC_STRING
+	PGC_STRING,
+	PGC_ENUM
 };
 
 union config_var_value
@@ -33,6 +34,16 @@ union config_var_value
 	int			intval;
 	double		realval;
 	char	   *stringval;
+	int			enumval;
+};
+
+/*
+ * Enum values are made up of an array of name-value pairs
+ */
+struct config_enum_entry
+{
+	const char *name;
+	int			val;
 };
 
 /*
@@ -210,6 +221,19 @@ struct config_string
 	char	   *reset_val;
 };
 
+struct config_enum
+{
+	struct config_generic gen;
+	/* constant fields, must be set correctly in initial value: */
+	int		   *variable;
+	int			boot_val;
+	const struct config_enum_entry *options;
+	GucEnumAssignHook assign_hook;
+	GucShowHook show_hook;
+	/* variable fields, initialized at runtime: */
+	int			reset_val;
+};
+
 /* constant tables corresponding to enums above and in guc.h */
 extern const char *const config_group_names[];
 extern const char *const config_type_names[];
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 3439642fe65aaded7fef76aa8e0188eb78731f06..124ebf87dcba828993e9835f6e0c33c92195b276 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1287,7 +1287,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
  pg_prepared_xacts        | SELECT p.transaction, p.gid, p.prepared, u.rolname AS owner, d.datname AS database FROM ((pg_prepared_xact() p(transaction xid, gid text, prepared timestamp with time zone, ownerid oid, dbid oid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid)));
  pg_roles                 | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, pg_authid.rolconnlimit, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig, pg_authid.oid FROM pg_authid;
  pg_rules                 | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
- pg_settings              | SELECT a.name, a.setting, a.unit, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, unit text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
+ pg_settings              | SELECT a.name, a.setting, a.unit, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val, a.enumvals FROM pg_show_all_settings() a(name text, setting text, unit text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text, enumvals text);
  pg_shadow                | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, pg_authid.rolconfig AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin;
  pg_stat_activity         | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.rolname AS usename, pg_stat_get_backend_activity(s.backendid) AS current_query, pg_stat_get_backend_waiting(s.backendid) AS waiting, pg_stat_get_backend_xact_start(s.backendid) AS xact_start, pg_stat_get_backend_activity_start(s.backendid) AS query_start, pg_stat_get_backend_start(s.backendid) AS backend_start, pg_stat_get_backend_client_addr(s.backendid) AS client_addr, pg_stat_get_backend_client_port(s.backendid) AS client_port FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_authid u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.oid));
  pg_stat_all_indexes      | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"]));