diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 7b5ba41f5fcec6382fbe73f3e87c477fece46f8f..dffc7379cbe850599f99c9f70d0450b6d073a00d 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.107 2009/06/11 14:48:57 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.108 2009/07/22 17:00:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -95,6 +95,7 @@
 #include "catalog/pg_type.h"
 #include "nodes/nodeFuncs.h"
 #include "storage/bufmgr.h"
+#include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/typcache.h"
 
@@ -1195,7 +1196,7 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
  * 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
+ * table function capability. Currently used by EXPLAIN and SHOW ALL.
  */
 TupOutputState *
 begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
@@ -1204,7 +1205,6 @@ begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
 
 	tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
 
-	tstate->metadata = TupleDescGetAttInMetadata(tupdesc);
 	tstate->slot = MakeSingleTupleTableSlot(tupdesc);
 	tstate->dest = dest;
 
@@ -1216,17 +1216,17 @@ begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
 /*
  * write a single tuple
  *
- * values is a list of the external C string representations of the values
- * to be projected.
- *
  * XXX This could be made more efficient, since in reality we probably only
  * need a virtual tuple.
  */
 void
-do_tup_output(TupOutputState *tstate, char **values)
+do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
 {
-	/* build a tuple from the input strings using the tupdesc */
-	HeapTuple	tuple = BuildTupleFromCStrings(tstate->metadata, values);
+	TupleDesc	tupdesc = tstate->slot->tts_tupleDescriptor;
+	HeapTuple	tuple;
+
+	/* form a tuple */
+	tuple = heap_form_tuple(tupdesc, values, isnull);
 
 	/* put it in a slot */
 	ExecStoreTuple(tuple, tstate->slot, InvalidBuffer, true);
@@ -1241,24 +1241,34 @@ do_tup_output(TupOutputState *tstate, char **values)
 /*
  * write a chunk of text, breaking at newline characters
  *
- * NB: scribbles on its input!
- *
  * Should only be used with a single-TEXT-attribute tupdesc.
  */
 void
 do_text_output_multiline(TupOutputState *tstate, char *text)
 {
+	Datum		values[1];
+	bool		isnull[1] = { false };
+
 	while (*text)
 	{
 		char	   *eol;
+		int			len;
 
 		eol = strchr(text, '\n');
 		if (eol)
-			*eol++ = '\0';
+		{
+			len = eol - text;
+			eol++;
+		}
 		else
-			eol = text +strlen(text);
+		{
+			len = strlen(text);
+			eol += len;
+		}
 
-		do_tup_output(tstate, &text);
+		values[0] = PointerGetDatum(cstring_to_text_with_len(text, len));
+		do_tup_output(tstate, values, isnull);
+		pfree(DatumGetPointer(values[0]));
 		text = eol;
 	}
 }
@@ -1269,6 +1279,5 @@ end_tup_output(TupOutputState *tstate)
 	(*tstate->dest->rShutdown) (tstate->dest);
 	/* note that destroying the dest is not ours to do */
 	ExecDropSingleTupleTableSlot(tstate->slot);
-	/* XXX worth cleaning up the attinmetadata? */
 	pfree(tstate);
 }
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f3b42da99b15de7284ec901f1835ad437d64aba2..76d3ec9da65470c59ba5aeb7aeac158f9685bb7f 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.508 2009/07/16 20:55:44 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.509 2009/07/22 17:00:23 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -5986,7 +5986,8 @@ ShowAllGUCConfig(DestReceiver *dest)
 	int			i;
 	TupOutputState *tstate;
 	TupleDesc	tupdesc;
-	char	   *values[3];
+	Datum	    values[3];
+	bool		isnull[3] = { false, false, false };
 
 	/* need a tuple descriptor representing three TEXT columns */
 	tupdesc = CreateTemplateTupleDesc(3, false);
@@ -5997,29 +5998,46 @@ ShowAllGUCConfig(DestReceiver *dest)
 	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
 					   TEXTOID, -1, 0);
 
-
 	/* 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];
+		char   *setting;
 
 		if ((conf->flags & GUC_NO_SHOW_ALL) ||
 			((conf->flags & GUC_SUPERUSER_ONLY) && !am_superuser))
 			continue;
 
 		/* assign to the values array */
-		values[0] = (char *) conf->name;
-		values[1] = _ShowOption(conf, true);
-		values[2] = (char *) conf->short_desc;
+		values[0] = PointerGetDatum(cstring_to_text(conf->name));
+
+		setting = _ShowOption(conf, true);
+		if (setting)
+		{
+			values[1] = PointerGetDatum(cstring_to_text(setting));
+			isnull[1] = false;
+		}
+		else
+		{
+			values[1] = PointerGetDatum(NULL);
+			isnull[1] = true;
+		}
+
+		values[2] = PointerGetDatum(cstring_to_text(conf->short_desc));
 
 		/* send it to dest */
-		do_tup_output(tstate, values);
+		do_tup_output(tstate, values, isnull);
 
 		/* clean up */
-		if (values[1] != NULL)
-			pfree(values[1]);
+		pfree(DatumGetPointer(values[0]));
+		if (setting)
+		{
+			pfree(setting);
+			pfree(DatumGetPointer(values[1]));
+		}
+		pfree(DatumGetPointer(values[2]));
 	}
 
 	end_tup_output(tstate);
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index ba625e8ed8c4d9cce4c08de33d7869aa678cabba..86148ed1354cf30944505602e274e16890c0096e 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.156 2009/07/18 19:15:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.157 2009/07/22 17:00:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -223,15 +223,13 @@ extern void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg);
 
 typedef struct TupOutputState
 {
-	/* use "struct" here to allow forward reference */
-	struct AttInMetadata *metadata;
 	TupleTableSlot *slot;
 	DestReceiver *dest;
 } TupOutputState;
 
 extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest,
 						 TupleDesc tupdesc);
-extern void do_tup_output(TupOutputState *tstate, char **values);
+extern void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull);
 extern void do_text_output_multiline(TupOutputState *tstate, char *text);
 extern void end_tup_output(TupOutputState *tstate);
 
@@ -240,11 +238,14 @@ extern void end_tup_output(TupOutputState *tstate);
  *
  * Should only be used with a single-TEXT-attribute tupdesc.
  */
-#define do_text_output_oneline(tstate, text_to_emit) \
+#define do_text_output_oneline(tstate, str_to_emit) \
 	do { \
-		char *values_[1]; \
-		values_[0] = (text_to_emit); \
-		do_tup_output(tstate, values_); \
+		Datum	values_[1]; \
+		bool	isnull_[1]; \
+		values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \
+		isnull_[0] = false; \
+		do_tup_output(tstate, values_, isnull_); \
+		pfree(DatumGetPointer(values_[0])); \
 	} while (0)