blob: db34c436fba745b7d8d6854de21281c090723187 [file] [log] [blame]
/*
* 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.Convention;
import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.util.Pair;
import java.util.*;
import static org.apache.solr.handler.sql.SolrAggregate.solrAggMetricId;
/**
* Relational expression that uses Solr calling convention.
*/
interface SolrRel extends RelNode {
void implement(Implementor implementor);
/** Calling convention for relational operations that occur in Solr. */
Convention CONVENTION = new Convention.Impl("Solr", SolrRel.class);
/** Callback for the implementation process that converts a tree of {@link SolrRel} nodes into a Solr query. */
class Implementor {
final Map<String, String> fieldMappings = new HashMap<>();
final Map<String, String> reverseAggMappings = new HashMap<>();
String query = null;
String havingPredicate;
boolean negativeQuery;
String limitValue = null;
String offsetValue = null;
final List<Pair<String, String>> orders = new ArrayList<>();
final List<String> buckets = new ArrayList<>();
final List<Pair<String, String>> metricPairs = new ArrayList<>();
RelOptTable table;
SolrTable solrTable;
void addFieldMapping(String key, String val, boolean overwrite) {
if(key != null) {
if(overwrite || !fieldMappings.containsKey(key)) {
this.fieldMappings.put(key, val);
}
}
}
void addReverseAggMapping(String key, String val) {
if(key != null && !reverseAggMappings.containsKey(key)) {
this.reverseAggMappings.put(key, val);
}
}
void addQuery(String query) {
this.query = query;
}
void setNegativeQuery(boolean negativeQuery) {
this.negativeQuery = negativeQuery;
}
void addOrder(String column, String direction) {
column = this.fieldMappings.getOrDefault(column, column);
this.orders.add(new Pair<>(column, direction));
}
void addBucket(String bucket) {
bucket = this.fieldMappings.getOrDefault(bucket, bucket);
this.buckets.add(bucket);
}
void addMetricPair(String outName, String metric, String column) {
column = this.fieldMappings.getOrDefault(column, column);
this.metricPairs.add(new Pair<>(metric, column));
if(outName != null) {
this.addFieldMapping(outName, solrAggMetricId(metric, column), true);
}
}
void setHavingPredicate(String havingPredicate) {
this.havingPredicate = havingPredicate;
}
void setLimit(String limit) {
limitValue = limit;
}
void setOffset(String offset) {
this.offsetValue = offset;
}
void visitChild(int ordinal, RelNode input) {
assert ordinal == 0;
((SolrRel) input).implement(this);
}
}
}