calcite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jh...@apache.org
Subject calcite git commit: [CALCITE-1742] Create a read-consistent view of CalciteSchema for each statement compilation
Date Tue, 23 May 2017 03:44:10 GMT
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 <maryann.xue@gmail.com>
Authored: Mon Apr 10 17:43:36 2017 -0700
Committer: Julian Hyde <jhyde@apache.org>
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
    *       }
    *     }
    *   ]
-   *
+   * &nbsp;
    * class FoodMart {
    *   public static final FoodMart instance() {
    *     return new FoodMart();
    *   }
-   *
+   * &nbsp;
    *   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);


Mime
View raw message