Commit ffaaf27e authored by Neil Conway's avatar Neil Conway

Provide a more descriptive error message when the return type of an SRF

does not match what the query expected. From Brendan Jurd, minor
editorializing by Neil Conway.
No related merge requests found
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.29 2004/12/31 21:59:45 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.30 2005/01/27 06:36:42 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -31,12 +31,13 @@ ...@@ -31,12 +31,13 @@
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/typcache.h" #include "utils/typcache.h"
static TupleTableSlot *FunctionNext(FunctionScanState *node); static TupleTableSlot *FunctionNext(FunctionScanState *node);
static bool tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc); static void tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Scan Support * Scan Support
...@@ -87,10 +88,8 @@ FunctionNext(FunctionScanState *node) ...@@ -87,10 +88,8 @@ FunctionNext(FunctionScanState *node)
* need to do this for functions returning RECORD, but might as * need to do this for functions returning RECORD, but might as
* well do it always. * well do it always.
*/ */
if (funcTupdesc && !tupledesc_match(node->tupdesc, funcTupdesc)) if (funcTupdesc)
ereport(ERROR, tupledesc_match(node->tupdesc, funcTupdesc);
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("query-specified return row and actual function return row do not match")));
} }
/* /*
...@@ -349,21 +348,26 @@ ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt) ...@@ -349,21 +348,26 @@ ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
} }
/* /*
* Check that function result tuple type (src_tupdesc) matches or can be * Check that function result tuple type (src_tupdesc) matches or can
* considered to match what the query expects (dst_tupdesc). * be considered to match what the query expects (dst_tupdesc). If
* they don't match, ereport.
* *
* We really only care about number of attributes and data type. * We really only care about number of attributes and data type.
* Also, we can ignore type mismatch on columns that are dropped in the * Also, we can ignore type mismatch on columns that are dropped in the
* destination type, so long as the physical storage matches. This is * destination type, so long as the physical storage matches. This is
* helpful in some cases involving out-of-date cached plans. * helpful in some cases involving out-of-date cached plans.
*/ */
static bool static void
tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc) tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
{ {
int i; int i;
if (dst_tupdesc->natts != src_tupdesc->natts) if (dst_tupdesc->natts != src_tupdesc->natts)
return false; ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("function return row and query-specified return row do not match"),
errdetail("Returned row contains %d attributes, but query expects %d.",
src_tupdesc->natts, dst_tupdesc->natts)));
for (i = 0; i < dst_tupdesc->natts; i++) for (i = 0; i < dst_tupdesc->natts; i++)
{ {
...@@ -373,11 +377,20 @@ tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc) ...@@ -373,11 +377,20 @@ tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
if (dattr->atttypid == sattr->atttypid) if (dattr->atttypid == sattr->atttypid)
continue; /* no worries */ continue; /* no worries */
if (!dattr->attisdropped) if (!dattr->attisdropped)
return false; ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("function return row and query-specified return row do not match"),
errdetail("Returned type %s at ordinal position %d, but query expects %s.",
format_type_be(sattr->atttypid),
i + 1,
format_type_be(dattr->atttypid))));
if (dattr->attlen != sattr->attlen || if (dattr->attlen != sattr->attlen ||
dattr->attalign != sattr->attalign) dattr->attalign != sattr->attalign)
return false; ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("function return row and query-specified return row do not match"),
errdetail("Physical storage mismatch on dropped attribute at ordinal position %d.",
i + 1)));
} }
return true;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment