| /* |
| * 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.solr.handler.sql; |
| |
| import org.apache.calcite.plan.RelOptCluster; |
| import org.apache.calcite.plan.RelTraitSet; |
| import org.apache.calcite.rel.RelNode; |
| import org.apache.calcite.rel.core.Aggregate; |
| import org.apache.calcite.rel.core.AggregateCall; |
| import org.apache.calcite.sql.SqlAggFunction; |
| import org.apache.calcite.sql.fun.SqlStdOperatorTable; |
| import org.apache.calcite.util.ImmutableBitSet; |
| import org.apache.calcite.util.Pair; |
| |
| import java.util.*; |
| |
| /** |
| * Implementation of {@link org.apache.calcite.rel.core.Aggregate} relational expression in Solr. |
| */ |
| class SolrAggregate extends Aggregate implements SolrRel { |
| private static final List<SqlAggFunction> SUPPORTED_AGGREGATIONS = Arrays.asList( |
| SqlStdOperatorTable.COUNT, |
| SqlStdOperatorTable.SUM, |
| SqlStdOperatorTable.SUM0, |
| SqlStdOperatorTable.MIN, |
| SqlStdOperatorTable.MAX, |
| SqlStdOperatorTable.AVG |
| ); |
| |
| SolrAggregate( |
| RelOptCluster cluster, |
| RelTraitSet traitSet, |
| RelNode child, |
| boolean indicator, |
| ImmutableBitSet groupSet, |
| List<ImmutableBitSet> groupSets, |
| List<AggregateCall> aggCalls) { |
| super(cluster, traitSet, child, indicator, groupSet, groupSets, aggCalls); |
| assert getConvention() == SolrRel.CONVENTION; |
| assert getConvention() == child.getConvention(); |
| } |
| |
| @Override |
| public Aggregate copy(RelTraitSet traitSet, RelNode input, |
| boolean indicator, ImmutableBitSet groupSet, |
| List<ImmutableBitSet> groupSets, List<AggregateCall> aggCalls) { |
| return new SolrAggregate(getCluster(), traitSet, input, indicator, groupSet, groupSets, aggCalls); |
| } |
| |
| public void implement(Implementor implementor) { |
| implementor.visitChild(0, getInput()); |
| |
| final List<String> inNames = SolrRules.solrFieldNames(getInput().getRowType()); |
| |
| |
| for(Pair<AggregateCall, String> namedAggCall : getNamedAggCalls()) { |
| |
| AggregateCall aggCall = namedAggCall.getKey(); |
| |
| Pair<String, String> metric = toSolrMetric(implementor, aggCall, inNames); |
| implementor.addReverseAggMapping(namedAggCall.getValue(), metric.getKey().toLowerCase(Locale.ROOT)+"("+metric.getValue()+")"); |
| implementor.addMetricPair(namedAggCall.getValue(), metric.getKey(), metric.getValue()); |
| /* |
| if(aggCall.getName() == null) { |
| System.out.println("AGG:"+namedAggCall.getValue()+":"+ aggCall.getAggregation().getName() + "(" + inNames.get(aggCall.getArgList().get(0)) + ")"); |
| implementor.addFieldMapping(namedAggCall.getValue(), |
| aggCall.getAggregation().getName() + "(" + inNames.get(aggCall.getArgList().get(0)) + ")"); |
| } |
| */ |
| } |
| |
| for(int group : getGroupSet()) { |
| String inName = inNames.get(group); |
| implementor.addBucket(inName); |
| } |
| } |
| |
| @SuppressWarnings({"fallthrough"}) |
| private Pair<String, String> toSolrMetric(Implementor implementor, AggregateCall aggCall, List<String> inNames) { |
| SqlAggFunction aggregation = aggCall.getAggregation(); |
| List<Integer> args = aggCall.getArgList(); |
| switch (args.size()) { |
| case 0: |
| if (aggregation.equals(SqlStdOperatorTable.COUNT)) { |
| return new Pair<>(aggregation.getName(), "*"); |
| } |
| case 1: |
| String inName = inNames.get(args.get(0)); |
| String name = implementor.fieldMappings.getOrDefault(inName, inName); |
| if(SUPPORTED_AGGREGATIONS.contains(aggregation)) { |
| return new Pair<>(aggregation.getName(), name); |
| } |
| default: |
| throw new AssertionError("Invalid aggregation " + aggregation + " with args " + args + " with names" + inNames); |
| } |
| } |
| } |
| |
| // End SolrAggregate.java |