Commit 7980ab30 authored by Tom Lane's avatar Tom Lane

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.
parent d97e98e8
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment