aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeFunctionscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeFunctionscan.c')
-rw-r--r--src/backend/executor/nodeFunctionscan.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 4cf77dac930..be1fbb05155 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -8,7 +8,7 @@
*
*
* 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 @@
#include "parser/parsetree.h"
#include "parser/parse_expr.h"
#include "parser/parse_type.h"
+#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/typcache.h"
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
@@ -87,10 +88,8 @@ FunctionNext(FunctionScanState *node)
* need to do this for functions returning RECORD, but might as
* well do it always.
*/
- if (funcTupdesc && !tupledesc_match(node->tupdesc, funcTupdesc))
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("query-specified return row and actual function return row do not match")));
+ if (funcTupdesc)
+ tupledesc_match(node->tupdesc, funcTupdesc);
}
/*
@@ -349,21 +348,26 @@ ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
}
/*
- * Check that function result tuple type (src_tupdesc) matches or can be
- * considered to match what the query expects (dst_tupdesc).
+ * Check that function result tuple type (src_tupdesc) matches or can
+ * 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.
* Also, we can ignore type mismatch on columns that are dropped in the
* destination type, so long as the physical storage matches. This is
* helpful in some cases involving out-of-date cached plans.
*/
-static bool
+static void
tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
{
int i;
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++)
{
@@ -373,11 +377,20 @@ tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
if (dattr->atttypid == sattr->atttypid)
continue; /* no worries */
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 ||
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;
}