Github user comnetwork commented on a diff in the pull request:
https://github.com/apache/phoenix/pull/417#discussion_r243723430
--- Diff:
phoenix-core/src/main/java/org/apache/phoenix/expression/Expression.java ---
@@ -88,4 +88,10 @@
* @return
*/
boolean requiresFinalEvaluation();
+
--- End diff --
ExpressionUtil.isConstant(Expression) is not suitable for
OrderPreservingTracker.IsConstantVisitor, because
ExpressionUtil.isConstant(Expression) depends on Expression.isStateless() and
Expression.getDeterminism(). Expression isStateless() is to check if the
expression is depend on the server state, even for RowKeyColumnExpression ,
isStateless() is false. What we want to check is if a expression is constant
when all children of it are constants, just consider following sql:
select a.ak3 from
(select rand() ak1,length(pk2) ak2,length(pk3) ak3,length(v1)
av1,length(v2) av2 from test order by pk2,pk3 limit 10) a
where a.ak1 = 0.0 and a.av2 = length(substr('abc',1,1))
group by a.ak3,CASE WHEN coalesce(a.ak1,1) > coalesce(a.av2,2) THEN
coalesce(a.ak1,1) ELSE coalesce(a.av2,2) END,a.av1
order by a.ak3,a.av1
Obviously , because of rand(), the Determinism of expression a.ak1 is
Determinism.PER_INVOCATION, so for expression "CASE WHEN coalesce(a.ak1,1) >
coalesce(a.av2,2) THEN coalesce(a.ak1,1) ELSE coalesce(a.av2,2) END", the
determinism is Determinism.PER_INVOCATION and isStateless is false , but
because the a.ak1 and a.av2 are both constants in where clause of outer query,
we can regard "CASE WHEN coalesce(a.ak1,1) > coalesce(a.av2,2) THEN
coalesce(a.ak1,1) ELSE coalesce(a.av2,2) END" as constant in IsConstantVisitor.
BTW. The value returned by ExpressionUtil.isConstant() is complicated and
runtime related because of Expression.getDeterminism(). In following
BaseCompoundExpression.init method, determinism is the combine of its children.
` private void init(List<Expression> children) {
this.children = ImmutableList.copyOf(children);
boolean isStateless = true;
boolean isNullable = false;
boolean requiresFinalEvaluation = false;
this.determinism = Determinism.ALWAYS;
for (int i = 0; i < children.size(); i++) {
Expression child = children.get(i);
isNullable |= child.isNullable();
isStateless &= child.isStateless();
this.determinism =
this.determinism.combine(child.getDeterminism());
requiresFinalEvaluation |= child.requiresFinalEvaluation();
}
this.isStateless = isStateless;
this.isNullable = isNullable;
this.requiresFinalEvaluation = requiresFinalEvaluation;
}`
---