diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 2c90df205afcc1e9aee8adcc448634ee0f3c071d..72acab0f1ebefee79b6c326cde65fcfa59904a09 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.81 2002/07/20 05:16:57 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.82 2002/07/20 05:49:27 momjian Exp $
  *
  */
 
@@ -15,6 +15,7 @@
 #include "access/heapam.h"
 #include "catalog/pg_type.h"
 #include "commands/explain.h"
+#include "executor/executor.h"
 #include "executor/instrument.h"
 #include "lib/stringinfo.h"
 #include "nodes/print.h"
@@ -38,15 +39,9 @@ typedef struct ExplainState
 	List	   *rtable;			/* range table */
 } ExplainState;
 
-typedef struct TextOutputState
-{
-	TupleDesc	tupdesc;
-	DestReceiver *destfunc;
-} TextOutputState;
-
 static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es);
 static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
-							TextOutputState *tstate);
+							TupOutputState *tstate);
 static void explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
 							int indent, ExplainState *es);
 static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel,
@@ -59,11 +54,6 @@ static void show_upper_qual(List *qual, const char *qlabel,
 static void show_sort_keys(List *tlist, int nkeys, const char *qlabel,
 						   StringInfo str, int indent, ExplainState *es);
 static Node *make_ors_ands_explicit(List *orclauses);
-static TextOutputState *begin_text_output(CommandDest dest, char *title);
-static void do_text_output(TextOutputState *tstate, char *aline);
-static void do_text_output_multiline(TextOutputState *tstate, char *text);
-static void end_text_output(TextOutputState *tstate);
-
 
 /*
  * ExplainQuery -
@@ -73,16 +63,23 @@ void
 ExplainQuery(ExplainStmt *stmt, CommandDest dest)
 {
 	Query	   *query = stmt->query;
-	TextOutputState *tstate;
+	TupOutputState *tstate;
+	TupleDesc	tupdesc;
 	List	   *rewritten;
 	List	   *l;
 
-	tstate = begin_text_output(dest, "QUERY PLAN");
+	/* need a tuple descriptor representing a single TEXT column */
+	tupdesc = CreateTemplateTupleDesc(1);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
+					   TEXTOID, -1, 0, false);
+
+	/* prepare for projection of tuples */
+	tstate = begin_tup_output_tupdesc(dest, tupdesc);
 
 	if (query->commandType == CMD_UTILITY)
 	{
 		/* rewriter will not cope with utility statements */
-		do_text_output(tstate, "Utility statements have no plan structure");
+		PROJECT_LINE_OF_TEXT("Utility statements have no plan structure");
 	}
 	else
 	{
@@ -92,7 +89,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
 		if (rewritten == NIL)
 		{
 			/* In the case of an INSTEAD NOTHING, tell at least that */
-			do_text_output(tstate, "Query rewrites to nothing");
+			PROJECT_LINE_OF_TEXT("Query rewrites to nothing");
 		}
 		else
 		{
@@ -102,12 +99,12 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
 				ExplainOneQuery(lfirst(l), stmt, tstate);
 				/* put a blank line between plans */
 				if (lnext(l) != NIL)
-					do_text_output(tstate, "");
+					PROJECT_LINE_OF_TEXT("");
 			}
 		}
 	}
 
-	end_text_output(tstate);
+	end_tup_output(tstate);
 }
 
 /*
@@ -115,7 +112,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
  *	  print out the execution plan for one query
  */
 static void
-ExplainOneQuery(Query *query, ExplainStmt *stmt, TextOutputState *tstate)
+ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
 {
 	Plan	   *plan;
 	ExplainState *es;
@@ -125,9 +122,9 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TextOutputState *tstate)
 	if (query->commandType == CMD_UTILITY)
 	{
 		if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
-			do_text_output(tstate, "NOTIFY");
+			PROJECT_LINE_OF_TEXT("NOTIFY");
 		else
-			do_text_output(tstate, "UTILITY");
+			PROJECT_LINE_OF_TEXT("UTILITY");
 		return;
 	}
 
