8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.165 2004/08/02 01:30:41 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.166 2004/08/17 18:47:08 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
44
44
#include "executor/nodeSubplan.h"
45
45
#include "funcapi.h"
46
46
#include "miscadmin.h"
47
+ #include "nodes/makefuncs.h"
47
48
#include "optimizer/planmain.h"
48
49
#include "parser/parse_expr.h"
49
50
#include "utils/acl.h"
@@ -2096,7 +2097,7 @@ ExecEvalRow(RowExprState *rstate,
2096
2097
HeapTuple tuple ;
2097
2098
Datum * values ;
2098
2099
char * nulls ;
2099
- int nargs ;
2100
+ int natts ;
2100
2101
ListCell * arg ;
2101
2102
int i ;
2102
2103
@@ -2106,9 +2107,12 @@ ExecEvalRow(RowExprState *rstate,
2106
2107
* isDone = ExprSingleResult ;
2107
2108
2108
2109
/* Allocate workspace */
2109
- nargs = list_length (rstate -> args );
2110
- values = (Datum * ) palloc (nargs * sizeof (Datum ));
2111
- nulls = (char * ) palloc (nargs * sizeof (char ));
2110
+ natts = rstate -> tupdesc -> natts ;
2111
+ values = (Datum * ) palloc0 (natts * sizeof (Datum ));
2112
+ nulls = (char * ) palloc (natts * sizeof (char ));
2113
+
2114
+ /* preset to nulls in case rowtype has some later-added columns */
2115
+ memset (nulls , 'n' , natts * sizeof (char ));
2112
2116
2113
2117
/* Evaluate field values */
2114
2118
i = 0 ;
@@ -2979,19 +2983,12 @@ ExecInitExpr(Expr *node, PlanState *parent)
2979
2983
{
2980
2984
RowExpr * rowexpr = (RowExpr * ) node ;
2981
2985
RowExprState * rstate = makeNode (RowExprState );
2986
+ Form_pg_attribute * attrs ;
2982
2987
List * outlist = NIL ;
2983
2988
ListCell * l ;
2989
+ int i ;
2984
2990
2985
2991
rstate -> xprstate .evalfunc = (ExprStateEvalFunc ) ExecEvalRow ;
2986
- foreach (l , rowexpr -> args )
2987
- {
2988
- Expr * e = (Expr * ) lfirst (l );
2989
- ExprState * estate ;
2990
-
2991
- estate = ExecInitExpr (e , parent );
2992
- outlist = lappend (outlist , estate );
2993
- }
2994
- rstate -> args = outlist ;
2995
2992
/* Build tupdesc to describe result tuples */
2996
2993
if (rowexpr -> row_typeid == RECORDOID )
2997
2994
{
@@ -3003,7 +3000,46 @@ ExecInitExpr(Expr *node, PlanState *parent)
3003
3000
{
3004
3001
/* it's been cast to a named type, use that */
3005
3002
rstate -> tupdesc = lookup_rowtype_tupdesc (rowexpr -> row_typeid , -1 );
3003
+ rstate -> tupdesc = CreateTupleDescCopy (rstate -> tupdesc );
3006
3004
}
3005
+ /* Set up evaluation, skipping any deleted columns */
3006
+ Assert (list_length (rowexpr -> args ) <= rstate -> tupdesc -> natts );
3007
+ attrs = rstate -> tupdesc -> attrs ;
3008
+ i = 0 ;
3009
+ foreach (l , rowexpr -> args )
3010
+ {
3011
+ Expr * e = (Expr * ) lfirst (l );
3012
+ ExprState * estate ;
3013
+
3014
+ if (!attrs [i ]-> attisdropped )
3015
+ {
3016
+ /*
3017
+ * Guard against ALTER COLUMN TYPE on rowtype
3018
+ * since the RowExpr was created. XXX should we
3019
+ * check typmod too? Not sure we can be sure it'll
3020
+ * be the same.
3021
+ */
3022
+ if (exprType ((Node * ) e ) != attrs [i ]-> atttypid )
3023
+ ereport (ERROR ,
3024
+ (errcode (ERRCODE_DATATYPE_MISMATCH ),
3025
+ errmsg ("ROW() column has type %s instead of type %s" ,
3026
+ format_type_be (exprType ((Node * ) e )),
3027
+ format_type_be (attrs [i ]-> atttypid ))));
3028
+ }
3029
+ else
3030
+ {
3031
+ /*
3032
+ * Ignore original expression and insert a NULL.
3033
+ * We don't really care what type of NULL it is,
3034
+ * so always make an int4 NULL.
3035
+ */
3036
+ e = (Expr * ) makeNullConst (INT4OID );
3037
+ }
3038
+ estate = ExecInitExpr (e , parent );
3039
+ outlist = lappend (outlist , estate );
3040
+ i ++ ;
3041
+ }
3042
+ rstate -> args = outlist ;
3007
3043
state = (ExprState * ) rstate ;
3008
3044
}
3009
3045
break ;
0 commit comments