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

Commit7fbc75b

Browse files
committed
Add soft error handling to some expression nodes
This adjusts the expression evaluation code for CoerceViaIO andCoerceToDomain to handle errors softly if needed.For CoerceViaIo, this means using InputFunctionCallSafe(), whichprovides the option to handle errors softly, instead of calling thetype input function directly.For CoerceToDomain, this simply entails replacing the ereport() inExecEvalConstraintCheck() by errsave().In both cases, the ErrorSaveContext to be used when evaluating theexpression is stored by ExecInitExprRec() in the expression's structin the expression's ExprEvalStep. The ErrorSaveContext is passed bysetting ExprState.escontext to point to it when callingExecInitExprRec() on the expression whose errors are to be handledsoftly.Note that no call site of ExecInitExprRec() has been changed in thiscommit, so there's no functional change. This is intended forimplementing new SQL/JSON expression nodes in future commits thatwill use to it suppress errors that may occur during type coercions.Reviewed-by: Álvaro HerreraDiscussion:https://postgr.es/m/CA+HiwqE4XTdfb1nW=Ojoy_tQSRhYt-q_kb6i5d4xcKyrLC1Nbg@mail.gmail.com
1 parent2940f1c commit7fbc75b

File tree

9 files changed

+96
-69
lines changed

9 files changed

+96
-69
lines changed

‎src/backend/executor/execExpr.c

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
139139
state->expr=node;
140140
state->parent=parent;
141141
state->ext_params=NULL;
142+
state->escontext=NULL;
142143

143144
/* Insert setup steps as needed */
144145
ExecCreateExprSetupSteps(state, (Node*)node);
@@ -176,6 +177,7 @@ ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
176177
state->expr=node;
177178
state->parent=NULL;
178179
state->ext_params=ext_params;
180+
state->escontext=NULL;
179181

180182
/* Insert setup steps as needed */
181183
ExecCreateExprSetupSteps(state, (Node*)node);
@@ -228,6 +230,7 @@ ExecInitQual(List *qual, PlanState *parent)
228230
state->expr= (Expr*)qual;
229231
state->parent=parent;
230232
state->ext_params=NULL;
233+
state->escontext=NULL;
231234

