getFunctionNames() {
+ return Collections.emptySet();
+ }
+
+ @Override public Expression getExpression(@Nullable final SchemaPlus parentSchema,
+ final String name) {
+ requireNonNull(parentSchema, "parentSchema");
+ return Schemas.subSchemaExpression(parentSchema, name, getClass());
+ }
+
+ @Override public boolean isMutable() {
+ return false;
+ }
+
+ @Override public Schema snapshot(final SchemaVersion version) {
+ return this;
+ }
+}
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcCatalogSchema.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcCatalogSchema.java
index 9329e2a829e..f40b9c9a011 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcCatalogSchema.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcCatalogSchema.java
@@ -16,33 +16,31 @@
*/
package org.apache.calcite.adapter.jdbc;
-import com.google.common.collect.ImmutableSet;
-
import org.apache.calcite.DataContext;
import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.linq4j.tree.Expressions;
-import org.apache.calcite.schema.lookup.LikePattern;
-import org.apache.calcite.schema.lookup.Lookup;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.schema.Schemas;
+import org.apache.calcite.schema.Table;
import org.apache.calcite.schema.Wrapper;
-import org.apache.calcite.schema.impl.AbstractSchema;
-import org.apache.calcite.schema.lookup.CachingLookup;
import org.apache.calcite.schema.lookup.IgnoreCaseLookup;
+import org.apache.calcite.schema.lookup.LikePattern;
+import org.apache.calcite.schema.lookup.LoadingCacheLookup;
+import org.apache.calcite.schema.lookup.Lookup;
import org.apache.calcite.sql.SqlDialect;
import org.apache.calcite.sql.SqlDialectFactory;
import org.apache.calcite.sql.SqlDialectFactoryImpl;
import org.apache.calcite.util.BuiltInMethod;
import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableSet;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import javax.sql.DataSource;
@@ -57,11 +55,11 @@
* an instance of {@link JdbcSchema}.
*
* This schema is lazy: it does not compute the list of schema names until
- * the first call to {@link #getSubSchemaMap()}. Then it creates a
- * {@link JdbcSchema} for each schema name. Each JdbcSchema will populate its
+ * the first call to {@link #subSchemas()} and {@link Lookup#get(String)}. Then it creates a
+ * {@link JdbcSchema} for this schema name. Each JdbcSchema will populate its
* tables on demand.
*/
-public class JdbcCatalogSchema extends AbstractSchema implements Wrapper {
+public class JdbcCatalogSchema extends JdbcBaseSchema implements Wrapper {
final DataSource dataSource;
public final SqlDialect dialect;
final JdbcConvention convention;
@@ -80,12 +78,11 @@ public JdbcCatalogSchema(DataSource dataSource, SqlDialect dialect,
this.dialect = requireNonNull(dialect, "dialect");
this.convention = requireNonNull(convention, "convention");
this.catalog = catalog;
- this.subSchemas = new CachingLookup<>(new IgnoreCaseLookup() {
- @Override
- public @Nullable JdbcSchema get(String name) {
+ this.subSchemas = new LoadingCacheLookup<>(new IgnoreCaseLookup() {
+ @Override public @Nullable JdbcSchema get(String name) {
try (Connection connection = dataSource.getConnection();
- ResultSet resultSet =
- connection.getMetaData().getSchemas(catalog, name)) {
+ ResultSet resultSet =
+ connection.getMetaData().getSchemas(catalog, name)) {
while (resultSet.next()) {
final String schemaName =
requireNonNull(resultSet.getString(1),
@@ -98,15 +95,15 @@ public JdbcCatalogSchema(DataSource dataSource, SqlDialect dialect,
return null;
}
- @Override
- public Set getNames(LikePattern pattern) {
+ @Override public Set getNames(LikePattern pattern) {
final ImmutableSet.Builder builder =
ImmutableSet.builder();
try (Connection connection = dataSource.getConnection();
- ResultSet resultSet =
- connection.getMetaData().getSchemas(catalog, pattern.pattern)) {
+ ResultSet resultSet =
+ connection.getMetaData().getSchemas(catalog, pattern.pattern)) {
while (resultSet.next()) {
- builder.add(requireNonNull(resultSet.getString(1),
+ builder.add(
+ requireNonNull(resultSet.getString(1),
"got null schemaName from the database"));
}
} catch (SQLException e) {
@@ -145,6 +142,10 @@ public static JdbcCatalogSchema create(
return new JdbcCatalogSchema(dataSource, dialect, convention, catalog);
}
+ @Override public Lookup tables() {
+ return Lookup.empty();
+ }
+
@Override public Lookup extends Schema> subSchemas() {
return subSchemas;
}
@@ -157,10 +158,6 @@ private String computeDefaultSchemaName() {
}
}
- @Override protected Map getSubSchemaMap() {
- throw new UnsupportedOperationException("getSubSchemaMap");
- }
-
/** Returns the name of the default sub-schema. */
public @Nullable String getDefaultSubSchemaName() {
return defaultSchemaName.get();
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java
index abd89ed8a85..cfebea44316 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java
@@ -26,7 +26,13 @@
import org.apache.calcite.rel.type.RelDataTypeImpl;
import org.apache.calcite.rel.type.RelDataTypeSystem;
import org.apache.calcite.rel.type.RelProtoDataType;
-import org.apache.calcite.schema.*;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.SchemaFactory;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.SchemaVersion;
+import org.apache.calcite.schema.Schemas;
+import org.apache.calcite.schema.Table;
+import org.apache.calcite.schema.Wrapper;
import org.apache.calcite.schema.lookup.IgnoreCaseLookup;
import org.apache.calcite.schema.lookup.LikePattern;
import org.apache.calcite.schema.lookup.Lookup;
@@ -39,9 +45,6 @@
import org.apache.calcite.util.Util;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -54,7 +57,6 @@
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -78,27 +80,23 @@
* queries against this schema are executed against those tables, pushing down
* as much as possible of the query logic to SQL.
*/
-public class JdbcSchema implements Schema, Wrapper {
+public class JdbcSchema extends JdbcBaseSchema implements Schema, Wrapper {
private static final Logger LOGGER = LoggerFactory.getLogger(JdbcSchema.class);
- public class TableNotFoundException extends RuntimeException {
- }
final DataSource dataSource;
final @Nullable String catalog;
final @Nullable String schema;
public final SqlDialect dialect;
final JdbcConvention convention;
private final Lookup tables = new IgnoreCaseLookup() {
- @Override
- public @Nullable Table get(String name) {
+ @Override public @Nullable Table get(String name) {
try (Stream s = getMetaTableStream(name)) {
- return s.findFirst().map(it -> jdbcTableMapper(it) ).orElse(null);
+ return s.findFirst().map(it -> jdbcTableMapper(it)).orElse(null);
}
}
- @Override
- public Set getNames(LikePattern pattern) {
- try( Stream s = getMetaTableStream(pattern.pattern)) {
+ @Override public Set getNames(LikePattern pattern) {
+ try (Stream s = getMetaTableStream(pattern.pattern)) {
return s.map(it -> it.tableName).collect(Collectors.toSet());
}
}
@@ -254,19 +252,6 @@ public DataSource getDataSource() {
return Schemas.subSchemaExpression(parentSchema, name, JdbcSchema.class);
}
- protected Multimap getFunctions() {
- // TODO: populate map from JDBC metadata
- return ImmutableMultimap.of();
- }
-
- @Override public final Collection getFunctions(String name) {
- return getFunctions().get(name); // never null
- }
-
- @Override public final Set getFunctionNames() {
- return getFunctions().keySet();
- }
-
private Stream getMetaTableStream(String tableNamePattern) {
final Pair<@Nullable String, @Nullable String> catalogSchema = getCatalogSchema();
final Stream tableDefs;
@@ -276,7 +261,8 @@ private Stream getMetaTableStream(String tableNamePattern) {
connection = dataSource.getConnection();
final List tableDefList = new ArrayList<>();
final DatabaseMetaData metaData = connection.getMetaData();
- resultSet = metaData.getTables(catalogSchema.left, catalogSchema.right, tableNamePattern, null);
+ resultSet =
+ metaData.getTables(catalogSchema.left, catalogSchema.right, tableNamePattern, null);
tableDefs = asStream(connection, resultSet)
.map(JdbcSchema::metaDataMapper);
} catch (SQLException e) {
@@ -288,35 +274,36 @@ private Stream getMetaTableStream(String tableNamePattern) {
}
private static Stream asStream(Connection connection, ResultSet resultSet) {
- return StreamSupport.stream(new Spliterators.AbstractSpliterator(
- Long.MAX_VALUE, Spliterator.ORDERED) {
- @Override
- public boolean tryAdvance(Consumer super ResultSet> action) {
- try {
- if(!resultSet.next()) return false;
- action.accept(resultSet);
- return true;
- } catch(SQLException ex) {
- throw new RuntimeException(ex);
- }
- }
- }, false).onClose(() -> {
- close(connection, null, resultSet);
- }) ;
+ return StreamSupport.stream(
+ new Spliterators.AbstractSpliterator(
+ Long.MAX_VALUE, Spliterator.ORDERED) {
+ @Override public boolean tryAdvance(Consumer super ResultSet> action) {
+ try {
+ if (!resultSet.next()) {
+ return false;
+ }
+ action.accept(resultSet);
+ return true;
+ } catch (SQLException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }, false).onClose(() -> close(connection, null, resultSet));
}
private JdbcTable jdbcTableMapper(MetaImpl.MetaTable tableDef) {
- return new JdbcTable(this, tableDef.tableCat, tableDef.tableSchem,
- tableDef.tableName, getTableType(tableDef.tableType));
+ return new JdbcTable(this, tableDef.tableCat, tableDef.tableSchem, tableDef.tableName,
+ getTableType(tableDef.tableType));
}
- private static MetaImpl.MetaTable metaDataMapper(ResultSet resultSet){
- try {
- return new MetaImpl.MetaTable(intern(resultSet.getString(1)), intern(resultSet.getString(2)), intern(resultSet.getString(3)),
- intern(resultSet.getString(4)));
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
+ private static MetaImpl.MetaTable metaDataMapper(ResultSet resultSet) {
+ try {
+ return new MetaImpl.MetaTable(intern(resultSet.getString(1)), intern(resultSet.getString(2)),
+ intern(resultSet.getString(3)),
+ intern(resultSet.getString(4)));
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
}
private static String intern(@Nullable String string) {
@@ -325,6 +312,7 @@ private static String intern(@Nullable String string) {
}
return string.intern();
}
+
private static TableType getTableType(String tableTypeName) {
// Clean up table type. In particular, this ensures that 'SYSTEM TABLE',
// returned by Phoenix among others, maps to TableType.SYSTEM_TABLE.
@@ -337,11 +325,11 @@ private static TableType getTableType(String tableTypeName) {
// not filter them as we keep all the other table types.
final String tableTypeName2 =
tableTypeName == null
- ? null
- : tableTypeName.toUpperCase(Locale.ROOT).replace(' ', '_');
+ ? null
+ : tableTypeName.toUpperCase(Locale.ROOT).replace(' ', '_');
final TableType tableType =
Util.enumVal(TableType.OTHER, tableTypeName2);
- if (tableType == TableType.OTHER && tableTypeName2 != null) {
+ if (tableType == TableType.OTHER && tableTypeName2 != null) {
LOGGER.info("Unknown table type: {}", tableTypeName2);
}
return tableType;
@@ -355,7 +343,7 @@ private static List version(DatabaseMetaData metaData) throws SQLExcept
/** Returns a pair of (catalog, schema) for the current connection. */
private Pair<@Nullable String, @Nullable String> getCatalogSchema() {
- try(Connection connection = dataSource.getConnection()) {
+ try (Connection connection = dataSource.getConnection()) {
final DatabaseMetaData metaData = connection.getMetaData();
final List version41 = ImmutableList.of(4, 1); // JDBC 4.1
String catalog = this.catalog;
@@ -377,7 +365,7 @@ private static List version(DatabaseMetaData metaData) throws SQLExcept
&& metaData.getDatabaseProductName().equals("PostgreSQL")) {
final String sql = "select current_database(), current_schema()";
try (Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery(sql)) {
+ ResultSet resultSet = statement.executeQuery(sql)) {
if (resultSet.next()) {
catalog = resultSet.getString(1);
schema = resultSet.getString(2);
@@ -390,10 +378,6 @@ private static List version(DatabaseMetaData metaData) throws SQLExcept
}
}
- @Deprecated @Override public @Nullable Table getTable(String name) {
- return tables.get(name);
- }
-
RelProtoDataType getRelDataType(String catalogName, String schemaName,
String tableName) throws SQLException {
Connection connection = null;
@@ -519,32 +503,6 @@ private static RelDataType parseTypeString(RelDataTypeFactory typeFactory,
}
}
- @Deprecated @Override public Set getTableNames() {
- return tables.getNames(LikePattern.any());
- }
-
- protected Map getTypes() {
- // TODO: populate map from JDBC metadata
- return ImmutableMap.of();
- }
-
- @Override public @Nullable RelProtoDataType getType(String name) {
- return getTypes().get(name);
- }
-
- @Override public Set getTypeNames() {
- //noinspection RedundantCast
- return (Set) getTypes().keySet();
- }
-
- @Deprecated @Override public @Nullable Schema getSubSchema(String name) {
- return subSchemas.get(name);
- }
-
- @Deprecated @Override public Set getSubSchemaNames() {
- return subSchemas.getNames(LikePattern.any());
- }
-
@Override public @Nullable T unwrap(Class clazz) {
if (clazz.isInstance(this)) {
return clazz.cast(this);
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CachingCalciteSchema.java b/core/src/main/java/org/apache/calcite/jdbc/CachingCalciteSchema.java
index 367200ebf6f..61d033f033c 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CachingCalciteSchema.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CachingCalciteSchema.java
@@ -16,15 +16,15 @@
*/
package org.apache.calcite.jdbc;
+import org.apache.calcite.linq4j.function.Function1;
import org.apache.calcite.rel.type.RelProtoDataType;
import org.apache.calcite.schema.Function;
-import org.apache.calcite.schema.lookup.LikePattern;
-import org.apache.calcite.schema.lookup.Lookup;
-import org.apache.calcite.schema.lookup.Named;
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.schema.lookup.CachedLookup;
+import org.apache.calcite.schema.lookup.Lookup;
import org.apache.calcite.util.NameMap;
import org.apache.calcite.util.NameMultimap;
import org.apache.calcite.util.NameSet;
@@ -37,7 +37,6 @@
import java.util.Collection;
import java.util.List;
-import java.util.Set;
import static org.apache.calcite.linq4j.Nullness.castNonNull;
@@ -46,14 +45,17 @@
* functions and sub-schemas.
*/
class CachingCalciteSchema extends CalciteSchema {
+ private final ImmutableList> caches;
private final Cached implicitFunctionCache;
private final Cached implicitTypeCache;
+
private boolean cache = true;
/** Creates a CachingCalciteSchema. */
CachingCalciteSchema(@Nullable CalciteSchema parent, Schema schema,
String name) {
- this(parent, schema, name, null, null, null, null, null, null, null, null);
+ this(parent, schema, name, null, null, null, null, null, null, null, null,
+ new LookupDecorator());
}
@SuppressWarnings({"argument.type.incompatible", "return.type.incompatible"})
@@ -66,9 +68,11 @@ private CachingCalciteSchema(@Nullable CalciteSchema parent, Schema schema,
@Nullable NameMultimap functionMap,
@Nullable NameSet functionNames,
@Nullable NameMap nullaryFunctionMap,
- @Nullable List extends List> path) {
+ @Nullable List extends List> path,
+ LookupDecorator lookupDecorator) {
super(parent, schema, name, subSchemaMap, tableMap, latticeMap, typeMap,
- functionMap, functionNames, nullaryFunctionMap, path);
+ functionMap, functionNames, nullaryFunctionMap, path, lookupDecorator);
+ this.caches = lookupDecorator.cacheBuilder.build();
this.implicitFunctionCache =
new AbstractCached() {
@Override public NameSet build() {
@@ -89,6 +93,7 @@ private CachingCalciteSchema(@Nullable CalciteSchema parent, Schema schema,
if (cache == this.cache) {
return;
}
+ enableCaches(cache);
final long now = System.currentTimeMillis();
implicitFunctionCache.enable(now, cache);
this.cache = cache;
@@ -99,7 +104,7 @@ private CachingCalciteSchema(@Nullable CalciteSchema parent, Schema schema,
}
@Override protected @Nullable CalciteSchema createSubSchema(Schema schema, String name) {
- return new CachingCalciteSchema(this, schema, name);
+ return new CachingCalciteSchema(this, schema, name);
}
/** Adds a child schema of this schema. */
@@ -197,7 +202,7 @@ private CachingCalciteSchema(@Nullable CalciteSchema parent, Schema schema,
CalciteSchema snapshot =
new CachingCalciteSchema(parent, schema.snapshot(version), name, null,
tableMap, latticeMap, typeMap,
- functionMap, functionNames, nullaryFunctionMap, getPath());
+ functionMap, functionNames, nullaryFunctionMap, getPath(), new LookupDecorator());
for (CalciteSchema subSchema : subSchemaMap.map().values()) {
CalciteSchema subSchemaSnapshot = subSchema.snapshot(snapshot, version);
snapshot.subSchemaMap.put(subSchema.name, subSchemaSnapshot);
@@ -205,6 +210,14 @@ private CachingCalciteSchema(@Nullable CalciteSchema parent, Schema schema,
return snapshot;
}
+ @Override public boolean removeTable(String name) {
+ if (cache) {
+ enableCaches(false);
+ enableCaches(true);
+ }
+ return super.removeTable(name);
+ }
+
@Override public boolean removeFunction(String name) {
if (cache) {
final long now = System.nanoTime();
@@ -214,6 +227,12 @@ private CachingCalciteSchema(@Nullable CalciteSchema parent, Schema schema,
return super.removeFunction(name);
}
+ private void enableCaches(final boolean cache) {
+ for (CachedLookup> lookupCache : caches) {
+ lookupCache.enable(cache);
+ }
+ }
+
/** Strategy for caching the value of an object and re-creating it if its
* value is out of date as of a given timestamp.
*
@@ -257,4 +276,17 @@ private abstract class AbstractCached implements Cached {
}
}
+ /**
+ * This class is used to decorate lookups with a cache.
+ */
+ private static class LookupDecorator implements Function1, Lookup>> {
+
+ final ImmutableList.Builder> cacheBuilder = ImmutableList.builder();
+
+ @Override public Lookup apply(final Lookup lookup) {
+ CachedLookup cachedLookup = new CachedLookup(lookup);
+ cacheBuilder.add(cachedLookup);
+ return cachedLookup;
+ }
+ }
}
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java
index 4f6765ea262..5d3811eacfd 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java
@@ -17,11 +17,17 @@
package org.apache.calcite.jdbc;
import org.apache.calcite.linq4j.function.Experimental;
-import org.apache.calcite.linq4j.function.Predicate1;
+import org.apache.calcite.linq4j.function.Function1;
import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.materialize.Lattice;
import org.apache.calcite.rel.type.RelProtoDataType;
-import org.apache.calcite.schema.*;
+import org.apache.calcite.schema.Function;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.SchemaVersion;
+import org.apache.calcite.schema.Table;
+import org.apache.calcite.schema.TableMacro;
+import org.apache.calcite.schema.Wrapper;
import org.apache.calcite.schema.impl.MaterializedViewTable;
import org.apache.calcite.schema.impl.StarTable;
import org.apache.calcite.schema.lookup.LikePattern;
@@ -45,8 +51,6 @@
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
import static com.google.common.base.Preconditions.checkArgument;
@@ -76,7 +80,6 @@ public abstract class CalciteSchema {
private @Nullable List extends List> path;
-
protected CalciteSchema(@Nullable CalciteSchema parent, Schema schema,
String name,
@Nullable NameMap subSchemaMap,
@@ -87,14 +90,35 @@ protected CalciteSchema(@Nullable CalciteSchema parent, Schema schema,
@Nullable NameSet functionNames,
@Nullable NameMap nullaryFunctionMap,
@Nullable List extends List> path) {
+ this(parent, schema, name, subSchemaMap, tableMap, latticeMap, typeMap, functionMap,
+ functionNames, nullaryFunctionMap, path, l -> l);
+ }
+
+ protected CalciteSchema(@Nullable CalciteSchema parent, Schema schema,
+ String name,
+ @Nullable NameMap subSchemaMap,
+ @Nullable NameMap tableMap,
+ @Nullable NameMap latticeMap,
+ @Nullable NameMap typeMap,
+ @Nullable NameMultimap functionMap,
+ @Nullable NameSet functionNames,
+ @Nullable NameMap nullaryFunctionMap,
+ @Nullable List extends List> path,
+ Function1, Lookup>> lookupDecorator) {
this.parent = parent;
this.schema = schema;
this.name = name;
this.tableMap = tableMap != null ? tableMap : new NameMap<>();
- this.tables = Lookup.concat(Lookup.of(this.tableMap),schema.tables().map((s,n) -> tableEntry(n,s)));
+ this.tables =
+ Lookup.concat(Lookup.of(this.tableMap),
+ (Lookup) lookupDecorator.apply(
+ schema.tables().map((s, n) -> tableEntry(n, s))));
this.latticeMap = latticeMap != null ? latticeMap : new NameMap<>();
this.subSchemaMap = subSchemaMap != null ? subSchemaMap : new NameMap<>();
- this.subSchemas = Lookup.concat(Lookup.of(this.subSchemaMap),schema.subSchemas().map((s,n) -> createSubSchema(s,n)));
+ this.subSchemas =
+ Lookup.concat(Lookup.of(this.subSchemaMap),
+ (Lookup) lookupDecorator.apply(
+ schema.subSchemas().map((s, n) -> createSubSchema(s, n))));
if (functionMap == null) {
this.functionMap = new NameMultimap<>();
this.functionNames = new NameSet();
@@ -115,8 +139,8 @@ protected CalciteSchema(@Nullable CalciteSchema parent, Schema schema,
this.path = path;
}
- /** Creates a sub-schema with a given name that is defined implicitly */
- protected abstract @Nullable CalciteSchema createSubSchema( Schema schema, String name);
+ /** Creates a sub-schema with a given name that is defined implicitly. */
+ protected abstract @Nullable CalciteSchema createSubSchema(Schema schema, String name);
/** Returns a type with a given name that is defined implicitly
* (that is, by the underlying {@link Schema} object, not explicitly
@@ -259,7 +283,7 @@ public List path(@Nullable String name) {
/** Returns a table with the given name. Does not look for views. */
public final @Nullable TableEntry getTable(String tableName, boolean caseSensitive) {
- return Lookup.get(tables,tableName,caseSensitive);
+ return Lookup.get(tables, tableName, caseSensitive);
}
public String getName() {
@@ -313,14 +337,14 @@ public NavigableMap getLatticeMap() {
/** Returns the set of all table names. Includes implicit and explicit tables
* and functions with zero parameters. */
+ public final Set getTableNames() {
+ return getTableNames(LikePattern.any());
+ }
+
+ /** Returns the set of filtered table names. Includes implicit and explicit tables
+ * and functions with zero parameters. */
public final Set getTableNames(LikePattern pattern) {
- Predicate1 predicate = pattern.matcher();
- return Stream.concat(
- tableMap.map().keySet()
- .stream()
- .filter(entry -> predicate.apply(entry)),
- schema.tables().getNames(pattern).stream())
- .collect(Collectors.toSet());
+ return tables.getNames(pattern);
}
/** Returns the set of all types names. */
@@ -595,29 +619,6 @@ protected LatticeEntry(CalciteSchema schema, String name) {
/** Implementation of {@link SchemaPlus} based on a
* {@link org.apache.calcite.jdbc.CalciteSchema}. */
private class SchemaPlusImpl implements SchemaPlus {
- private final Lookup tables;
- private final Lookup extends SchemaPlus> subSchemas;
- private SchemaPlusImpl() {
- this.tables = new Lookup() {
- @Override
- public @Nullable Table get(String name) {
- final TableEntry entry = CalciteSchema.this.getTable(name,true);
- return entry == null ? null : entry.getTable();
- }
-
- @Override
- public @Nullable Named getIgnoreCase(String name) {
- final TableEntry entry = CalciteSchema.this.getTable(name,false);
- return entry == null ? null : new Named<>(entry.name, entry.getTable());
- }
-
- @Override
- public Set getNames(LikePattern pattern) {
- return CalciteSchema.this.getTableNames(pattern);
- }
- };
- this.subSchemas = CalciteSchema.this.subSchemas.map((schema,name) -> schema.plus());
- }
CalciteSchema calciteSchema() {
return CalciteSchema.this;
}
@@ -651,19 +652,19 @@ CalciteSchema calciteSchema() {
}
@Override public Lookup tables() {
- return tables;
+ return CalciteSchema.this.tables.map((table, name) -> table.getTable());
}
@Override public Lookup extends SchemaPlus> subSchemas() {
- return subSchemas;
+ return CalciteSchema.this.subSchemas.map((schema, name) -> schema.plus());
}
- @Deprecated @Override public @Nullable Table getTable(String name) {
+ @Override public @Nullable Table getTable(String name) {
final TableEntry entry = CalciteSchema.this.getTable(name, true);
return entry == null ? null : entry.getTable();
}
- @Deprecated @Override public Set getTableNames() {
+ @Override public Set getTableNames() {
return CalciteSchema.this.getTableNames(LikePattern.any());
}
@@ -684,13 +685,12 @@ CalciteSchema calciteSchema() {
return CalciteSchema.this.getFunctionNames();
}
- @Deprecated @Override public @Nullable SchemaPlus getSubSchema(String name) {
- return subSchemas.get(name);
+ @Override public @Nullable SchemaPlus getSubSchema(String name) {
+ return subSchemas().get(name);
}
- @Deprecated @Override public Set getSubSchemaNames() {
- //noinspection RedundantCast
- return subSchemas.getNames(LikePattern.any());
+ @Override public Set getSubSchemaNames() {
+ return subSchemas().getNames(LikePattern.any());
}
@Override public SchemaPlus add(String name, Schema schema) {
diff --git a/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java b/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java
index 6c4cd1c02c1..0e247c21fbc 100644
--- a/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java
+++ b/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java
@@ -34,6 +34,7 @@
import org.apache.calcite.schema.TableMacro;
import org.apache.calcite.schema.Wrapper;
import org.apache.calcite.schema.impl.ScalarFunctionImpl;
+import org.apache.calcite.schema.lookup.LikePattern;
import org.apache.calcite.sql.SqlFunctionCategory;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlKind;
diff --git a/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java b/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java
index de3d1fa968d..a68994d0e28 100644
--- a/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java
+++ b/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java
@@ -34,10 +34,21 @@
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rel.type.RelProtoDataType;
import org.apache.calcite.rel.type.RelRecordType;
-import org.apache.calcite.schema.*;
+import org.apache.calcite.schema.ColumnStrategy;
+import org.apache.calcite.schema.ModifiableTable;
+import org.apache.calcite.schema.Path;
+import org.apache.calcite.schema.ScannableTable;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.SchemaVersion;
+import org.apache.calcite.schema.Schemas;
+import org.apache.calcite.schema.StreamableTable;
+import org.apache.calcite.schema.Table;
+import org.apache.calcite.schema.TemporalTable;
+import org.apache.calcite.schema.TranslatableTable;
+import org.apache.calcite.schema.Wrapper;
import org.apache.calcite.schema.lookup.LikePattern;
import org.apache.calcite.schema.lookup.Lookup;
-import org.apache.calcite.schema.lookup.Named;
import org.apache.calcite.sql.SqlAccessType;
import org.apache.calcite.sql.validate.SqlModality;
import org.apache.calcite.sql.validate.SqlMonotonicity;
@@ -427,7 +438,7 @@ private static class MySchemaPlus implements SchemaPlus {
this.parent = parent;
this.name = name;
this.schema = schema;
- this.subSchemas = schema.subSchemas().map((s,key) -> new MySchemaPlus(this, key, s));
+ this.subSchemas = schema.subSchemas().map((s, key) -> new MySchemaPlus(this, key, s));
}
public static MySchemaPlus create(Path path) {
@@ -501,15 +512,16 @@ public static MySchemaPlus create(Path path) {
@Override public @Nullable Lookup tables() {
return schema.tables();
}
+
@Override public @Nullable Lookup extends SchemaPlus> subSchemas() {
return subSchemas;
}
- @Deprecated @Override public @Nullable Table getTable(String name) {
+ @Override public @Nullable Table getTable(String name) {
return tables().get(name);
}
- @Deprecated @Override public Set getTableNames() {
+ @Override public Set getTableNames() {
return schema.tables().getNames(LikePattern.any());
}
@@ -530,7 +542,7 @@ public static MySchemaPlus create(Path path) {
return schema.getFunctionNames();
}
- @Deprecated @Override public Set getSubSchemaNames() {
+ @Override public Set getSubSchemaNames() {
return schema.subSchemas().getNames(LikePattern.any());
}
diff --git a/core/src/main/java/org/apache/calcite/schema/Schema.java b/core/src/main/java/org/apache/calcite/schema/Schema.java
index 409ef238ea5..bd0dcd32616 100644
--- a/core/src/main/java/org/apache/calcite/schema/Schema.java
+++ b/core/src/main/java/org/apache/calcite/schema/Schema.java
@@ -18,9 +18,7 @@
import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.rel.type.RelProtoDataType;
-
-import org.apache.calcite.schema.lookup.SimpleLookup;
-
+import org.apache.calcite.schema.lookup.CompatibilityLookup;
import org.apache.calcite.schema.lookup.LikePattern;
import org.apache.calcite.schema.lookup.Lookup;
@@ -63,38 +61,40 @@
public interface Schema {
/**
- * Returns a lookup object to find tables
+ * Returns a lookup object to find tables.
*
* @return Lookup
*/
default Lookup tables() {
- return new SimpleLookup(this::getTable, this::getTableNames);
+ return new CompatibilityLookup<>(this::getTable, this::getTableNames);
}
+ /**
+ * Returns a lookup object to find sub schemas.
+ *
+ * @return Lookup
+ */
default Lookup extends Schema> subSchemas() {
- return new SimpleLookup(this::getSubSchema, this::getSubSchemaNames);
+ return new CompatibilityLookup<>(this::getSubSchema, this::getSubSchemaNames);
}
/**
* Returns a table with a given name, or null if not found.
*
- * @deprecated
- * Please use {@link Schema#tables()} and {@link Lookup#get(String)} instead.
+ * Please use {@link Schema#tables()} and {@link Lookup#get(String)} instead.
*
* @param name Table name
* @return Table, or null
*/
- @Deprecated
- @Nullable Table getTable(String name) ;
+ @Nullable Table getTable(String name);
/**
* Returns the names of the tables in this schema.
*
- * @deprecated
- * Please use {@link Schema#tables()} and {@link Lookup#getNames(LikePattern)} instead.
+ *
Please use {@link Schema#tables()} and {@link Lookup#getNames(LikePattern)} instead.
+ *
* @return Names of the tables in this schema
*/
- @Deprecated
Set getTableNames();
/**
@@ -131,22 +131,20 @@ default Lookup extends Schema> subSchemas() {
/**
* Returns a sub-schema with a given name, or null.
*
+ * Please use {@link Schema#subSchemas()} and {@link Lookup#get(String)} instead.
+ *
* @param name Sub-schema name
- * @deprecated
- * Please use {@link Schema#subSchemas()} ()} and {@link Lookup#get(String)} instead.
* @return Sub-schema with a given name, or null
*/
- @Deprecated
@Nullable Schema getSubSchema(String name);
/**
* Returns the names of this schema's child schemas.
*
- * @deprecated
- * Please use {@link Schema#subSchemas()} ()} and {@link Lookup#getNames(LikePattern)} instead.
+ *
Please use {@link Schema#subSchemas()} and {@link Lookup#getNames(LikePattern)} instead.
+ *
* @return Names of this schema's child schemas
*/
- @Deprecated
Set getSubSchemaNames();
/**
diff --git a/core/src/main/java/org/apache/calcite/schema/SchemaPlus.java b/core/src/main/java/org/apache/calcite/schema/SchemaPlus.java
index 3161ef5e9a2..0c8f687fc24 100644
--- a/core/src/main/java/org/apache/calcite/schema/SchemaPlus.java
+++ b/core/src/main/java/org/apache/calcite/schema/SchemaPlus.java
@@ -18,11 +18,10 @@
import org.apache.calcite.materialize.Lattice;
import org.apache.calcite.rel.type.RelProtoDataType;
+import org.apache.calcite.schema.lookup.Lookup;
import com.google.common.collect.ImmutableList;
-import org.apache.calcite.schema.lookup.Lookup;
-
import org.checkerframework.checker.nullness.qual.Nullable;
/**
@@ -48,6 +47,9 @@
*/
public interface SchemaPlus extends Schema {
+ /**
+ * Returns a lookup object to find sub schemas.
+ */
Lookup extends SchemaPlus> subSchemas();
/**
* Returns the parent schema, or null if this schema has no parent.
@@ -63,7 +65,7 @@ public interface SchemaPlus extends Schema {
String getName();
// override with stricter return
- @Deprecated @Override @Nullable SchemaPlus getSubSchema(String name);
+ @Override @Nullable SchemaPlus getSubSchema(String name);
/** Adds a schema as a sub-schema of this schema, and returns the wrapped
* object. */
diff --git a/core/src/main/java/org/apache/calcite/schema/impl/AbstractSchema.java b/core/src/main/java/org/apache/calcite/schema/impl/AbstractSchema.java
index 43eae233322..661498f7d5d 100644
--- a/core/src/main/java/org/apache/calcite/schema/impl/AbstractSchema.java
+++ b/core/src/main/java/org/apache/calcite/schema/impl/AbstractSchema.java
@@ -18,16 +18,20 @@
import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.rel.type.RelProtoDataType;
-import org.apache.calcite.schema.*;
+import org.apache.calcite.schema.Function;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.SchemaFactory;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.SchemaVersion;
+import org.apache.calcite.schema.Schemas;
+import org.apache.calcite.schema.Table;
+import org.apache.calcite.schema.lookup.CompatibilityLookup;
+import org.apache.calcite.schema.lookup.Lookup;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
-import org.apache.calcite.schema.lookup.Lookup;
-
-import org.apache.calcite.schema.lookup.SimpleLookup;
-
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collection;
@@ -55,8 +59,9 @@
*/
public class AbstractSchema implements Schema {
- private Lookup tables = new SimpleLookup(this::getTable, this::getTableNames);
- private Lookup subSchemas = new SimpleLookup(this::getSubSchema, this::getSubSchemaNames);
+ private Lookup tables = new CompatibilityLookup<>(this::getTable, this::getTableNames);
+ private Lookup subSchemas =
+ new CompatibilityLookup<>(this::getSubSchema, this::getSubSchemaNames);
public AbstractSchema() {
}
@@ -64,6 +69,7 @@ public AbstractSchema() {
@Override public Lookup tables() {
return tables;
}
+
@Override public Lookup extends Schema> subSchemas() {
return subSchemas;
}
@@ -95,12 +101,12 @@ protected Map getTableMap() {
return ImmutableMap.of();
}
- @Deprecated @Override public final Set getTableNames() {
+ @Override public final Set getTableNames() {
//noinspection RedundantCast
return (Set) getTableMap().keySet();
}
- @Deprecated @Override public final @Nullable Table getTable(String name) {
+ @Override public final @Nullable Table getTable(String name) {
return getTableMap().get(name);
}
@@ -166,12 +172,12 @@ protected Map getSubSchemaMap() {
return ImmutableMap.of();
}
- @Deprecated @Override public final Set getSubSchemaNames() {
+ @Override public final Set getSubSchemaNames() {
//noinspection RedundantCast
return (Set) getSubSchemaMap().keySet();
}
- @Deprecated @Override public final @Nullable Schema getSubSchema(String name) {
+ @Override public final @Nullable Schema getSubSchema(String name) {
return getSubSchemaMap().get(name);
}
diff --git a/core/src/main/java/org/apache/calcite/schema/impl/DelegatingSchema.java b/core/src/main/java/org/apache/calcite/schema/impl/DelegatingSchema.java
index 5a04d05f41b..9b1bd5e4712 100644
--- a/core/src/main/java/org/apache/calcite/schema/impl/DelegatingSchema.java
+++ b/core/src/main/java/org/apache/calcite/schema/impl/DelegatingSchema.java
@@ -19,12 +19,12 @@
import org.apache.calcite.linq4j.tree.Expression;
import org.apache.calcite.rel.type.RelProtoDataType;
import org.apache.calcite.schema.Function;
-import org.apache.calcite.schema.lookup.LikePattern;
-import org.apache.calcite.schema.lookup.Lookup;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.schema.SchemaVersion;
import org.apache.calcite.schema.Table;
+import org.apache.calcite.schema.lookup.LikePattern;
+import org.apache.calcite.schema.lookup.Lookup;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -67,11 +67,11 @@ public DelegatingSchema(Schema schema) {
return schema.tables();
}
- @Deprecated @Override public @Nullable Table getTable(String name) {
+ @Override public @Nullable Table getTable(String name) {
return schema.tables().get(name);
}
- @Deprecated @Override public Set getTableNames() {
+ @Override public Set getTableNames() {
return schema.tables().getNames(LikePattern.any());
}
@@ -95,11 +95,11 @@ public DelegatingSchema(Schema schema) {
return schema.subSchemas();
}
- @Deprecated @Override public @Nullable Schema getSubSchema(String name) {
+ @Override public @Nullable Schema getSubSchema(String name) {
return subSchemas().get(name);
}
- @Deprecated @Override public Set getSubSchemaNames() {
+ @Override public Set getSubSchemaNames() {
return subSchemas().getNames(LikePattern.any());
}
}
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/CachedLookup.java b/core/src/main/java/org/apache/calcite/schema/lookup/CachedLookup.java
new file mode 100644
index 00000000000..359ae2957b3
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/CachedLookup.java
@@ -0,0 +1,77 @@
+/*
+ * 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.schema.lookup;
+
+import org.apache.calcite.util.NameMap;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.Set;
+
+/**
+ * This class can be used to make a snapshot of a lookups.
+ *
+ * @param Element Type
+ */
+public class CachedLookup implements Lookup {
+
+ private final Lookup delegate;
+ private Lookup cachedDelegate = null;
+ private boolean enabled = true;
+
+ public CachedLookup(Lookup delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override public @Nullable T get(final String name) {
+ return delegate().get(name);
+ }
+
+ @Override public @Nullable Named getIgnoreCase(final String name) {
+ return delegate().getIgnoreCase(name);
+ }
+
+ @Override public Set getNames(final LikePattern pattern) {
+ return delegate().getNames(pattern);
+ }
+
+ private Lookup delegate() {
+ if (!enabled) {
+ return delegate;
+ }
+ if (cachedDelegate == null) {
+ synchronized (this) {
+ if (cachedDelegate == null) {
+ NameMap map = new NameMap<>();
+ for (String name : delegate.getNames(LikePattern.any())) {
+ map.put(name, delegate.get(name));
+ }
+ cachedDelegate = new NameMapLookup<>(map);
+ }
+ }
+ }
+ return cachedDelegate;
+ }
+
+ public void enable(boolean enabled) {
+ if (!enabled) {
+ cachedDelegate = null;
+ }
+ this.enabled = enabled;
+ }
+
+}
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/CompatibilityLookup.java b/core/src/main/java/org/apache/calcite/schema/lookup/CompatibilityLookup.java
new file mode 100644
index 00000000000..d67f0ca5d34
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/CompatibilityLookup.java
@@ -0,0 +1,55 @@
+/*
+ * 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.schema.lookup;
+
+import org.apache.calcite.linq4j.function.Predicate1;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+/**
+ * This class can be used to wrap existing schemas with a pair of {@code get...}
+ * and {@code get...Names} into a Lookup object.
+ *
+ * @param Element type
+ */
+public class CompatibilityLookup extends IgnoreCaseLookup {
+
+ private final Function get;
+ private final Supplier> getNames;
+
+ public CompatibilityLookup(Function get, Supplier> getNames) {
+ this.get = get;
+ this.getNames = getNames;
+ }
+
+ @Nullable
+ @Override public T get(String name) {
+ return get.apply(name);
+ }
+
+ @Override public @Nullable Set getNames(LikePattern pattern) {
+ final Predicate1 matcher = pattern.matcher();
+ return getNames.get().stream()
+ .filter(name -> matcher.apply(name))
+ .collect(Collectors.toSet());
+ }
+}
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/ConcatLookup.java b/core/src/main/java/org/apache/calcite/schema/lookup/ConcatLookup.java
index 7db1e24a1ca..8bc456a5d26 100644
--- a/core/src/main/java/org/apache/calcite/schema/lookup/ConcatLookup.java
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/ConcatLookup.java
@@ -14,42 +14,47 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.calcite.schema.lookup;
import org.checkerframework.checker.nullness.qual.Nullable;
-import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+/**
+ * This class can be used to concat a list of lookups.
+ *
+ * @param Element type
+ */
class ConcatLookup implements Lookup {
private final Lookup[] lookups;
ConcatLookup(Lookup[] lookups) {
this.lookups = lookups;
}
- @Override
- public @Nullable T get(String name) {
- for ( Lookup lookup : lookups) {
+
+ @Override public @Nullable T get(String name) {
+ for (Lookup lookup : lookups) {
T t = lookup.get(name);
- if ( t != null) return t;
+ if (t != null) {
+ return t;
+ }
}
return null;
}
- @Override
- public @Nullable Named getIgnoreCase(String name) {
- for ( Lookup lookup : lookups) {
+ @Override public @Nullable Named getIgnoreCase(String name) {
+ for (Lookup lookup : lookups) {
Named t = lookup.getIgnoreCase(name);
- if ( t != null) return t;
+ if (t != null) {
+ return t;
+ }
}
return null;
}
- @Override
- public @Nullable Set getNames(LikePattern pattern) {
+ @Override public @Nullable Set getNames(LikePattern pattern) {
return Stream.of(lookups)
.flatMap(lookup -> lookup.getNames(pattern).stream())
.collect(Collectors.toSet());
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/EmptyLookup.java b/core/src/main/java/org/apache/calcite/schema/lookup/EmptyLookup.java
index c9f113993fa..7488b24cab4 100644
--- a/core/src/main/java/org/apache/calcite/schema/lookup/EmptyLookup.java
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/EmptyLookup.java
@@ -18,34 +18,28 @@
import com.google.common.collect.ImmutableSet;
-import org.apache.calcite.schema.lookup.LikePattern;
-import org.apache.calcite.schema.lookup.Lookup;
-import org.apache.calcite.schema.lookup.Named;
-
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Set;
/**
- * An abstract base class for lookups. implementing case insensitive lookup
+ * This class implements an empty Lookup.
*
+ * @param Element type
*/
class EmptyLookup implements Lookup {
- static Lookup> INSTANCE = new EmptyLookup<>();
+ static final Lookup> INSTANCE = new EmptyLookup<>();
- @Override
- public @Nullable T get(String name) {
+ @Override public @Nullable T get(String name) {
return null;
}
- @Override
- public @Nullable Named getIgnoreCase(String name) {
+ @Override public @Nullable Named getIgnoreCase(String name) {
return null;
}
- @Override
- public Set getNames(LikePattern pattern) {
+ @Override public Set getNames(LikePattern pattern) {
return ImmutableSet.of();
}
}
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/EntryNotFoundException.java b/core/src/main/java/org/apache/calcite/schema/lookup/EntryNotFoundException.java
index a3a1a7e527e..6ddfc93cb68 100644
--- a/core/src/main/java/org/apache/calcite/schema/lookup/EntryNotFoundException.java
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/EntryNotFoundException.java
@@ -14,11 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.calcite.schema.lookup;
/**
- * Exceptions used in caches to signal none existing entries
+ * Exceptions used in caches to signal none existing entries.
*/
-class EntryNotFoundException extends RuntimeException{
+class EntryNotFoundException extends RuntimeException {
}
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/IgnoreCaseLookup.java b/core/src/main/java/org/apache/calcite/schema/lookup/IgnoreCaseLookup.java
index 9f1de2f0085..fafb2bc8470 100644
--- a/core/src/main/java/org/apache/calcite/schema/lookup/IgnoreCaseLookup.java
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/IgnoreCaseLookup.java
@@ -16,9 +16,6 @@
*/
package org.apache.calcite.schema.lookup;
-import org.apache.calcite.schema.lookup.LikePattern;
-import org.apache.calcite.schema.lookup.Lookup;
-import org.apache.calcite.schema.lookup.Named;
import org.apache.calcite.util.NameMap;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -29,6 +26,7 @@
/**
* An abstract base class for lookups. implementing case insensitive lookup
*
+ * @param Element type
*/
public abstract class IgnoreCaseLookup implements Lookup {
@@ -43,7 +41,7 @@ public IgnoreCaseLookup() {
* @param name Name
* @return Entity, or null
*/
- @Nullable public abstract T get(String name) ;
+ @Nullable public abstract T get(String name);
/**
* Returns a named entity with a given name ignoring the case, or null if not found.
@@ -51,24 +49,24 @@ public IgnoreCaseLookup() {
* @param name Name
* @return Entity, or null
*/
- @Override @Nullable public Named getIgnoreCase(String name){
+ @Override @Nullable public Named getIgnoreCase(String name) {
Map.Entry entry = getNameMap(false).range(name, false).firstEntry();
if (entry == null) {
- entry = getNameMap(true).range(name, false).firstEntry();
- if ( entry == null) {
- return null;
- }
+ entry = getNameMap(true).range(name, false).firstEntry();
+ if (entry == null) {
+ return null;
+ }
}
T result = get(entry.getValue());
- return result == null ? null : new Named<>(entry.getKey(),result);
+ return result == null ? null : new Named<>(entry.getKey(), result);
}
@Nullable public abstract Set getNames(LikePattern pattern);
private NameMap getNameMap(boolean forceReload) {
- if ( nameMap == null || forceReload) {
+ if (nameMap == null || forceReload) {
synchronized (this) {
- if ( nameMap == null || forceReload) {
+ if (nameMap == null || forceReload) {
NameMap tmp = new NameMap<>();
for (String name : getNames(LikePattern.any())) {
tmp.put(name, name);
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/LikePattern.java b/core/src/main/java/org/apache/calcite/schema/lookup/LikePattern.java
index 23eac10ebfb..f00f40e3614 100644
--- a/core/src/main/java/org/apache/calcite/schema/lookup/LikePattern.java
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/LikePattern.java
@@ -14,13 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.calcite.schema.lookup;
import org.apache.calcite.linq4j.function.Predicate1;
import java.util.regex.Pattern;
+/**
+ * This class is used as parameter to Lookup.getNames
+ */
public class LikePattern {
private static final String ANY = "%";
public final String pattern;
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/LoadingCacheLookup.java b/core/src/main/java/org/apache/calcite/schema/lookup/LoadingCacheLookup.java
new file mode 100644
index 00000000000..dda5add7214
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/LoadingCacheLookup.java
@@ -0,0 +1,101 @@
+/*
+ * 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.schema.lookup;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This class can be used to cache lookups.
+ *
+ * @param Element Type
+ */
+public class LoadingCacheLookup implements Lookup {
+ private final Lookup delegate;
+
+ private final LoadingCache cache;
+ private final LoadingCache> cacheIgnoreCase;
+
+ public LoadingCacheLookup(Lookup delegate) {
+ this.delegate = delegate;
+ this.cache = CacheBuilder.newBuilder()
+ .expireAfterWrite(1, TimeUnit.MINUTES)
+ .build(new CacheLoader() {
+ @Override public T load(String name) throws Exception {
+ return Optional.ofNullable(delegate.get(name))
+ .orElseThrow(() -> new EntryNotFoundException());
+ }
+ });
+ this.cacheIgnoreCase = CacheBuilder.newBuilder()
+ .expireAfterWrite(1, TimeUnit.MINUTES)
+ .build(new CacheLoader>() {
+ @Override public Named load(String name) throws Exception {
+ return Optional.ofNullable(delegate.getIgnoreCase(name))
+ .orElseThrow(() -> new EntryNotFoundException());
+ }
+ });
+ }
+
+ @Override public @Nullable T get(String name) {
+ try {
+ return cache.get(name);
+ } catch (UncheckedExecutionException e) {
+ if (e.getCause() instanceof EntryNotFoundException) {
+ return null;
+ }
+ throw e;
+ } catch (ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override public @Nullable Named getIgnoreCase(String name) {
+ try {
+ return cacheIgnoreCase.get(name);
+ } catch (UncheckedExecutionException e) {
+ if (e.getCause() instanceof EntryNotFoundException) {
+ return null;
+ }
+ throw e;
+ } catch (ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override public Set getNames(LikePattern pattern) {
+ return delegate.getNames(pattern);
+ }
+
+ public void invalidate(String name) {
+ cache.invalidate(name);
+ cacheIgnoreCase.invalidate(name);
+ }
+
+ public void invalidateAll() {
+ cache.invalidateAll();
+ cacheIgnoreCase.invalidateAll();
+ }
+}
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/Lookup.java b/core/src/main/java/org/apache/calcite/schema/lookup/Lookup.java
index 001b513d91b..23a8f69a8df 100644
--- a/core/src/main/java/org/apache/calcite/schema/lookup/Lookup.java
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/Lookup.java
@@ -22,11 +22,11 @@
import java.util.Set;
import java.util.function.BiFunction;
-import java.util.function.Function;
/**
- * A case sensitive/insensitive lookup for tables or functions
+ * A casesensitive/insensitive lookup for tables, schems, functions ...
*
+ * @param Element type
*/
public interface Lookup {
/**
@@ -35,7 +35,7 @@ public interface Lookup {
* @param name Name
* @return Entity, or null
*/
- @Nullable T get(String name) ;
+ @Nullable T get(String name);
/**
* Returns a named entity with a given name ignoring the case, or null if not found.
@@ -43,7 +43,7 @@ public interface Lookup {
* @param name Name
* @return Entity, or null
*/
- @Nullable Named getIgnoreCase(String name) ;
+ @Nullable Named getIgnoreCase(String name);
/**
* Returns the names of the entities in matching pattern.
@@ -52,14 +52,20 @@ public interface Lookup {
*/
Set getNames(LikePattern pattern);
- default Lookup map(BiFunction mapper) {
- return new MappedLookup<>(this,mapper);
+ default Lookup map(BiFunction mapper) {
+ return new MappedLookup<>(this, mapper);
}
- static T get(Lookup lookup, String name, boolean caseSensitive) {
- if ( caseSensitive) {
+ /**
+ * Helper method to call Lookup.get(String) or Lookup.getIgnoreCase(String)
+ * depending on the parameter caseSensitive.
+ *
+ * @return Entity, or null
+ */
+ @Nullable static T get(Lookup lookup, String name, boolean caseSensitive) {
+ if (caseSensitive) {
T entry = lookup.get(name);
- if ( entry == null ) {
+ if (entry == null) {
return null;
}
return entry;
@@ -67,15 +73,24 @@ static T get(Lookup lookup, String name, boolean caseSensitive) {
return Named.entity(lookup.getIgnoreCase(name));
}
+ /**
+ * Returns an empty lookup.
+ */
static Lookup empty() {
return (Lookup) EmptyLookup.INSTANCE;
}
+ /**
+ * Creates a new lookup object based on a NameMap.
+ */
static Lookup of(NameMap map) {
return new NameMapLookup<>(map);
}
- static Lookup concat(Lookup ...lookups) {
+ /**
+ * Concat a list of lookups.
+ */
+ static Lookup concat(Lookup... lookups) {
return new ConcatLookup<>(lookups);
}
}
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/MappedLookup.java b/core/src/main/java/org/apache/calcite/schema/lookup/MappedLookup.java
index 65fb91a679b..c55d5b78c37 100644
--- a/core/src/main/java/org/apache/calcite/schema/lookup/MappedLookup.java
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/MappedLookup.java
@@ -14,39 +14,41 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.calcite.schema.lookup;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Set;
import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-class MappedLookup implements Lookup {
+/**
+ * A Lookup class which can be used to map different element types.
+ *
+ * @param Source element type
+ * @param Target element type
+ */
+class MappedLookup implements Lookup {
private final Lookup lookup;
- private final BiFunction mapper;
+ private final BiFunction mapper;
- MappedLookup(Lookup lookup, BiFunction mapper) {
+ MappedLookup(Lookup lookup, BiFunction mapper) {
this.lookup = lookup;
this.mapper = mapper;
}
- @Override
- public @Nullable T get(String name) {
+
+ @Override public @Nullable T get(String name) {
S entity = lookup.get(name);
- return entity == null ? null : mapper.apply(entity,name);
+ return entity == null ? null : mapper.apply(entity, name);
}
- @Override
- public @Nullable Named getIgnoreCase(String name) {
+ @Override public @Nullable Named getIgnoreCase(String name) {
Named named = lookup.getIgnoreCase(name);
- return named == null ? null : new Named<>(named.name(),mapper.apply(named.entity(),named.name()));
+ return named == null
+ ? null
+ : new Named<>(named.name(), mapper.apply(named.entity(), named.name()));
}
- @Override
- public @Nullable Set getNames(LikePattern pattern) {
+ @Override public @Nullable Set getNames(LikePattern pattern) {
return lookup.getNames(pattern);
}
}
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/NameMapLookup.java b/core/src/main/java/org/apache/calcite/schema/lookup/NameMapLookup.java
index 0d6c8237e48..5079d34133c 100644
--- a/core/src/main/java/org/apache/calcite/schema/lookup/NameMapLookup.java
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/NameMapLookup.java
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.calcite.schema.lookup;
import org.apache.calcite.linq4j.function.Predicate1;
@@ -26,28 +25,35 @@
import java.util.Set;
import java.util.stream.Collectors;
+/**
+ * A Lookup class which is based on a NameMap.
+ *
+ * @param Element type
+ */
class NameMapLookup implements Lookup {
private final NameMap map;
NameMapLookup(NameMap map) {
this.map = map;
}
- @Override
- public @Nullable T get(String name) {
- Map.Entry entry = map.range(name,true).firstEntry();
- if ( entry != null) return entry.getValue();
+
+ @Override public @Nullable T get(String name) {
+ Map.Entry entry = map.range(name, true).firstEntry();
+ if (entry != null) {
+ return entry.getValue();
+ }
return null;
}
- @Override
- public @Nullable Named getIgnoreCase(String name) {
- Map.Entry entry = map.range(name,false).firstEntry();
- if ( entry != null) return new Named<>(entry.getKey(),entry.getValue());
+ @Override public @Nullable Named getIgnoreCase(String name) {
+ Map.Entry entry = map.range(name, false).firstEntry();
+ if (entry != null) {
+ return new Named<>(entry.getKey(), entry.getValue());
+ }
return null;
}
- @Override
- public @Nullable Set getNames(LikePattern pattern) {
+ @Override public @Nullable Set getNames(LikePattern pattern) {
final Predicate1 matcher = pattern.matcher();
return map.map().keySet().stream()
.filter(name -> matcher.apply(name))
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/Named.java b/core/src/main/java/org/apache/calcite/schema/lookup/Named.java
index 836df72afc4..881ec0b65f1 100644
--- a/core/src/main/java/org/apache/calcite/schema/lookup/Named.java
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/Named.java
@@ -14,11 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.calcite.schema.lookup;
import java.security.InvalidParameterException;
+/**
+ * This class is used to hold an object including its name.
+ *
+ * @param Element type
+ */
public class Named {
private final String name;
private final T entity;
diff --git a/core/src/main/java/org/apache/calcite/schema/lookup/package-info.java b/core/src/main/java/org/apache/calcite/schema/lookup/package-info.java
new file mode 100644
index 00000000000..edd5b38d382
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/schema/lookup/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/**
+ * Schema Lookup SPI.
+ *
+ * The interfaces and classes in this package are used to lookup
+ * tables and subschemas within a schema.
+ */
+@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.FIELD)
+@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.PARAMETER)
+@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.RETURN)
+package org.apache.calcite.schema.lookup;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+import org.checkerframework.framework.qual.TypeUseLocation;
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index e08aadf9535..f40edf36fd0 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -7575,7 +7575,7 @@ private void checkGetTimestamp(Connection con) throws SQLException {
// create schema "/a/b1". Appears only when we disable caching.
aSubSchemaMap.put("b1", new AbstractSchema());
- assertThat(aSchema.subSchemas().getNames(LikePattern.any()), hasSize(1));
+ assertThat(aSchema.subSchemas().getNames(LikePattern.any()), hasSize(0));
assertThat(aSchema.subSchemas().get("b1"), nullValue());
aSchema.setCacheEnabled(false);
assertThat(aSchema.subSchemas().getNames(LikePattern.any()), hasSize(1));