Skip to content

Commit facc245

Browse files
author
hackorum
committed
Apply dont_error_on_const_folding_with_invalid_input.patch
1 parent b597835 commit facc245

6 files changed

Lines changed: 44 additions & 10 deletions

File tree

src/backend/executor/execExpr.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,17 @@ static void ExecInitJsonCoercion(ExprState *state, JsonReturning *returning,
140140
* although ExecQual and ExecCheck will accept one (and treat it as "true").
141141
*/
142142
ExprState *
143-
ExecInitExpr(Expr *node, PlanState *parent)
143+
ExecInitExpr(Expr* node, PlanState* parent)
144+
{
145+
return ExecInitExprWithErrorContext(node, parent, NULL);
146+
}
147+
148+
/*
149+
* As ExecInitExpr but attempt to save errors into 'err_context' when
150+
* supported by the functions being called. XXX write something better here.
151+
*/
152+
ExprState *
153+
ExecInitExprWithErrorContext(Expr *node, PlanState *parent, fmNodePtr *err_context)
144154
{
145155
ExprState *state;
146156
ExprEvalStep scratch = {0};
@@ -154,6 +164,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
154164
state->expr = node;
155165
state->parent = parent;
156166
state->ext_params = NULL;
167+
state->err_context = err_context;
157168

158169
/* Insert setup steps as needed */
159170
ExecCreateExprSetupSteps(state, (Node *) node);
@@ -2736,7 +2747,7 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
27362747

27372748
/* Initialize function call parameter structure too */
27382749
InitFunctionCallInfoData(*fcinfo, flinfo,
2739-
nargs, inputcollid, NULL, NULL);
2750+
nargs, inputcollid, (fmNodePtr) state->err_context, NULL);
27402751

27412752
/* Keep extra copies of this info to save an indirection at runtime */
27422753
scratch->d.func.fn_addr = flinfo->fn_addr;

src/backend/optimizer/util/clauses.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "funcapi.h"
3333
#include "miscadmin.h"
3434
#include "nodes/makefuncs.h"
35+
#include "nodes/miscnodes.h"
3536
#include "nodes/multibitmapset.h"
3637
#include "nodes/nodeFuncs.h"
3738
#include "nodes/subscripting.h"
@@ -2705,7 +2706,7 @@ estimate_expression_value(PlannerInfo *root, Node *node)
27052706
((Node *) evaluate_expr((Expr *) (node), \
27062707
exprType((Node *) (node)), \
27072708
exprTypmod((Node *) (node)), \
2708-
exprCollation((Node *) (node))))
2709+
exprCollation((Node *) (node)), false))
27092710

27102711
/*
27112712
* Recursive guts of eval_const_expressions/estimate_expression_value
@@ -3741,7 +3742,8 @@ eval_const_expressions_mutator(Node *node,
37413742
return (Node *) evaluate_expr((Expr *) svf,
37423743
svf->type,
37433744
svf->typmod,
3744-
InvalidOid);
3745+
InvalidOid,
3746+
false);
37453747
else
37463748
return copyObject((Node *) svf);
37473749
}
@@ -5293,7 +5295,7 @@ evaluate_function(Oid funcid, Oid result_type, int32 result_typmod,
52935295
newexpr->location = -1;
52945296

52955297
return evaluate_expr((Expr *) newexpr, result_type, result_typmod,
5296-
result_collid);
5298+
result_collid, true);
52975299
}
52985300

52995301
/*
@@ -5747,11 +5749,16 @@ sql_inline_error_callback(void *arg)
57475749
*
57485750
* We use the executor's routine ExecEvalExpr() to avoid duplication of
57495751
* code and ensure we get the same result as the executor would get.
5752+
*
5753+
* 'null_on_error' may be passed as true to have the expression evalulation
5754+
* code attempt to supress ERRORs and save them. This of course requires
5755+
* functions properly errsave/ereturn rather than elog/ereport.
57505756
*/
57515757
Expr *
57525758
evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
5753-
Oid result_collation)
5759+
Oid result_collation, bool null_on_error)
57545760
{
5761+
ErrorSaveContext escontext = {T_ErrorSaveContext};
57555762
EState *estate;
57565763
ExprState *exprstate;
57575764
MemoryContext oldcontext;
@@ -5775,7 +5782,12 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
57755782
* Prepare expr for execution. (Note: we can't use ExecPrepareExpr
57765783
* because it'd result in recursively invoking eval_const_expressions.)
57775784
*/
5778-
exprstate = ExecInitExpr(expr, NULL);
5785+
if (null_on_error)
5786+
exprstate = ExecInitExprWithErrorContext(expr,
5787+
NULL,
5788+
(fmNodePtr *) &escontext);
5789+
else
5790+
exprstate = ExecInitExpr(expr, NULL);
57795791

57805792
/*
57815793
* And evaluate it.
@@ -5803,7 +5815,7 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
58035815
* data. (makeConst would handle detoasting anyway, but it's worth a few
58045816
* extra lines here so that we can do the copy and detoast in one step.)
58055817
*/
5806-
if (!const_is_null)
5818+
if (!escontext.error_occurred && !const_is_null)
58075819
{
58085820
if (resultTypLen == -1)
58095821
const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
@@ -5814,6 +5826,9 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
58145826
/* Release all the junk we just created */
58155827
FreeExecutorState(estate);
58165828

5829+
if (escontext.error_occurred)
5830+
return NULL;
5831+
58175832
/*
58185833
* Make the constant result node.
58195834
*/

src/backend/parser/parse_utilcmd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5212,7 +5212,7 @@ transformPartitionBoundValue(ParseState *pstate, Node *val,
52125212
assign_expr_collations(pstate, value);
52135213
value = (Node *) expression_planner((Expr *) value);
52145214
value = (Node *) evaluate_expr((Expr *) value, colType, colTypmod,
5215-
partCollation);
5215+
partCollation, false);
52165216
if (!IsA(value, Const))
52175217
elog(ERROR, "could not evaluate partition bound expression");
52185218
}

src/include/executor/executor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ ExecProcNode(PlanState *node)
332332
* prototypes from functions in execExpr.c
333333
*/
334334
extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
335+
extern ExprState *ExecInitExprWithErrorContext(Expr *node, PlanState *parent,
336+
fmNodePtr *err_context);
335337
extern ExprState *ExecInitExprWithParams(Expr *node, ParamListInfo ext_params);
336338
extern ExprState *ExecInitQual(List *qual, PlanState *parent);
337339
extern ExprState *ExecInitCheck(List *qual, PlanState *parent);

src/include/nodes/execnodes.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ typedef struct ExprState
146146
PlanState *parent; /* parent PlanState node, if any */
147147
ParamListInfo ext_params; /* for compiling PARAM_EXTERN nodes */
148148

149+
/*
150+
* ErrorSaveContext pointer to record any saved ERRORs into or NULL if
151+
* errors are to be raised right away.
152+
*/
153+
fmNodePtr *err_context;
154+
149155
Datum *innermost_caseval;
150156
bool *innermost_casenull;
151157

src/include/optimizer/optimizer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ extern void convert_saop_to_hashed_saop(Node *node);
151151
extern Node *estimate_expression_value(PlannerInfo *root, Node *node);
152152

153153
extern Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
154-
Oid result_collation);
154+
Oid result_collation, bool null_on_error);
155155

156156
extern bool var_is_nonnullable(PlannerInfo *root, Var *var,
157157
NotNullSource source);

0 commit comments

Comments
 (0)