Change do_tup_output() to take Datum/isnull arrays instead of a char * array,

so it doesn't go through BuildTupleFromCStrings.  This is more or less a
wash for current uses, but will avoid inefficiency for planned changes to
EXPLAIN.

Robert Haas
This commit is contained in:
Tom Lane 2009-07-22 17:00:23 +00:00
parent ea382424ee
commit 846c364dd4
3 changed files with 60 additions and 32 deletions

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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 "catalog/pg_type.h"
#include "nodes/nodeFuncs.h" #include "nodes/nodeFuncs.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/typcache.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) * 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 * 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 * 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 * TupOutputState *
begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc) 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 = (TupOutputState *) palloc(sizeof(TupOutputState));
tstate->metadata = TupleDescGetAttInMetadata(tupdesc);
tstate->slot = MakeSingleTupleTableSlot(tupdesc); tstate->slot = MakeSingleTupleTableSlot(tupdesc);
tstate->dest = dest; tstate->dest = dest;
@ -1216,17 +1216,17 @@ begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
/* /*
* write a single tuple * 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 * XXX This could be made more efficient, since in reality we probably only
* need a virtual tuple. * need a virtual tuple.
*/ */
void 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 */ TupleDesc tupdesc = tstate->slot->tts_tupleDescriptor;
HeapTuple tuple = BuildTupleFromCStrings(tstate->metadata, values); HeapTuple tuple;
/* form a tuple */
tuple = heap_form_tuple(tupdesc, values, isnull);
/* put it in a slot */ /* put it in a slot */
ExecStoreTuple(tuple, tstate->slot, InvalidBuffer, true); 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 * write a chunk of text, breaking at newline characters
* *
* NB: scribbles on its input!
*
* Should only be used with a single-TEXT-attribute tupdesc. * Should only be used with a single-TEXT-attribute tupdesc.
*/ */
void void
do_text_output_multiline(TupOutputState *tstate, char *text) do_text_output_multiline(TupOutputState *tstate, char *text)
{ {
Datum values[1];
bool isnull[1] = { false };
while (*text) while (*text)
{ {
char *eol; char *eol;
int len;
eol = strchr(text, '\n'); eol = strchr(text, '\n');
if (eol) if (eol)
*eol++ = '\0'; {
len = eol - text;
eol++;
}
else 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; text = eol;
} }
} }
@ -1269,6 +1279,5 @@ end_tup_output(TupOutputState *tstate)
(*tstate->dest->rShutdown) (tstate->dest); (*tstate->dest->rShutdown) (tstate->dest);
/* note that destroying the dest is not ours to do */ /* note that destroying the dest is not ours to do */
ExecDropSingleTupleTableSlot(tstate->slot); ExecDropSingleTupleTableSlot(tstate->slot);
/* XXX worth cleaning up the attinmetadata? */
pfree(tstate); pfree(tstate);
} }

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* IDENTIFICATION * 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; int i;
TupOutputState *tstate; TupOutputState *tstate;
TupleDesc tupdesc; TupleDesc tupdesc;
char *values[3]; Datum values[3];
bool isnull[3] = { false, false, false };
/* need a tuple descriptor representing three TEXT columns */ /* need a tuple descriptor representing three TEXT columns */
tupdesc = CreateTemplateTupleDesc(3, false); tupdesc = CreateTemplateTupleDesc(3, false);
@ -5997,29 +5998,46 @@ ShowAllGUCConfig(DestReceiver *dest)
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description", TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
TEXTOID, -1, 0); TEXTOID, -1, 0);
/* prepare for projection of tuples */ /* prepare for projection of tuples */
tstate = begin_tup_output_tupdesc(dest, tupdesc); tstate = begin_tup_output_tupdesc(dest, tupdesc);
for (i = 0; i < num_guc_variables; i++) for (i = 0; i < num_guc_variables; i++)
{ {
struct config_generic *conf = guc_variables[i]; struct config_generic *conf = guc_variables[i];
char *setting;
if ((conf->flags & GUC_NO_SHOW_ALL) || if ((conf->flags & GUC_NO_SHOW_ALL) ||
((conf->flags & GUC_SUPERUSER_ONLY) && !am_superuser)) ((conf->flags & GUC_SUPERUSER_ONLY) && !am_superuser))
continue; continue;
/* assign to the values array */ /* assign to the values array */
values[0] = (char *) conf->name; values[0] = PointerGetDatum(cstring_to_text(conf->name));
values[1] = _ShowOption(conf, true);
values[2] = (char *) conf->short_desc; 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 */ /* send it to dest */
do_tup_output(tstate, values); do_tup_output(tstate, values, isnull);
/* clean up */ /* clean up */
if (values[1] != NULL) pfree(DatumGetPointer(values[0]));
pfree(values[1]); if (setting)
{
pfree(setting);
pfree(DatumGetPointer(values[1]));
}
pfree(DatumGetPointer(values[2]));
} }
end_tup_output(tstate); end_tup_output(tstate);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 typedef struct TupOutputState
{ {
/* use "struct" here to allow forward reference */
struct AttInMetadata *metadata;
TupleTableSlot *slot; TupleTableSlot *slot;
DestReceiver *dest; DestReceiver *dest;
} TupOutputState; } TupOutputState;
extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest, extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest,
TupleDesc tupdesc); 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 do_text_output_multiline(TupOutputState *tstate, char *text);
extern void end_tup_output(TupOutputState *tstate); 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. * 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 { \ do { \
char *values_[1]; \ Datum values_[1]; \
values_[0] = (text_to_emit); \ bool isnull_[1]; \
do_tup_output(tstate, values_); \ values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \
isnull_[0] = false; \
do_tup_output(tstate, values_, isnull_); \
pfree(DatumGetPointer(values_[0])); \
} while (0) } while (0)