Add a new tuplestore API function, tuplestore_putvalues(). This is
authorNeil Conway <neilc@samurai.com>
Tue, 25 Mar 2008 19:26:54 +0000 (19:26 +0000)
committerNeil Conway <neilc@samurai.com>
Tue, 25 Mar 2008 19:26:54 +0000 (19:26 +0000)
identical to tuplestore_puttuple(), except it operates on arrays of
Datums + nulls rather than a fully-formed HeapTuple. In several places
that use the tuplestore API, this means we can avoid creating a
HeapTuple altogether, saving a copy.

src/backend/commands/prepare.c
src/backend/executor/execQual.c
src/backend/utils/mmgr/portalmem.c
src/backend/utils/sort/tuplestore.c
src/include/utils/tuplestore.h
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_exec.c

index 2199e109d46ec142c0fa3c0626e9e252a9009975..9db486581ed543362f97c7ae0048e1adf30085df 100644 (file)
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.80 2008/01/01 19:45:49 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.81 2008/03/25 19:26:53 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -764,7 +764,6 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
                hash_seq_init(&hash_seq, prepared_queries);
                while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL)
                {
-                       HeapTuple       tuple;
                        Datum           values[5];
                        bool            nulls[5];
 
@@ -787,11 +786,9 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
                                                                                  prep_stmt->plansource->num_params);
                        values[4] = BoolGetDatum(prep_stmt->from_sql);
 
-                       tuple = heap_form_tuple(tupdesc, values, nulls);
-
                        /* switch to appropriate context while storing the tuple */
                        MemoryContextSwitchTo(per_query_ctx);
-                       tuplestore_puttuple(tupstore, tuple);
+                       tuplestore_putvalues(tupstore, tupdesc, values, nulls);
                }
        }
 
index 6e7daa40e8fe7ed8b0bf8d2cdb11ac199fc34866..97d22dc2cd345e23f5317627b6d69331faff88fc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.226 2008/01/01 19:45:49 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.227 2008/03/25 19:26:53 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1547,7 +1547,6 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
        for (;;)
        {
                Datum           result;
-               HeapTuple       tuple;
 
                CHECK_FOR_INTERRUPTS();
 
@@ -1649,15 +1648,15 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
                                 */
                                tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
                                tmptup.t_data = td;
-                               tuple = &tmptup;
+
+                               oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+                               tuplestore_puttuple(tupstore, &tmptup);
                        }
                        else
                        {
-                               tuple = heap_form_tuple(tupdesc, &result, &fcinfo.isnull);
+                               oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+                               tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull);
                        }
-
-                       oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
-                       tuplestore_puttuple(tupstore, tuple);
                        MemoryContextSwitchTo(oldcontext);
 
                        /*
@@ -1702,15 +1701,13 @@ no_function_result:
                        int                     natts = expectedDesc->natts;
                        Datum      *nulldatums;
                        bool       *nullflags;
-                       HeapTuple       tuple;
 
                        MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
                        nulldatums = (Datum *) palloc0(natts * sizeof(Datum));
                        nullflags = (bool *) palloc(natts * sizeof(bool));
                        memset(nullflags, true, natts * sizeof(bool));
-                       tuple = heap_form_tuple(expectedDesc, nulldatums, nullflags);
                        MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
-                       tuplestore_puttuple(tupstore, tuple);
+                       tuplestore_putvalues(tupstore, expectedDesc, nulldatums, nullflags);
                }
        }
 
index ca5604a61d5162666508912fb707a022ce144bf5..63bf48124a81f7265436fffe0c38d714490d4ed9 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.106 2008/01/01 19:45:55 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.107 2008/03/25 19:26:53 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -911,7 +911,6 @@ pg_cursor(PG_FUNCTION_ARGS)
        while ((hentry = hash_seq_search(&hash_seq)) != NULL)
        {
                Portal          portal = hentry->portal;
-               HeapTuple       tuple;
                Datum           values[6];
                bool            nulls[6];
 
@@ -935,11 +934,9 @@ pg_cursor(PG_FUNCTION_ARGS)
                values[4] = BoolGetDatum(portal->cursorOptions & CURSOR_OPT_SCROLL);
                values[5] = TimestampTzGetDatum(portal->creation_time);
 
-               tuple = heap_form_tuple(tupdesc, values, nulls);
-
                /* switch to appropriate context while storing the tuple */
                MemoryContextSwitchTo(per_query_ctx);
-               tuplestore_puttuple(tupstore, tuple);
+               tuplestore_putvalues(tupstore, tupdesc, values, nulls);
        }
 
        /* clean up and return the tuplestore */
index d6c192993e2de40b1db4821894ec972d07360176..da8de84d684b12c4e0dc09deb453c14622893fa2 100644 (file)
@@ -38,7 +38,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.37 2008/03/10 20:06:27 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.38 2008/03/25 19:26:53 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -366,8 +366,6 @@ tuplestore_puttupleslot(Tuplestorestate *state,
 /*
  * "Standard" case to copy from a HeapTuple.  This is actually now somewhat
  * deprecated, but not worth getting rid of in view of the number of callers.
- * (Consider adding something that takes a tupdesc+values/nulls arrays so
- * that we can use heap_form_minimal_tuple() and avoid a copy step.)
  */
 void
 tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
@@ -380,6 +378,22 @@ tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
        tuplestore_puttuple_common(state, (void *) tuple);
 }
 