@@ -192,7 +189,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TextOutputState *tstate)
 			do_text_output_multiline(tstate, f);
 			pfree(f);
 			if (es->printCost)
-				do_text_output(tstate, "");	/* separator line */
+				PROJECT_LINE_OF_TEXT("");	/* separator line */
 		}
 	}
 
@@ -837,78 +834,3 @@ make_ors_ands_explicit(List *orclauses)
 		return (Node *) make_orclause(args);
 	}
 }
-
-
-/*
- * Functions for sending text to the frontend (or other specified destination)
- * as though it is a SELECT result.
- *
- * We tell the frontend that the table structure is a single TEXT column.
- */
-
-static TextOutputState *
-begin_text_output(CommandDest dest, char *title)
-{
-	TextOutputState *tstate;
-	TupleDesc	tupdesc;
-
-	tstate = (TextOutputState *) palloc(sizeof(TextOutputState));
-
-	/* need a tuple descriptor representing a single TEXT column */
-	tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 1, title,
-					   TEXTOID, -1, 0, false);
-
-	tstate->tupdesc = tupdesc;
-	tstate->destfunc = DestToFunction(dest);
-
-	(*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT,
-								NULL, tupdesc);
-
-	return tstate;
-}
-
-/* write a single line of text */
-static void
-do_text_output(TextOutputState *tstate, char *aline)
-{
-	HeapTuple	tuple;
-	Datum		values[1];
-	char		nulls[1];
-
-	/* form a tuple and send it to the receiver */
-	values[0] = DirectFunctionCall1(textin, CStringGetDatum(aline));
-	nulls[0] = ' ';
-	tuple = heap_formtuple(tstate->tupdesc, values, nulls);
-	(*tstate->destfunc->receiveTuple) (tuple,
-									   tstate->tupdesc,
-									   tstate->destfunc);
-	pfree(DatumGetPointer(values[0]));
-	heap_freetuple(tuple);
-}
-
-/* write a chunk of text, breaking at newline characters */
-/* NB: scribbles on its input! */
-static void
-do_text_output_multiline(TextOutputState *tstate, char *text)
-{
-	while (*text)
-	{
-		char   *eol;
-
-		eol = strchr(text, '\n');
-		if (eol)
-			*eol++ = '\0';
-		else
-			eol = text + strlen(text);
-		do_text_output(tstate, text);
-		text = eol;
-	}
-}
-
-static void
-end_text_output(TextOutputState *tstate)
-{
-	(*tstate->destfunc->cleanup) (tstate->destfunc);
-	pfree(tstate);
-}
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 5124bd023fb826e8c63407d9ba1320901bf02e9d..06a784ce26d1f92d39395473ab064542ad46fb8f 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.55 2002/07/20 05:16:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.56 2002/07/20 05:49:27 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -791,3 +791,73 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
 	return tuple;
 }
 
