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

Commitbf94076

Browse files
committed
Fix array coercion expressions to ensure that the correct volatility is
seen by code inspecting the expression. The best way to do this seemsto be to drop the original representation as a function invocation, andinstead make a special expression node type that represents applyingthe element-type coercion function to each array element. In this waythe element function is exposed and will be checked for volatility.Per report from Guillaume Smet.
1 parent87564ff commitbf94076

File tree

24 files changed

+565
-441
lines changed

24 files changed

+565
-441
lines changed

‎src/backend/catalog/dependency.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.64 2007/02/14 01:58:56 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.65 2007/03/27 23:21:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1315,6 +1315,17 @@ find_expr_references_walker(Node *node,
13151315
add_object_address(OCLASS_TYPE,relab->resulttype,0,
13161316
context->addrs);
13171317
}
1318+
if (IsA(node,ArrayCoerceExpr))
1319+
{
1320+
ArrayCoerceExpr*acoerce= (ArrayCoerceExpr*)node;
1321+
1322+
if (OidIsValid(acoerce->elemfuncid))
1323+
add_object_address(OCLASS_PROC,acoerce->elemfuncid,0,
1324+
context->addrs);
1325+
add_object_address(OCLASS_TYPE,acoerce->resulttype,0,
1326+
context->addrs);
1327+
/* fall through to examine arguments */
1328+
}
13181329
if (IsA(node,ConvertRowtypeExpr))
13191330
{
13201331
ConvertRowtypeExpr*cvt= (ConvertRowtypeExpr*)node;

‎src/backend/executor/execQual.c

Lines changed: 101 additions & 1 deletion
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.215 2007/02/27 23:48:07 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.216 2007/03/27 23:21:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -145,6 +145,9 @@ static Datum ExecEvalFieldStore(FieldStoreState *fstate,
145145
staticDatumExecEvalRelabelType(GenericExprState*exprstate,
146146
ExprContext*econtext,
147147
bool*isNull,ExprDoneCond*isDone);
148+
staticDatumExecEvalArrayCoerceExpr(ArrayCoerceExprState*astate,
149+
ExprContext*econtext,
150+
bool*isNull,ExprDoneCond*isDone);
148151

149152

150153
/* ----------------------------------------------------------------
@@ -3501,6 +3504,83 @@ ExecEvalRelabelType(GenericExprState *exprstate,
35013504
returnExecEvalExpr(exprstate->arg,econtext,isNull,isDone);
35023505
}
35033506

3507+
/* ----------------------------------------------------------------
3508+
*ExecEvalArrayCoerceExpr
3509+
*
3510+
*Evaluate an ArrayCoerceExpr node.
3511+
* ----------------------------------------------------------------
3512+
*/
3513+
staticDatum
3514+
ExecEvalArrayCoerceExpr(ArrayCoerceExprState*astate,
3515+
ExprContext*econtext,
3516+
bool*isNull,ExprDoneCond*isDone)
3517+
{
3518+
ArrayCoerceExpr*acoerce= (ArrayCoerceExpr*)astate->xprstate.expr;
3519+
Datumresult;
3520+
ArrayType*array;
3521+
FunctionCallInfoDatalocfcinfo;
3522+
3523+
result=ExecEvalExpr(astate->arg,econtext,isNull,isDone);
3524+
3525+
if (isDone&&*isDone==ExprEndResult)
3526+
returnresult;/* nothing to do */
3527+
if (*isNull)
3528+
returnresult;/* nothing to do */
3529+
3530+
/*
3531+
* If it's binary-compatible, modify the element type in the array header,
3532+
* but otherwise leave the array as we received it.
3533+
*/
3534+
if (!OidIsValid(acoerce->elemfuncid))
3535+
{
3536+
/* Detoast input array if necessary, and copy in any case */
3537+
array=DatumGetArrayTypePCopy(result);
3538+
ARR_ELEMTYPE(array)=astate->resultelemtype;
3539+
PG_RETURN_ARRAYTYPE_P(array);
3540+
}
3541+
3542+
/* Detoast input array if necessary, but don't make a useless copy */
3543+
array=DatumGetArrayTypeP(result);
3544+
3545+
/* Initialize function cache if first time through */
3546+
if (astate->elemfunc.fn_oid==InvalidOid)
3547+
{
3548+
AclResultaclresult;
3549+
3550+
/* Check permission to call function */
3551+
aclresult=pg_proc_aclcheck(acoerce->elemfuncid,GetUserId(),
3552+
ACL_EXECUTE);
3553+
if (aclresult!=ACLCHECK_OK)
3554+
aclcheck_error(aclresult,ACL_KIND_PROC,
3555+
get_func_name(acoerce->elemfuncid));
3556+
3557+
/* Set up the primary fmgr lookup information */
3558+
fmgr_info_cxt(acoerce->elemfuncid,&(astate->elemfunc),
3559+
econtext->ecxt_per_query_memory);
3560+
3561+
/* Initialize additional info */
3562+
astate->elemfunc.fn_expr= (Node*)acoerce;
3563+
}
3564+
3565+
/*
3566+
* Use array_map to apply the function to each array element.
3567+
*
3568+
* We pass on the desttypmod and isExplicit flags whether or not the
3569+
* function wants them.
3570+
*/
3571+
InitFunctionCallInfoData(locfcinfo,&(astate->elemfunc),3,
3572+
NULL,NULL);
3573+
locfcinfo.arg[0]=PointerGetDatum(array);
3574+
locfcinfo.arg[1]=Int32GetDatum(acoerce->resulttypmod);
3575+
locfcinfo.arg[2]=BoolGetDatum(acoerce->isExplicit);
3576+
locfcinfo.argnull[0]= false;
3577+
locfcinfo.argnull[1]= false;
3578+
locfcinfo.argnull[2]= false;
3579+
3580+
returnarray_map(&locfcinfo,ARR_ELEMTYPE(array),astate->resultelemtype,
3581+
astate->amstate);
3582+
}
3583+
35043584

35053585
/*
35063586
* ExecEvalExprSwitchContext
@@ -3770,6 +3850,26 @@ ExecInitExpr(Expr *node, PlanState *parent)
37703850
state= (ExprState*)gstate;
37713851
}
37723852
break;
3853+
caseT_ArrayCoerceExpr:
3854+
{
3855+
ArrayCoerceExpr*acoerce= (ArrayCoerceExpr*)node;
3856+
ArrayCoerceExprState*astate=makeNode(ArrayCoerceExprState);
3857+
3858+
astate->xprstate.evalfunc= (ExprStateEvalFunc)ExecEvalArrayCoerceExpr;
3859+
astate->arg=ExecInitExpr(acoerce->arg,parent);
3860+
astate->resultelemtype=get_element_type(acoerce->resulttype);
3861+
if (astate->resultelemtype==InvalidOid)
3862+
ereport(ERROR,
3863+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3864+
errmsg("target type is not an array")));
3865+
/* Arrays over domains aren't supported yet */
3866+
Assert(getBaseType(astate->resultelemtype)==
3867+
astate->resultelemtype);
3868+
astate->elemfunc.fn_oid=InvalidOid;/* not initialized */
3869+
astate->amstate= (ArrayMapState*)palloc0(sizeof(ArrayMapState));
3870+
state= (ExprState*)astate;
3871+
}
3872+
break;
37733873
caseT_ConvertRowtypeExpr:
37743874
{
37753875
ConvertRowtypeExpr*convert= (ConvertRowtypeExpr*)node;

‎src/backend/nodes/copyfuncs.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.371 2007/03/17 00:11:03 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.372 2007/03/27 23:21:09 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1020,6 +1020,24 @@ _copyRelabelType(RelabelType *from)
10201020
returnnewnode;
10211021
}
10221022

1023+
/*
1024+
* _copyArrayCoerceExpr
1025+
*/
1026+
staticArrayCoerceExpr*
1027+
_copyArrayCoerceExpr(ArrayCoerceExpr*from)
1028+
{
1029+
ArrayCoerceExpr*newnode=makeNode(ArrayCoerceExpr);
1030+
1031+
COPY_NODE_FIELD(arg);
1032+
COPY_SCALAR_FIELD(elemfuncid);
1033+
COPY_SCALAR_FIELD(resulttype);
1034+
COPY_SCALAR_FIELD(resulttypmod);
1035+
COPY_SCALAR_FIELD(isExplicit);
1036+
COPY_SCALAR_FIELD(coerceformat);
1037+
1038+
returnnewnode;
1039+
}
1040+
10231041
/*
10241042
* _copyConvertRowtypeExpr
10251043
*/
@@ -3067,6 +3085,9 @@ copyObject(void *from)
30673085
caseT_RelabelType:
30683086
retval=_copyRelabelType(from);
30693087
break;
3088+
caseT_ArrayCoerceExpr:
3089+
retval=_copyArrayCoerceExpr(from);
3090+
break;
30703091
caseT_ConvertRowtypeExpr:
30713092
retval=_copyConvertRowtypeExpr(from);
30723093
break;

‎src/backend/nodes/equalfuncs.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* Portions Copyright (c) 1994, Regents of the University of California
1919
*
2020
* IDENTIFICATION
21-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.302 2007/03/17 00:11:03 tgl Exp $
21+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.303 2007/03/27 23:21:09 tgl Exp $
2222
*
2323
*-------------------------------------------------------------------------
2424
*/
@@ -359,6 +359,27 @@ _equalRelabelType(RelabelType *a, RelabelType *b)
359359
return true;
360360
}
361361

