| /* |
| * 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.jdbc; |
| |
| import org.apache.calcite.rel.type.RelProtoDataType; |
| import org.apache.calcite.schema.Function; |
| import org.apache.calcite.schema.Schema; |
| import org.apache.calcite.schema.SchemaVersion; |
| import org.apache.calcite.schema.Table; |
| import org.apache.calcite.schema.TableMacro; |
| import org.apache.calcite.util.NameMap; |
| import org.apache.calcite.util.NameMultimap; |
| import org.apache.calcite.util.NameSet; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSortedMap; |
| import com.google.common.collect.ImmutableSortedSet; |
| |
| import org.checkerframework.checker.nullness.qual.Nullable; |
| |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Set; |
| |
| /** |
| * A concrete implementation of {@link org.apache.calcite.jdbc.CalciteSchema} |
| * that maintains minimal state. |
| */ |
| class SimpleCalciteSchema extends CalciteSchema { |
| /** Creates a SimpleCalciteSchema. |
| * |
| * <p>Use {@link CalciteSchema#createRootSchema(boolean)} |
| * or {@link #add(String, Schema)}. */ |
| SimpleCalciteSchema(@Nullable CalciteSchema parent, Schema schema, String name) { |
| this(parent, schema, name, null, null, null, null, null, null, null, null); |
| } |
| |
| private SimpleCalciteSchema(@Nullable CalciteSchema parent, |
| Schema schema, |
| String name, |
| @Nullable NameMap<CalciteSchema> subSchemaMap, |
| @Nullable NameMap<TableEntry> tableMap, |
| @Nullable NameMap<LatticeEntry> latticeMap, |
| @Nullable NameMap<TypeEntry> typeMap, |
| @Nullable NameMultimap<FunctionEntry> functionMap, |
| @Nullable NameSet functionNames, |
| @Nullable NameMap<FunctionEntry> nullaryFunctionMap, |
| @Nullable List<? extends List<String>> path) { |
| super(parent, schema, name, subSchemaMap, tableMap, latticeMap, typeMap, |
| functionMap, functionNames, nullaryFunctionMap, path); |
| } |
| |
| @Override public void setCache(boolean cache) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override public CalciteSchema add(String name, Schema schema) { |
| final CalciteSchema calciteSchema = |
| new SimpleCalciteSchema(this, schema, name); |
| subSchemaMap.put(name, calciteSchema); |
| return calciteSchema; |
| } |
| |
| private static @Nullable String caseInsensitiveLookup(Set<String> candidates, String name) { |
| // Exact string lookup |
| if (candidates.contains(name)) { |
| return name; |
| } |
| // Upper case string lookup |
| final String upperCaseName = name.toUpperCase(Locale.ROOT); |
| if (candidates.contains(upperCaseName)) { |
| return upperCaseName; |
| } |
| // Lower case string lookup |
| final String lowerCaseName = name.toLowerCase(Locale.ROOT); |
| if (candidates.contains(lowerCaseName)) { |
| return lowerCaseName; |
| } |
| // Fall through: Set iteration |
| for (String candidate: candidates) { |
| if (candidate.equalsIgnoreCase(name)) { |
| return candidate; |
| } |
| } |
| return null; |
| } |
| |
| @Override protected @Nullable CalciteSchema getImplicitSubSchema(String schemaName, |
| boolean caseSensitive) { |
| // Check implicit schemas. |
| final String schemaName2 = caseSensitive ? schemaName : caseInsensitiveLookup( |
| schema.getSubSchemaNames(), schemaName); |
| if (schemaName2 == null) { |
| return null; |
| } |
| final Schema s = schema.getSubSchema(schemaName2); |
| if (s == null) { |
| return null; |
| } |
| return new SimpleCalciteSchema(this, s, schemaName2); |
| } |
| |
| @Override protected @Nullable TableEntry getImplicitTable(String tableName, |
| boolean caseSensitive) { |
| // Check implicit tables. |
| final String tableName2 = caseSensitive ? tableName : caseInsensitiveLookup( |
| schema.getTableNames(), tableName); |
| if (tableName2 == null) { |
| return null; |
| } |
| final Table table = schema.getTable(tableName2); |
| if (table == null) { |
| return null; |
| } |
| return tableEntry(tableName2, table); |
| } |
| |
| @Override protected @Nullable TypeEntry getImplicitType(String name, boolean caseSensitive) { |
| // Check implicit types. |
| final String name2 = caseSensitive ? name : caseInsensitiveLookup( |
| schema.getTypeNames(), name); |
| if (name2 == null) { |
| return null; |
| } |
| final RelProtoDataType type = schema.getType(name2); |
| if (type == null) { |
| return null; |
| } |
| return typeEntry(name2, type); |
| } |
| |
| @Override protected void addImplicitSubSchemaToBuilder( |
| ImmutableSortedMap.Builder<String, CalciteSchema> builder) { |
| ImmutableSortedMap<String, CalciteSchema> explicitSubSchemas = builder.build(); |
| for (String schemaName : schema.getSubSchemaNames()) { |
| if (explicitSubSchemas.containsKey(schemaName)) { |
| // explicit subschema wins. |
| continue; |
| } |
| Schema s = schema.getSubSchema(schemaName); |
| if (s != null) { |
| CalciteSchema calciteSchema = new SimpleCalciteSchema(this, s, schemaName); |
| builder.put(schemaName, calciteSchema); |
| } |
| } |
| } |
| |
| @Override protected void addImplicitTableToBuilder(ImmutableSortedSet.Builder<String> builder) { |
| builder.addAll(schema.getTableNames()); |
| } |
| |
| @Override protected void addImplicitFunctionsToBuilder( |
| ImmutableList.Builder<Function> builder, |
| String name, boolean caseSensitive) { |
| Collection<Function> functions = schema.getFunctions(name); |
| if (functions != null) { |
| builder.addAll(functions); |
| } |
| } |
| |
| @Override protected void addImplicitFuncNamesToBuilder( |
| ImmutableSortedSet.Builder<String> builder) { |
| builder.addAll(schema.getFunctionNames()); |
| } |
| |
| @Override protected void addImplicitTypeNamesToBuilder( |
| ImmutableSortedSet.Builder<String> builder) { |
| builder.addAll(schema.getTypeNames()); |
| } |
| |
| @Override protected void addImplicitTablesBasedOnNullaryFunctionsToBuilder( |
| ImmutableSortedMap.Builder<String, Table> builder) { |
| ImmutableSortedMap<String, Table> explicitTables = builder.build(); |
| |
| for (String s : schema.getFunctionNames()) { |
| // explicit table wins. |
| if (explicitTables.containsKey(s)) { |
| continue; |
| } |
| for (Function function : schema.getFunctions(s)) { |
| if (function instanceof TableMacro |
| && function.getParameters().isEmpty()) { |
| final Table table = ((TableMacro) function).apply(ImmutableList.of()); |
| builder.put(s, table); |
| } |
| } |
| } |
| } |
| |
| @Override protected @Nullable TableEntry getImplicitTableBasedOnNullaryFunction(String tableName, |
| boolean caseSensitive) { |
| Collection<Function> functions = schema.getFunctions(tableName); |
| if (functions != null) { |
| for (Function function : functions) { |
| if (function instanceof TableMacro |
| && function.getParameters().isEmpty()) { |
| final Table table = ((TableMacro) function).apply(ImmutableList.of()); |
| return tableEntry(tableName, table); |
| } |
| } |
| } |
| return null; |
| } |
| |
| @Override protected CalciteSchema snapshot(@Nullable CalciteSchema parent, |
| SchemaVersion version) { |
| CalciteSchema snapshot = new SimpleCalciteSchema(parent, |
| schema.snapshot(version), name, null, tableMap, latticeMap, typeMap, |
| functionMap, functionNames, nullaryFunctionMap, getPath()); |
| for (CalciteSchema subSchema : subSchemaMap.map().values()) { |
| CalciteSchema subSchemaSnapshot = subSchema.snapshot(snapshot, version); |
| snapshot.subSchemaMap.put(subSchema.name, subSchemaSnapshot); |
| } |
| return snapshot; |
| } |
| |
| @Override protected boolean isCacheEnabled() { |
| return false; |
| } |
| |
| } |