+/*
+ * Functions for sending tuples to the frontend (or other specified destination)
+ * as though it is a SELECT result. These are used by utility commands that
+ * need to project directly to the destination and don't need or want full
+ * Table Function capability. Currently used by EXPLAIN and SHOW ALL
+ */
+TupOutputState *
+begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc)
+{
+	TupOutputState *tstate;
+
+	tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
+
+	tstate->tupdesc = tupdesc;
+	tstate->destfunc = DestToFunction(dest);
+
+	(*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT,
+								NULL, tupdesc);
+
+	return tstate;
+}
+
+/*
+ * write a single tuple
+ *
+ * values is a list of the external C string representations of the values
+ * to be projected.
+ */
+void
+do_tup_output(TupOutputState *tstate, char **values)
+{
+	/* build a tuple from the input strings using the tupdesc */
+	AttInMetadata *attinmeta = TupleDescGetAttInMetadata(tstate->tupdesc);
+	HeapTuple	tuple = BuildTupleFromCStrings(attinmeta, values);
+
+	/* send the tuple to the receiver */
+	(*tstate->destfunc->receiveTuple) (tuple,
+									   tstate->tupdesc,
+									   tstate->destfunc);
+	/* clean up */
+	heap_freetuple(tuple);
+}
+
+/* write a chunk of text, breaking at newline characters
+ * NB: scribbles on its input!
+ * Should only be used for a single TEXT attribute tupdesc.
+ */
+void
+do_text_output_multiline(TupOutputState *tstate, char *text)
+{
+	while (*text)
+	{
+		char   *eol;
+
+		eol = strchr(text, '\n');
+		if (eol)
+			*eol++ = '\0';
+		else
+			eol = text + strlen(text);
+		do_tup_output(tstate, &text);
+		text = eol;
+	}
+}
+
+void
+end_tup_output(TupOutputState *tstate)
+{
+	(*tstate->destfunc->cleanup) (tstate->destfunc);
+	pfree(tstate);
+}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 482423f805f5e3e526ec253a7c334c7318583df2..d63d603b1dbe435c7edae5b15f7df27058d19cbe 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -5,7 +5,7 @@
  * command, configuration file, and command line options.
  * See src/backend/utils/misc/README for more information.
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.72 2002/07/18 02:02:30 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.73 2002/07/20 05:49:27 momjian Exp $
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -23,8 +23,10 @@
 
 #include "access/xlog.h"
 #include "catalog/namespace.h"
+#include "catalog/pg_type.h"
 #include "commands/async.h"
 #include "commands/variable.h"
+#include "executor/executor.h"
 #include "fmgr.h"
 #include "libpq/auth.h"
 #include "libpq/pqcomm.h"
@@ -826,7 +828,7 @@ static char *guc_string_workspace; /* for avoiding memory leaks */
 
 
 static int guc_var_compare(const void *a, const void *b);
-static void _ShowOption(struct config_generic *record);
+static char *_ShowOption(struct config_generic *record);
 
 
 /*
@@ -2167,6 +2169,57 @@ SetPGVariable(const char *name, List *args, bool is_local)
 					  true);
 }
 
+/*
+ * SET command wrapped as a SQL callable function.
+ */
+Datum
+set_config_by_name(PG_FUNCTION_ARGS)
+{
+	char   *name;
+	char   *value;
+	char   *new_value;
+	bool	is_local;
+	text   *result_text;
+
+	if (PG_ARGISNULL(0))
+		elog(ERROR, "SET variable name is required");
+
+	/* Get the GUC variable name */
+	name = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
+
+	/* Get the desired value or set to NULL for a reset request */
+	if (PG_ARGISNULL(1))
+		value = NULL;
+	else
+		value = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(1))));
+
+	/*
+	 * Get the desired state of is_local. Default to false
+	 * if provided value is NULL
+	 */
+	if (PG_ARGISNULL(2))
+		is_local = false;
+	else
+		is_local = PG_GETARG_BOOL(2);
+
+	/* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */
+	set_config_option(name,
+					  value,
+					  (superuser() ? PGC_SUSET : PGC_USERSET),
+					  PGC_S_SESSION,
+					  is_local,
+					  true);
+
+	/* get the new current value */
+	new_value = GetConfigOptionByName(name);
+
+	/* Convert return string to text */
+	result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(new_value)));
+
+	/* return it */
+	PG_RETURN_TEXT_P(result_text);
+}
+
 /*
  * SHOW command
  */
@@ -2203,13 +2256,26 @@ ResetPGVariable(const char *name)
 void
 ShowGUCConfigOption(const char *name)
 {
-	struct config_generic *record;
+	TupOutputState *tstate;
+	TupleDesc		tupdesc;
+	CommandDest		dest = whereToSendOutput;
+	char		   *value;
 
-	record = find_option(name);
-	if (record == NULL)
-		elog(ERROR, "Option '%s' is not recognized", name);
+	/* need a tuple descriptor representing a single TEXT column */
+	tupdesc = CreateTemplateTupleDesc(1);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, (char *) name,
+					   TEXTOID, -1, 0, false);
+
+	/* prepare for projection of tuples */
+	tstate = begin_tup_output_tupdesc(dest, tupdesc);
 
