diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-08-17 18:47:09 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-08-17 18:47:09 +0000 |
commit | fcaad7e2c11b74c9bd30ad483b99d45a71e3f925 (patch) | |
tree | d3ccb4120ce4f2d115df852cd37ca49a3c5f87b8 /src/backend/optimizer/util/clauses.c | |
parent | 388ffad0401e7ebe0c44b0a4bfb85ce0ed48b294 (diff) |
Standardize on the assumption that the arguments of a RowExpr correspond
to the physical layout of the rowtype, ie, there are dummy arguments
corresponding to any dropped columns in the rowtype. We formerly had a
couple of places that did it this way and several others that did not.
Fixes Gaetano Mendola's "cache lookup failed for type 0" bug of 5-Aug.
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 68d2529889e..f941375127c 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.177 2004/08/02 01:30:43 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.178 2004/08/17 18:47:08 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -40,6 +40,7 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/syscache.h" +#include "utils/typcache.h" typedef struct @@ -1054,6 +1055,33 @@ set_coercionform_dontcare_walker(Node *node, void *context) context); } +/* + * Helper for eval_const_expressions: check that datatype of an attribute + * is still what it was when the expression was parsed. This is needed to + * guard against improper simplification after ALTER COLUMN TYPE. (XXX we + * may well need to make similar checks elsewhere?) + */ +static bool +rowtype_field_matches(Oid rowtypeid, int fieldnum, + Oid expectedtype, int32 expectedtypmod) +{ + TupleDesc tupdesc; + Form_pg_attribute attr; + + /* No issue for RECORD, since there is no way to ALTER such a type */ + if (rowtypeid == RECORDOID) + return true; + tupdesc = lookup_rowtype_tupdesc(rowtypeid, -1); + if (fieldnum <= 0 || fieldnum > tupdesc->natts) + return false; + attr = tupdesc->attrs[fieldnum - 1]; + if (attr->attisdropped || + attr->atttypid != expectedtype || + attr->atttypmod != expectedtypmod) + return false; + return true; +} + /*-------------------- * eval_const_expressions @@ -1630,6 +1658,10 @@ eval_const_expressions_mutator(Node *node, * parser, because ParseComplexProjection short-circuits it. But * it can arise while simplifying functions.) Also, we can * optimize field selection from a RowExpr construct. + * + * We must however check that the declared type of the field is + * still the same as when the FieldSelect was created --- this + * can change if someone did ALTER COLUMN TYPE on the rowtype. */ FieldSelect *fselect = (FieldSelect *) node; FieldSelect *newfselect; @@ -1640,11 +1672,15 @@ eval_const_expressions_mutator(Node *node, if (arg && IsA(arg, Var) && ((Var *) arg)->varattno == InvalidAttrNumber) { - return (Node *) makeVar(((Var *) arg)->varno, - fselect->fieldnum, - fselect->resulttype, - fselect->resulttypmod, - ((Var *) arg)->varlevelsup); + if (rowtype_field_matches(((Var *) arg)->vartype, + fselect->fieldnum, + fselect->resulttype, + fselect->resulttypmod)) + return (Node *) makeVar(((Var *) arg)->varno, + fselect->fieldnum, + fselect->resulttype, + fselect->resulttypmod, + ((Var *) arg)->varlevelsup); } if (arg && IsA(arg, RowExpr)) { @@ -1652,7 +1688,18 @@ eval_const_expressions_mutator(Node *node, if (fselect->fieldnum > 0 && fselect->fieldnum <= list_length(rowexpr->args)) - return (Node *) list_nth(rowexpr->args, fselect->fieldnum - 1); + { + Node *fld = (Node *) list_nth(rowexpr->args, + fselect->fieldnum - 1); + + if (rowtype_field_matches(rowexpr->row_typeid, + fselect->fieldnum, + fselect->resulttype, + fselect->resulttypmod) && + fselect->resulttype == exprType(fld) && + fselect->resulttypmod == exprTypmod(fld)) + return fld; + } } newfselect = makeNode(FieldSelect); newfselect->arg = (Expr *) arg; |