+/*
+ * Similar to tuplestore_puttuple(), but start from the values + nulls
+ * array. This avoids requiring that the caller construct a HeapTuple,
+ * saving a copy.
+ */
+void
+tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc,
+                                        Datum *values, bool *isnull)
+{
+       MinimalTuple tuple;
+
+       tuple = heap_form_minimal_tuple(tdesc, values, isnull);
+
+       tuplestore_puttuple_common(state, (void *) tuple);
+}
+
 static void
 tuplestore_puttuple_common(Tuplestorestate *state, void *tuple)
 {
index ee7d22b6114a3fc227ee3170dade67a6dd6b4d52..37f99fea3bd56288adebb64cd98ac22eb4430d74 100644 (file)
@@ -22,7 +22,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/tuplestore.h,v 1.22 2008/01/01 19:45:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/tuplestore.h,v 1.23 2008/03/25 19:26:53 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,6 +51,8 @@ extern void tuplestore_set_eflags(Tuplestorestate *state, int eflags);
 extern void tuplestore_puttupleslot(Tuplestorestate *state,
                                                TupleTableSlot *slot);
 extern void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple);
+extern void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc,
+                                                                Datum *values, bool *isnull);
 
 /* tuplestore_donestoring() used to be required, but is no longer used */
 #define tuplestore_donestoring(state)  ((void) 0)
index 452c69cec733be72cbd0677d835ef18ba0397ad6..3ce8f60c2625bb03c62e4edee11ec4fc6eec633a 100644 (file)
@@ -1,7 +1,7 @@
 /**********************************************************************
  * plperl.c - perl as a procedural language for PostgreSQL
  *
- *       $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.136 2008/01/23 00:55:47 adunstan Exp $
+ *       $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.137 2008/03/25 19:26:53 neilc Exp $
  *
  **********************************************************************/
 
@@ -1869,7 +1869,6 @@ plperl_return_next(SV *sv)
        FunctionCallInfo fcinfo;
        ReturnSetInfo *rsi;
        MemoryContext old_cxt;
-       HeapTuple       tuple;
 
        if (!sv)
                return;
@@ -1944,8 +1943,15 @@ plperl_return_next(SV *sv)
 
        if (prodesc->fn_retistuple)
        {
+               HeapTuple tuple;
+
                tuple = plperl_build_tuple_result((HV *) SvRV(sv),
                                                                                  current_call_data->attinmeta);
+
+               /* Make sure to store the tuple in a long-lived memory context */
+               MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
+               tuplestore_puttuple(current_call_data->tuple_store, tuple);
+               MemoryContextSwitchTo(old_cxt);
        }
        else
        {
@@ -1967,14 +1973,14 @@ plperl_return_next(SV *sv)
                        isNull = true;
                }
 
-               tuple = heap_form_tuple(current_call_data->ret_tdesc, &ret, &isNull);
+               /* Make sure to store the tuple in a long-lived memory context */
+               MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
+               tuplestore_putvalues(current_call_data->tuple_store,
+                                                        current_call_data->ret_tdesc,
+                                                        &ret, &isNull);
+               MemoryContextSwitchTo(old_cxt);
        }
 
-       /* Make sure to store the tuple in a long-lived memory context */
-       MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
-       tuplestore_puttuple(current_call_data->tuple_store, tuple);
-       MemoryContextSwitchTo(old_cxt);
-
        MemoryContextReset(current_call_data->tmp_cxt);
 }
 
index 976246f67480c5279c1f2334c4cbde38b7a148c3..25702f2a8785aaa006c9c8b5242566cdcb816eb1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.202 2008/01/01 19:46:00 momjian Exp $
+ *       $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.203 2008/03/25 19:26:54 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2007,10 +2007,11 @@ static int
 exec_stmt_return_next(PLpgSQL_execstate *estate,
                                          PLpgSQL_stmt_return_next *stmt)
 {
-       TupleDesc       tupdesc;
-       int                     natts;
-       HeapTuple       tuple;
-       bool            free_tuple = false;
+       TupleDesc               tupdesc;
+       int                             natts;
+       MemoryContext   oldcxt;
+       HeapTuple               tuple = NULL;
+       bool                    free_tuple = false;
 
        if (!estate->retisset)
                ereport(ERROR,
@@ -2048,9 +2049,10 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
                                                                                                tupdesc->attrs[0]->atttypmod,
                                                                                                        isNull);
 
-                                       tuple = heap_form_tuple(tupdesc, &retval, &isNull);
-
-                                       free_tuple = true;
+                                       oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
+                                       tuplestore_putvalues(estate->tuple_store, tupdesc,
+                                                                                &retval, &isNull);
+                                       MemoryContextSwitchTo(oldcxt);
                                }
                                break;
 
@@ -2087,7 +2089,6 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
 
                        default:
                                elog(ERROR, "unrecognized dtype: %d", retvar->dtype);
-                               tuple = NULL;   /* keep compiler quiet */
                                break;
                }
        }
@@ -2114,9 +2115,10 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
                                                                                tupdesc->attrs[0]->atttypmod,
                                                                                isNull);
 
-               tuple = heap_form_tuple(tupdesc, &retval, &isNull);
-
-               free_tuple = true;
+               oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
+               tuplestore_putvalues(estate->tuple_store, tupdesc,
+                                                        &retval, &isNull);
+               MemoryContextSwitchTo(oldcxt);
 
                exec_eval_cleanup(estate);
        }
@@ -2125,13 +2127,10 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
                ereport(ERROR,
                                (errcode(ERRCODE_SYNTAX_ERROR),
                                 errmsg("RETURN NEXT must have a parameter")));
-               tuple = NULL;                   /* keep compiler quiet */
        }
 
        if (HeapTupleIsValid(tuple))
        {
-               MemoryContext oldcxt;
-
                oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
                tuplestore_puttuple(estate->tuple_store, tuple);
                MemoryContextSwitchTo(oldcxt);