-	_ShowOption(record);
+	/* Get the value */
+	value = GetConfigOptionByName(name);
+
+	/* Send it */
+	PROJECT_LINE_OF_TEXT(value);
+
+	end_tup_output(tstate);
 }
 
 /*
@@ -2219,17 +2285,115 @@ void
 ShowAllGUCConfig(void)
 {
 	int			i;
+	TupOutputState *tstate;
+	TupleDesc		tupdesc;
+	CommandDest		dest = whereToSendOutput;
+	char		   *name;
+	char		   *value;
+	char		  *values[2];
+
+	/* need a tuple descriptor representing two TEXT columns */
+	tupdesc = CreateTemplateTupleDesc(2);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
+					   TEXTOID, -1, 0, false);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
+					   TEXTOID, -1, 0, false);
+
+	/* prepare for projection of tuples */
+	tstate = begin_tup_output_tupdesc(dest, tupdesc);
 
 	for (i = 0; i < num_guc_variables; i++)
 	{
-		struct config_generic *conf = guc_variables[i];
+		/* Get the next GUC variable name and value */
+		value = GetConfigOptionByNum(i, &name);
+
+		/* assign to the values array */
+		values[0] = name;
+		values[1] = value;
 
-		if ((conf->flags & GUC_NO_SHOW_ALL) == 0)
-			_ShowOption(conf);
+		/* send it to dest */
+		do_tup_output(tstate, values);
+
+		/*
+		 * clean up
+		 */
+		/* we always should have a name */
+		pfree(name);
+
+		/* but value can be returned to us as a NULL */
+		if (value != NULL)
+			pfree(value);
 	}
+
+	end_tup_output(tstate);
 }
 
-static void
+/*
+ * Return GUC variable value by name
+ */
+char *
+GetConfigOptionByName(const char *name)
+{
+	struct config_generic *record;
+
+	record = find_option(name);
+	if (record == NULL)
+		elog(ERROR, "Option '%s' is not recognized", name);
+
+	return _ShowOption(record);
+}
+
+/*
+ * Return GUC variable value and set varname for a specific
+ * variable by number.
+ */
+char *
+GetConfigOptionByNum(int varnum, char **varname)
+{
+	struct config_generic *conf = guc_variables[varnum];
+
+	*varname = pstrdup(conf->name);
+
+	if ((conf->flags & GUC_NO_SHOW_ALL) == 0)
+		return _ShowOption(conf);
+	else
+		return NULL;
+}
+
+/*
+ * Return the total number of GUC variables
+ */
+int
+GetNumConfigOptions(void)
+{
+	return num_guc_variables;
+}
+
+/*
+ * show_config_by_name - equiv to SHOW X command but implemented as
+ * a function.
+ */
+Datum
+show_config_by_name(PG_FUNCTION_ARGS)
+{
+	char   *varname;
+	char   *varval;
+	text   *result_text;
+
+	/* Get the GUC variable name */
+	varname = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
+
+	/* Get the value */
+	varval = GetConfigOptionByName(varname);
+
+	/* Convert to text */
+	result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(varval)));
+
+	/* return it */
+	PG_RETURN_TEXT_P(result_text);
+}
+
+static char *
 _ShowOption(struct config_generic *record)
 {
 	char		buffer[256];
@@ -2297,7 +2461,7 @@ _ShowOption(struct config_generic *record)
 			break;
 	}
 
-	elog(INFO, "%s is %s", record->name, val);
+	return pstrdup(val);
 }
 
 
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index c84ac13a9591d7e9c11f4933d767eb28bf264c2b..49667819453c80e988c1732db780640d16b88b45 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.244 2002/07/18 23:11:30 petere Exp $
+ * $Id: pg_proc.h,v 1.245 2002/07/20 05:49:27 momjian Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -2881,6 +2881,11 @@ DESCR("substitutes regular expression");
 DATA(insert OID = 2074 (  substring			PGNSP PGUID 14 f f f t f i 3 25 "25 25 25" 100 0 0 100	"select substring($1, like_escape($2, $3))" - _null_ ));
 DESCR("substitutes regular expression with escape argument");
 
