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/executor/execQual.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/executor/execQual.c')
-rw-r--r-- | src/backend/executor/execQual.c | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 6ac61d3c5be..7394b3d32a9 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.165 2004/08/02 01:30:41 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.166 2004/08/17 18:47:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,6 +44,7 @@ #include "executor/nodeSubplan.h" #include "funcapi.h" #include "miscadmin.h" +#include "nodes/makefuncs.h" #include "optimizer/planmain.h" #include "parser/parse_expr.h" #include "utils/acl.h" @@ -2096,7 +2097,7 @@ ExecEvalRow(RowExprState *rstate, HeapTuple tuple; Datum *values; char *nulls; - int nargs; + int natts; ListCell *arg; int i; @@ -2106,9 +2107,12 @@ ExecEvalRow(RowExprState *rstate, *isDone = ExprSingleResult; /* Allocate workspace */ - nargs = list_length(rstate->args); - values = (Datum *) palloc(nargs * sizeof(Datum)); - nulls = (char *) palloc(nargs * sizeof(char)); + natts = rstate->tupdesc->natts; + values = (Datum *) palloc0(natts * sizeof(Datum)); + nulls = (char *) palloc(natts * sizeof(char)); + + /* preset to nulls in case rowtype has some later-added columns */ + memset(nulls, 'n', natts * sizeof(char)); /* Evaluate field values */ i = 0; @@ -2979,19 +2983,12 @@ ExecInitExpr(Expr *node, PlanState *parent) { RowExpr *rowexpr = (RowExpr *) node; RowExprState *rstate = makeNode(RowExprState); + Form_pg_attribute *attrs; List *outlist = NIL; ListCell *l; + int i; rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRow; - foreach(l, rowexpr->args) - { - Expr *e = (Expr *) lfirst(l); - ExprState *estate; - - estate = ExecInitExpr(e, parent); - outlist = lappend(outlist, estate); - } - rstate->args = outlist; /* Build tupdesc to describe result tuples */ if (rowexpr->row_typeid == RECORDOID) { @@ -3003,7 +3000,46 @@ ExecInitExpr(Expr *node, PlanState *parent) { /* it's been cast to a named type, use that */ rstate->tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1); + rstate->tupdesc = CreateTupleDescCopy(rstate->tupdesc); } + /* Set up evaluation, skipping any deleted columns */ + Assert(list_length(rowexpr->args) <= rstate->tupdesc->natts); + attrs = rstate->tupdesc->attrs; + i = 0; + foreach(l, rowexpr->args) + { + Expr *e = (Expr *) lfirst(l); + ExprState *estate; + + if (!attrs[i]->attisdropped) + { + /* + * Guard against ALTER COLUMN TYPE on rowtype + * since the RowExpr was created. XXX should we + * check typmod too? Not sure we can be sure it'll + * be the same. + */ + if (exprType((Node *) e) != attrs[i]->atttypid) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("ROW() column has type %s instead of type %s", + format_type_be(exprType((Node *) e)), + format_type_be(attrs[i]->atttypid)))); + } + else + { + /* + * Ignore original expression and insert a NULL. + * We don't really care what type of NULL it is, + * so always make an int4 NULL. + */ + e = (Expr *) makeNullConst(INT4OID); + } + estate = ExecInitExpr(e, parent); + outlist = lappend(outlist, estate); + i++; + } + rstate->args = outlist; state = (ExprState *) rstate; } break; |