mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-01 06:31:20 +02:00
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.
This commit is contained in:
parent
305d3ce576
commit
ab843085f1
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.66 2000/04/16 01:55:45 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.67 2000/05/28 20:33:28 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -1307,7 +1307,7 @@ eval_const_expressions_mutator(Node *node, void *context)
|
|||||||
* the expression here. This would avoid much runtime overhead, and perhaps
|
* the expression here. This would avoid much runtime overhead, and perhaps
|
||||||
* expose opportunities for constant-folding within the expression even if
|
* expose opportunities for constant-folding within the expression even if
|
||||||
* not all the func's input args are constants. It'd be appropriate to do
|
* not all the func's input args are constants. It'd be appropriate to do
|
||||||
* here, and not in the parser, since we wouldn't want it to happen until
|
* that here, not in the parser, since we wouldn't want it to happen until
|
||||||
* after rule substitution/rewriting.
|
* after rule substitution/rewriting.
|
||||||
*/
|
*/
|
||||||
static Expr *
|
static Expr *
|
||||||
@ -1321,26 +1321,38 @@ simplify_op_or_func(Expr *expr, List *args)
|
|||||||
Type resultType;
|
Type resultType;
|
||||||
Expr *newexpr;
|
Expr *newexpr;
|
||||||
Datum const_val;
|
Datum const_val;
|
||||||
|
bool has_nonconst_input = false;
|
||||||
|
bool has_null_input = false;
|
||||||
bool const_is_null;
|
bool const_is_null;
|
||||||
bool isDone;
|
bool isDone;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For an operator or function, we cannot simplify unless all the
|
* Check for constant inputs and especially constant-NULL inputs.
|
||||||
* inputs are constants. (XXX possible future improvement: if the
|
|
||||||
* op/func is strict and at least one input is NULL, we could simplify
|
|
||||||
* to NULL. But we do not currently have any way to know if the
|
|
||||||
* op/func is strict or not. For now, a NULL input is treated the
|
|
||||||
* same as any other constant node.)
|
|
||||||
*/
|
*/
|
||||||
foreach(arg, args)
|
foreach(arg, args)
|
||||||
{
|
{
|
||||||
if (!IsA(lfirst(arg), Const))
|
if (IsA(lfirst(arg), Const))
|
||||||
return NULL;
|
has_null_input |= ((Const *) lfirst(arg))->constisnull;
|
||||||
|
else
|
||||||
|
has_nonconst_input = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the function is strict and has a constant-NULL input, it will
|
||||||
|
* never be called at all, so we can replace the call by a NULL
|
||||||
|
* constant even if there are other inputs that aren't constant.
|
||||||
|
* Otherwise, we can only simplify if all inputs are constants.
|
||||||
|
* We can skip the function lookup if neither case applies.
|
||||||
|
*/
|
||||||
|
if (has_nonconst_input && !has_null_input)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the function procedure's OID and look to see whether it is
|
* Get the function procedure's OID and look to see whether it is
|
||||||
* marked proiscachable.
|
* marked proiscachable.
|
||||||
|
*
|
||||||
|
* XXX would it be better to take the result type from the pg_proc tuple,
|
||||||
|
* rather than the Oper or Func node?
|
||||||
*/
|
*/
|
||||||
if (expr->opType == OP_EXPR)
|
if (expr->opType == OP_EXPR)
|
||||||
{
|
{
|
||||||
@ -1373,6 +1385,31 @@ simplify_op_or_func(Expr *expr, List *args)
|
|||||||
if (funcform->proretset)
|
if (funcform->proretset)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now that we know if the function is strict, we can finish the
|
||||||
|
* checks for simplifiable inputs that we started above.
|
||||||
|
*/
|
||||||
|
if (funcform->proisstrict && has_null_input)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* It's strict and has NULL input, so must produce NULL output.
|
||||||
|
* Return a NULL constant of the right type.
|
||||||
|
*/
|
||||||
|
resultType = typeidType(result_typeid);
|
||||||
|
return (Expr *) makeConst(result_typeid, typeLen(resultType),
|
||||||
|
(Datum) 0, true,
|
||||||
|
typeByVal(resultType),
|
||||||
|
false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Otherwise, can simplify only if all inputs are constants.
|
||||||
|
* (For a non-strict function, constant NULL inputs are treated
|
||||||
|
* the same as constant non-NULL inputs.)
|
||||||
|
*/
|
||||||
|
if (has_nonconst_input)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OK, looks like we can simplify this operator/function.
|
* OK, looks like we can simplify this operator/function.
|
||||||
*
|
*
|
||||||
@ -1402,9 +1439,6 @@ simplify_op_or_func(Expr *expr, List *args)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Make the constant result node.
|
* Make the constant result node.
|
||||||
*
|
|
||||||
* XXX would it be better to take the result type from the pg_proc tuple,
|
|
||||||
* rather than the Oper or Func node?
|
|
||||||
*/
|
*/
|
||||||
resultType = typeidType(result_typeid);
|
resultType = typeidType(result_typeid);
|
||||||
return (Expr *) makeConst(result_typeid, typeLen(resultType),
|
return (Expr *) makeConst(result_typeid, typeLen(resultType),
|
||||||
|
Loading…
Reference in New Issue
Block a user