362+
staticbool
363+
_equalArrayCoerceExpr(ArrayCoerceExpr*a,ArrayCoerceExpr*b)
364+
{
365+
COMPARE_NODE_FIELD(arg);
366+
COMPARE_SCALAR_FIELD(elemfuncid);
367+
COMPARE_SCALAR_FIELD(resulttype);
368+
COMPARE_SCALAR_FIELD(resulttypmod);
369+
COMPARE_SCALAR_FIELD(isExplicit);
370+
371+
/*
372+
* Special-case COERCE_DONTCARE, so that planner can build coercion nodes
373+
* that are equal() to both explicit and implicit coercions.
374+
*/
375+
if (a->coerceformat!=b->coerceformat&&
376+
a->coerceformat!=COERCE_DONTCARE&&
377+
b->coerceformat!=COERCE_DONTCARE)
378+
return false;
379+
380+
return true;
381+
}
382+
362383
staticbool
363384
_equalConvertRowtypeExpr(ConvertRowtypeExpr*a,ConvertRowtypeExpr*b)
364385
{
@@ -2013,6 +2034,9 @@ equal(void *a, void *b)
20132034
caseT_RelabelType:
20142035
retval=_equalRelabelType(a,b);
20152036
break;
2037+
caseT_ArrayCoerceExpr:
2038+
retval=_equalArrayCoerceExpr(a,b);
2039+
break;
20162040
caseT_ConvertRowtypeExpr:
20172041
retval=_equalConvertRowtypeExpr(a,b);
20182042
break;

‎src/backend/nodes/outfuncs.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.304 2007/03/17 00:11:03 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.305 2007/03/27 23:21:09 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -869,6 +869,19 @@ _outRelabelType(StringInfo str, RelabelType *node)
869869
WRITE_ENUM_FIELD(relabelformat,CoercionForm);
870870
}
871871

