]> granicus.if.org Git - postgresql/commitdiff
Add some errdetail to checkRuleResultList().
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 Jul 2014 16:31:27 +0000 (12:31 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 Jul 2014 16:31:27 +0000 (12:31 -0400)
This function wasn't originally thought to be really user-facing,
because converting a table to a view isn't something we expect people
to do manually.  So not all that much effort was spent on the error
messages; in particular, while the code will complain that you got
the column types wrong it won't say exactly what they are.  But since
we repurposed the code to also check compatibility of rule RETURNING
lists, it's definitely user-facing.  It now seems worthwhile to add
errdetail messages showing exactly what the conflict is when there's
a mismatch of column names or types.  This is prompted by bug #10836
from Matthias Raffelsieper, which might have been forestalled if the
error message had reported the wrong column type as being "record".

Back-patch to 9.4, but not into older branches where the set of
translatable error strings is supposed to be stable.

src/backend/rewrite/rewriteDefine.c

index 50ecf7e884c1dbba7f4110d5fe16d2b2027c39a5..660d06934606aabf314aaf1a87413ff38871b64e 100644 (file)
@@ -633,6 +633,7 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect,
        foreach(tllist, targetList)
        {
                TargetEntry *tle = (TargetEntry *) lfirst(tllist);
+               Oid                     tletypid;
                int32           tletypmod;
                Form_pg_attribute attr;
                char       *attname;
@@ -664,19 +665,32 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect,
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                         errmsg("cannot convert relation containing dropped columns to view")));
 
+               /* Check name match if required; no need for two error texts here */
                if (requireColumnNameMatch && strcmp(tle->resname, attname) != 0)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                                        errmsg("SELECT rule's target entry %d has different column name from \"%s\"", i, attname)));
-
-               if (attr->atttypid != exprType((Node *) tle->expr))
+                                        errmsg("SELECT rule's target entry %d has different column name from column \"%s\"",
+                                                       i, attname),
+                                        errdetail("SELECT target entry is named \"%s\".",
+                                                          tle->resname)));
+
+               /* Check type match. */
+               tletypid = exprType((Node *) tle->expr);
+               if (attr->atttypid != tletypid)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                         isSelect ?
                                         errmsg("SELECT rule's target entry %d has different type from column \"%s\"",
                                                        i, attname) :
                                         errmsg("RETURNING list's entry %d has different type from column \"%s\"",
-                                                       i, attname)));
+                                                       i, attname),
+                                        isSelect ?
+                                        errdetail("SELECT target entry has type %s, but column has type %s.",
+                                                          format_type_be(tletypid),
+                                                          format_type_be(attr->atttypid)) :
+                                        errdetail("RETURNING list entry has type %s, but column has type %s.",
+                                                          format_type_be(tletypid),
+                                                          format_type_be(attr->atttypid))));
 
                /*
                 * Allow typmods to be different only if one of them is -1, ie,
@@ -693,7 +707,16 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect,
                                         errmsg("SELECT rule's target entry %d has different size from column \"%s\"",
                                                        i, attname) :
                                         errmsg("RETURNING list's entry %d has different size from column \"%s\"",
-                                                       i, attname)));
+                                                       i, attname),
+                                        isSelect ?
+                                        errdetail("SELECT target entry has type %s, but column has type %s.",
+                                                          format_type_with_typemod(tletypid, tletypmod),
+                                                          format_type_with_typemod(attr->atttypid,
+                                                                                                               attr->atttypmod)) :
+                                        errdetail("RETURNING list entry has type %s, but column has type %s.",
+                                                          format_type_with_typemod(tletypid, tletypmod),
+                                                          format_type_with_typemod(attr->atttypid,
+                                                                                                               attr->atttypmod))));
        }
 
        if (i != resultDesc->natts)