88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.29 2004/12/31 21:59:45 pgsql Exp $
11+ * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.30 2005/01/27 06:36:42 neilc Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
3131#include "parser/parsetree.h"
3232#include "parser/parse_expr.h"
3333#include "parser/parse_type.h"
34+ #include "utils/builtins.h"
3435#include "utils/lsyscache.h"
3536#include "utils/typcache.h"
3637
3738
3839static TupleTableSlot * FunctionNext (FunctionScanState * node );
39- static bool tupledesc_match (TupleDesc dst_tupdesc ,TupleDesc src_tupdesc );
40+ static void tupledesc_match (TupleDesc dst_tupdesc ,TupleDesc src_tupdesc );
4041
4142/* ----------------------------------------------------------------
4243 *Scan Support
@@ -87,10 +88,8 @@ FunctionNext(FunctionScanState *node)
8788 * need to do this for functions returning RECORD, but might as
8889 * well do it always.
8990 */
90- if (funcTupdesc && !tupledesc_match (node -> tupdesc ,funcTupdesc ))
91- ereport (ERROR ,
92- (errcode (ERRCODE_DATATYPE_MISMATCH ),
93- errmsg ("query-specified return row and actual function return row do not match" )));
91+ if (funcTupdesc )
92+ tupledesc_match (node -> tupdesc ,funcTupdesc );
9493}
9594
9695/*
@@ -349,21 +348,26 @@ ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
349348}
350349
351350/*
352- * Check that function result tuple type (src_tupdesc) matches or can be
353- * considered to match what the query expects (dst_tupdesc).
351+ * Check that function result tuple type (src_tupdesc) matches or can
352+ * be considered to match what the query expects (dst_tupdesc). If
353+ * they don't match, ereport.
354354 *
355355 * We really only care about number of attributes and data type.
356356 * Also, we can ignore type mismatch on columns that are dropped in the
357357 * destination type, so long as the physical storage matches. This is
358358 * helpful in some cases involving out-of-date cached plans.
359359 */
360- static bool
360+ static void
361361tupledesc_match (TupleDesc dst_tupdesc ,TupleDesc src_tupdesc )
362362{
363363int i ;
364364
365365if (dst_tupdesc -> natts != src_tupdesc -> natts )
366- return false;
366+ ereport (ERROR ,
367+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
368+ errmsg ("function return row and query-specified return row do not match" ),
369+ errdetail ("Returned row contains %d attributes, but query expects %d." ,
370+ src_tupdesc -> natts ,dst_tupdesc -> natts )));
367371
368372for (i = 0 ;i < dst_tupdesc -> natts ;i ++ )
369373{
@@ -373,11 +377,20 @@ tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
373377if (dattr -> atttypid == sattr -> atttypid )
374378continue ;/* no worries */
375379if (!dattr -> attisdropped )
376- return false;
380+ ereport (ERROR ,
381+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
382+ errmsg ("function return row and query-specified return row do not match" ),
383+ errdetail ("Returned type %s at ordinal position %d, but query expects %s." ,
384+ format_type_be (sattr -> atttypid ),
385+ i + 1 ,
386+ format_type_be (dattr -> atttypid ))));
387+
377388if (dattr -> attlen != sattr -> attlen ||
378389dattr -> attalign != sattr -> attalign )
379- return false;
390+ ereport (ERROR ,
391+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
392+ errmsg ("function return row and query-specified return row do not match" ),
393+ errdetail ("Physical storage mismatch on dropped attribute at ordinal position %d." ,
394+ i + 1 )));
380395}
381-
382- return true;
383396}