/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.cache.query.internal; import org.apache.geode.cache.query.AmbiguousNameException; import org.apache.geode.cache.query.FunctionDomainException; import org.apache.geode.cache.query.NameResolutionException; import org.apache.geode.cache.query.QueryInvocationTargetException; import org.apache.geode.cache.query.TypeMismatchException; import org.apache.geode.cache.query.internal.aggregate.AvgBucketNode; import org.apache.geode.cache.query.internal.aggregate.AvgDistinct; import org.apache.geode.cache.query.internal.aggregate.AvgDistinctPRQueryNode; import org.apache.geode.cache.query.internal.aggregate.AvgPRQueryNode; import org.apache.geode.cache.query.internal.aggregate.Count; import org.apache.geode.cache.query.internal.aggregate.CountDistinct; import org.apache.geode.cache.query.internal.aggregate.CountDistinctPRQueryNode; import org.apache.geode.cache.query.internal.aggregate.SumDistinctPRQueryNode; import org.apache.geode.cache.query.internal.aggregate.CountPRQueryNode; import org.apache.geode.cache.query.internal.aggregate.DistinctAggregator; import org.apache.geode.cache.query.internal.aggregate.MaxMin; import org.apache.geode.cache.query.internal.aggregate.Avg; import org.apache.geode.cache.query.internal.aggregate.Sum; import org.apache.geode.cache.query.internal.aggregate.SumDistinct; import org.apache.geode.cache.query.internal.parse.OQLLexerTokenTypes; import org.apache.geode.cache.query.internal.types.ObjectTypeImpl; import org.apache.geode.cache.query.types.ObjectType; /** * * */ public class CompiledAggregateFunction extends AbstractCompiledValue { private final CompiledValue expr; private final int aggFuncType; private final boolean distinctOnly; public CompiledAggregateFunction(CompiledValue expr, int aggFunc) { this(expr, aggFunc, false); } public CompiledAggregateFunction(CompiledValue expr, int aggFunc, boolean distinctOnly) { this.expr = expr; this.aggFuncType = aggFunc; this.distinctOnly = distinctOnly; } @Override public int getType() { return AGG_FUNC; } @Override public Object evaluate(ExecutionContext context) throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException { boolean isPRQueryNode = context.getIsPRQueryNode(); boolean isBucketNode = context.getBucketList() != null; switch (this.aggFuncType) { case OQLLexerTokenTypes.SUM: if (isPRQueryNode) { return this.distinctOnly ? new SumDistinctPRQueryNode() : new Sum(); } else { return this.distinctOnly ? (isBucketNode ? new DistinctAggregator() : new SumDistinct()) : new Sum(); } case OQLLexerTokenTypes.MAX: return new MaxMin(true); case OQLLexerTokenTypes.MIN: return new MaxMin(false); case OQLLexerTokenTypes.AVG: if (isPRQueryNode) { return this.distinctOnly ? new AvgDistinctPRQueryNode() : new AvgPRQueryNode(); } else { return this.distinctOnly ? (isBucketNode ? new DistinctAggregator() : new AvgDistinct()) : (isBucketNode ? new AvgBucketNode() : new Avg()); } case OQLLexerTokenTypes.COUNT: if (isPRQueryNode) { return this.distinctOnly ? new CountDistinctPRQueryNode() : new CountPRQueryNode(); } else { return this.distinctOnly ? (isBucketNode ? new DistinctAggregator() : new CountDistinct()) : new Count(); } default: throw new UnsupportedOperationException("Aggregate function not implemented"); } } private String getStringRep() { switch (this.aggFuncType) { case OQLLexerTokenTypes.SUM: return "sum"; case OQLLexerTokenTypes.MAX: return "max"; case OQLLexerTokenTypes.MIN: return "min"; case OQLLexerTokenTypes.AVG: return "avg"; case OQLLexerTokenTypes.COUNT: return "count"; default: throw new UnsupportedOperationException("Aggregate function not implemented"); } } public int getFunctionType() { return this.aggFuncType; } public CompiledValue getParameter() { return this.expr; } public ObjectType getObjectType() { switch (this.aggFuncType) { case OQLLexerTokenTypes.SUM: case OQLLexerTokenTypes.MAX: case OQLLexerTokenTypes.MIN: case OQLLexerTokenTypes.AVG: return new ObjectTypeImpl(Number.class); case OQLLexerTokenTypes.COUNT: return new ObjectTypeImpl(Integer.class); default: throw new UnsupportedOperationException("Aggregate function not implemented"); } } @Override public void generateCanonicalizedExpression(StringBuffer clauseBuffer, ExecutionContext context) throws AmbiguousNameException, TypeMismatchException, NameResolutionException { clauseBuffer.insert(0, ')'); if (this.expr != null) { this.expr.generateCanonicalizedExpression(clauseBuffer, context); } else { clauseBuffer.insert(0, '*'); } if (this.distinctOnly) { clauseBuffer.insert(0, "distinct "); } clauseBuffer.insert(0, '('); clauseBuffer.insert(0, getStringRep()); } }