blob: f4a02717abc18034e4da3e9f3ca9696fc5f194f5 [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.calcite.test.catalog;
import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rel.type.RelDataTypeFieldImpl;
import org.apache.calcite.rel.type.StructKind;
import org.apache.calcite.util.Pair;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** ColumnResolver implementation that resolves CompoundNameColumn by simulating
* Phoenix behaviors. */
final class CompoundNameColumnResolver implements MockCatalogReader.ColumnResolver {
private final Map<String, Integer> nameMap = new HashMap<>();
private final Map<String, Map<String, Integer>> groupMap = new HashMap<>();
private final String defaultColumnGroup;
CompoundNameColumnResolver(
List<CompoundNameColumn> columns, String defaultColumnGroup) {
this.defaultColumnGroup = defaultColumnGroup;
for (Ord<CompoundNameColumn> column : Ord.zip(columns)) {
nameMap.put(column.e.getName(), column.i);
Map<String, Integer> subMap =
groupMap.computeIfAbsent(column.e.first, k -> new HashMap<>());
subMap.put(column.e.second, column.i);
}
}
@Override public List<Pair<RelDataTypeField, List<String>>> resolveColumn(
RelDataType rowType, RelDataTypeFactory typeFactory, List<String> names) {
List<Pair<RelDataTypeField, List<String>>> ret = new ArrayList<>();
if (names.size() >= 2) {
Map<String, Integer> subMap = groupMap.get(names.get(0));
if (subMap != null) {
Integer index = subMap.get(names.get(1));
if (index != null) {
ret.add(
new Pair<RelDataTypeField, List<String>>(
rowType.getFieldList().get(index),
names.subList(2, names.size())));
}
}
}
final String columnName = names.get(0);
final List<String> remainder = names.subList(1, names.size());
Integer index = nameMap.get(columnName);
if (index != null) {
ret.add(
new Pair<RelDataTypeField, List<String>>(
rowType.getFieldList().get(index), remainder));
return ret;
}
final List<String> priorityGroups = Arrays.asList("", defaultColumnGroup);
for (String group : priorityGroups) {
Map<String, Integer> subMap = groupMap.get(group);
if (subMap != null) {
index = subMap.get(columnName);
if (index != null) {
ret.add(
new Pair<RelDataTypeField, List<String>>(
rowType.getFieldList().get(index), remainder));
return ret;
}
}
}
for (Map.Entry<String, Map<String, Integer>> entry : groupMap.entrySet()) {
if (priorityGroups.contains(entry.getKey())) {
continue;
}
index = entry.getValue().get(columnName);
if (index != null) {
ret.add(
new Pair<RelDataTypeField, List<String>>(
rowType.getFieldList().get(index), remainder));
}
}
if (ret.isEmpty() && names.size() == 1) {
Map<String, Integer> subMap = groupMap.get(columnName);
if (subMap != null) {
List<Map.Entry<String, Integer>> entries =
new ArrayList<>(subMap.entrySet());
entries.sort((o1, o2) -> o1.getValue() - o2.getValue());
ret.add(
new Pair<RelDataTypeField, List<String>>(
new RelDataTypeFieldImpl(
columnName, -1,
createStructType(
rowType,
typeFactory,
entries)),
remainder));
}
}
return ret;
}
private static RelDataType createStructType(
final RelDataType rowType,
RelDataTypeFactory typeFactory,
final List<Map.Entry<String, Integer>> entries) {
return typeFactory.createStructType(
StructKind.PEEK_FIELDS,
new AbstractList<RelDataType>() {
@Override public RelDataType get(int index) {
final int i = entries.get(index).getValue();
return rowType.getFieldList().get(i).getType();
}
@Override public int size() {
return entries.size();
}
},
new AbstractList<String>() {
@Override public String get(int index) {
return entries.get(index).getKey();
}
@Override public int size() {
return entries.size();
}
});
}
}