872+
staticvoid
873+
_outArrayCoerceExpr(StringInfostr,ArrayCoerceExpr*node)
874+
{
875+
WRITE_NODE_TYPE("ARRAYCOERCEEXPR");
876+
877+
WRITE_NODE_FIELD(arg);
878+
WRITE_OID_FIELD(elemfuncid);
879+
WRITE_OID_FIELD(resulttype);
880+
WRITE_INT_FIELD(resulttypmod);
881+
WRITE_BOOL_FIELD(isExplicit);
882+
WRITE_ENUM_FIELD(coerceformat,CoercionForm);
883+
}
884+
872885
staticvoid
873886
_outConvertRowtypeExpr(StringInfostr,ConvertRowtypeExpr*node)
874887
{
@@ -2149,6 +2162,9 @@ _outNode(StringInfo str, void *obj)
21492162
caseT_RelabelType:
21502163
_outRelabelType(str,obj);
21512164
break;
2165+
caseT_ArrayCoerceExpr:
2166+
_outArrayCoerceExpr(str,obj);
2167+
break;
21522168
caseT_ConvertRowtypeExpr:
21532169
_outConvertRowtypeExpr(str,obj);
21542170
break;

‎src/backend/nodes/readfuncs.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.204 2007/03/17 00:11:04 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.205 2007/03/27 23:21:09 tgl Exp $
1212
*
1313
* NOTES
1414
* Path and Plan nodes do not have any readfuncs support, because we
@@ -584,6 +584,24 @@ _readRelabelType(void)
584584
READ_DONE();
585585
}
586586

