Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfcaad7e

Browse files
committed
Standardize on the assumption that the arguments of a RowExpr correspond
to the physical layout of the rowtype, ie, there are dummy argumentscorresponding to any dropped columns in the rowtype. We formerly had acouple 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.
1 parent388ffad commitfcaad7e

File tree

8 files changed

+237
-61
lines changed

8 files changed

+237
-61
lines changed

‎src/backend/executor/execQual.c

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* 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 $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -44,6 +44,7 @@
4444
#include"executor/nodeSubplan.h"
4545
#include"funcapi.h"
4646
#include"miscadmin.h"
47+
#include"nodes/makefuncs.h"
4748
#include"optimizer/planmain.h"
4849
#include"parser/parse_expr.h"
4950
#include"utils/acl.h"
@@ -2096,7 +2097,7 @@ ExecEvalRow(RowExprState *rstate,
20962097
HeapTupletuple;
20972098
Datum*values;
20982099
char*nulls;
2099-
intnargs;
2100+
intnatts;
21002101
ListCell*arg;
21012102
inti;
21022103

@@ -2106,9 +2107,12 @@ ExecEvalRow(RowExprState *rstate,
21062107
*isDone=ExprSingleResult;
21072108

21082109
/* 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));
21122116

21132117
/* Evaluate field values */
21142118
i=0;
@@ -2979,19 +2983,12 @@ ExecInitExpr(Expr *node, PlanState *parent)
29792983
{
29802984
RowExpr*rowexpr= (RowExpr*)node;
29812985
RowExprState*rstate=makeNode(RowExprState);
2986+
Form_pg_attribute*attrs;
29822987
List*outlist=NIL;
29832988
ListCell*l;
2989+
inti;
29842990

29852991
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;
29952992
/* Build tupdesc to describe result tuples */
29962993
if (rowexpr->row_typeid==RECORDOID)
29972994
{
@@ -3003,7 +3000,46 @@ ExecInitExpr(Expr *node, PlanState *parent)
30033000
{
30043001
/* it's been cast to a named type, use that */
30053002
rstate->tupdesc=lookup_rowtype_tupdesc(rowexpr->row_typeid,-1);
3003+
rstate->tupdesc=CreateTupleDescCopy(rstate->tupdesc);
30063004
}
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;
30073043
state= (ExprState*)rstate;
30083044
}
30093045
break;

‎src/backend/optimizer/util/clauses.c

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.177 2004/08/02 01:30:43 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.178 2004/08/17 18:47:08 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHORDATEMAJOR EVENT
@@ -40,6 +40,7 @@
4040
#include"utils/lsyscache.h"
4141
#include"utils/memutils.h"
4242
#include"utils/syscache.h"
43+
#include"utils/typcache.h"
4344

4445

4546
typedefstruct
@@ -1054,6 +1055,33 @@ set_coercionform_dontcare_walker(Node *node, void *context)
10541055
context);
10551056
}
10561057

1058+
/*
1059+
* Helper for eval_const_expressions: check that datatype of an attribute
1060+
* is still what it was when the expression was parsed. This is needed to
1061+
* guard against improper simplification after ALTER COLUMN TYPE. (XXX we
1062+
* may well need to make similar checks elsewhere?)
1063+
*/
1064+
staticbool
1065+
rowtype_field_matches(Oidrowtypeid,intfieldnum,
1066+
Oidexpectedtype,int32expectedtypmod)
1067+
{
1068+
TupleDesctupdesc;
1069+
Form_pg_attributeattr;
1070+
1071+
/* No issue for RECORD, since there is no way to ALTER such a type */
1072+
if (rowtypeid==RECORDOID)
1073+
return true;
1074+
tupdesc=lookup_rowtype_tupdesc(rowtypeid,-1);
1075+
if (fieldnum <=0||fieldnum>tupdesc->natts)
1076+
return false;
1077+
attr=tupdesc->attrs[fieldnum-1];
1078+
if (attr->attisdropped||
1079+
attr->atttypid!=expectedtype||
1080+
attr->atttypmod!=expectedtypmod)
1081+
return false;
1082+
return true;
1083+
}
1084+
10571085

10581086
/*--------------------
10591087
* eval_const_expressions
@@ -1630,6 +1658,10 @@ eval_const_expressions_mutator(Node *node,
16301658
* parser, because ParseComplexProjection short-circuits it. But
16311659
* it can arise while simplifying functions.) Also, we can
16321660
* optimize field selection from a RowExpr construct.
1661+
*
1662+
* We must however check that the declared type of the field is
1663+
* still the same as when the FieldSelect was created --- this
1664+
* can change if someone did ALTER COLUMN TYPE on the rowtype.
16331665
*/
16341666
FieldSelect*fselect= (FieldSelect*)node;
16351667
FieldSelect*newfselect;
@@ -1640,19 +1672,34 @@ eval_const_expressions_mutator(Node *node,
16401672
if (arg&&IsA(arg,Var)&&
16411673
((Var*)arg)->varattno==InvalidAttrNumber)
16421674
{
1643-
return (Node*)makeVar(((Var*)arg)->varno,
1644-
fselect->fieldnum,
1645-
fselect->resulttype,
1646-
fselect->resulttypmod,
1647-
((Var*)arg)->varlevelsup);
1675+
if (rowtype_field_matches(((Var*)arg)->vartype,
1676+
fselect->fieldnum,
1677+
fselect->resulttype,
1678+
fselect->resulttypmod))
1679+
return (Node*)makeVar(((Var*)arg)->varno,
1680+
fselect->fieldnum,
1681+
fselect->resulttype,
1682+
fselect->resulttypmod,
1683+
((Var*)arg)->varlevelsup);
16481684
}
16491685
if (arg&&IsA(arg,RowExpr))
16501686
{
16511687
RowExpr*rowexpr= (RowExpr*)arg;
16521688

16531689
if (fselect->fieldnum>0&&
16541690
fselect->fieldnum <=list_length(rowexpr->args))
1655-
return (Node*)list_nth(rowexpr->args,fselect->fieldnum-1);
1691+
{
1692+
Node*fld= (Node*)list_nth(rowexpr->args,
1693+
fselect->fieldnum-1);
1694+
1695+
if (rowtype_field_matches(rowexpr->row_typeid,
1696+
fselect->fieldnum,
1697+
fselect->resulttype,
1698+
fselect->resulttypmod)&&
1699+
fselect->resulttype==exprType(fld)&&
1700+
fselect->resulttypmod==exprTypmod(fld))
1701+
returnfld;
1702+
}
16561703
}
16571704
newfselect=makeNode(FieldSelect);
16581705
newfselect->arg= (Expr*)arg;

‎src/backend/parser/parse_coerce.c

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.119 2004/06/16 01:26:44 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.120 2004/08/17 18:47:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -648,10 +648,15 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
648648
List*args=NIL;
649649
List*newargs;
650650
inti;
651+
intucolno;
651652
ListCell*arg;
652653

653654
if (node&&IsA(node,RowExpr))
654655
{
656+
/*
657+
* Since the RowExpr must be of type RECORD, we needn't worry
658+
* about it containing any dropped columns.
659+
*/
655660
args= ((RowExpr*)node)->args;
656661
}
657662
elseif (node&&IsA(node,Var)&&
@@ -670,6 +675,8 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
670675
Oidvartype;
671676
int32vartypmod;
672677

678+
if (get_rte_attribute_is_dropped(rte,nf))
679+
continue;
673680
get_rte_attribute_type(rte,nf,&vartype,&vartypmod);
674681
args=lappend(args,
675682
makeVar(((Var*)node)->varno,
@@ -687,19 +694,34 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
687694
format_type_be(targetTypeId))));
688695

689696
tupdesc=lookup_rowtype_tupdesc(targetTypeId,-1);
690-
if (list_length(args)!=tupdesc->natts)
691-
ereport(ERROR,
692-
(errcode(ERRCODE_CANNOT_COERCE),
693-
errmsg("cannot cast type %s to %s",
694-
format_type_be(RECORDOID),
695-
format_type_be(targetTypeId)),
696-
errdetail("Input has wrong number of columns.")));
697697
newargs=NIL;
698-
i=0;
699-
foreach(arg,args)
698+
ucolno=1;
699+
arg=list_head(args);
700+
for (i=0;i<tupdesc->natts;i++)
700701
{
701-
Node*expr= (Node*)lfirst(arg);
702-
Oidexprtype=exprType(expr);
702+
Node*expr;
703+
Oidexprtype;
704+
705+
/* Fill in NULLs for dropped columns in rowtype */
706+
if (tupdesc->attrs[i]->attisdropped)
707+
{
708+
/*
709+
* can't use atttypid here, but it doesn't really matter
710+
* what type the Const claims to be.
711+
*/
712+
newargs=lappend(newargs,makeNullConst(INT4OID));
713+
continue;
714+
}
715+
716+
if (arg==NULL)
717+
ereport(ERROR,
718+
(errcode(ERRCODE_CANNOT_COERCE),
719+
errmsg("cannot cast type %s to %s",
720+
format_type_be(RECORDOID),
721+
format_type_be(targetTypeId)),
722+
errdetail("Input has too few columns.")));
723+
expr= (Node*)lfirst(arg);
724+
exprtype=exprType(expr);
703725

704726
expr=coerce_to_target_type(pstate,
705727
expr,exprtype,
@@ -716,10 +738,18 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
716738
errdetail("Cannot cast type %s to %s in column %d.",
717739
format_type_be(exprtype),
718740
format_type_be(tupdesc->attrs[i]->atttypid),
719-
i+1)));
741+
ucolno)));
720742
newargs=lappend(newargs,expr);
721-
i++;
743+
ucolno++;
744+
arg=lnext(arg);
722745
}
746+
if (arg!=NULL)
747+
ereport(ERROR,
748+
(errcode(ERRCODE_CANNOT_COERCE),
749+
errmsg("cannot cast type %s to %s",
750+
format_type_be(RECORDOID),
751+
format_type_be(targetTypeId)),
752+
errdetail("Input has too many columns.")));
723753

