From cec3be05f624bc32599c2a056ec1b47bec917510 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 2 Jul 2014 12:31:27 -0400 Subject: [PATCH] Add some errdetail to checkRuleResultList(). 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 | 33 ++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 50ecf7e884..660d069346 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -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) -- 2.40.0