587+
/*
588+
* _readArrayCoerceExpr
589+
*/
590+
staticArrayCoerceExpr*
591+
_readArrayCoerceExpr(void)
592+
{
593+
READ_LOCALS(ArrayCoerceExpr);
594+
595+
READ_NODE_FIELD(arg);
596+
READ_OID_FIELD(elemfuncid);
597+
READ_OID_FIELD(resulttype);
598+
READ_INT_FIELD(resulttypmod);
599+
READ_BOOL_FIELD(isExplicit);
600+
READ_ENUM_FIELD(coerceformat,CoercionForm);
601+
602+
READ_DONE();
603+
}
604+
587605
/*
588606
* _readConvertRowtypeExpr
589607
*/
@@ -1024,6 +1042,8 @@ parseNodeString(void)
10241042
return_value=_readFieldStore();
10251043
elseif (MATCH("RELABELTYPE",11))
10261044
return_value=_readRelabelType();
1045+
elseif (MATCH("ARRAYCOERCEEXPR",15))
1046+
return_value=_readArrayCoerceExpr();
10271047
elseif (MATCH("CONVERTROWTYPEEXPR",18))
10281048
return_value=_readConvertRowtypeExpr();
10291049
elseif (MATCH("CASE",4))

‎src/backend/optimizer/path/costsize.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
* Portions Copyright (c) 1994, Regents of the University of California
5555
*
5656
* IDENTIFICATION
57-
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.178 2007/02/22 22:00:24 tgl Exp $
57+
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.179 2007/03/27 23:21:09 tgl Exp $
5858
*
5959
*-------------------------------------------------------------------------
6060
*/
@@ -1891,6 +1891,15 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
18911891
context->total.per_tuple+=get_func_cost(saop->opfuncid)*
18921892
cpu_operator_cost*estimate_array_length(arraynode)*0.5;
18931893
}
1894+
elseif (IsA(node,ArrayCoerceExpr))
1895+
{
1896+
ArrayCoerceExpr*acoerce= (ArrayCoerceExpr*)node;
1897+
Node*arraynode= (Node*)acoerce->arg;
1898+
1899+
if (OidIsValid(acoerce->elemfuncid))
1900+
context->total.per_tuple+=get_func_cost(acoerce->elemfuncid)*
1901+
cpu_operator_cost*estimate_array_length(arraynode);
1902+
}
18941903
elseif (IsA(node,RowCompareExpr))
18951904
{
18961905
/* Conservatively assume we will check all the columns */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp