You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2014/12/09 22:49:48 UTC

[4/8] incubator-calcite git commit: [CALCITE-93] Calcite RPC server; [CALCITE-94] Remote JDBC driver

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/94752a60/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 769ffe8..88ec54b 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
@@ -21,7 +21,6 @@ import org.apache.calcite.adapter.java.JavaTypeFactory;
 import org.apache.calcite.avatica.AvaticaConnection;
 import org.apache.calcite.avatica.AvaticaFactory;
 import org.apache.calcite.avatica.AvaticaParameter;
-import org.apache.calcite.avatica.AvaticaPrepareResult;
 import org.apache.calcite.avatica.AvaticaStatement;
 import org.apache.calcite.avatica.Helper;
 import org.apache.calcite.avatica.InternalProperty;
@@ -30,7 +29,9 @@ import org.apache.calcite.avatica.UnregisteredDriver;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.config.CalciteConnectionConfigImpl;
 import org.apache.calcite.linq4j.BaseQueryable;
+import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.linq4j.QueryProvider;
 import org.apache.calcite.linq4j.Queryable;
 import org.apache.calcite.linq4j.function.Function0;
@@ -54,14 +55,14 @@ import org.apache.calcite.sql.validate.SqlValidatorWithHints;
 import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Holder;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
 
 import java.io.Serializable;
 import java.lang.reflect.Type;
-import java.sql.PreparedStatement;
 import java.sql.SQLException;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -119,12 +120,8 @@ abstract class CalciteConnectionImpl
     this.properties.put(InternalProperty.QUOTING, cfg.quoting());
   }
 
-  @Override protected Meta createMeta() {
-    return new MetaImpl(this);
-  }
-
-  MetaImpl meta() {
-    return (MetaImpl) meta;
+  CalciteMetaImpl meta() {
+    return (CalciteMetaImpl) meta;
   }
 
   public CalciteConnectionConfig config() {
@@ -144,32 +141,22 @@ abstract class CalciteConnectionImpl
     }
   }
 
