]> granicus.if.org Git - postgresql/commitdiff
Provide a more descriptive error message when the return type of an SRF
authorNeil Conway <neilc@samurai.com>
Thu, 27 Jan 2005 06:36:42 +0000 (06:36 +0000)
committerNeil Conway <neilc@samurai.com>
Thu, 27 Jan 2005 06:36:42 +0000 (06:36 +0000)
does not match what the query expected. From Brendan Jurd, minor
editorializing by Neil Conway.

src/backend/executor/nodeFunctionscan.c

index 4cf77dac930fabc54691aa498cbc9e8a7f82830c..be1fbb051557389d46dabb850e034d4b91904904 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 #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;
 }