Repository: calcite Updated Branches: refs/heads/master f8ab9078b -> 4519ef6e5
[CALCITE-1742] Create a read-consistent view of CalciteSchema for each statement compilation Add interface Schema#snapshot(long). CalciteCatalogReader should not add resolved tables into CalciteSchema's explicit table map. Close apache/calcite#421 Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/4519ef6e Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/4519ef6e Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/4519ef6e Branch: refs/heads/master Commit: 4519ef6e599ebe9b1c182016bea62d0ac920ea1a Parents: f8ab907 Author: maryannxue <[email protected]> Authored: Mon Apr 10 17:43:36 2017 -0700 Committer: Julian Hyde <[email protected]> Committed: Mon May 22 19:06:11 2017 -0700 ---------------------------------------------------------------------- .../calcite/adapter/java/ReflectiveSchema.java | 31 ++++++-- .../apache/calcite/adapter/jdbc/JdbcSchema.java | 54 ++++++++----- .../calcite/jdbc/CachingCalciteSchema.java | 26 ++++++- .../calcite/jdbc/CalciteConnectionImpl.java | 21 +++-- .../apache/calcite/jdbc/CalciteMetaImpl.java | 21 ++--- .../org/apache/calcite/jdbc/CalcitePrepare.java | 8 +- .../apache/calcite/jdbc/CalciteResultSet.java | 2 +- .../org/apache/calcite/jdbc/CalciteSchema.java | 80 +++++++++++++++++--- .../calcite/jdbc/SimpleCalciteSchema.java | 27 ++++++- .../materialize/MaterializationService.java | 8 +- .../calcite/prepare/CalciteCatalogReader.java | 5 +- .../calcite/prepare/CalcitePrepareImpl.java | 4 +- .../apache/calcite/prepare/RelOptTableImpl.java | 4 + .../java/org/apache/calcite/rex/RexUtil.java | 2 +- .../java/org/apache/calcite/schema/Schema.java | 10 +++ .../java/org/apache/calcite/schema/Schemas.java | 14 ++-- .../calcite/schema/impl/AbstractSchema.java | 4 + .../calcite/schema/impl/DelegatingSchema.java | 4 + .../apache/calcite/sql/validate/EmptyScope.java | 4 +- .../org/apache/calcite/rex/RexExecutorTest.java | 2 +- .../calcite/test/LinqFrontJdbcBackTest.java | 6 +- .../apache/calcite/test/MockRelOptPlanner.java | 2 +- .../calcite/test/MultiJdbcSchemaJoinTest.java | 29 ++++--- .../calcite/test/RexImplicationCheckerTest.java | 2 +- .../apache/calcite/adapter/csv/CsvSchema.java | 8 ++ 25 files changed, 280 insertions(+), 98 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java b/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java index 0a07f35..12e4a00 100644 --- a/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java +++ b/core/src/main/java/org/apache/calcite/adapter/java/ReflectiveSchema.java @@ -70,6 +70,8 @@ public class ReflectiveSchema extends AbstractSchema { private final Class clazz; private Object target; + private Map<String, Table> tableMap; + private Multimap<String, Function> functionMap; /** * Creates a ReflectiveSchema. @@ -97,6 +99,13 @@ public class ReflectiveSchema @SuppressWarnings({ "rawtypes", "unchecked" }) @Override protected Map<String, Table> getTableMap() { + if (tableMap == null) { + tableMap = createTableMap(); + } + return tableMap; + } + + private Map<String, Table> createTableMap() { final ImmutableMap.Builder<String, Table> builder = ImmutableMap.builder(); for (Field field : clazz.getFields()) { final String fieldName = field.getName(); @@ -131,6 +140,13 @@ public class ReflectiveSchema } @Override protected Multimap<String, Function> getFunctionMultimap() { + if (functionMap == null) { + functionMap = createFunctionMap(); + } + return functionMap; + } + + private Multimap<String, Function> createFunctionMap() { final ImmutableMultimap.Builder<String, Function> builder = ImmutableMultimap.builder(); for (Method method : clazz.getMethods()) { @@ -254,10 +270,10 @@ public class ReflectiveSchema * * <p>The following example instantiates a {@code FoodMart} object as a schema * that contains tables called {@code EMPS} and {@code DEPTS} based on the - * object's fields.</p> + * object's fields. * - * <pre> - * {@code schemas: [ + * <blockquote><pre> + * schemas: [ * { * name: "foodmart", * type: "custom", @@ -268,17 +284,16 @@ public class ReflectiveSchema * } * } * ] - * + * * class FoodMart { * public static final FoodMart instance() { * return new FoodMart(); * } - * + * * Employee[] EMPS; * Department[] DEPTS; - * } - * }</pre> - * */ + * }</pre></blockquote> + */ public static class Factory implements SchemaFactory { public Schema create(SchemaPlus parentSchema, String name, Map<String, Object> operand) { http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java ---------------------------------------------------------------------- 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 faf0e94..5cd4b0b 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 @@ -35,6 +35,7 @@ import org.apache.calcite.sql.type.SqlTypeFactoryImpl; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.Util; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; @@ -65,6 +66,7 @@ public class JdbcSchema implements Schema { public final SqlDialect dialect; final JdbcConvention convention; private ImmutableMap<String, JdbcTable> tableMap; + private final boolean snapshot; /** * Creates a JDBC schema. @@ -77,14 +79,20 @@ public class JdbcSchema implements Schema { */ public JdbcSchema(DataSource dataSource, SqlDialect dialect, JdbcConvention convention, String catalog, String schema) { + this(dataSource, dialect, convention, catalog, schema, null); + } + + private JdbcSchema(DataSource dataSource, SqlDialect dialect, + JdbcConvention convention, String catalog, String schema, + ImmutableMap<String, JdbcTable> tableMap) { super(); - this.dataSource = dataSource; - this.dialect = dialect; + this.dataSource = Preconditions.checkNotNull(dataSource); + this.dialect = Preconditions.checkNotNull(dialect); this.convention = convention; this.catalog = catalog; this.schema = schema; - assert dialect != null; - assert dataSource != null; + this.tableMap = tableMap; + this.snapshot = tableMap != null; } public static JdbcSchema create( @@ -159,6 +167,11 @@ public class JdbcSchema implements Schema { return false; } + public Schema snapshot(long now) { + return new JdbcSchema(dataSource, dialect, convention, catalog, schema, + tableMap); + } + // Used by generated code. public DataSource getDataSource() { return dataSource; @@ -362,7 +375,7 @@ public class JdbcSchema implements Schema { public Set<String> getTableNames() { // This method is called during a cache refresh. We can take it as a signal // that we need to re-build our own cache. - return getTableMap(true).keySet(); + return getTableMap(!snapshot).keySet(); } public Schema getSubSchema(String name) { @@ -401,27 +414,28 @@ public class JdbcSchema implements Schema { /** Schema factory that creates a * {@link org.apache.calcite.adapter.jdbc.JdbcSchema}. - * This allows you to create a jdbc schema inside a model.json file. * - * <pre>{@code + * <p>This allows you to create a jdbc schema inside a model.json file, like + * this: + * + * <blockquote><pre> * { - * version: '1.0', - * defaultSchema: 'FOODMART_CLONE', - * schemas: [ + * "version": "1.0", + * "defaultSchema": "FOODMART_CLONE", + * "schemas": [ * { - * name: 'FOODMART_CLONE', - * type: 'custom', - * factory: 'org.apache.calcite.adapter.jdbc.JdbcSchema$Factory', - * operand: { - * jdbcDriver: 'com.mysql.jdbc.Driver', - * jdbcUrl: 'jdbc:mysql://localhost/foodmart', - * jdbcUser: 'foodmart', - * jdbcPassword: 'foodmart' + * "name": "FOODMART_CLONE", + * "type": "custom", + * "factory": "org.apache.calcite.adapter.jdbc.JdbcSchema$Factory", + * "operand": { + * "jdbcDriver": "com.mysql.jdbc.Driver", + * "jdbcUrl": "jdbc:mysql://localhost/foodmart", + * "jdbcUser": "foodmart", + * "jdbcPassword": "foodmart" * } * } * ] - * } - * }</pre> + * }</pre></blockquote> */ public static class Factory implements SchemaFactory { public static final Factory INSTANCE = new Factory(); http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/jdbc/CachingCalciteSchema.java ---------------------------------------------------------------------- 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 9414996..3ac1429 100644 --- a/core/src/main/java/org/apache/calcite/jdbc/CachingCalciteSchema.java +++ b/core/src/main/java/org/apache/calcite/jdbc/CachingCalciteSchema.java @@ -20,6 +20,8 @@ import org.apache.calcite.schema.Function; import org.apache.calcite.schema.Schema; 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.cache.CacheBuilder; @@ -30,6 +32,7 @@ import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedSet; import java.util.Collection; +import java.util.List; import java.util.Set; /** @@ -45,7 +48,17 @@ class CachingCalciteSchema extends CalciteSchema { /** Creates a CachingCalciteSchema. */ CachingCalciteSchema(CalciteSchema parent, Schema schema, String name) { - super(parent, schema, name); + this(parent, schema, name, null, null, null, null, null, null, null); + } + + private CachingCalciteSchema(CalciteSchema parent, Schema schema, + String name, NameMap<CalciteSchema> subSchemaMap, + NameMap<TableEntry> tableMap, NameMap<LatticeEntry> latticeMap, + NameMultimap<FunctionEntry> functionMap, NameSet functionNames, + NameMap<FunctionEntry> nullaryFunctionMap, + List<? extends List<String>> path) { + super(parent, schema, name, subSchemaMap, tableMap, latticeMap, + functionMap, functionNames, nullaryFunctionMap, path); this.implicitSubSchemaCache = new AbstractCached<SubSchemaCache>() { public SubSchemaCache build() { @@ -201,6 +214,17 @@ class CachingCalciteSchema extends CalciteSchema { return null; } + protected CalciteSchema snapshot(CalciteSchema parent, long now) { + CalciteSchema snapshot = new CachingCalciteSchema(parent, + schema.snapshot(now), name, null, tableMap, latticeMap, + functionMap, functionNames, nullaryFunctionMap, getPath()); + for (CalciteSchema subSchema : subSchemaMap.map().values()) { + CalciteSchema subSchemaSnapshot = subSchema.snapshot(snapshot, now); + snapshot.subSchemaMap.put(subSchema.name, subSchemaSnapshot); + } + return snapshot; + } + /** Strategy for caching the value of an object and re-creating it if its * value is out of date as of a given timestamp. * http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java index 5717603..97744a8 100644 --- a/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java +++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java @@ -290,15 +290,16 @@ abstract class CalciteConnectionImpl throw new RuntimeException(e); } map.put(DataContext.Variable.CANCEL_FLAG.camelName, cancelFlag); - final DataContext dataContext = createDataContext(map); + final DataContext dataContext = createDataContext(map, signature.rootSchema); return signature.enumerable(dataContext); } - public DataContext createDataContext(Map<String, Object> parameterValues) { + public DataContext createDataContext(Map<String, Object> parameterValues, + CalciteSchema rootSchema) { if (config().spark()) { return new SlimDataContext(); } - return new DataContextImpl(this, parameterValues); + return new DataContextImpl(this, parameterValues, rootSchema); } // do not make public @@ -373,10 +374,10 @@ abstract class CalciteConnectionImpl private final JavaTypeFactory typeFactory; DataContextImpl(CalciteConnectionImpl connection, - Map<String, Object> parameters) { + Map<String, Object> parameters, CalciteSchema rootSchema) { this.queryProvider = connection; this.typeFactory = connection.getTypeFactory(); - this.rootSchema = connection.rootSchema; + this.rootSchema = rootSchema; // Store the time at which the query started executing. The SQL // standard says that functions such as CURRENT_TIMESTAMP return the @@ -432,7 +433,7 @@ abstract class CalciteConnectionImpl } public SchemaPlus getRootSchema() { - return rootSchema.plus(); + return rootSchema == null ? null : rootSchema.plus(); } public JavaTypeFactory getTypeFactory() { @@ -447,9 +448,12 @@ abstract class CalciteConnectionImpl /** Implementation of Context. */ static class ContextImpl implements CalcitePrepare.Context { private final CalciteConnectionImpl connection; + private final CalciteSchema rootSchema; ContextImpl(CalciteConnectionImpl connection) { this.connection = Preconditions.checkNotNull(connection); + long now = System.currentTimeMillis(); + this.rootSchema = connection.rootSchema.createSnapshot(now); } public JavaTypeFactory getTypeFactory() { @@ -457,7 +461,7 @@ abstract class CalciteConnectionImpl } public CalciteSchema getRootSchema() { - return connection.rootSchema; + return rootSchema; } public List<String> getDefaultSchemaPath() { @@ -472,7 +476,8 @@ abstract class CalciteConnectionImpl } public DataContext getDataContext() { - return connection.createDataContext(ImmutableMap.<String, Object>of()); + return connection.createDataContext(ImmutableMap.<String, Object>of(), + rootSchema); } public CalcitePrepare.SparkHandler spark() { http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java index 95bca51..efd9764 100644 --- a/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java +++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java @@ -28,6 +28,7 @@ import org.apache.calcite.avatica.MetaImpl; import org.apache.calcite.avatica.NoSuchStatementException; import org.apache.calcite.avatica.QueryState; import org.apache.calcite.avatica.remote.TypedValue; +import org.apache.calcite.jdbc.CalcitePrepare.Context; import org.apache.calcite.linq4j.Enumerable; import org.apache.calcite.linq4j.Enumerator; import org.apache.calcite.linq4j.Linq4j; @@ -211,7 +212,7 @@ public class CalciteMetaImpl extends MetaImpl { final CalcitePrepare.CalciteSignature<Object> signature = new CalcitePrepare.CalciteSignature<Object>("", ImmutableList.<AvaticaParameter>of(), internalParameters, null, - columns, cursorFactory, ImmutableList.<RelCollation>of(), -1, + columns, cursorFactory, null, ImmutableList.<RelCollation>of(), -1, null, Meta.StatementType.SELECT) { @Override public Enumerable<Object> enumerable( DataContext dataContext) { @@ -573,9 +574,9 @@ public class CalciteMetaImpl extends MetaImpl { // Not possible. We just created a statement. throw new AssertionError("missing statement", e); } - h.signature = - calciteConnection.parseQuery(toQuery(statement, sql), - statement.createPrepareContext(), maxRowCount); + final Context context = statement.createPrepareContext(); + final CalcitePrepare.Query<Object> query = toQuery(context, sql); + h.signature = calciteConnection.parseQuery(query, context, maxRowCount); statement.setSignature(h.signature); return h; } @@ -597,8 +598,9 @@ public class CalciteMetaImpl extends MetaImpl { final CalciteConnectionImpl calciteConnection = getConnection(); CalciteServerStatement statement = calciteConnection.server.getStatement(h); - signature = calciteConnection.parseQuery(toQuery(statement, sql), - statement.createPrepareContext(), maxRowCount); + final Context context = statement.createPrepareContext(); + final CalcitePrepare.Query<Object> query = toQuery(context, sql); + signature = calciteConnection.parseQuery(query, context, maxRowCount); statement.setSignature(signature); callback.assign(signature, null, -1); } @@ -616,12 +618,12 @@ public class CalciteMetaImpl extends MetaImpl { * {@link org.apache.calcite.jdbc.CalcitePrepare.Query} object, giving the * {@link Hook#STRING_TO_QUERY} hook chance to override. */ private CalcitePrepare.Query<Object> toQuery( - CalciteServerStatement statement, String sql) { + Context context, String sql) { final Holder<CalcitePrepare.Query<Object>> queryHolder = Holder.of(CalcitePrepare.Query.of(sql)); final FrameworkConfig config = Frameworks.newConfigBuilder() .parserConfig(SqlParser.Config.DEFAULT) - .defaultSchema(statement.createPrepareContext().getRootSchema().plus()) + .defaultSchema(context.getRootSchema().plus()) .build(); Hook.STRING_TO_QUERY.run(Pair.of(config, queryHolder)); return queryHolder.get(); @@ -743,7 +745,8 @@ public class CalciteMetaImpl extends MetaImpl { @VisibleForTesting public static DataContext createDataContext(CalciteConnection connection) { return ((CalciteConnectionImpl) connection) - .createDataContext(ImmutableMap.<String, Object>of()); + .createDataContext(ImmutableMap.<String, Object>of(), + CalciteSchema.from(connection.getRootSchema())); } /** A trojan-horse method, subject to change without notice. */ http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java b/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java index 6d2a8ac..6ebd146 100644 --- a/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java +++ b/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java @@ -293,6 +293,7 @@ public interface CalcitePrepare { * statement directly, without an explicit prepare step. */ class CalciteSignature<T> extends Meta.Signature { @JsonIgnore public final RelDataType rowType; + @JsonIgnore public final CalciteSchema rootSchema; @JsonIgnore private final List<RelCollation> collationList; private final long maxRowCount; private final Bindable<T> bindable; @@ -300,10 +301,11 @@ public interface CalcitePrepare { public CalciteSignature(String sql, List<AvaticaParameter> parameterList, Map<String, Object> internalParameters, RelDataType rowType, List<ColumnMetaData> columns, Meta.CursorFactory cursorFactory, - List<RelCollation> collationList, long maxRowCount, - Bindable<T> bindable) { + CalciteSchema rootSchema, List<RelCollation> collationList, + long maxRowCount, Bindable<T> bindable) { super(columns, sql, parameterList, internalParameters, cursorFactory, null); this.rowType = rowType; + this.rootSchema = rootSchema; this.collationList = collationList; this.maxRowCount = maxRowCount; this.bindable = bindable; @@ -315,6 +317,7 @@ public interface CalcitePrepare { RelDataType rowType, List<ColumnMetaData> columns, Meta.CursorFactory cursorFactory, + CalciteSchema rootSchema, List<RelCollation> collationList, long maxRowCount, Bindable<T> bindable, @@ -322,6 +325,7 @@ public interface CalcitePrepare { super(columns, sql, parameterList, internalParameters, cursorFactory, statementType); this.rowType = rowType; + this.rootSchema = rootSchema; this.collationList = collationList; this.maxRowCount = maxRowCount; this.bindable = bindable; http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java index e022a66..6bc59c7 100644 --- a/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java +++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java @@ -83,7 +83,7 @@ public class CalciteResultSet extends AvaticaResultSet { new CalcitePrepare.CalciteSignature<>(signature.sql, signature.parameters, signature.internalParameters, signature.rowType, columnMetaDataList, Meta.CursorFactory.ARRAY, - ImmutableList.<RelCollation>of(), -1, null); + signature.rootSchema, ImmutableList.<RelCollation>of(), -1, null); ResultSetMetaData subResultSetMetaData = new AvaticaResultSetMetaData(statement, null, newSignature); final CalciteResultSet resultSet = http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java ---------------------------------------------------------------------- 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 4b1bc02..dcd93a0 100644 --- a/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java +++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteSchema.java @@ -58,19 +58,50 @@ public abstract class CalciteSchema { public final String name; /** Tables explicitly defined in this schema. Does not include tables in * {@link #schema}. */ - protected final NameMap<TableEntry> tableMap = new NameMap<>(); - protected final NameMultimap<FunctionEntry> functionMap = - new NameMultimap<>(); - protected final NameMap<LatticeEntry> latticeMap = new NameMap<>(); - protected final NameSet functionNames = new NameSet(); - protected final NameMap<FunctionEntry> nullaryFunctionMap = new NameMap<>(); - protected final NameMap<CalciteSchema> subSchemaMap = new NameMap<>(); - private ImmutableList<ImmutableList<String>> path; - - CalciteSchema(CalciteSchema parent, Schema schema, String name) { + protected final NameMap<TableEntry> tableMap; + protected final NameMultimap<FunctionEntry> functionMap; + protected final NameMap<LatticeEntry> latticeMap; + protected final NameSet functionNames; + protected final NameMap<FunctionEntry> nullaryFunctionMap; + protected final NameMap<CalciteSchema> subSchemaMap; + private List<? extends List<String>> path; + + protected CalciteSchema(CalciteSchema parent, Schema schema, + String name, NameMap<CalciteSchema> subSchemaMap, + NameMap<TableEntry> tableMap, NameMap<LatticeEntry> latticeMap, + NameMultimap<FunctionEntry> functionMap, NameSet functionNames, + NameMap<FunctionEntry> nullaryFunctionMap, + List<? extends List<String>> path) { this.parent = parent; this.schema = schema; this.name = name; + if (tableMap == null) { + this.tableMap = new NameMap<>(); + } else { + this.tableMap = Preconditions.checkNotNull(tableMap); + } + if (latticeMap == null) { + this.latticeMap = new NameMap<>(); + } else { + this.latticeMap = Preconditions.checkNotNull(latticeMap); + } + if (subSchemaMap == null) { + this.subSchemaMap = new NameMap<>(); + } else { + this.subSchemaMap = Preconditions.checkNotNull(subSchemaMap); + } + if (functionMap == null) { + this.functionMap = new NameMultimap<>(); + this.functionNames = new NameSet(); + this.nullaryFunctionMap = new NameMap<>(); + } else { + // If you specify functionMap, you must also specify functionNames and + // nullaryFunctionMap. + this.functionMap = Preconditions.checkNotNull(functionMap); + this.functionNames = Preconditions.checkNotNull(functionNames); + this.nullaryFunctionMap = Preconditions.checkNotNull(nullaryFunctionMap); + } + this.path = path; } /** Returns a sub-schema with a given name that is defined implicitly @@ -112,6 +143,9 @@ public abstract class CalciteSchema { protected abstract void addImplicitTablesBasedOnNullaryFunctionsToBuilder( ImmutableSortedMap.Builder<String, Table> builder); + /** Returns a snapshot representation of this CalciteSchema. */ + protected abstract CalciteSchema snapshot(CalciteSchema parent, long now); + protected abstract boolean isCacheEnabled(); public abstract void setCache(boolean cache); @@ -343,6 +377,26 @@ public abstract class CalciteSchema { return getImplicitTableBasedOnNullaryFunction(tableName, caseSensitive); } + /** Creates a snapshot of this CalciteSchema as of the specified time. All + * explicit objects in this CalciteSchema will be copied into the snapshot + * CalciteSchema, while the contents of the snapshot of the underlying schema + * should not change as specified in {@link Schema#snapshot(long)}. Snapshots + * of explicit sub schemas will be created and copied recursively. + * + * <p>Currently, to accommodate the requirement of creating tables on the fly + * for materializations, the snapshot will still use the same table map and + * lattice map as in the original CalciteSchema instead of making copies.</p> + * + * @param now The current time in millis, as returned by + * {@link System#currentTimeMillis()} + * + * @return the schema snapshot. + */ + public CalciteSchema createSnapshot(long now) { + Preconditions.checkArgument(this.isRoot(), "must be root schema"); + return snapshot(null, now); + } + /** Returns a subset of a map whose keys match the given string * case-insensitively. */ protected static <V> NavigableMap<String, V> find(NavigableMap<String, V> map, @@ -432,7 +486,7 @@ public abstract class CalciteSchema { /** Membership of a table in a schema. */ public abstract static class TableEntry extends Entry { - public final List<String> sqls; + public final ImmutableList<String> sqls; public TableEntry(CalciteSchema schema, String name, ImmutableList<String> sqls) { @@ -498,6 +552,10 @@ public abstract class CalciteSchema { return schema.contentsHaveChangedSince(lastCheck, now); } + public Schema snapshot(long now) { + throw new UnsupportedOperationException(); + } + public Expression getExpression(SchemaPlus parentSchema, String name) { return schema.getExpression(parentSchema, name); } http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/jdbc/SimpleCalciteSchema.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/jdbc/SimpleCalciteSchema.java b/core/src/main/java/org/apache/calcite/jdbc/SimpleCalciteSchema.java index d235ba6..64da625 100644 --- a/core/src/main/java/org/apache/calcite/jdbc/SimpleCalciteSchema.java +++ b/core/src/main/java/org/apache/calcite/jdbc/SimpleCalciteSchema.java @@ -20,12 +20,16 @@ import org.apache.calcite.schema.Function; import org.apache.calcite.schema.Schema; 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 java.util.Collection; +import java.util.List; /** * A concrete implementation of {@link org.apache.calcite.jdbc.CalciteSchema} @@ -37,7 +41,17 @@ class SimpleCalciteSchema extends CalciteSchema { * <p>Use {@link CalciteSchema#createRootSchema(boolean)} * or {@link #add(String, Schema)}. */ SimpleCalciteSchema(CalciteSchema parent, Schema schema, String name) { - super(parent, schema, name); + this(parent, schema, name, null, null, null, null, null, null, null); + } + + private SimpleCalciteSchema(CalciteSchema parent, Schema schema, + String name, NameMap<CalciteSchema> subSchemaMap, + NameMap<TableEntry> tableMap, NameMap<LatticeEntry> latticeMap, + NameMultimap<FunctionEntry> functionMap, NameSet functionNames, + NameMap<FunctionEntry> nullaryFunctionMap, + List<? extends List<String>> path) { + super(parent, schema, name, subSchemaMap, tableMap, latticeMap, + functionMap, functionNames, nullaryFunctionMap, path); } public void setCache(boolean cache) { @@ -138,6 +152,17 @@ class SimpleCalciteSchema extends CalciteSchema { return null; } + protected CalciteSchema snapshot(CalciteSchema parent, long now) { + CalciteSchema snapshot = new SimpleCalciteSchema(parent, + schema.snapshot(now), name, null, tableMap, latticeMap, + functionMap, functionNames, nullaryFunctionMap, getPath()); + for (CalciteSchema subSchema : subSchemaMap.map().values()) { + CalciteSchema subSchemaSnapshot = subSchema.snapshot(snapshot, now); + snapshot.subSchemaMap.put(subSchema.name, subSchemaSnapshot); + } + return snapshot; + } + protected boolean isCacheEnabled() { return false; } http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java b/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java index 1372d8b..1b9fd88 100644 --- a/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java +++ b/core/src/main/java/org/apache/calcite/materialize/MaterializationService.java @@ -314,7 +314,7 @@ public class MaterializationService { final List<Prepare.Materialization> list = new ArrayList<>(); for (MaterializationActor.Materialization materialization : actor.keyMap.values()) { - if (materialization.rootSchema == rootSchema + if (materialization.rootSchema.schema == rootSchema.schema && materialization.materializedTable != null) { list.add( new Prepare.Materialization(materialization.materializedTable, @@ -379,7 +379,8 @@ public class MaterializationService { new AbstractQueryable<Object>() { public Enumerator<Object> enumerator() { final DataContext dataContext = - Schemas.createDataContext(connection); + Schemas.createDataContext(connection, + calciteSignature.rootSchema.plus()); return calciteSignature.enumerable(dataContext).enumerator(); } @@ -397,7 +398,8 @@ public class MaterializationService { public Iterator<Object> iterator() { final DataContext dataContext = - Schemas.createDataContext(connection); + Schemas.createDataContext(connection, + calciteSignature.rootSchema.plus()); return calciteSignature.enumerable(dataContext).iterator(); } }); http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java ---------------------------------------------------------------------- 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 6f834c7..9ec3df4 100644 --- a/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java +++ b/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java @@ -137,7 +137,6 @@ public class CalciteCatalogReader implements Prepare.CatalogReader { } if (entry != null) { final Table table = entry.getTable(); - final String name2 = entry.name; if (table instanceof Wrapper) { final Prepare.PreparingTable relOptTable = ((Wrapper) table).unwrap(Prepare.PreparingTable.class); @@ -145,8 +144,8 @@ public class CalciteCatalogReader implements Prepare.CatalogReader { return relOptTable; } } - return RelOptTableImpl.create(this, table.getRowType(typeFactory), - schema.add(name2, table), null); + return RelOptTableImpl.create(this, table.getRowType(typeFactory), entry, + null); } return null; } http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java index a5059ae..eb933f0 100644 --- a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java +++ b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java @@ -669,6 +669,7 @@ public class CalcitePrepareImpl implements CalcitePrepare { x, columns, cursorFactory, + context.getRootSchema(), ImmutableList.<RelCollation>of(), -1, new Bindable<T>() { @@ -772,7 +773,7 @@ public class CalcitePrepareImpl implements CalcitePrepare { ImmutableList.<AvaticaParameter>of(), ImmutableMap.<String, Object>of(), null, ImmutableList.<ColumnMetaData>of(), Meta.CursorFactory.OBJECT, - ImmutableList.<RelCollation>of(), -1, bindable); + null, ImmutableList.<RelCollation>of(), -1, bindable); } final SqlValidator validator = @@ -841,6 +842,7 @@ public class CalcitePrepareImpl implements CalcitePrepare { jdbcType, columns, cursorFactory, + context.getRootSchema(), preparedResult instanceof Prepare.PreparedResultImpl ? ((Prepare.PreparedResultImpl) preparedResult).collations : ImmutableList.<RelCollation>of(), http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java ---------------------------------------------------------------------- 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 2cc8492..ee82512 100644 --- a/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java +++ b/core/src/main/java/org/apache/calcite/prepare/RelOptTableImpl.java @@ -434,6 +434,10 @@ public class RelOptTableImpl extends Prepare.AbstractPreparingTable { long now) { return schema.contentsHaveChangedSince(lastCheck, now); } + + @Override public Schema snapshot(long now) { + throw new UnsupportedOperationException(); + } } } http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/rex/RexUtil.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rex/RexUtil.java b/core/src/main/java/org/apache/calcite/rex/RexUtil.java index 916313b..df82fc9 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java +++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java @@ -109,7 +109,7 @@ public class RexUtil { /** Executor for a bit of constant reduction. The user can pass in another executor. */ public static final RexExecutor EXECUTOR = - new RexExecutorImpl(Schemas.createDataContext(null)); + new RexExecutorImpl(Schemas.createDataContext(null, null)); private RexUtil() { } http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/schema/Schema.java ---------------------------------------------------------------------- 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 5f59e8c..7514e8d 100644 --- a/core/src/main/java/org/apache/calcite/schema/Schema.java +++ b/core/src/main/java/org/apache/calcite/schema/Schema.java @@ -142,6 +142,16 @@ public interface Schema { */ boolean contentsHaveChangedSince(long lastCheck, long now); + /** Returns the snapshot of this schema as of the specified time. The + * contents of the schema snapshot should not change over time. + * + * @param now The current time in millis, as returned by + * {@link System#currentTimeMillis()} + * + * @return the schema snapshot. + */ + Schema snapshot(long now); + /** Table type. */ enum TableType { /** A regular table. http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/schema/Schemas.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/schema/Schemas.java b/core/src/main/java/org/apache/calcite/schema/Schemas.java index 86275c4..69cc44e 100644 --- a/core/src/main/java/org/apache/calcite/schema/Schemas.java +++ b/core/src/main/java/org/apache/calcite/schema/Schemas.java @@ -200,8 +200,9 @@ public final class Schemas { return Types.castIfNecessary(clazz, expression); } - public static DataContext createDataContext(Connection connection) { - return new DummyDataContext((CalciteConnection) connection); + public static DataContext createDataContext( + Connection connection, SchemaPlus rootSchema) { + return new DummyDataContext((CalciteConnection) connection, rootSchema); } /** Returns a {@link Queryable}, given a fully-qualified table name. */ @@ -363,7 +364,7 @@ public final class Schemas { final CalciteConnectionConfig config = mutate(connection.config(), propValues); return makeContext(config, connection.getTypeFactory(), - createDataContext(connection), schema, schemaPath); + createDataContext(connection, schema.root().plus()), schema, schemaPath); } } @@ -538,16 +539,19 @@ public final class Schemas { /** Dummy data context that has no variables. */ private static class DummyDataContext implements DataContext { private final CalciteConnection connection; + private final SchemaPlus rootSchema; private final ImmutableMap<String, Object> map; - public DummyDataContext(CalciteConnection connection) { + public DummyDataContext(CalciteConnection connection, + SchemaPlus rootSchema) { this.connection = connection; + this.rootSchema = rootSchema; this.map = ImmutableMap.<String, Object>of("timeZone", TimeZone.getDefault()); } public SchemaPlus getRootSchema() { - return connection.getRootSchema(); + return rootSchema; } public JavaTypeFactory getTypeFactory() { http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/schema/impl/AbstractSchema.java ---------------------------------------------------------------------- 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 cf537eb..f8ad4b0 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 @@ -65,6 +65,10 @@ public class AbstractSchema implements Schema { return false; } + public Schema snapshot(long now) { + return this; + } + public Expression getExpression(SchemaPlus parentSchema, String name) { return Schemas.subSchemaExpression(parentSchema, name, getClass()); } http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/schema/impl/DelegatingSchema.java ---------------------------------------------------------------------- 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 0612a59..5be33e7 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 @@ -53,6 +53,10 @@ public class DelegatingSchema implements Schema { return schema.contentsHaveChangedSince(lastCheck, now); } + public Schema snapshot(long now) { + return schema.snapshot(now); + } + public Expression getExpression(SchemaPlus parentSchema, String name) { return schema.getExpression(parentSchema, name); } http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/main/java/org/apache/calcite/sql/validate/EmptyScope.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/sql/validate/EmptyScope.java b/core/src/main/java/org/apache/calcite/sql/validate/EmptyScope.java index bafa309..0b90516 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/EmptyScope.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/EmptyScope.java @@ -149,7 +149,6 @@ class EmptyScope implements SqlValidatorScope { path = path.plus(null, -1, entry.name, StructKind.NONE); remainingNames = Util.skip(remainingNames); final Table table = entry.getTable(); - final String name2 = entry.name; SqlValidatorTable table2 = null; if (table instanceof Wrapper) { table2 = ((Wrapper) table).unwrap(Prepare.PreparingTable.class); @@ -158,8 +157,7 @@ class EmptyScope implements SqlValidatorScope { final RelOptSchema relOptSchema = validator.catalogReader.unwrap(RelOptSchema.class); final RelDataType rowType = table.getRowType(validator.typeFactory); - table2 = RelOptTableImpl.create(relOptSchema, rowType, - schema.add(name2, table), null); + table2 = RelOptTableImpl.create(relOptSchema, rowType, entry, null); } namespace = new TableNamespace(validator, table2); resolved.found(namespace, false, this, path, remainingNames); http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java b/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java index 3a1227f..46190df 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java @@ -73,7 +73,7 @@ public class RexExecutorTest { SchemaPlus rootSchema, CalciteServerStatement statement) { final RexBuilder rexBuilder = cluster.getRexBuilder(); DataContext dataContext = - Schemas.createDataContext(statement.getConnection()); + Schemas.createDataContext(statement.getConnection(), rootSchema); final RexExecutorImpl executor = new RexExecutorImpl(dataContext); action.check(rexBuilder, executor); return null; http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/test/java/org/apache/calcite/test/LinqFrontJdbcBackTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/LinqFrontJdbcBackTest.java b/core/src/test/java/org/apache/calcite/test/LinqFrontJdbcBackTest.java index d25d64a..646ea85 100644 --- a/core/src/test/java/org/apache/calcite/test/LinqFrontJdbcBackTest.java +++ b/core/src/test/java/org/apache/calcite/test/LinqFrontJdbcBackTest.java @@ -39,12 +39,12 @@ public class LinqFrontJdbcBackTest { CalciteAssert.that(CalciteAssert.Config.JDBC_FOODMART).connect(); final CalciteConnection calciteConnection = connection.unwrap(CalciteConnection.class); - final SchemaPlus schema = - calciteConnection.getRootSchema().getSubSchema("foodmart"); + final SchemaPlus rootSchema = calciteConnection.getRootSchema(); ParameterExpression c = Expressions.parameter(JdbcTest.Customer.class, "c"); String s = - Schemas.queryable(Schemas.createDataContext(connection), schema, + Schemas.queryable(Schemas.createDataContext(connection, rootSchema), + rootSchema.getSubSchema("foodmart"), JdbcTest.Customer.class, "customer") .where( Expressions.<Predicate1<JdbcTest.Customer>>lambda( http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/test/java/org/apache/calcite/test/MockRelOptPlanner.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/MockRelOptPlanner.java b/core/src/test/java/org/apache/calcite/test/MockRelOptPlanner.java index 0462e38..adce9a9 100644 --- a/core/src/test/java/org/apache/calcite/test/MockRelOptPlanner.java +++ b/core/src/test/java/org/apache/calcite/test/MockRelOptPlanner.java @@ -55,7 +55,7 @@ public class MockRelOptPlanner extends AbstractRelOptPlanner { /** Creates MockRelOptPlanner. */ public MockRelOptPlanner() { super(RelOptCostImpl.FACTORY, null); - setExecutor(new RexExecutorImpl(Schemas.createDataContext(null))); + setExecutor(new RexExecutorImpl(Schemas.createDataContext(null, null))); } // implement RelOptPlanner http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/test/java/org/apache/calcite/test/MultiJdbcSchemaJoinTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/MultiJdbcSchemaJoinTest.java b/core/src/test/java/org/apache/calcite/test/MultiJdbcSchemaJoinTest.java index 80ee5b1..a97b1f9 100644 --- a/core/src/test/java/org/apache/calcite/test/MultiJdbcSchemaJoinTest.java +++ b/core/src/test/java/org/apache/calcite/test/MultiJdbcSchemaJoinTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -168,7 +169,7 @@ public class MultiJdbcSchemaJoinTest { } } - @Test public void testSchemaCache() throws Exception { + @Test public void testSchemaConsistency() throws Exception { // Create a database final String db = TempDb.INSTANCE.getUrl(); Connection c1 = DriverManager.getConnection(db, "", ""); @@ -183,9 +184,7 @@ public class MultiJdbcSchemaJoinTest { SchemaPlus rootSchema = calciteConnection.getRootSchema(); final DataSource ds = JdbcSchema.dataSource(db, "org.hsqldb.jdbcDriver", "", ""); - final SchemaPlus s = - rootSchema.add("DB", - JdbcSchema.create(rootSchema, "DB", ds, null, null)); + rootSchema.add("DB", JdbcSchema.create(rootSchema, "DB", ds, null, null)); Statement stmt3 = connection.createStatement(); ResultSet rs; @@ -203,19 +202,19 @@ public class MultiJdbcSchemaJoinTest { + "field1 varchar(10))"); stmt1.execute("insert into table2 values('a', 'aaaa')"); - // fails, table not visible due to caching - try { - rs = stmt3.executeQuery("select * from db.table2"); - fail("expected error, got " + rs); - } catch (SQLException e) { - assertThat(e.getCause().getCause().getMessage(), - equalTo("Object 'TABLE2' not found within 'DB'")); - } + PreparedStatement stmt2 = + connection.prepareStatement("select * from db.table2"); - // disable caching and table becomes visible - s.setCacheEnabled(false); - rs = stmt3.executeQuery("select * from db.table2"); + stmt1.execute("alter table table2 add column field2 varchar(10)"); + + // "field2" not visible to stmt2 + rs = stmt2.executeQuery(); assertThat(CalciteAssert.toString(rs), equalTo("ID=a; FIELD1=aaaa\n")); + + // "field2" visible to a new query + rs = stmt3.executeQuery("select * from db.table2"); + assertThat(CalciteAssert.toString(rs), + equalTo("ID=a; FIELD1=aaaa; FIELD2=null\n")); c1.close(); } http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java b/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java index c027164..ee2511d 100644 --- a/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java +++ b/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java @@ -412,7 +412,7 @@ public class RexImplicationCheckerTest { SchemaPlus rootSchema, CalciteServerStatement statement) { DataContext dataContext = - Schemas.createDataContext(statement.getConnection()); + Schemas.createDataContext(statement.getConnection(), rootSchema); holder.set(new RexExecutorImpl(dataContext)); return null; } http://git-wip-us.apache.org/repos/asf/calcite/blob/4519ef6e/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvSchema.java ---------------------------------------------------------------------- diff --git a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvSchema.java b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvSchema.java index 27e735d..7c971f5 100644 --- a/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvSchema.java +++ b/example/csv/src/main/java/org/apache/calcite/adapter/csv/CsvSchema.java @@ -34,6 +34,7 @@ import java.util.Map; public class CsvSchema extends AbstractSchema { private final File directoryFile; private final CsvTable.Flavor flavor; + private Map<String, Table> tableMap; /** * Creates a CSV schema. @@ -66,6 +67,13 @@ public class CsvSchema extends AbstractSchema { } @Override protected Map<String, Table> getTableMap() { + if (tableMap == null) { + tableMap = createTableMap(); + } + return tableMap; + } + + private Map<String, Table> createTableMap() { // Look for files in the directory ending in ".csv", ".csv.gz", ".json", // ".json.gz". final Source baseSource = Sources.of(directoryFile);
