aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execQual.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-06-11 17:25:39 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-06-11 17:25:39 +0000
commit0c19f05803523eda14d0b5bc78bf82893fb64167 (patch)
treefea3e437e787ee8c7e518d725062d83e71cd6c1b /src/backend/executor/execQual.c
parent772a074d4a89153231467cccd2e49400bbde9f6c (diff)
downloadpostgresql-0c19f05803523eda14d0b5bc78bf82893fb64167.tar.gz
postgresql-0c19f05803523eda14d0b5bc78bf82893fb64167.zip
Fix things so that you can still do "select foo()" where foo is a SQL
function returning setof record. This used to work, more or less accidentally, but I had broken it while extending the code to allow materialize-mode functions to be called in select lists. Add a regression test case so it doesn't get broken again. Per gripe from Greg Davidson.
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r--src/backend/executor/execQual.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index a0e4566630b..b1bd9e4e7e1 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.249 2009/06/11 14:48:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.250 2009/06/11 17:25:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1089,9 +1089,15 @@ init_fcache(Oid foid, FuncExprState *fcache,
fcache->funcResultDesc = tupdesc;
fcache->funcReturnsTuple = false;
}
+ else if (functypclass == TYPEFUNC_RECORD)
+ {
+ /* This will work if function doesn't need an expectedDesc */
+ fcache->funcResultDesc = NULL;
+ fcache->funcReturnsTuple = true;
+ }
else
{
- /* Else, we will complain if function wants materialize mode */
+ /* Else, we will fail if function needs an expectedDesc */
fcache->funcResultDesc = NULL;
}
@@ -1252,18 +1258,32 @@ ExecPrepareTuplestoreResult(FuncExprState *fcache,
if (fcache->funcResultSlot == NULL)
{
/* Create a slot so we can read data out of the tuplestore */
+ TupleDesc slotDesc;
MemoryContext oldcontext;
- /* We must have been able to determine the result rowtype */
- if (fcache->funcResultDesc == NULL)
+ oldcontext = MemoryContextSwitchTo(fcache->func.fn_mcxt);
+
+ /*
+ * If we were not able to determine the result rowtype from context,
+ * and the function didn't return a tupdesc, we have to fail.
+ */
+ if (fcache->funcResultDesc)
+ slotDesc = fcache->funcResultDesc;
+ else if (resultDesc)
+ {
+ /* don't assume resultDesc is long-lived */
+ slotDesc = CreateTupleDescCopy(resultDesc);
+ }
+ else
+ {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("function returning setof record called in "
"context that cannot accept type record")));
+ slotDesc = NULL; /* keep compiler quiet */
+ }
- oldcontext = MemoryContextSwitchTo(fcache->func.fn_mcxt);
- fcache->funcResultSlot =
- MakeSingleTupleTableSlot(fcache->funcResultDesc);
+ fcache->funcResultSlot = MakeSingleTupleTableSlot(slotDesc);
MemoryContextSwitchTo(oldcontext);
}