8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
31
31
#include "parser/parsetree.h"
32
32
#include "parser/parse_expr.h"
33
33
#include "parser/parse_type.h"
34
+ #include "utils/builtins.h"
34
35
#include "utils/lsyscache.h"
35
36
#include "utils/typcache.h"
36
37
37
38
38
39
static 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 );
40
41
41
42
/* ----------------------------------------------------------------
42
43
* Scan Support
@@ -87,10 +88,8 @@ FunctionNext(FunctionScanState *node)
87
88
* need to do this for functions returning RECORD, but might as
88
89
* well do it always.
89
90
*/
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 );
94
93
}
95
94
96
95
/*
@@ -349,21 +348,26 @@ ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
349
348
}
350
349
351
350
/*
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.
354
354
*
355
355
* We really only care about number of attributes and data type.
356
356
* Also, we can ignore type mismatch on columns that are dropped in the
357
357
* destination type, so long as the physical storage matches. This is
358
358
* helpful in some cases involving out-of-date cached plans.
359
359
*/
360
- static bool
360
+ static void
361
361
tupledesc_match (TupleDesc dst_tupdesc , TupleDesc src_tupdesc )
362
362
{
363
363
int i ;
364
364
365
365
if (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 )));
367
371
368
372
for (i = 0 ; i < dst_tupdesc -> natts ; i ++ )
369
373
{
@@ -373,11 +377,20 @@ tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc)
373
377
if (dattr -> atttypid == sattr -> atttypid )
374
378
continue ; /* no worries */
375
379
if (!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
+
377
388
if (dattr -> attlen != sattr -> attlen ||
378
389
dattr -> 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 )));
380
395
}
381
-
382
- return true;
383
396
}
0 commit comments