724754
rowexpr=makeNode(RowExpr);
725755
rowexpr->args=newargs;

‎src/backend/parser/parse_relation.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.96 2004/05/30 23:40:35 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.97 2004/08/17 18:47:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -42,8 +42,6 @@ static Node *scanNameSpaceForRelid(ParseState *pstate, Node *nsnode,
4242
staticvoidscanNameSpaceForConflict(ParseState*pstate,Node*nsnode,
4343
RangeTblEntry*rte1,constchar*aliasname1);
4444
staticboolisForUpdate(ParseState*pstate,char*refname);
45-
staticboolget_rte_attribute_is_dropped(RangeTblEntry*rte,
46-
AttrNumberattnum);
4745
staticintspecialAttNum(constchar*attname);
4846
staticvoidwarnAutoRange(ParseState*pstate,RangeVar*relation);
4947

@@ -1699,7 +1697,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
16991697
* get_rte_attribute_is_dropped
17001698
*Check whether attempted attribute ref is to a dropped column
17011699
*/
1702-
staticbool
1700+
bool
17031701
get_rte_attribute_is_dropped(RangeTblEntry*rte,AttrNumberattnum)
17041702
{
17051703
boolresult;

‎src/backend/rewrite/rewriteManip.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.84 2004/05/30 23:40:35 neilc Exp $
10+
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.85 2004/08/17 18:47:09 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
1414
#include"postgres.h"
1515

16+
#include"catalog/pg_type.h"
1617
#include"nodes/makefuncs.h"
1718
#include"optimizer/clauses.h"
1819
#include"optimizer/tlist.h"
@@ -938,18 +939,30 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
938939

939940
for (nf=1;nf <=nfields;nf++)
940941
{
941-
Oidvartype;
942-
int32vartypmod;
943-
Var*newvar;
944-
945-
get_rte_attribute_type(rte,nf,&vartype,&vartypmod);
946-
newvar=makeVar(this_varno,
947-
nf,
948-
vartype,
949-
vartypmod,
950-
this_varlevelsup);
951-
fields=lappend(fields,
952-
resolve_one_var(newvar,context));
942+
if (get_rte_attribute_is_dropped(rte,nf))
943+
{
944+
/*
945+
* can't determine att type here, but it doesn't
946+
* really matter what type the Const claims to be.
947+
*/
948+
fields=lappend(fields,
949+
makeNullConst(INT4OID));
950+
}
951+
else
952+
{
953+
Oidvartype;
954+
int32vartypmod;
955+
Var*newvar;
956+
957+
get_rte_attribute_type(rte,nf,&vartype,&vartypmod);
958+
newvar=makeVar(this_varno,
959+
nf,
960+
vartype,
961+
vartypmod,
962+
this_varlevelsup);
963+
fields=lappend(fields,
964+
resolve_one_var(newvar,context));
965+
}
953966
}
954967

955968
rowexpr=makeNode(RowExpr);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp