diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 2199e109d46ec142c0fa3c0626e9e252a9009975..9db486581ed543362f97c7ae0048e1adf30085df 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -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); } } diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 6e7daa40e8fe7ed8b0bf8d2cdb11ac199fc34866..97d22dc2cd345e23f5317627b6d69331faff88fc 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -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); } } diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index ca5604a61d5162666508912fb707a022ce144bf5..63bf48124a81f7265436fffe0c38d714490d4ed9 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -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 */ diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c index d6c192993e2de40b1db4821894ec972d07360176..da8de84d684b12c4e0dc09deb453c14622893fa2 100644 --- a/src/backend/utils/sort/tuplestore.c +++ b/src/backend/utils/sort/tuplestore.c @@ -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) { diff --git a/src/include/utils/tuplestore.h b/src/include/utils/tuplestore.h index ee7d22b6114a3fc227ee3170dade67a6dd6b4d52..37f99fea3bd56288adebb64cd98ac22eb4430d74 100644 --- a/src/include/utils/tuplestore.h +++ b/src/include/utils/tuplestore.h @@ -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) diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 452c69cec733be72cbd0677d835ef18ba0397ad6..3ce8f60c2625bb03c62e4edee11ec4fc6eec633a 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -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); } diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 976246f67480c5279c1f2334c4cbde38b7a148c3..25702f2a8785aaa006c9c8b5242566cdcb816eb1 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -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);