-  @Override public AvaticaStatement createStatement(int resultSetType,
+  @Override public CalciteStatement createStatement(int resultSetType,
       int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-    CalciteStatement statement =
-        (CalciteStatement) super.createStatement(
-            resultSetType, resultSetConcurrency, resultSetHoldability);
-    server.addStatement(statement);
-    return statement;
+    return (CalciteStatement) super.createStatement(resultSetType,
+        resultSetConcurrency, resultSetHoldability);
   }
 
-  @Override public PreparedStatement prepareStatement(
+  @Override public CalcitePreparedStatement prepareStatement(
       String sql,
       int resultSetType,
       int resultSetConcurrency,
       int resultSetHoldability) throws SQLException {
     try {
-      AvaticaPrepareResult prepareResult =
+      Meta.Signature signature =
           parseQuery(sql, new ContextImpl(this), -1);
-      CalcitePreparedStatement statement =
-          (CalcitePreparedStatement) factory.newPreparedStatement(
-              this,
-              prepareResult,
-              resultSetType,
-              resultSetConcurrency,
-              resultSetHoldability);
-      server.addStatement(statement);
-      return statement;
+      return (CalcitePreparedStatement) factory.newPreparedStatement(this, null,
+          signature, resultSetType, resultSetConcurrency, resultSetHoldability);
     } catch (RuntimeException e) {
       throw Helper.INSTANCE.createException(
           "Error while preparing statement [" + sql + "]", e);
@@ -179,7 +166,7 @@ abstract class CalciteConnectionImpl
     }
   }
 
-  <T> CalcitePrepare.PrepareResult<T> parseQuery(String sql,
+  <T> CalcitePrepare.CalciteSignature<T> parseQuery(String sql,
       CalcitePrepare.Context prepareContext, int maxRowCount) {
     CalcitePrepare.Dummy.push(prepareContext);
     try {
@@ -227,16 +214,28 @@ abstract class CalciteConnectionImpl
   public <T> Enumerator<T> executeQuery(Queryable<T> queryable) {
     try {
       CalciteStatement statement = (CalciteStatement) createStatement();
-      CalcitePrepare.PrepareResult<T> enumerable =
+      CalcitePrepare.CalciteSignature<T> signature =
           statement.prepare(queryable);
-      final DataContext dataContext =
-          createDataContext(ImmutableMap.<String, Object>of());
-      return enumerable.enumerator(dataContext);
+      return enumerable(statement.handle, signature).enumerator();
     } catch (SQLException e) {
       throw new RuntimeException(e);
     }
   }
 
+  public <T> Enumerable<T> enumerable(Meta.StatementHandle handle,
+      CalcitePrepare.CalciteSignature<T> signature) throws SQLException {
+    Map<String, Object> map = Maps.newLinkedHashMap();
+    AvaticaStatement statement = lookupStatement(handle);
+    final List<Object> parameterValues =
+        TROJAN.getParameterValues(statement);
+    for (Ord<Object> o : Ord.zip(parameterValues)) {
+      map.put("?" + o.i, o.e);
+    }
+    map.putAll(signature.internalParameters);
+    final DataContext dataContext = createDataContext(map);
+    return signature.enumerable(dataContext);
+  }
+
   public DataContext createDataContext(Map<String, Object> parameterValues) {
     if (config().spark()) {
       return new SlimDataContext();
@@ -268,15 +267,20 @@ abstract class CalciteConnectionImpl
 
   /** Implementation of Server. */
   private static class CalciteServerImpl implements CalciteServer {
-    final List<CalciteServerStatement> statementList =
-        new ArrayList<CalciteServerStatement>();
+    final Map<Integer, CalciteServerStatement> statementMap = Maps.newHashMap();
+
+    public void removeStatement(Meta.StatementHandle h) {
+      statementMap.remove(h.id);
+    }
 
-    public void removeStatement(CalciteServerStatement calciteServerStatement) {
-      statementList.add(calciteServerStatement);
+    public void addStatement(CalciteConnection connection,
+        Meta.StatementHandle h) {
+      final CalciteConnectionImpl c = (CalciteConnectionImpl) connection;
+      statementMap.put(h.id, new CalciteServerStatementImpl(c));
     }
 
-    public void addStatement(CalciteServerStatement statement) {
-      statementList.add(statement);
+    public CalciteServerStatement getStatement(Meta.StatementHandle h) {
+      return statementMap.get(h.id);
     }
   }
 
@@ -378,7 +382,7 @@ abstract class CalciteConnectionImpl
     private final CalciteConnectionImpl connection;
 
     public ContextImpl(CalciteConnectionImpl connection) {
-      this.connection = connection;
+      this.connection = Preconditions.checkNotNull(connection);
     }
 
     public JavaTypeFactory getTypeFactory() {
@@ -430,6 +434,23 @@ abstract class CalciteConnectionImpl
     }
   }
 
+  /** Implementation of {@link CalciteServerStatement}. */
+  static class CalciteServerStatementImpl
+      implements CalciteServerStatement {
+    private final CalciteConnectionImpl connection;
+
+    public CalciteServerStatementImpl(CalciteConnectionImpl connection) {
+      this.connection = Preconditions.checkNotNull(connection);
+    }
+
+    public ContextImpl createPrepareContext() {
+      return new ContextImpl(connection);
+    }
+
+    public CalciteConnection getConnection() {
+      return connection;
+    }
+  }
 }
 
 // End CalciteConnectionImpl.java

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/94752a60/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java
index 73efcaa..0b87f0f 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteJdbc41Factory.java
@@ -20,11 +20,10 @@ import org.apache.calcite.adapter.java.JavaTypeFactory;
 import org.apache.calcite.avatica.AvaticaConnection;
 import org.apache.calcite.avatica.AvaticaDatabaseMetaData;
 import org.apache.calcite.avatica.AvaticaFactory;
-import org.apache.calcite.avatica.AvaticaPrepareResult;
 import org.apache.calcite.avatica.AvaticaPreparedStatement;
 import org.apache.calcite.avatica.AvaticaResultSetMetaData;
 import org.apache.calcite.avatica.AvaticaStatement;
-import org.apache.calcite.avatica.ColumnMetaData;
+import org.apache.calcite.avatica.Meta;
 import org.apache.calcite.avatica.UnregisteredDriver;
 
 import java.io.InputStream;
@@ -34,7 +33,6 @@ import java.sql.ResultSetMetaData;
 import java.sql.RowId;
 import java.sql.SQLException;
 import java.sql.SQLXML;
-import java.util.List;
 import java.util.Properties;
 import java.util.TimeZone;
 
@@ -67,43 +65,44 @@ public class CalciteJdbc41Factory extends CalciteFactory {
         (CalciteConnectionImpl) connection);
   }
 
-  public CalciteJdbc41Statement newStatement(
-      AvaticaConnection connection,
+  public CalciteJdbc41Statement newStatement(AvaticaConnection connection,
+      Meta.StatementHandle h,
       int resultSetType,
       int resultSetConcurrency,
       int resultSetHoldability) {
     return new CalciteJdbc41Statement(
-        (CalciteConnectionImpl) connection, resultSetType, resultSetConcurrency,
+        (CalciteConnectionImpl) connection,
+        h,
+        resultSetType, resultSetConcurrency,
         resultSetHoldability);
   }
 
   public AvaticaPreparedStatement newPreparedStatement(
       AvaticaConnection connection,
-      AvaticaPrepareResult prepareResult,
+      Meta.StatementHandle h,
+      Meta.Signature signature,
       int resultSetType,
       int resultSetConcurrency,
       int resultSetHoldability) throws SQLException {
     return new CalciteJdbc41PreparedStatement(
-        (CalciteConnectionImpl) connection,
-        (CalcitePrepare.PrepareResult) prepareResult, resultSetType,
+        (CalciteConnectionImpl) connection, h,
+        (CalcitePrepare.CalciteSignature) signature, resultSetType,
         resultSetConcurrency, resultSetHoldability);
   }
 
-  public CalciteResultSet newResultSet(
-      AvaticaStatement statement,
-      AvaticaPrepareResult prepareResult,
-      TimeZone timeZone) {
+  public CalciteResultSet newResultSet(AvaticaStatement statement,
+      Meta.Signature signature, TimeZone timeZone, Iterable<Object> iterable) {
     final ResultSetMetaData metaData =
-        newResultSetMetaData(statement, prepareResult.getColumnList());
-    return new CalciteResultSet(statement,
-        (CalcitePrepare.PrepareResult) prepareResult, metaData, timeZone);
+        newResultSetMetaData(statement, signature);
+    final CalcitePrepare.CalciteSignature calciteSignature =
+        (CalcitePrepare.CalciteSignature) signature;
+    return new CalciteResultSet(statement, calciteSignature, metaData, timeZone,
+        iterable);
   }
 
-  public ResultSetMetaData newResultSetMetaData(
-      AvaticaStatement statement,
-      List<ColumnMetaData> columnMetaDataList) {
-    return new AvaticaResultSetMetaData(
-        statement, null, columnMetaDataList);
+  public ResultSetMetaData newResultSetMetaData(AvaticaStatement statement,
+      Meta.Signature signature) {
+    return new AvaticaResultSetMetaData(statement, null, signature);
   }
 
   /** Implementation of connection for JDBC 4.1. */
@@ -117,12 +116,10 @@ public class CalciteJdbc41Factory extends CalciteFactory {
 
   /** Implementation of statement for JDBC 4.1. */
   private static class CalciteJdbc41Statement extends CalciteStatement {
-    public CalciteJdbc41Statement(
-        CalciteConnectionImpl connection,
-        int resultSetType,
-        int resultSetConcurrency,
+    public CalciteJdbc41Statement(CalciteConnectionImpl connection,
+        Meta.StatementHandle h, int resultSetType, int resultSetConcurrency,
         int resultSetHoldability) {
-      super(connection, resultSetType, resultSetConcurrency,
+      super(connection, h, resultSetType, resultSetConcurrency,
           resultSetHoldability);
     }
   }
@@ -130,122 +127,132 @@ public class CalciteJdbc41Factory extends CalciteFactory {
   /** Implementation of prepared statement for JDBC 4.1. */
   private static class CalciteJdbc41PreparedStatement
       extends CalcitePreparedStatement {
-    CalciteJdbc41PreparedStatement(
-        CalciteConnectionImpl connection,
-        CalcitePrepare.PrepareResult prepareResult,
-        int resultSetType,
-        int resultSetConcurrency,
-        int resultSetHoldability) throws SQLException {
-      super(
-          connection, prepareResult, resultSetType, resultSetConcurrency,
+    CalciteJdbc41PreparedStatement(CalciteConnectionImpl connection,
+        Meta.StatementHandle h, CalcitePrepare.CalciteSignature signature,
+        int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+        throws SQLException {
+      super(connection, h, signature, resultSetType, resultSetConcurrency,
           resultSetHoldability);
     }
 
     public void setRowId(
         int parameterIndex,
         RowId x) throws SQLException {
-      getParameter(parameterIndex).setRowId(x);
+      getParameter(parameterIndex).setRowId(slots, parameterIndex, x);
     }
 
     public void setNString(
         int parameterIndex, String value) throws SQLException {
-      getParameter(parameterIndex).setNString(value);
+      getParameter(parameterIndex).setNString(slots, parameterIndex, value);
     }
 
     public void setNCharacterStream(
         int parameterIndex,
         Reader value,
         long length) throws SQLException {
-      getParameter(parameterIndex).setNCharacterStream(value, length);
+      getParameter(parameterIndex)
+          .setNCharacterStream(slots, parameterIndex, value, length);
     }
 
     public void setNClob(
         int parameterIndex,
         NClob value) throws SQLException {
-      getParameter(parameterIndex).setNClob(value);
+      getParameter(parameterIndex).setNClob(slots, parameterIndex, value);
     }
 
     public void setClob(
         int parameterIndex,
         Reader reader,
         long length) throws SQLException {
-      getParameter(parameterIndex).setClob(reader, length);
+      getParameter(parameterIndex)
+          .setClob(slots, parameterIndex, reader, length);
     }
 
     public void setBlob(
         int parameterIndex,
         InputStream inputStream,
         long length) throws SQLException {
-      getParameter(parameterIndex).setBlob(inputStream, length);
+      getParameter(parameterIndex)
+          .setBlob(slots, parameterIndex, inputStream, length);
     }
 
     public void setNClob(
         int parameterIndex,
         Reader reader,
         long length) throws SQLException {
-      getParameter(parameterIndex).setNClob(reader, length);
+      getParameter(parameterIndex).setNClob(slots,
+          parameterIndex,
+          reader,
+          length);
     }
 
     public void setSQLXML(
         int parameterIndex, SQLXML xmlObject) throws SQLException {
-      getParameter(parameterIndex).setSQLXML(xmlObject);
+      getParameter(parameterIndex).setSQLXML(slots, parameterIndex, xmlObject);
     }
 
     public void setAsciiStream(
         int parameterIndex,
         InputStream x,
         long length) throws SQLException {
-      getParameter(parameterIndex).setAsciiStream(x, length);
+      getParameter(parameterIndex)
+          .setAsciiStream(slots, parameterIndex, x, length);
     }
 
     public void setBinaryStream(
         int parameterIndex,
         InputStream x,
         long length) throws SQLException {
-      getParameter(parameterIndex).setBinaryStream(x, length);
+      getParameter(parameterIndex)
+          .setBinaryStream(slots, parameterIndex, x, length);
     }
 
     public void setCharacterStream(
         int parameterIndex,
         Reader reader,
         long length) throws SQLException {
-      getParameter(parameterIndex).setCharacterStream(reader, length);
+      getParameter(parameterIndex)
+          .setCharacterStream(slots, parameterIndex, reader, length);
     }
 
     public void setAsciiStream(
         int parameterIndex, InputStream x) throws SQLException {
-      getParameter(parameterIndex).setAsciiStream(x);
+      getParameter(parameterIndex).setAsciiStream(slots, parameterIndex, x);
     }
 
     public void setBinaryStream(
         int parameterIndex, InputStream x) throws SQLException {
-      getParameter(parameterIndex).setBinaryStream(x);
+      getParameter(parameterIndex).setBinaryStream(slots, parameterIndex, x);
     }
 
     public void setCharacterStream(
         int parameterIndex, Reader reader) throws SQLException {
-      getParameter(parameterIndex).setCharacterStream(reader);
+      getParameter(parameterIndex)
+          .setCharacterStream(slots, parameterIndex, reader);
     }
 
     public void setNCharacterStream(
         int parameterIndex, Reader value) throws SQLException {
-      getParameter(parameterIndex).setNCharacterStream(value);
+      getParameter(parameterIndex)
+          .setNCharacterStream(slots, parameterIndex, value);
     }
 
     public void setClob(
         int parameterIndex,
         Reader reader) throws SQLException {
-      getParameter(parameterIndex).setClob(reader);
+      getParameter(parameterIndex).setClob(slots, parameterIndex, reader);
     }
 
     public void setBlob(
         int parameterIndex, InputStream inputStream) throws SQLException {
-      getParameter(parameterIndex).setBlob(inputStream);
+      getParameter(parameterIndex)
+          .setBlob(slots, parameterIndex, inputStream);
     }
 
     public void setNClob(
         int parameterIndex, Reader reader) throws SQLException {
-      getParameter(parameterIndex).setNClob(reader);
+      getParameter(parameterIndex)
+          .setNClob(slots, parameterIndex, reader);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/94752a60/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
new file mode 100644
index 0000000..152e918
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteMetaImpl.java
@@ -0,0 +1,555 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.jdbc;
+
+import org.apache.calcite.DataContext;
+import org.apache.calcite.adapter.java.AbstractQueryableTable;
+import org.apache.calcite.adapter.java.JavaTypeFactory;
+import org.apache.calcite.avatica.AvaticaParameter;
+import org.apache.calcite.avatica.AvaticaStatement;
+import org.apache.calcite.avatica.AvaticaUtils;
+import org.apache.calcite.avatica.ColumnMetaData;
+import org.apache.calcite.avatica.MetaImpl;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.linq4j.Linq4j;
+import org.apache.calcite.linq4j.QueryProvider;
+import org.apache.calcite.linq4j.Queryable;
+import org.apache.calcite.linq4j.function.Function1;
+import org.apache.calcite.linq4j.function.Functions;
+import org.apache.calcite.linq4j.function.Predicate1;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeFactoryImpl;
+import org.apache.calcite.rel.type.RelDataTypeField;
+import org.apache.calcite.runtime.FlatLists;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.Table;
+import org.apache.calcite.schema.impl.AbstractTableQueryable;
+import org.apache.calcite.server.CalciteServerStatement;
+import org.apache.calcite.sql.SqlJdbcFunctionCall;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.util.Util;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import java.lang.reflect.Field;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * Helper for implementing the {@code getXxx} methods such as
+ * {@link org.apache.calcite.avatica.AvaticaDatabaseMetaData#getTables}.
+ */
+public class CalciteMetaImpl extends MetaImpl {
+  static final Driver DRIVER = new Driver();
+
+  public CalciteMetaImpl(CalciteConnectionImpl connection) {
+    super(connection);
+  }
+
+  static <T extends Named> Predicate1<T> namedMatcher(final Pat pattern) {
+    if (pattern.s == null || pattern.s.equals("%")) {
+      return Functions.truePredicate1();
+    }
+    final Pattern regex = likeToRegex(pattern);
+    return new Predicate1<T>() {
+      public boolean apply(T v1) {
+        return regex.matcher(v1.getName()).matches();
+      }
+    };
+  }
+
+  static Predicate1<String> matcher(final Pat pattern) {
+    if (pattern.s == null || pattern.s.equals("%")) {
+      return Functions.truePredicate1();
+    }
+    final Pattern regex = likeToRegex(pattern);
+    return new Predicate1<String>() {
+      public boolean apply(String v1) {
+        return regex.matcher(v1).matches();
+      }
+    };
+  }
+
+  /** Converts a LIKE-style pattern (where '%' represents a wild-card, escaped
+   * using '\') to a Java regex. */
+  public static Pattern likeToRegex(Pat pattern) {
+    StringBuilder buf = new StringBuilder("^");
+    char[] charArray = pattern.s.toCharArray();
+    int slash = -2;
+    for (int i = 0; i < charArray.length; i++) {
+      char c = charArray[i];
+      if (slash == i - 1) {
+        buf.append('[').append(c).append(']');
+      } else {
+        switch (c) {
+        case '\\':
+          slash = i;
+          break;
+        case '%':
+          buf.append(".*");
+          break;
+        case '[':
+          buf.append("\\[");
+          break;
+        case ']':
+          buf.append("\\]");
+          break;
+        default:
+          buf.append('[').append(c).append(']');
+        }
+      }
+    }
+    buf.append("$");
+    return Pattern.compile(buf.toString());
+  }
+
+  @Override public StatementHandle createStatement(ConnectionHandle ch) {
+    final StatementHandle h = super.createStatement(ch);
+    final CalciteConnectionImpl calciteConnection = getConnection();
+    calciteConnection.server.addStatement(calciteConnection, h);
+    return h;
+  }
+
+  private <E> MetaResultSet createResultSet(Enumerable<E> enumerable,
+      Class clazz, String... names) {
+    final List<ColumnMetaData> columns = new ArrayList<ColumnMetaData>();
+    final List<Field> fields = new ArrayList<Field>();
+    final List<String> fieldNames = new ArrayList<String>();
+    for (String name : names) {
+      final int index = fields.size();
+      final String fieldName = AvaticaUtils.toCamelCase(name);
+      final Field field;
+      try {
+        field = clazz.getField(fieldName);
+      } catch (NoSuchFieldException e) {
+        throw new RuntimeException(e);
+      }
+      columns.add(columnMetaData(name, index, field.getType()));
+      fields.add(field);
+      fieldNames.add(fieldName);
+    }
+    //noinspection unchecked
+    final Iterable<Object> iterable = (Iterable<Object>) (Iterable) enumerable;
+    return createResultSet(Collections.<String, Object>emptyMap(),
+        columns, CursorFactory.record(clazz, fields, fieldNames),
+        iterable);
+  }
+
+  @Override protected <E> MetaResultSet
+  createEmptyResultSet(final Class<E> clazz) {
+    final List<ColumnMetaData> columns = fieldMetaData(clazz).columns;
+    final CursorFactory cursorFactory = CursorFactory.deduce(columns, clazz);
+    return createResultSet(Collections.<String, Object>emptyMap(), columns,
+        cursorFactory, Collections.emptyList());
+  }
+
+  protected MetaResultSet createResultSet(
+      Map<String, Object> internalParameters, List<ColumnMetaData> columns,
+      CursorFactory cursorFactory, final Iterable<Object> iterable) {
+    try {
+      final CalciteConnectionImpl connection = getConnection();
+      final AvaticaStatement statement = connection.createStatement();
+      final CalcitePrepare.CalciteSignature<Object> signature =
+          new CalcitePrepare.CalciteSignature<Object>("",
+              ImmutableList.<AvaticaParameter>of(), internalParameters, null,
+              columns, cursorFactory, -1, null) {
+            @Override public Enumerable<Object> enumerable(
+                DataContext dataContext) {
+              return Linq4j.asEnumerable(iterable);
+            }
+          };
+      return new MetaResultSet(statement.getId(), true, signature, iterable);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  CalciteConnectionImpl getConnection() {
+    return (CalciteConnectionImpl) connection;
+  }
+
+  public String getSqlKeywords() {
+    return SqlParser.create("").getMetadata().getJdbcKeywords();
+  }
+
+  public String getNumericFunctions() {
+    return SqlJdbcFunctionCall.getNumericFunctions();
+  }
+
+  public String getStringFunctions() {
+    return SqlJdbcFunctionCall.getStringFunctions();
+  }
+
+  public String getSystemFunctions() {
+    return SqlJdbcFunctionCall.getSystemFunctions();
+  }
+
+  public String getTimeDateFunctions() {
+    return SqlJdbcFunctionCall.getTimeDateFunctions();
+  }
+
+  public MetaResultSet getTables(String catalog,
+      final Pat schemaPattern,
+      final Pat tableNamePattern,
+      final List<String> typeList) {
+    final Predicate1<MetaTable> typeFilter;
+    if (typeList == null) {
+      typeFilter = Functions.truePredicate1();
+    } else {
+      typeFilter = new Predicate1<MetaTable>() {
+        public boolean apply(MetaTable v1) {
+          return typeList.contains(v1.tableType);
+        }
+      };
+    }
+    final Predicate1<MetaSchema> schemaMatcher = namedMatcher(schemaPattern);
+    return createResultSet(schemas(catalog)
+            .where(schemaMatcher)
+            .selectMany(
+                new Function1<MetaSchema, Enumerable<MetaTable>>() {
+                  public Enumerable<MetaTable> apply(MetaSchema schema) {
+                    return tables(schema, matcher(tableNamePattern));
+                  }
+                })
+            .where(typeFilter),
+        MetaTable.class,
+        "TABLE_CAT",
+        "TABLE_SCHEM",
+        "TABLE_NAME",
+        "TABLE_TYPE",
+        "REMARKS",
+        "TYPE_CAT",
+        "TYPE_SCHEM",
+        "TYPE_NAME",
+        "SELF_REFERENCING_COL_NAME",
+        "REF_GENERATION");
+  }
+
+  public MetaResultSet getColumns(String catalog,
+      Pat schemaPattern,
+      Pat tableNamePattern,
+      Pat columnNamePattern) {
+    final Predicate1<String> tableNameMatcher = matcher(tableNamePattern);
+    final Predicate1<MetaSchema> schemaMatcher = namedMatcher(schemaPattern);
+    final Predicate1<MetaColumn> columnMatcher =
+        namedMatcher(columnNamePattern);
+    return createResultSet(schemas(catalog)
+            .where(schemaMatcher)
+            .selectMany(
+                new Function1<MetaSchema, Enumerable<MetaTable>>() {
+                  public Enumerable<MetaTable> apply(MetaSchema schema) {
+                    return tables(schema, tableNameMatcher);
+                  }
+                })
+            .selectMany(
+                new Function1<MetaTable, Enumerable<MetaColumn>>() {
+                  public Enumerable<MetaColumn> apply(MetaTable schema) {
+                    return columns(schema);
+                  }
+                })
+            .where(columnMatcher),
+        MetaColumn.class,
+        "TABLE_CAT",
+        "TABLE_SCHEM",
+        "TABLE_NAME",
+        "COLUMN_NAME",
+        "DATA_TYPE",
+        "TYPE_NAME",
+        "COLUMN_SIZE",
+        "BUFFER_LENGTH",
+        "DECIMAL_DIGITS",
+        "NUM_PREC_RADIX",
+        "NULLABLE",
+        "REMARKS",
+        "COLUMN_DEF",
+        "SQL_DATA_TYPE",
+        "SQL_DATETIME_SUB",
+        "CHAR_OCTET_LENGTH",
+        "ORDINAL_POSITION",
+        "IS_NULLABLE",
+        "SCOPE_CATALOG",
+        "SCOPE_TABLE",
+        "SOURCE_DATA_TYPE",
+        "IS_AUTOINCREMENT",
+        "IS_GENERATEDCOLUMN");
+  }
+
+  Enumerable<MetaCatalog> catalogs() {
+    return Linq4j.asEnumerable(
+        ImmutableList.of(new MetaCatalog(connection.getCatalog())));
+  }
+
+  Enumerable<MetaTableType> tableTypes() {
+    return Linq4j.asEnumerable(
+        ImmutableList.of(
+            new MetaTableType("TABLE"), new MetaTableType("VIEW")));
+  }
+
+  Enumerable<MetaSchema> schemas(String catalog) {
+    return Linq4j.asEnumerable(
+        getConnection().rootSchema.getSubSchemaMap().values())
+        .select(
+            new Function1<CalciteSchema, MetaSchema>() {
+              public MetaSchema apply(CalciteSchema calciteSchema) {
+                return new CalciteMetaSchema(
+                    calciteSchema,
+                    connection.getCatalog(),
+                    calciteSchema.getName());
+              }
+            })
+        .orderBy(
+            new Function1<MetaSchema, Comparable>() {
+              public Comparable apply(MetaSchema metaSchema) {
+                return (Comparable) FlatLists.of(
+                    Util.first(metaSchema.tableCatalog, ""),
+                    metaSchema.tableSchem);
+              }
+            });
+  }
+
+  Enumerable<MetaTable> tables(String catalog) {
+    return schemas(catalog)
+        .selectMany(
+            new Function1<MetaSchema, Enumerable<MetaTable>>() {
+              public Enumerable<MetaTable> apply(MetaSchema schema) {
+                return tables(schema, Functions.<String>truePredicate1());
+              }
+            });
+  }
+
+  Enumerable<MetaTable> tables(final MetaSchema schema_) {
+    final CalciteMetaSchema schema = (CalciteMetaSchema) schema_;
+    return Linq4j.asEnumerable(schema.calciteSchema.getTableNames())
+        .select(
+            new Function1<String, MetaTable>() {
+              public MetaTable apply(String name) {
+                final Table table =
+                    schema.calciteSchema.getTable(name, true).getValue();
+                return new CalciteMetaTable(table,
+                    schema.tableCatalog,
+                    schema.tableSchem,
+                    name);
+              }
+            })
+        .concat(
+            Linq4j.asEnumerable(
+                schema.calciteSchema.getTablesBasedOnNullaryFunctions()
+                    .entrySet())
+                .select(
+                    new Function1<Map.Entry<String, Table>, MetaTable>() {
+                      public MetaTable apply(Map.Entry<String, Table> pair) {
+                        final Table table = pair.getValue();
+                        return new CalciteMetaTable(table,
+                            schema.tableCatalog,
+                            schema.tableSchem,
+                            pair.getKey());
+                      }
+                    }));
+  }
+
+  Enumerable<MetaTable> tables(
+      final MetaSchema schema,
+      final Predicate1<String> matcher) {
+    return tables(schema)
+        .where(
+            new Predicate1<MetaTable>() {
+              public boolean apply(MetaTable v1) {
+                return matcher.apply(v1.getName());
+              }
+            });
+  }
+
+  public Enumerable<MetaColumn> columns(final MetaTable table_) {
+    final CalciteMetaTable table = (CalciteMetaTable) table_;
+    final RelDataType rowType =
+        table.calciteTable.getRowType(getConnection().typeFactory);
+    return Linq4j.asEnumerable(rowType.getFieldList())
+        .select(
+            new Function1<RelDataTypeField, MetaColumn>() {
+              public MetaColumn apply(RelDataTypeField field) {
+                final int precision =
+                    field.getType().getSqlTypeName().allowsPrec()
+                        && !(field.getType()
+                        instanceof RelDataTypeFactoryImpl.JavaType)
+                        ? field.getType().getPrecision()
+                        : -1;
+                return new MetaColumn(
+                    table.tableCat,
+                    table.tableSchem,
+                    table.tableName,
+                    field.getName(),
+                    field.getType().getSqlTypeName().getJdbcOrdinal(),
+                    field.getType().getFullTypeString(),
+                    precision,
+                    field.getType().getSqlTypeName().allowsScale()
+                        ? field.getType().getScale()
+                        : null,
+                    10,
+                    field.getType().isNullable()
+                        ? DatabaseMetaData.columnNullable
+                        : DatabaseMetaData.columnNoNulls,
+                    precision,
+                    field.getIndex() + 1,
+                    field.getType().isNullable() ? "YES" : "NO");
+              }
+            });
+  }
+
+  public MetaResultSet getSchemas(String catalog, Pat schemaPattern) {
+    final Predicate1<MetaSchema> schemaMatcher = namedMatcher(schemaPattern);
+    return createResultSet(schemas(catalog).where(schemaMatcher),
+        MetaSchema.class,
+        "TABLE_SCHEM",
+        "TABLE_CATALOG");
+  }
+
+  public MetaResultSet getCatalogs() {
+    return createResultSet(catalogs(),
+        MetaCatalog.class,
+        "TABLE_CATALOG");
+  }
+
+  public MetaResultSet getTableTypes() {
+    return createResultSet(tableTypes(),
+        MetaTableType.class,
+        "TABLE_TYPE");
+  }
+
+  @Override public Iterable<Object> createIterable(StatementHandle handle,
+      Signature signature, Iterable<Object> iterable) {
+    try {
+      //noinspection unchecked
+      final CalcitePrepare.CalciteSignature<Object> calciteSignature =
+          (CalcitePrepare.CalciteSignature<Object>) signature;
+      return getConnection().enumerable(handle, calciteSignature);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public Signature prepare(StatementHandle h, String sql, int maxRowCount) {
+    final CalciteConnectionImpl calciteConnection = getConnection();
+    CalciteServerStatement statement = calciteConnection.server.getStatement(h);
+    return calciteConnection.parseQuery(sql, statement.createPrepareContext(),
+        maxRowCount);
+  }
+
+  public MetaResultSet prepareAndExecute(StatementHandle h, String sql,
+      int maxRowCount, PrepareCallback callback) {
+    final CalcitePrepare.CalciteSignature<Object> signature;
+    try {
+      synchronized (callback.getMonitor()) {
+        callback.clear();
+        final CalciteConnectionImpl calciteConnection = getConnection();
+        CalciteServerStatement statement =
+            calciteConnection.server.getStatement(h);
+        signature = calciteConnection.parseQuery(sql,
+            statement.createPrepareContext(), maxRowCount);
+        callback.assign(signature, null);
+      }
+      callback.execute();
+      return new MetaResultSet(h.id, false, signature, null);
+    } catch (SQLException e) {
+      throw new RuntimeException(e);
+    }
+    // TODO: share code with prepare and createIterable
+  }
+
+  /** A trojan-horse method, subject to change without notice. */
+  @VisibleForTesting
+  public static DataContext createDataContext(CalciteConnection connection) {
+    return ((CalciteConnectionImpl) connection)
+        .createDataContext(ImmutableMap.<String, Object>of());
+  }
+
+  /** A trojan-horse method, subject to change without notice. */
+  @VisibleForTesting
+  public static CalciteConnection connect(CalciteRootSchema schema,
+      JavaTypeFactory typeFactory) {
+    return DRIVER.connect(schema, typeFactory);
+  }
+
+  /** Metadata describing a Calcite table. */
+  private static class CalciteMetaTable extends MetaTable {
+    private final Table calciteTable;
+
+    public CalciteMetaTable(Table calciteTable, String tableCat,
+        String tableSchem, String tableName) {
+      super(tableCat, tableSchem, tableName,
+          calciteTable.getJdbcTableType().name());
+      this.calciteTable = Preconditions.checkNotNull(calciteTable);
+    }
+  }
+
+  /** Metadata describing a Calcite schema. */
+  private static class CalciteMetaSchema extends MetaSchema {
+    private final CalciteSchema calciteSchema;
+
+    public CalciteMetaSchema(CalciteSchema calciteSchema,
+        String tableCatalog, String tableSchem) {
+      super(tableCatalog, tableSchem);
+      this.calciteSchema = calciteSchema;
+    }
+  }
+
+  /** Table whose contents are metadata. */
+  abstract static class MetadataTable<E> extends AbstractQueryableTable {
+    public MetadataTable(Class<E> clazz) {
+      super(clazz);
+    }
+
+    public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+      return ((JavaTypeFactory) typeFactory).createType(elementType);
+    }
+
+    @Override public Schema.TableType getJdbcTableType() {
+      return Schema.TableType.SYSTEM_TABLE;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override public Class<E> getElementType() {
+      return (Class<E>) elementType;
+    }
+
+    protected abstract Enumerator<E> enumerator(CalciteMetaImpl connection);
+
+    public <T> Queryable<T> asQueryable(QueryProvider queryProvider,
+        SchemaPlus schema, String tableName) {
+      return new AbstractTableQueryable<T>(queryProvider, schema, this,
+          tableName) {
+        @SuppressWarnings("unchecked")
+        public Enumerator<T> enumerator() {
+          return (Enumerator<T>) MetadataTable.this.enumerator(
+              ((CalciteConnectionImpl) queryProvider).meta());
+        }
+      };
+    }
+  }
+}
+
+// End CalciteMetaImpl.java

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/94752a60/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 9f17655..00e61b1 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalcitePrepare.java
@@ -19,13 +19,11 @@ package org.apache.calcite.jdbc;
 import org.apache.calcite.DataContext;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
 import org.apache.calcite.avatica.AvaticaParameter;
-import org.apache.calcite.avatica.AvaticaPrepareResult;
 import org.apache.calcite.avatica.ColumnMetaData;
-import org.apache.calcite.avatica.Cursor;
+import org.apache.calcite.avatica.Meta;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.linq4j.Enumerable;
 import org.apache.calcite.linq4j.EnumerableDefaults;
-import org.apache.calcite.linq4j.Enumerator;
 import org.apache.calcite.linq4j.Queryable;
 import org.apache.calcite.linq4j.function.Function0;
 import org.apache.calcite.linq4j.tree.ClassDeclaration;
@@ -35,19 +33,17 @@ import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.runtime.ArrayEnumeratorCursor;
 import org.apache.calcite.runtime.Bindable;
-import org.apache.calcite.runtime.ObjectEnumeratorCursor;
-import org.apache.calcite.runtime.RecordEnumeratorCursor;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.util.Stacks;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -72,14 +68,14 @@ public interface CalcitePrepare {
 
   ConvertResult convert(Context context, String sql);
 
-  <T> PrepareResult<T> prepareSql(
+  <T> CalciteSignature<T> prepareSql(
       Context context,
       String sql,
       Queryable<T> expression,
       Type elementType,
       int maxRowCount);
 
-  <T> PrepareResult<T> prepareQueryable(
+  <T> CalciteSignature<T> prepareQueryable(
       Context context,
       Queryable<T> queryable);
 
@@ -226,62 +222,26 @@ public interface CalcitePrepare {
   /** The result of preparing a query. It gives the Avatica driver framework
    * the information it needs to create a prepared statement, or to execute a
    * statement directly, without an explicit prepare step. */
-  public static class PrepareResult<T> implements AvaticaPrepareResult {
-    public final String sql; // for debug
-    public final List<AvaticaParameter> parameterList;
-    private final Map<String, Object> internalParameters;
-    public final RelDataType rowType;
-    public final ColumnMetaData.StructType structType;
+  public static class CalciteSignature<T> extends Meta.Signature {
+    @JsonIgnore public final RelDataType rowType;
     private final int maxRowCount;
     private final Bindable<T> bindable;
-    public final Class resultClazz;
 
-    public PrepareResult(String sql,
+    public CalciteSignature(String sql,
         List<AvaticaParameter> parameterList,
         Map<String, Object> internalParameters,
         RelDataType rowType,
-        ColumnMetaData.StructType structType,
+        List<ColumnMetaData> columns,
+        Meta.CursorFactory cursorFactory,
         int maxRowCount,
-        Bindable<T> bindable,
-        Class resultClazz) {
-      super();
-      this.sql = sql;
-      this.parameterList = parameterList;
-      this.internalParameters = internalParameters;
+        Bindable<T> bindable) {
+      super(columns, sql, parameterList, internalParameters, cursorFactory);
       this.rowType = rowType;
-      this.structType = structType;
       this.maxRowCount = maxRowCount;
       this.bindable = bindable;
-      this.resultClazz = resultClazz;
     }
 
-    public Cursor createCursor(DataContext dataContext) {
-      Enumerator<?> enumerator = enumerator(dataContext);
-      //noinspection unchecked
-      return structType.columns.size() == 1
-          ? new ObjectEnumeratorCursor((Enumerator) enumerator)
-          : resultClazz != null && !resultClazz.isArray()
-          ? new RecordEnumeratorCursor((Enumerator) enumerator, resultClazz)
-          : new ArrayEnumeratorCursor((Enumerator) enumerator);
-    }
-
-    public List<ColumnMetaData> getColumnList() {
-      return structType.columns;
-    }
-
-    public List<AvaticaParameter> getParameterList() {
-      return parameterList;
-    }
-
-    public Map<String, Object> getInternalParameters() {
-      return internalParameters;
-    }
-
-    public String getSql() {
-      return sql;
-    }
-
-    private Enumerable<T> getEnumerable(DataContext dataContext) {
+    public Enumerable<T> enumerable(DataContext dataContext) {
       Enumerable<T> enumerable = bindable.bind(dataContext);
       if (maxRowCount >= 0) {
         // Apply limit. In JDBC 0 means "no limit". But for us, -1 means
@@ -290,14 +250,6 @@ public interface CalcitePrepare {
       }
       return enumerable;
     }
-
-    public Enumerator<T> enumerator(DataContext dataContext) {
-      return getEnumerable(dataContext).enumerator();
-    }
-
-    public Iterator<T> iterator(DataContext dataContext) {
-      return getEnumerable(dataContext).iterator();
-    }
   }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/94752a60/core/src/main/java/org/apache/calcite/jdbc/CalcitePreparedStatement.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalcitePreparedStatement.java b/core/src/main/java/org/apache/calcite/jdbc/CalcitePreparedStatement.java
index 86e657b..dbbc351 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalcitePreparedStatement.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalcitePreparedStatement.java
@@ -16,9 +16,8 @@
  */
 package org.apache.calcite.jdbc;
 
-import org.apache.calcite.avatica.AvaticaPrepareResult;
 import org.apache.calcite.avatica.AvaticaPreparedStatement;
-import org.apache.calcite.server.CalciteServerStatement;
+import org.apache.calcite.avatica.Meta;
 
 import java.sql.SQLException;
 
@@ -30,36 +29,28 @@ import java.sql.SQLException;
  * it is instantiated using
  * {@link org.apache.calcite.avatica.AvaticaFactory#newPreparedStatement}.
  */
-abstract class CalcitePreparedStatement
-    extends AvaticaPreparedStatement
-    implements CalciteServerStatement {
+abstract class CalcitePreparedStatement extends AvaticaPreparedStatement {
   /**
    * Creates a CalcitePreparedStatement.
    *
    * @param connection Connection
-   * @param prepareResult Result of preparing statement
-   *
+   * @param h Statement handle
+   * @param signature Result of preparing statement
+   * @param resultSetType Result set type
+   * @param resultSetConcurrency Result set concurrency
+   * @param resultSetHoldability Result set holdability
    * @throws SQLException if database error occurs
    */
-  protected CalcitePreparedStatement(
-      CalciteConnectionImpl connection,
-      AvaticaPrepareResult prepareResult,
-      int resultSetType,
-      int resultSetConcurrency,
-      int resultSetHoldability)
-      throws SQLException {
-    super(
-        connection, prepareResult, resultSetType, resultSetConcurrency,
+  protected CalcitePreparedStatement(CalciteConnectionImpl connection,
+      Meta.StatementHandle h, Meta.Signature signature, int resultSetType,
+      int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+    super(connection, h, signature, resultSetType, resultSetConcurrency,
         resultSetHoldability);
   }
 
   @Override public CalciteConnectionImpl getConnection() {
     return (CalciteConnectionImpl) super.getConnection();
   }
-
-  public CalciteConnectionImpl.ContextImpl createPrepareContext() {
-    return new CalciteConnectionImpl.ContextImpl(getConnection());
-  }
 }
 
 // End CalcitePreparedStatement.java

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/94752a60/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 3e16c39..72f31ef 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteResultSet.java
@@ -19,8 +19,8 @@ package org.apache.calcite.jdbc;
 import org.apache.calcite.avatica.AvaticaResultSet;
 import org.apache.calcite.avatica.AvaticaStatement;
 import org.apache.calcite.avatica.ColumnMetaData;
-import org.apache.calcite.avatica.Cursor;
 import org.apache.calcite.avatica.Handler;
+import org.apache.calcite.avatica.util.Cursor;
 import org.apache.calcite.linq4j.Enumerator;
 import org.apache.calcite.linq4j.Linq4j;
 import org.apache.calcite.runtime.ArrayEnumeratorCursor;
@@ -40,9 +40,10 @@ import java.util.TimeZone;
  */
 public class CalciteResultSet extends AvaticaResultSet {
   CalciteResultSet(AvaticaStatement statement,
-      CalcitePrepare.PrepareResult prepareResult,
-      ResultSetMetaData resultSetMetaData, TimeZone timeZone) {
-    super(statement, prepareResult, resultSetMetaData, timeZone);
+      CalcitePrepare.CalciteSignature calciteSignature,
+      ResultSetMetaData resultSetMetaData, TimeZone timeZone,
+      Iterable<Object> iterable) {
+    super(statement, calciteSignature, resultSetMetaData, timeZone, iterable);
   }
 
   @Override protected CalciteResultSet execute() throws SQLException {
@@ -63,11 +64,11 @@ public class CalciteResultSet extends AvaticaResultSet {
   }
 
   @Override public ResultSet create(ColumnMetaData.AvaticaType elementType,
-      Iterable iterable) {
+      Iterable<Object> iterable) {
     final CalciteResultSet resultSet =
         new CalciteResultSet(statement,
-            (CalcitePrepare.PrepareResult) prepareResult, resultSetMetaData,
-            localCalendar.getTimeZone());
+            (CalcitePrepare.CalciteSignature) signature, resultSetMetaData,
+            localCalendar.getTimeZone(), iterable);
     final Cursor cursor = resultSet.createCursor(elementType, iterable);
     final List<ColumnMetaData> columnMetaDataList;
     if (elementType instanceof ColumnMetaData.StructType) {
@@ -90,8 +91,9 @@ public class CalciteResultSet extends AvaticaResultSet {
   }
 
   // do not make public
-  CalcitePrepare.PrepareResult getPrepareResult() {
-    return (CalcitePrepare.PrepareResult) prepareResult;
+  <T> CalcitePrepare.CalciteSignature<T> getSignature() {
+    //noinspection unchecked
+    return (CalcitePrepare.CalciteSignature) signature;
   }
 
   // do not make public

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/94752a60/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java
index c8f0e17..fa875e4 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteStatement.java
@@ -18,27 +18,42 @@ package org.apache.calcite.jdbc;
 
 import org.apache.calcite.avatica.AvaticaResultSet;
 import org.apache.calcite.avatica.AvaticaStatement;
+import org.apache.calcite.avatica.Meta;
 import org.apache.calcite.linq4j.Queryable;
 import org.apache.calcite.server.CalciteServerStatement;
 
+import java.sql.SQLException;
+
 /**
  * Implementation of {@link java.sql.Statement}
  * for the Calcite engine.
  */
-public abstract class CalciteStatement
-    extends AvaticaStatement
-    implements CalciteServerStatement {
-  CalciteStatement(
-      CalciteConnectionImpl connection,
-      int resultSetType,
-      int resultSetConcurrency,
-      int resultSetHoldability) {
-    super(connection, resultSetType, resultSetConcurrency,
+public abstract class CalciteStatement extends AvaticaStatement {
+  /**
+   * Creates a CalciteStatement.
+   *
+   * @param connection Connection
+   * @param h Statement handle
+   * @param resultSetType Result set type
+   * @param resultSetConcurrency Result set concurrency
+   * @param resultSetHoldability Result set holdability
+   */
+  CalciteStatement(CalciteConnectionImpl connection, Meta.StatementHandle h,
+      int resultSetType, int resultSetConcurrency, int resultSetHoldability) {
+    super(connection, h, resultSetType, resultSetConcurrency,
         resultSetHoldability);
   }
 
   // implement Statement
 
+  @Override public <T> T unwrap(Class<T> iface) throws SQLException {
+    if (iface == CalciteServerStatement.class) {
+      //noinspection unchecked
+      return (T) getConnection().server.getStatement(handle);
+    }
+    return super.unwrap(iface);
+  }
+
   @Override public CalciteConnectionImpl getConnection() {
     return (CalciteConnectionImpl) connection;
   }
@@ -47,10 +62,15 @@ public abstract class CalciteStatement
     return new CalciteConnectionImpl.ContextImpl(getConnection());
   }
 
-  protected <T> CalcitePrepare.PrepareResult<T> prepare(
+  protected <T> CalcitePrepare.CalciteSignature<T> prepare(
       Queryable<T> queryable) {
-    final CalcitePrepare prepare = getConnection().prepareFactory.apply();
-    return prepare.prepareQueryable(createPrepareContext(), queryable);
+    final CalciteConnectionImpl calciteConnection = getConnection();
+    final CalcitePrepare prepare = calciteConnection.prepareFactory.apply();
+    final CalciteServerStatement serverStatement =
+        calciteConnection.server.getStatement(handle);
+    final CalcitePrepare.Context prepareContext =
+        serverStatement.createPrepareContext();
+    return prepare.prepareQueryable(prepareContext, queryable);
   }
 
   @Override protected void close_() {
@@ -58,7 +78,7 @@ public abstract class CalciteStatement
       closed = true;
       final CalciteConnectionImpl connection1 =
           (CalciteConnectionImpl) connection;
-      connection1.server.removeStatement(this);
+      connection1.server.removeStatement(handle);
       if (openResultSet != null) {
         AvaticaResultSet c = openResultSet;
         openResultSet = null;

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/94752a60/core/src/main/java/org/apache/calcite/jdbc/Driver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/Driver.java b/core/src/main/java/org/apache/calcite/jdbc/Driver.java
index 5997f22..228cfde 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/Driver.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/Driver.java
@@ -23,6 +23,7 @@ import org.apache.calcite.avatica.ConnectionProperty;
 import org.apache.calcite.avatica.DriverVersion;
 import org.apache.calcite.avatica.Handler;
 import org.apache.calcite.avatica.HandlerImpl;
+import org.apache.calcite.avatica.Meta;
 import org.apache.calcite.avatica.UnregisteredDriver;
 import org.apache.calcite.config.CalciteConnectionProperty;
 import org.apache.calcite.linq4j.function.Function0;
@@ -110,6 +111,10 @@ public class Driver extends UnregisteredDriver {
     return list;
   }
 
+  @Override public Meta createMeta(AvaticaConnection connection) {
+    return new CalciteMetaImpl((CalciteConnectionImpl) connection);
+  }
+
   /** Creates an internal connection. */
   CalciteConnection connect(CalciteRootSchema rootSchema,
       JavaTypeFactory typeFactory) {

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/94752a60/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java b/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
index 3f3fabb..7349b07 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
@@ -17,7 +17,7 @@
 package org.apache.calcite.jdbc;
 
 import org.apache.calcite.adapter.java.JavaTypeFactory;
-import org.apache.calcite.avatica.ByteString;
+import org.apache.calcite.avatica.util.ByteString;
 import org.apache.calcite.linq4j.Ord;
 import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.linq4j.tree.Types;