From: Tom Lane Date: Fri, 30 Aug 2002 19:56:49 +0000 (+0000) Subject: Fix for breakage of C-coded SRFs, from Joe Conway. X-Git-Tag: REL7_3~671 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=549928d99bab650f684fd69dd5ef95553438a957;p=postgresql Fix for breakage of C-coded SRFs, from Joe Conway. --- diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c index 35ba972fe1..0df872cf92 100644 --- a/src/backend/utils/fmgr/funcapi.c +++ b/src/backend/utils/fmgr/funcapi.c @@ -7,7 +7,7 @@ * Copyright (c) 2002, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/funcapi.c,v 1.4 2002/08/29 17:14:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/funcapi.c,v 1.5 2002/08/30 19:56:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -83,8 +83,16 @@ per_MultiFuncCall(PG_FUNCTION_ARGS) { FuncCallContext *retval = (FuncCallContext *) fcinfo->flinfo->fn_extra; - /* make sure we start with a fresh slot */ - if(retval->slot != NULL) + /* + * Clear the TupleTableSlot, if present. This is for safety's sake: + * the Slot will be in a long-lived context (it better be, if the + * FuncCallContext is pointing to it), but in most usage patterns the + * tuples stored in it will be in the function's per-tuple context. + * So at the beginning of each call, the Slot will hold a dangling + * pointer to an already-recycled tuple. We clear it out here. (See + * also the definition of TupleGetDatum() in funcapi.h!) + */ + if (retval->slot != NULL) ExecClearTuple(retval->slot); return retval; diff --git a/src/include/funcapi.h b/src/include/funcapi.h index fcfb6acb69..ba862b6b1f 100644 --- a/src/include/funcapi.h +++ b/src/include/funcapi.h @@ -9,7 +9,7 @@ * * Copyright (c) 2002, PostgreSQL Global Development Group * - * $Id: funcapi.h,v 1.6 2002/08/29 17:14:33 tgl Exp $ + * $Id: funcapi.h,v 1.7 2002/08/30 19:56:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -147,8 +147,12 @@ extern TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc); extern AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc); extern HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values); +/* + * Note we pass shouldFree = false; this is needed because the tuple will + * typically be in a shorter-lived memory context than the TupleTableSlot. + */ #define TupleGetDatum(_slot, _tuple) \ - PointerGetDatum(ExecStoreTuple(_tuple, _slot, InvalidBuffer, true)) + PointerGetDatum(ExecStoreTuple(_tuple, _slot, InvalidBuffer, false)) /*---------- diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index bf7d2df24d..844cccc639 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -1,3 +1,15 @@ +SELECT * FROM pg_settings WHERE name LIKE 'enable%'; + name | setting +------------------+--------- + enable_hashjoin | on + enable_indexscan | on + enable_mergejoin | on + enable_nestloop | on + enable_seqscan | on + enable_sort | on + enable_tidscan | on +(7 rows) + CREATE TABLE foo2(fooid int, f2 int); INSERT INTO foo2 VALUES(1, 11); INSERT INTO foo2 VALUES(2, 22); diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql index 03a3a55846..6522fdda10 100644 --- a/src/test/regress/sql/rangefuncs.sql +++ b/src/test/regress/sql/rangefuncs.sql @@ -1,3 +1,5 @@ +SELECT * FROM pg_settings WHERE name LIKE 'enable%'; + CREATE TABLE foo2(fooid int, f2 int); INSERT INTO foo2 VALUES(1, 11); INSERT INTO foo2 VALUES(2, 22);