Provide a more descriptive error message when the return type of an SRF
authorNeil Conway
Thu, 27 Jan 2005 06:36:42 +0000 (06:36 +0000)
committerNeil Conway
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;
 }