mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-12 18:34:36 +08:00
Avoid misbehavior in foreign key checks when casting to a datatype for which
the parser supplies a default typmod that can result in data loss (ie, truncation). Currently that appears to be only CHARACTER and BIT. We can avoid the problem by specifying the type's internal name instead of using SQL-spec syntax. Since the queries generated here are only used internally, there's no need to worry about portability. This problem is new in 8.3; before we just let the parser do whatever it wanted to resolve the operator, but 8.3 is trying to be sure that the semantics of FK checks are consistent. Per report from Harald Fuchs.
This commit is contained in:
parent
d9c7f63244
commit
9b43c245e3
@ -15,7 +15,7 @@
|
||||
*
|
||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.102 2008/01/25 04:46:07 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.103 2008/02/07 22:58:35 tgl Exp $
|
||||
*
|
||||
* ----------
|
||||
*/
|
||||
@ -185,6 +185,7 @@ static void ri_GenerateQual(StringInfo buf,
|
||||
const char *leftop, Oid leftoptype,
|
||||
Oid opoid,
|
||||
const char *rightop, Oid rightoptype);
|
||||
static void ri_add_cast_to(StringInfo buf, Oid typid);
|
||||
static int ri_NullCheck(Relation rel, HeapTuple tup,
|
||||
RI_QueryKey *key, int pairidx);
|
||||
static void ri_BuildQueryKeyFull(RI_QueryKey *key,
|
||||
@ -2893,8 +2894,10 @@ quoteRelationName(char *buffer, Relation rel)
|
||||
* The idea is to append " sep leftop op rightop" to buf. The complexity
|
||||
* comes from needing to be sure that the parser will select the desired
|
||||
* operator. We always name the operator using OPERATOR(schema.op) syntax
|
||||
* (readability isn't a big priority here). We have to emit casts too,
|
||||
* if either input isn't already the input type of the operator.
|
||||
* (readability isn't a big priority here), so as to avoid search-path
|
||||
* uncertainties. We have to emit casts too, if either input isn't already
|
||||
* the input type of the operator; else we are at the mercy of the parser's
|
||||
* heuristics for ambiguous-operator resolution.
|
||||
*/
|
||||
static void
|
||||
ri_GenerateQual(StringInfo buf,
|
||||
@ -2921,16 +2924,48 @@ ri_GenerateQual(StringInfo buf,
|
||||
|
||||
appendStringInfo(buf, " %s %s", sep, leftop);
|
||||
if (leftoptype != operform->oprleft)
|
||||
appendStringInfo(buf, "::%s", format_type_be(operform->oprleft));
|
||||
ri_add_cast_to(buf, operform->oprleft);
|
||||
appendStringInfo(buf, " OPERATOR(%s.", quote_identifier(nspname));
|
||||
appendStringInfoString(buf, oprname);
|
||||
appendStringInfo(buf, ") %s", rightop);
|
||||
if (rightoptype != operform->oprright)
|
||||
appendStringInfo(buf, "::%s", format_type_be(operform->oprright));
|
||||
ri_add_cast_to(buf, operform->oprright);
|
||||
|
||||
ReleaseSysCache(opertup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a cast specification to buf. We spell out the type name the hard way,
|
||||
* intentionally not using format_type_be(). This is to avoid corner cases
|
||||
* for CHARACTER, BIT, and perhaps other types, where specifying the type
|
||||
* using SQL-standard syntax results in undesirable data truncation. By
|
||||
* doing it this way we can be certain that the cast will have default (-1)
|
||||
* target typmod.
|
||||
*/
|
||||
static void
|
||||
ri_add_cast_to(StringInfo buf, Oid typid)
|
||||
{
|
||||
HeapTuple typetup;
|
||||
Form_pg_type typform;
|
||||
char *typname;
|
||||
char *nspname;
|
||||
|
||||
typetup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(typid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(typetup))
|
||||
elog(ERROR, "cache lookup failed for type %u", typid);
|
||||
typform = (Form_pg_type) GETSTRUCT(typetup);
|
||||
|
||||
typname = NameStr(typform->typname);
|
||||
nspname = get_namespace_name(typform->typnamespace);
|
||||
|
||||
appendStringInfo(buf, "::%s.%s",
|
||||
quote_identifier(nspname), quote_identifier(typname));
|
||||
|
||||
ReleaseSysCache(typetup);
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* ri_BuildQueryKeyFull -
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user