+DATA(insert OID = 2090 (  current_setting	PGNSP PGUID 12 f f f t f s 1 25 "25" 100 0 0 100 show_config_by_name - _null_ ));
+DESCR("SHOW X as a function");
+DATA(insert OID = 2091 (  set_config		PGNSP PGUID 12 f f f f f v 3 25 "25 25 16" 100 0 0 100 set_config_by_name - _null_ ));
+DESCR("SET X as a function");
+
 /* Aggregates (moved here from pg_aggregate for 7.3) */
 
 DATA(insert OID = 2100 (  avg				PGNSP PGUID 12 t f f f f i 1 1700 "20" 100 0 0 100  aggregate_dummy - _null_ ));
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 427c146a574c0caa1bbe7e0843c62364bf789a39..5b121546d960529ef7d11bc1fe9c9f7590a06236 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: executor.h,v 1.70 2002/07/20 05:16:59 momjian Exp $
+ * $Id: executor.h,v 1.71 2002/07/20 05:49:28 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -121,6 +121,25 @@ extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
 extern TupleDesc ExecTypeFromTL(List *targetList, hasoid_t withoid);
 extern void SetChangedParamList(Plan *node, List *newchg);
 
+typedef struct TupOutputState
+{
+	TupleDesc	tupdesc;
+	DestReceiver *destfunc;
+} TupOutputState;
+
+extern TupOutputState *begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc);
+extern void do_tup_output(TupOutputState *tstate, char **values);
+extern void do_text_output_multiline(TupOutputState *tstate, char *text);
+extern void end_tup_output(TupOutputState *tstate);
+
+#define PROJECT_LINE_OF_TEXT(text_to_project) \
+	do { \
+		char *values[1]; \
+		values[0] = text_to_project; \
+		do_tup_output(tstate, values); \
+	} while (0)
+
+
 /*
  * prototypes from functions in execUtils.c
  */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index d79b1c6dcb3025dd152618ec87893deb2fcde5bd..02a537ca4ee63be6aed52dc70e4a84ee1d09be56 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.186 2002/06/20 20:29:52 momjian Exp $
+ * $Id: builtins.h,v 1.187 2002/07/20 05:49:28 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -633,4 +633,8 @@ extern int32 type_maximum_size(Oid type_oid, int32 typemod);
 extern Datum quote_ident(PG_FUNCTION_ARGS);
 extern Datum quote_literal(PG_FUNCTION_ARGS);
 
+/* guc.c */
+extern Datum show_config_by_name(PG_FUNCTION_ARGS);
+extern Datum set_config_by_name(PG_FUNCTION_ARGS);
+
 #endif   /* BUILTINS_H */
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index ce1b10be839ea551dfaa004a09924fcb51468d5d..35c56eba76e826008f24c2a529f27c523115b834 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -4,7 +4,7 @@
  * External declarations pertaining to backend/utils/misc/guc.c and
  * backend/utils/misc/guc-file.l
  *
- * $Id: guc.h,v 1.17 2002/05/17 01:19:19 tgl Exp $
+ * $Id: guc.h,v 1.18 2002/07/20 05:49:28 momjian Exp $
  */
 #ifndef GUC_H
 #define GUC_H
@@ -86,6 +86,9 @@ extern bool set_config_option(const char *name, const char *value,
 							  bool isLocal, bool DoIt);
 extern void ShowGUCConfigOption(const char *name);
 extern void ShowAllGUCConfig(void);
+extern char *GetConfigOptionByName(const char *name);
+extern char *GetConfigOptionByNum(int varnum, char **varname);
+extern int GetNumConfigOptions(void);
 
 extern void SetPGVariable(const char *name, List *args, bool is_local);
 extern void GetPGVariable(const char *name);