Skip to content

Commit ab84308

Browse files
committed
Constant-expression simplifier now knows how to simplify strict functions
that have at least one constant-NULL input, even if other inputs are not constants.
1 parent 305d3ce commit ab84308

File tree

1 file changed

+47
-13
lines changed

1 file changed

+47
-13
lines changed

src/backend/optimizer/util/clauses.c

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.66 2000/04/16 01:55:45 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.67 2000/05/28 20:33:28 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHOR DATE MAJOR EVENT
@@ -1307,7 +1307,7 @@ eval_const_expressions_mutator(Node *node, void *context)
13071307
* the expression here. This would avoid much runtime overhead, and perhaps
13081308
* expose opportunities for constant-folding within the expression even if
13091309
* not all the func's input args are constants. It'd be appropriate to do
1310-
* here, and not in the parser, since we wouldn't want it to happen until
1310+
* that here, not in the parser, since we wouldn't want it to happen until
13111311
* after rule substitution/rewriting.
13121312
*/
13131313
static Expr *
@@ -1321,26 +1321,38 @@ simplify_op_or_func(Expr *expr, List *args)
13211321
Type resultType;
13221322
Expr *newexpr;
13231323
Datum const_val;
1324+
bool has_nonconst_input = false;
1325+
bool has_null_input = false;
13241326
bool const_is_null;
13251327
bool isDone;
13261328

13271329
/*
1328-
* For an operator or function, we cannot simplify unless all the
1329-
* inputs are constants. (XXX possible future improvement: if the
1330-
* op/func is strict and at least one input is NULL, we could simplify
1331-
* to NULL. But we do not currently have any way to know if the
1332-
* op/func is strict or not. For now, a NULL input is treated the
1333-
* same as any other constant node.)
1330+
* Check for constant inputs and especially constant-NULL inputs.
13341331
*/
13351332
foreach(arg, args)
13361333
{
1337-
if (!IsA(lfirst(arg), Const))
1338-
return NULL;
1334+
if (IsA(lfirst(arg), Const))
1335+
has_null_input |= ((Const *) lfirst(arg))->constisnull;
1336+
else
1337+
has_nonconst_input = true;
13391338
}
13401339

1340+
/*
1341+
* If the function is strict and has a constant-NULL input, it will
1342+
* never be called at all, so we can replace the call by a NULL
1343+
* constant even if there are other inputs that aren't constant.
1344+
* Otherwise, we can only simplify if all inputs are constants.
1345+
* We can skip the function lookup if neither case applies.
1346+
*/
1347+
if (has_nonconst_input && !has_null_input)
1348+
return NULL;
1349+
13411350
/*
13421351
* Get the function procedure's OID and look to see whether it is
13431352
* marked proiscachable.
1353+
*
1354+
* XXX would it be better to take the result type from the pg_proc tuple,
1355+
* rather than the Oper or Func node?
13441356
*/
13451357
if (expr->opType == OP_EXPR)
13461358
{
@@ -1373,6 +1385,31 @@ simplify_op_or_func(Expr *expr, List *args)
13731385
if (funcform->proretset)
13741386
return NULL;
13751387

1388+
/*
1389+
* Now that we know if the function is strict, we can finish the
1390+
* checks for simplifiable inputs that we started above.
1391+
*/
1392+
if (funcform->proisstrict && has_null_input)
1393+
{
1394+
/*
1395+
* It's strict and has NULL input, so must produce NULL output.
1396+
* Return a NULL constant of the right type.
1397+
*/
1398+
resultType = typeidType(result_typeid);
1399+
return (Expr *) makeConst(result_typeid, typeLen(resultType),
1400+
(Datum) 0, true,
1401+
typeByVal(resultType),
1402+
false, false);
1403+
}
1404+
1405+
/*
1406+
* Otherwise, can simplify only if all inputs are constants.
1407+
* (For a non-strict function, constant NULL inputs are treated
1408+
* the same as constant non-NULL inputs.)
1409+
*/
1410+
if (has_nonconst_input)
1411+
return NULL;
1412+
13761413
/*
13771414
* OK, looks like we can simplify this operator/function.
13781415
*
@@ -1402,9 +1439,6 @@ simplify_op_or_func(Expr *expr, List *args)
14021439

14031440
/*
14041441
* Make the constant result node.
1405-
*
1406-
* XXX would it be better to take the result type from the pg_proc tuple,
1407-
* rather than the Oper or Func node?
14081442
*/
14091443
resultType = typeidType(result_typeid);
14101444
return (Expr *) makeConst(result_typeid, typeLen(resultType),

0 commit comments

Comments
 (0)