diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execQual.c | 34 | ||||
-rw-r--r-- | src/backend/executor/functions.c | 6 |
2 files changed, 30 insertions, 10 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); } diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index b0d8b9008a8..fe25798a21e 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.134 2009/06/11 14:48:57 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.135 2009/06/11 17:25:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -634,11 +634,11 @@ fmgr_sql(PG_FUNCTION_ARGS) * For simplicity, we require callers to support both set eval modes. * There are cases where we must use one or must use the other, and * it's not really worthwhile to postpone the check till we know. + * But note we do not require caller to provide an expectedDesc. */ if (!rsi || !IsA(rsi, ReturnSetInfo) || (rsi->allowedModes & SFRM_ValuePerCall) == 0 || - (rsi->allowedModes & SFRM_Materialize) == 0 || - rsi->expectedDesc == NULL) + (rsi->allowedModes & SFRM_Materialize) == 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("set-valued function called in context that cannot accept a set"))); |