232235
/* mark expression as to be used with ExecQual() */
233236
state->flags=EEO_FLAG_IS_QUAL;
@@ -373,6 +376,7 @@ ExecBuildProjectionInfo(List *targetList,
373376
state->expr= (Expr*)targetList;
374377
state->parent=parent;
375378
state->ext_params=NULL;
379+
state->escontext=NULL;
376380

377381
state->resultslot=slot;
378382

@@ -544,6 +548,7 @@ ExecBuildUpdateProjection(List *targetList,
544548
state->expr=NULL;/* not used */
545549
state->parent=parent;
546550
state->ext_params=NULL;
551+
state->escontext=NULL;
547552

548553
state->resultslot=slot;
549554

@@ -1549,8 +1554,6 @@ ExecInitExprRec(Expr *node, ExprState *state,
15491554
CoerceViaIO*iocoerce= (CoerceViaIO*)node;
15501555
Oidiofunc;
15511556
booltypisvarlena;
1552-
Oidtypioparam;
1553-
FunctionCallInfofcinfo_in;
15541557

15551558
/* evaluate argument into step's result area */
15561559
ExecInitExprRec(iocoerce->arg,state,resv,resnull);
@@ -1579,25 +1582,13 @@ ExecInitExprRec(Expr *node, ExprState *state,
15791582

15801583
/* lookup the result type's input function */
15811584
scratch.d.iocoerce.finfo_in=palloc0(sizeof(FmgrInfo));
1582-
scratch.d.iocoerce.fcinfo_data_in=palloc0(SizeForFunctionCallInfo(3));
1583-
15841585
getTypeInputInfo(iocoerce->resulttype,
1585-
&iofunc,&typioparam);
1586+
&iofunc,&scratch.d.iocoerce.typioparam);
15861587
fmgr_info(iofunc,scratch.d.iocoerce.finfo_in);
15871588
fmgr_info_set_expr((Node*)node,scratch.d.iocoerce.finfo_in);
1588-
InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in,
1589-
scratch.d.iocoerce.finfo_in,
1590-
3,InvalidOid,NULL,NULL);
15911589

1592-
/*
1593-
* We can preload the second and third arguments for the input
1594-
* function, since they're constants.
1595-
*/
1596-
fcinfo_in=scratch.d.iocoerce.fcinfo_data_in;
1597-
fcinfo_in->args[1].value=ObjectIdGetDatum(typioparam);
1598-
fcinfo_in->args[1].isnull= false;
1599-
fcinfo_in->args[2].value=Int32GetDatum(-1);
1600-
fcinfo_in->args[2].isnull= false;
1590+
/* Set ErrorSaveContext if passed by the caller. */
1591+
scratch.d.iocoerce.escontext=state->escontext;
16011592

16021593
ExprEvalPushStep(state,&scratch);
16031594
break;
@@ -1628,6 +1619,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
16281619
elemstate->expr=acoerce->elemexpr;
16291620
elemstate->parent=state->parent;
16301621
elemstate->ext_params=state->ext_params;
1622+
state->escontext=NULL;
16311623

16321624
elemstate->innermost_caseval= (Datum*)palloc(sizeof(Datum));
16331625
elemstate->innermost_casenull= (bool*)palloc(sizeof(bool));
@@ -3306,6 +3298,8 @@ ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest,
33063298
/* we'll allocate workspace only if needed */
33073299
scratch->d.domaincheck.checkvalue=NULL;
33083300
scratch->d.domaincheck.checknull=NULL;
3301+
/* Set ErrorSaveContext if passed by the caller. */
3302+
scratch->d.domaincheck.escontext=state->escontext;
33093303

33103304
/*
33113305
* Evaluate argument - it's fine to directly store it into resv/resnull,

‎src/backend/executor/execExprInterp.c

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,29 +1177,27 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
11771177
/* call input function (similar to InputFunctionCall) */
11781178
if (!op->d.iocoerce.finfo_in->fn_strict||str!=NULL)
11791179
{
1180-
FunctionCallInfofcinfo_in;
1181-
Datumd;
1180+
boolerror;
11821181

1183-
fcinfo_in=op->d.iocoerce.fcinfo_data_in;
1184-
fcinfo_in->args[0].value=PointerGetDatum(str);
1185-
fcinfo_in->args[0].isnull=*op->resnull;
1186-
/* second and third arguments are already set up */
1187-
1188-
fcinfo_in->isnull= false;
1189-
d=FunctionCallInvoke(fcinfo_in);
1190-
*op->resvalue=d;
1182+
/*
1183+
* InputFunctionCallSafe() writes directly into *op->resvalue.
1184+
* Return NULL if an error is reported.
1185+
*/
1186+
error= !InputFunctionCallSafe(op->d.iocoerce.finfo_in,str,
1187+
op->d.iocoerce.typioparam,-1,
1188+
(Node*)op->d.iocoerce.escontext,
1189+
op->resvalue);
1190+
if (error)
1191+
*op->resnull= true;
11911192

1192-
/* Should get null result if and only if str is NULL */
1193-
if (str==NULL)
1194-
{
1193+
/*
1194+
* Should get null result if and only if str is NULL or if we
1195+
* got an error above.
1196+
*/
1197+
if (str==NULL||error)
11951198
Assert(*op->resnull);
1196-
Assert(fcinfo_in->isnull);
1197-
}
11981199
else
1199-
{
12001200
Assert(!*op->resnull);
1201-
Assert(!fcinfo_in->isnull);
1202-
}
12031201
}
12041202

12051203
EEO_NEXT();
@@ -3745,7 +3743,7 @@ ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op)
37453743
{
37463744
if (!*op->d.domaincheck.checknull&&
37473745
!DatumGetBool(*op->d.domaincheck.checkvalue))
3748-
ereport(ERROR,
3746+
errsave((Node*)op->d.domaincheck.escontext,
37493747
(errcode(ERRCODE_CHECK_VIOLATION),
37503748
errmsg("value for domain %s violates check constraint \"%s\"",
37513749
format_type_be(op->d.domaincheck.resulttype),

‎src/backend/jit/llvm/llvmjit.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,14 @@ LLVMTypeRef StructHeapTupleTableSlot;
7070
LLVMTypeRefStructMinimalTupleTableSlot;
7171
LLVMTypeRefStructMemoryContextData;
7272
LLVMTypeRefStructFunctionCallInfoData;
73+
LLVMTypeRefStructFmgrInfo;
7374
LLVMTypeRefStructExprContext;
7475
LLVMTypeRefStructExprEvalStep;
7576
LLVMTypeRefStructExprState;
7677
LLVMTypeRefStructAggState;
7778
LLVMTypeRefStructAggStatePerGroupData;
7879
LLVMTypeRefStructAggStatePerTransData;
80+
LLVMTypeRefStructErrorSaveContext;
7981

8082
LLVMValueRefAttributeTemplate;
8183

@@ -1118,6 +1120,7 @@ llvm_create_types(void)
11181120
StructExprEvalStep=llvm_pg_var_type("StructExprEvalStep");
11191121
StructExprState=llvm_pg_var_type("StructExprState");
11201122
StructFunctionCallInfoData=llvm_pg_var_type("StructFunctionCallInfoData");
1123+
StructFmgrInfo=llvm_pg_var_type("StructFmgrInfo");
11211124
StructMemoryContextData=llvm_pg_var_type("StructMemoryContextData");
11221125
StructTupleTableSlot=llvm_pg_var_type("StructTupleTableSlot");
11231126
StructHeapTupleTableSlot=llvm_pg_var_type("StructHeapTupleTableSlot");
@@ -1127,6 +1130,7 @@ llvm_create_types(void)
11271130
StructAggState=llvm_pg_var_type("StructAggState");
11281131
StructAggStatePerGroupData=llvm_pg_var_type("StructAggStatePerGroupData");
11291132
StructAggStatePerTransData=llvm_pg_var_type("StructAggStatePerTransData");
1133+
StructErrorSaveContext=llvm_pg_var_type("StructErrorSaveContext");
11301134

11311135
AttributeTemplate=LLVMGetNamedFunction(llvm_types_module,"AttributeTemplate");
11321136
}

‎src/backend/jit/llvm/llvmjit_expr.c

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,14 +1251,9 @@ llvm_compile_expr(ExprState *state)
12511251

12521252
caseEEOP_IOCOERCE:
12531253
{
1254-
FunctionCallInfofcinfo_out,
1255-
fcinfo_in;
1256-
LLVMValueRefv_fn_out,
1257-
v_fn_in;
1258-
LLVMValueRefv_fcinfo_out,
1259-
v_fcinfo_in;
1260-
LLVMValueRefv_fcinfo_in_isnullp;
1261-
LLVMValueRefv_retval;
1254+
FunctionCallInfofcinfo_out;
1255+
LLVMValueRefv_fn_out;
1256+
LLVMValueRefv_fcinfo_out;
12621257
LLVMValueRefv_resvalue;
12631258
LLVMValueRefv_resnull;
12641259

@@ -1271,7 +1266,6 @@ llvm_compile_expr(ExprState *state)
12711266
LLVMBasicBlockRefb_inputcall;
12721267

12731268
fcinfo_out=op->d.iocoerce.fcinfo_data_out;
1274-
fcinfo_in=op->d.iocoerce.fcinfo_data_in;
12751269

12761270
b_skipoutput=l_bb_before_v(opblocks[opno+1],
12771271
"op.%d.skipoutputnull",opno);
@@ -1283,14 +1277,7 @@ llvm_compile_expr(ExprState *state)
12831277
"op.%d.inputcall",opno);
12841278

12851279
v_fn_out=llvm_function_reference(context,b,mod,fcinfo_out);
1286-
v_fn_in=llvm_function_reference(context,b,mod,fcinfo_in);
12871280
v_fcinfo_out=l_ptr_const(fcinfo_out,l_ptr(StructFunctionCallInfoData));
1288-
v_fcinfo_in=l_ptr_const(fcinfo_in,l_ptr(StructFunctionCallInfoData));
1289-
1290-
v_fcinfo_in_isnullp=
1291-
LLVMBuildStructGEP(b,v_fcinfo_in,
1292-
FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
1293-
"v_fcinfo_in_isnull");
12941281

12951282
/* output functions are not called on nulls */
12961283
v_resnull=LLVMBuildLoad(b,v_resnullp,"");
@@ -1356,24 +1343,44 @@ llvm_compile_expr(ExprState *state)
13561343
LLVMBuildBr(b,b_inputcall);
13571344
}
13581345

1346+
/*
1347+
* Call the input function.
1348+
*
1349+
* If op->d.iocoerce.escontext references an
1350+
* ErrorSaveContext, InputFunctionCallSafe() would return
1351+
* false upon encountering an error.
1352+
*/
13591353
LLVMPositionBuilderAtEnd(b,b_inputcall);
1360-
/* set arguments */
1361-
/* arg0: output */
1362-
LLVMBuildStore(b,v_output,
1363-
l_funcvaluep(b,v_fcinfo_in,0));
1364-
LLVMBuildStore(b,v_resnull,
1365-
l_funcnullp(b,v_fcinfo_in,0));
1366-
1367-
/* arg1: ioparam: preset in execExpr.c */
1368-
/* arg2: typmod: preset in execExpr.c */
1369-
1370-
/* reset fcinfo_in->isnull */
1371-
LLVMBuildStore(b,l_sbool_const(0),v_fcinfo_in_isnullp);
1372-
/* and call function */
1373-
v_retval=LLVMBuildCall(b,v_fn_in,&v_fcinfo_in,1,
1374-
"funccall_iocoerce_in");
1354+
{
1355+
Oidioparam=op->d.iocoerce.typioparam;
1356+
LLVMValueRefv_params[6];
1357+
LLVMValueRefv_success;
1358+
1359+
v_params[0]=l_ptr_const(op->d.iocoerce.finfo_in,
1360+
l_ptr(StructFmgrInfo));
1361+
v_params[1]=v_output;
1362+
v_params[2]=l_oid_const(lc,ioparam);
1363+
v_params[3]=l_int32_const(lc,-1);
1364+
v_params[4]=l_ptr_const(op->d.iocoerce.escontext,
1365+
l_ptr(StructErrorSaveContext));
13751366

1376-
LLVMBuildStore(b,v_retval,v_resvaluep);
1367+
/*
1368+
* InputFunctionCallSafe() will write directly into
1369+
* *op->resvalue.
1370+
*/
1371+
v_params[5]=v_resvaluep;
1372+
1373+
v_success=LLVMBuildCall(b,llvm_pg_func(mod,"InputFunctionCallSafe"),
1374+
v_params,lengthof(v_params),
1375+
"funccall_iocoerce_in_safe");
1376+
1377+
/*
1378+
* Return null if InputFunctionCallSafe() encountered
1379+
* an error.
1380+
*/
1381+
v_resnullp=LLVMBuildICmp(b,LLVMIntEQ,v_success,
1382+
l_sbool_const(0),"");
1383+
}
13771384

13781385
LLVMBuildBr(b,opblocks[opno+1]);
13791386
break;

‎src/backend/jit/llvm/llvmjit_types.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@ AggStatePerTransData StructAggStatePerTransData;
5959
ExprContextStructExprContext;
6060
ExprEvalStepStructExprEvalStep;
6161
ExprStateStructExprState;
62+
FmgrInfoStructFmgrInfo;
6263
FunctionCallInfoBaseDataStructFunctionCallInfoData;
6364
HeapTupleDataStructHeapTupleData;
6465
MemoryContextDataStructMemoryContextData;
6566
TupleTableSlotStructTupleTableSlot;
6667
HeapTupleTableSlotStructHeapTupleTableSlot;
6768
MinimalTupleTableSlotStructMinimalTupleTableSlot;
6869
TupleDescDataStructTupleDescData;
70+
ErrorSaveContextStructErrorSaveContext;
6971

7072

7173
/*
@@ -136,6 +138,7 @@ void *referenced_functions[] =
136138
ExecEvalJsonConstructor,
137139
ExecEvalJsonIsPredicate,
138140
MakeExpandedObjectReadOnlyInternal,
141+
InputFunctionCallSafe,
139142
slot_getmissingattrs,
140143
slot_getsomeattrs_int,
141144
strlen,

‎src/include/executor/execExpr.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include"executor/nodeAgg.h"
1818
#include"nodes/execnodes.h"
19+
#include"nodes/miscnodes.h"
1920

2021
/* forward references to avoid circularity */
2122
structExprEvalStep;
@@ -416,7 +417,8 @@ typedef struct ExprEvalStep
416417
FunctionCallInfofcinfo_data_out;
417418
/* lookup and call info for result type's input function */
418419
FmgrInfo*finfo_in;
419-
FunctionCallInfofcinfo_data_in;
420+
Oidtypioparam;
421+
ErrorSaveContext*escontext;
420422
}iocoerce;
421423

422424
/* for EEOP_SQLVALUEFUNCTION */
@@ -547,6 +549,7 @@ typedef struct ExprEvalStep
547549
bool*checknull;
548550
/* OID of domain type */
549551
Oidresulttype;
552+
ErrorSaveContext*escontext;
550553
}domaincheck;
551554

552555
/* for EEOP_CONVERT_ROWTYPE */

‎src/include/jit/llvmjit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,15 @@ extern PGDLLIMPORT LLVMTypeRef StructTupleTableSlot;
7575
externPGDLLIMPORTLLVMTypeRefStructHeapTupleTableSlot;
7676
externPGDLLIMPORTLLVMTypeRefStructMinimalTupleTableSlot;
7777
externPGDLLIMPORTLLVMTypeRefStructMemoryContextData;
78+
externPGDLLIMPORTLLVMTypeRefStructFmgrInfo;
7879
externPGDLLIMPORTLLVMTypeRefStructFunctionCallInfoData;
7980
externPGDLLIMPORTLLVMTypeRefStructExprContext;
8081
externPGDLLIMPORTLLVMTypeRefStructExprEvalStep;
8182
externPGDLLIMPORTLLVMTypeRefStructExprState;
8283
externPGDLLIMPORTLLVMTypeRefStructAggState;
8384
externPGDLLIMPORTLLVMTypeRefStructAggStatePerTransData;
8485
externPGDLLIMPORTLLVMTypeRefStructAggStatePerGroupData;
86+
externPGDLLIMPORTLLVMTypeRefStructErrorSaveContext;
8587

8688
externPGDLLIMPORTLLVMValueRefAttributeTemplate;
8789

‎src/include/jit/llvmjit_emit.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ l_sizet_const(size_t i)
8585
returnLLVMConstInt(TypeSizeT,i, false);
8686
}
8787

88+
/*
89+
* Emit constant oid.
90+
*/
91+
staticinlineLLVMValueRef
92+
l_oid_const(LLVMContextReflc,Oidi)
93+
{
94+
returnLLVMConstInt(LLVMInt32TypeInContext(lc),i, false);
95+
}
96+
8897
/*
8998
* Emit constant boolean, as used for storage (e.g. global vars, structs).
9099
*/

‎src/include/nodes/execnodes.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include"fmgr.h"
3535
#include"lib/ilist.h"
3636
#include"lib/pairingheap.h"
37+
#include"nodes/miscnodes.h"
3738
#include"nodes/params.h"
3839
#include"nodes/plannodes.h"
3940
#include"nodes/tidbitmap.h"
@@ -129,6 +130,12 @@ typedef struct ExprState
129130

130131
Datum*innermost_domainval;
131132
bool*innermost_domainnull;
133+
134+
/*
135+
* For expression nodes that support soft errors. Should be set to NULL
136+
* before calling ExecInitExprRec() if the caller wants errors thrown.
137+
*/
138+
ErrorSaveContext*escontext;
132139
}ExprState;
133140

134141

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp