You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by el...@apache.org on 2016/03/07 19:28:13 UTC

[35/59] [partial] calcite git commit: [CALCITE-1078] Detach avatica from the core calcite Maven project

http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/main/java/org/apache/calcite/avatica/remote/Service.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/remote/Service.java b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/Service.java
new file mode 100644
index 0000000..5790848
--- /dev/null
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/Service.java
@@ -0,0 +1,2771 @@
+/*
+ * 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.avatica.remote;
+
+import org.apache.calcite.avatica.AvaticaClientRuntimeException;
+import org.apache.calcite.avatica.AvaticaConnection;
+import org.apache.calcite.avatica.AvaticaSeverity;
+import org.apache.calcite.avatica.BuiltInConnectionProperty;
+import org.apache.calcite.avatica.ConnectionPropertiesImpl;
+import org.apache.calcite.avatica.Meta;
+import org.apache.calcite.avatica.QueryState;
+import org.apache.calcite.avatica.proto.Common;
+import org.apache.calcite.avatica.proto.Requests;
+import org.apache.calcite.avatica.proto.Responses;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.HBaseZeroCopyByteString;
+import com.google.protobuf.Message;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Properties;
+
+/**
+ * API for request-response calls to an Avatica server.
+ */
+public interface Service {
+  ResultSetResponse apply(CatalogsRequest request);
+  ResultSetResponse apply(SchemasRequest request);
+  ResultSetResponse apply(TablesRequest request);
+  ResultSetResponse apply(TableTypesRequest request);
+  ResultSetResponse apply(TypeInfoRequest request);
+  ResultSetResponse apply(ColumnsRequest request);
+  PrepareResponse apply(PrepareRequest request);
+  ExecuteResponse apply(ExecuteRequest request);
+  ExecuteResponse apply(PrepareAndExecuteRequest request);
+  SyncResultsResponse apply(SyncResultsRequest request);
+  FetchResponse apply(FetchRequest request);
+  CreateStatementResponse apply(CreateStatementRequest request);
+  CloseStatementResponse apply(CloseStatementRequest request);
+  OpenConnectionResponse apply(OpenConnectionRequest request);
+  CloseConnectionResponse apply(CloseConnectionRequest request);
+  ConnectionSyncResponse apply(ConnectionSyncRequest request);
+  DatabasePropertyResponse apply(DatabasePropertyRequest request);
+  CommitResponse apply(CommitRequest request);
+  RollbackResponse apply(RollbackRequest request);
+
+  /**
+   * Sets server-level metadata for RPCs. This includes information that is static across all RPCs.
+   *
+   * @param metadata The server-level metadata.
+   */
+  void setRpcMetadata(RpcMetadataResponse metadata);
+
+  /** Factory that creates a {@code Service}. */
+  interface Factory {
+    Service create(AvaticaConnection connection);
+  }
+
+  /** Base class for request and response. */
+  abstract class Base {
+    static final int PRIME = 31;
+
+    protected static int p(int result, Object o) {
+      return PRIME * result + ((o == null) ? 0 : o.hashCode());
+    }
+
+    protected static int p(int result, boolean v) {
+      return PRIME * result + (v ? 1231 : 1237);
+    }
+
+    protected static int p(int result, int v) {
+      return PRIME * result + v;
+    }
+
+    protected static int p(int result, long v) {
+      return PRIME * result + (int) (v ^ (v >>> 32));
+    }
+  }
+
+  /** Base class for all service request messages. */
+  @JsonTypeInfo(
+      use = JsonTypeInfo.Id.NAME,
+      property = "request",
+      defaultImpl = SchemasRequest.class)
+  @JsonSubTypes({
+      @JsonSubTypes.Type(value = CatalogsRequest.class, name = "getCatalogs"),
+      @JsonSubTypes.Type(value = SchemasRequest.class, name = "getSchemas"),
+      @JsonSubTypes.Type(value = TablesRequest.class, name = "getTables"),
+      @JsonSubTypes.Type(value = TableTypesRequest.class, name = "getTableTypes"),
+      @JsonSubTypes.Type(value = TypeInfoRequest.class, name = "getTypeInfo"),
+      @JsonSubTypes.Type(value = ColumnsRequest.class, name = "getColumns"),
+      @JsonSubTypes.Type(value = ExecuteRequest.class, name = "execute"),
+      @JsonSubTypes.Type(value = PrepareRequest.class, name = "prepare"),
+      @JsonSubTypes.Type(value = PrepareAndExecuteRequest.class,
+          name = "prepareAndExecute"),
+      @JsonSubTypes.Type(value = FetchRequest.class, name = "fetch"),
+      @JsonSubTypes.Type(value = CreateStatementRequest.class,
+          name = "createStatement"),
+      @JsonSubTypes.Type(value = CloseStatementRequest.class,
+          name = "closeStatement"),
+      @JsonSubTypes.Type(value = OpenConnectionRequest.class,
+          name = "openConnection"),
+      @JsonSubTypes.Type(value = CloseConnectionRequest.class,
+          name = "closeConnection"),
+      @JsonSubTypes.Type(value = ConnectionSyncRequest.class, name = "connectionSync"),
+      @JsonSubTypes.Type(value = DatabasePropertyRequest.class, name = "databaseProperties"),
+      @JsonSubTypes.Type(value = SyncResultsRequest.class, name = "syncResults"),
+      @JsonSubTypes.Type(value = CommitRequest.class, name = "commit"),
+      @JsonSubTypes.Type(value = RollbackRequest.class, name = "rollback") })
+  abstract class Request extends Base {
+    abstract Response accept(Service service);
+    abstract Request deserialize(Message genericMsg);
+    abstract Message serialize();
+  }
+
+  /** Base class for all service response messages. */
+  @JsonTypeInfo(
+      use = JsonTypeInfo.Id.NAME,
+      property = "response",
+      defaultImpl = ResultSetResponse.class)
+  @JsonSubTypes({
+      @JsonSubTypes.Type(value = OpenConnectionResponse.class, name = "openConnection"),
+      @JsonSubTypes.Type(value = ResultSetResponse.class, name = "resultSet"),
+      @JsonSubTypes.Type(value = PrepareResponse.class, name = "prepare"),
+      @JsonSubTypes.Type(value = FetchResponse.class, name = "fetch"),
+      @JsonSubTypes.Type(value = CreateStatementResponse.class,
+          name = "createStatement"),
+      @JsonSubTypes.Type(value = CloseStatementResponse.class,
+          name = "closeStatement"),
+      @JsonSubTypes.Type(value = CloseConnectionResponse.class,
+          name = "closeConnection"),
+      @JsonSubTypes.Type(value = ConnectionSyncResponse.class, name = "connectionSync"),
+      @JsonSubTypes.Type(value = DatabasePropertyResponse.class, name = "databaseProperties"),
+      @JsonSubTypes.Type(value = ExecuteResponse.class, name = "executeResults"),
+      @JsonSubTypes.Type(value = ErrorResponse.class, name = "error"),
+      @JsonSubTypes.Type(value = SyncResultsResponse.class, name = "syncResults"),
+      @JsonSubTypes.Type(value = RpcMetadataResponse.class, name = "rpcMetadata"),
+      @JsonSubTypes.Type(value = CommitResponse.class, name = "commit"),
+      @JsonSubTypes.Type(value = RollbackResponse.class, name = "rollback") })
+  abstract class Response extends Base {
+    abstract Response deserialize(Message genericMsg);
+    abstract Message serialize();
+  }
+
+  /** Request for
+   * {@link org.apache.calcite.avatica.Meta#getCatalogs(Meta.ConnectionHandle)}. */
+  class CatalogsRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.CatalogsRequest.
+        getDescriptor().findFieldByNumber(Requests.CatalogsRequest.CONNECTION_ID_FIELD_NUMBER);
+    public final String connectionId;
+
+    public CatalogsRequest() {
+      connectionId = null;
+    }
+
+    @JsonCreator
+    public CatalogsRequest(@JsonProperty("connectionId") String connectionId) {
+      this.connectionId = connectionId;
+    }
+
+    ResultSetResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override CatalogsRequest deserialize(Message genericMsg) {
+      final Requests.CatalogsRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.CatalogsRequest.class);
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      return new CatalogsRequest(connectionId);
+    }
+
+    @Override Requests.CatalogsRequest serialize() {
+      Requests.CatalogsRequest.Builder builder = Requests.CatalogsRequest.newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof CatalogsRequest
+          && Objects.equals(connectionId, ((CatalogsRequest) o).connectionId);
+    }
+  }
+
+  /** Request for
+   * {@link org.apache.calcite.avatica.Meta#getDatabaseProperties(Meta.ConnectionHandle)}. */
+  class DatabasePropertyRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR =
+        Requests.DatabasePropertyRequest.getDescriptor().
+        findFieldByNumber(Requests.DatabasePropertyRequest.CONNECTION_ID_FIELD_NUMBER);
+
+    public final String connectionId;
+
+    public DatabasePropertyRequest() {
+      connectionId = null;
+    }
+
+    @JsonCreator
+    public DatabasePropertyRequest(@JsonProperty("connectionId") String connectionId) {
+      this.connectionId = connectionId;
+    }
+
+    DatabasePropertyResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override DatabasePropertyRequest deserialize(Message genericMsg) {
+      final Requests.DatabasePropertyRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.DatabasePropertyRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      return new DatabasePropertyRequest(connectionId);
+    }
+
+    @Override Requests.DatabasePropertyRequest serialize() {
+      Requests.DatabasePropertyRequest.Builder builder =
+          Requests.DatabasePropertyRequest.newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof DatabasePropertyRequest
+          && Objects.equals(connectionId, ((DatabasePropertyRequest) o).connectionId);
+    }
+  }
+
+  /** Request for
+   * {@link Meta#getSchemas(Meta.ConnectionHandle, String, Meta.Pat)}. */
+  class SchemasRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.SchemasRequest.
+        getDescriptor().findFieldByNumber(Requests.SchemasRequest.CONNECTION_ID_FIELD_NUMBER);
+    private static final FieldDescriptor CATALOG_DESCRIPTOR = Requests.SchemasRequest.
+        getDescriptor().findFieldByNumber(Requests.SchemasRequest.CATALOG_FIELD_NUMBER);
+    private static final FieldDescriptor SCHEMA_PATTERN_DESCRIPTOR = Requests.SchemasRequest.
+        getDescriptor().findFieldByNumber(Requests.SchemasRequest.SCHEMA_PATTERN_FIELD_NUMBER);
+
+    public final String connectionId;
+    public final String catalog;
+    public final String schemaPattern;
+
+    SchemasRequest() {
+      connectionId = null;
+      catalog = null;
+      schemaPattern = null;
+    }
+
+    @JsonCreator
+    public SchemasRequest(@JsonProperty("connectionId") String connectionId,
+        @JsonProperty("catalog") String catalog,
+        @JsonProperty("schemaPattern") String schemaPattern) {
+      this.connectionId = connectionId;
+      this.catalog = catalog;
+      this.schemaPattern = schemaPattern;
+    }
+
+    ResultSetResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override SchemasRequest deserialize(Message genericMsg) {
+      final Requests.SchemasRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.SchemasRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      String catalog = null;
+      if (msg.hasField(CATALOG_DESCRIPTOR)) {
+        catalog = msg.getCatalog();
+      }
+
+      String schemaPattern = null;
+      if (msg.hasField(SCHEMA_PATTERN_DESCRIPTOR)) {
+        schemaPattern = msg.getSchemaPattern();
+      }
+
+      return new SchemasRequest(connectionId, catalog, schemaPattern);
+    }
+
+    @Override Requests.SchemasRequest serialize() {
+      Requests.SchemasRequest.Builder builder = Requests.SchemasRequest.newBuilder();
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+      if (null != catalog) {
+        builder.setCatalog(catalog);
+      }
+      if (null != schemaPattern) {
+        builder.setSchemaPattern(schemaPattern);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, catalog);
+      result = p(result, schemaPattern);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof SchemasRequest
+          && Objects.equals(connectionId, ((SchemasRequest) o).connectionId)
+          && Objects.equals(catalog, ((SchemasRequest) o).catalog)
+          && Objects.equals(schemaPattern, ((SchemasRequest) o).schemaPattern);
+    }
+  }
+
+  /** Request for
+   * {@link Meta#getTables(Meta.ConnectionHandle, String, org.apache.calcite.avatica.Meta.Pat, org.apache.calcite.avatica.Meta.Pat, java.util.List)}
+   */
+  class TablesRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.TablesRequest.
+        getDescriptor().findFieldByNumber(Requests.TablesRequest.CONNECTION_ID_FIELD_NUMBER);
+    private static final FieldDescriptor CATALOG_DESCRIPTOR = Requests.TablesRequest.
+        getDescriptor().findFieldByNumber(Requests.TablesRequest.CATALOG_FIELD_NUMBER);
+    private static final FieldDescriptor SCHEMA_PATTERN_DESCRIPTOR = Requests.TablesRequest.
+        getDescriptor().findFieldByNumber(Requests.TablesRequest.SCHEMA_PATTERN_FIELD_NUMBER);
+    private static final FieldDescriptor TABLE_NAME_PATTERN_DESCRIPTOR = Requests.TablesRequest.
+        getDescriptor().findFieldByNumber(Requests.TablesRequest.TABLE_NAME_PATTERN_FIELD_NUMBER);
+
+    public final String connectionId;
+    public final String catalog;
+    public final String schemaPattern;
+    public final String tableNamePattern;
+    public final List<String> typeList;
+
+    TablesRequest() {
+      connectionId = null;
+      catalog = null;
+      schemaPattern = null;
+      tableNamePattern = null;
+      typeList = null;
+    }
+
+    @JsonCreator
+    public TablesRequest(@JsonProperty("connectionId") String connectionId,
+        @JsonProperty("catalog") String catalog,
+        @JsonProperty("schemaPattern") String schemaPattern,
+        @JsonProperty("tableNamePattern") String tableNamePattern,
+        @JsonProperty("typeList") List<String> typeList) {
+      this.connectionId = connectionId;
+      this.catalog = catalog;
+      this.schemaPattern = schemaPattern;
+      this.tableNamePattern = tableNamePattern;
+      this.typeList = typeList;
+    }
+
+    @Override Response accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override Request deserialize(Message genericMsg) {
+      final Requests.TablesRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.TablesRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      String catalog = null;
+      if (msg.hasField(CATALOG_DESCRIPTOR)) {
+        catalog = msg.getCatalog();
+      }
+
+      String schemaPattern = null;
+      if (msg.hasField(SCHEMA_PATTERN_DESCRIPTOR)) {
+        schemaPattern = msg.getSchemaPattern();
+      }
+
+      String tableNamePattern = null;
+      if (msg.hasField(TABLE_NAME_PATTERN_DESCRIPTOR)) {
+        tableNamePattern = msg.getTableNamePattern();
+      }
+
+      // Cannot determine if a value was set for a repeated field. Must use an extra boolean
+      // parameter to distinguish an empty and null typeList.
+      List<String> typeList = null;
+      if (msg.getHasTypeList()) {
+        typeList = msg.getTypeListList();
+      }
+
+      return new TablesRequest(connectionId, catalog, schemaPattern, tableNamePattern, typeList);
+    }
+
+    @Override Requests.TablesRequest serialize() {
+      Requests.TablesRequest.Builder builder = Requests.TablesRequest.newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+      if (null != catalog) {
+        builder.setCatalog(catalog);
+      }
+      if (null != schemaPattern) {
+        builder.setSchemaPattern(schemaPattern);
+      }
+      if (null != tableNamePattern) {
+        builder.setTableNamePattern(tableNamePattern);
+      }
+      if (null != typeList) {
+        builder.setHasTypeList(true);
+        builder.addAllTypeList(typeList);
+      } else {
+        builder.setHasTypeList(false);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, catalog);
+      result = p(result, schemaPattern);
+      result = p(result, tableNamePattern);
+      result = p(result, typeList);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof TablesRequest
+          && Objects.equals(connectionId, ((TablesRequest) o).connectionId)
+          && Objects.equals(catalog, ((TablesRequest) o).catalog)
+          && Objects.equals(schemaPattern, ((TablesRequest) o).schemaPattern)
+          && Objects.equals(tableNamePattern, ((TablesRequest) o).tableNamePattern)
+          && Objects.equals(typeList, ((TablesRequest) o).typeList);
+    }
+  }
+
+  /**
+   * Request for {@link Meta#getTableTypes(Meta.ConnectionHandle)}.
+   */
+  class TableTypesRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.TableTypesRequest.
+        getDescriptor().findFieldByNumber(Requests.TableTypesRequest.CONNECTION_ID_FIELD_NUMBER);
+    public final String connectionId;
+
+    public TableTypesRequest() {
+      this.connectionId = null;
+    }
+
+    @JsonCreator
+    public TableTypesRequest(@JsonProperty("connectionId") String connectionId) {
+      this.connectionId = connectionId;
+    }
+
+    @Override ResultSetResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override TableTypesRequest deserialize(Message genericMsg) {
+      final Requests.TableTypesRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.TableTypesRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      return new TableTypesRequest(connectionId);
+    }
+
+    @Override Requests.TableTypesRequest serialize() {
+      Requests.TableTypesRequest.Builder builder = Requests.TableTypesRequest.newBuilder();
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof TableTypesRequest
+          && Objects.equals(connectionId, ((TableTypesRequest) o).connectionId);
+    }
+  }
+
+  /** Request for
+   * {@link Meta#getColumns(Meta.ConnectionHandle, String, org.apache.calcite.avatica.Meta.Pat, org.apache.calcite.avatica.Meta.Pat, org.apache.calcite.avatica.Meta.Pat)}.
+   */
+  class ColumnsRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.ColumnsRequest.
+        getDescriptor().findFieldByNumber(Requests.ColumnsRequest.CONNECTION_ID_FIELD_NUMBER);
+    private static final FieldDescriptor CATALOG_DESCRIPTOR = Requests.ColumnsRequest.
+        getDescriptor().findFieldByNumber(Requests.ColumnsRequest.CATALOG_FIELD_NUMBER);
+    private static final FieldDescriptor SCHEMA_PATTERN_DESCRIPTOR = Requests.ColumnsRequest.
+        getDescriptor().findFieldByNumber(Requests.ColumnsRequest.SCHEMA_PATTERN_FIELD_NUMBER);
+    private static final FieldDescriptor TABLE_NAME_PATTERN_DESCRIPTOR = Requests.ColumnsRequest.
+        getDescriptor().findFieldByNumber(Requests.ColumnsRequest.TABLE_NAME_PATTERN_FIELD_NUMBER);
+    private static final FieldDescriptor COLUMN_NAME_PATTERN_DESCRIPTOR = Requests.ColumnsRequest.
+        getDescriptor().findFieldByNumber(Requests.ColumnsRequest.COLUMN_NAME_PATTERN_FIELD_NUMBER);
+
+    public final String connectionId;
+    public final String catalog;
+    public final String schemaPattern;
+    public final String tableNamePattern;
+    public final String columnNamePattern;
+
+    ColumnsRequest() {
+      connectionId = null;
+      catalog = null;
+      schemaPattern = null;
+      tableNamePattern = null;
+      columnNamePattern = null;
+    }
+
+    @JsonCreator
+    public ColumnsRequest(@JsonProperty("connectionId") String connectionId,
+        @JsonProperty("catalog") String catalog,
+        @JsonProperty("schemaPattern") String schemaPattern,
+        @JsonProperty("tableNamePattern") String tableNamePattern,
+        @JsonProperty("columnNamePattern") String columnNamePattern) {
+      this.connectionId = connectionId;
+      this.catalog = catalog;
+      this.schemaPattern = schemaPattern;
+      this.tableNamePattern = tableNamePattern;
+      this.columnNamePattern = columnNamePattern;
+    }
+
+    ResultSetResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override ColumnsRequest deserialize(Message genericMsg) {
+      final Requests.ColumnsRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.ColumnsRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      String catalog = null;
+      if (msg.hasField(CATALOG_DESCRIPTOR)) {
+        catalog = msg.getCatalog();
+      }
+
+      String schemaPattern = null;
+      if (msg.hasField(SCHEMA_PATTERN_DESCRIPTOR)) {
+        schemaPattern = msg.getSchemaPattern();
+      }
+
+      String tableNamePattern = null;
+      if (msg.hasField(TABLE_NAME_PATTERN_DESCRIPTOR)) {
+        tableNamePattern = msg.getTableNamePattern();
+      }
+
+      String columnNamePattern = null;
+      if (msg.hasField(COLUMN_NAME_PATTERN_DESCRIPTOR)) {
+        columnNamePattern = msg.getColumnNamePattern();
+      }
+
+      return new ColumnsRequest(connectionId, catalog, schemaPattern, tableNamePattern,
+          columnNamePattern);
+    }
+
+    @Override Requests.ColumnsRequest serialize() {
+      Requests.ColumnsRequest.Builder builder = Requests.ColumnsRequest.newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+      if (null != catalog) {
+        builder.setCatalog(catalog);
+      }
+      if (null != schemaPattern) {
+        builder.setSchemaPattern(schemaPattern);
+      }
+      if (null != tableNamePattern) {
+        builder.setTableNamePattern(tableNamePattern);
+      }
+      if (null != columnNamePattern) {
+        builder.setColumnNamePattern(columnNamePattern);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, catalog);
+      result = p(result, columnNamePattern);
+      result = p(result, schemaPattern);
+      result = p(result, tableNamePattern);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof ColumnsRequest
+          && Objects.equals(connectionId, ((ColumnsRequest) o).connectionId)
+          && Objects.equals(catalog, ((ColumnsRequest) o).catalog)
+          && Objects.equals(schemaPattern, ((ColumnsRequest) o).schemaPattern)
+          && Objects.equals(tableNamePattern, ((ColumnsRequest) o).tableNamePattern)
+          && Objects.equals(columnNamePattern, ((ColumnsRequest) o).columnNamePattern);
+    }
+  }
+
+  /** Request for
+   * {@link Meta#getTypeInfo(Meta.ConnectionHandle)}. */
+  class TypeInfoRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.TypeInfoRequest.
+        getDescriptor().findFieldByNumber(Requests.TypeInfoRequest.CONNECTION_ID_FIELD_NUMBER);
+    public final String connectionId;
+
+    public TypeInfoRequest() {
+      connectionId = null;
+    }
+
+    @JsonCreator
+    public TypeInfoRequest(@JsonProperty("connectionId") String connectionId) {
+      this.connectionId = connectionId;
+    }
+
+    @Override ResultSetResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override TypeInfoRequest deserialize(Message genericMsg) {
+      final Requests.TypeInfoRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.TypeInfoRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      return new TypeInfoRequest(connectionId);
+    }
+
+    @Override Requests.TypeInfoRequest serialize() {
+      Requests.TypeInfoRequest.Builder builder = Requests.TypeInfoRequest.newBuilder();
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof TypeInfoRequest
+          && Objects.equals(connectionId, ((TypeInfoRequest) o).connectionId);
+    }
+  }
+
+  /** Response that contains a result set.
+   *
+   * <p>Regular result sets have {@code updateCount} -1;
+   * any other value means a dummy result set that is just a count, and has
+   * no signature and no other data.
+   *
+   * <p>Several types of request, including
+   * {@link org.apache.calcite.avatica.Meta#getCatalogs(Meta.ConnectionHandle)} and
+   * {@link org.apache.calcite.avatica.Meta#getSchemas(Meta.ConnectionHandle, String, org.apache.calcite.avatica.Meta.Pat)}
+   * {@link Meta#getTables(Meta.ConnectionHandle, String, Meta.Pat, Meta.Pat, List)}
+   * {@link Meta#getTableTypes(Meta.ConnectionHandle)}
+   * return this response. */
+  class ResultSetResponse extends Response {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Responses.ResultSetResponse.
+        getDescriptor().findFieldByNumber(Responses.ResultSetResponse.CONNECTION_ID_FIELD_NUMBER);
+    private static final FieldDescriptor SIGNATURE_DESCRIPTOR = Responses.ResultSetResponse.
+        getDescriptor().findFieldByNumber(Responses.ResultSetResponse.SIGNATURE_FIELD_NUMBER);
+    private static final FieldDescriptor FIRST_FRAME_DESCRIPTOR = Responses.ResultSetResponse.
+        getDescriptor().findFieldByNumber(Responses.ResultSetResponse.FIRST_FRAME_FIELD_NUMBER);
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.ResultSetResponse.
+        getDescriptor().findFieldByNumber(Responses.ResultSetResponse.METADATA_FIELD_NUMBER);
+
+    public final String connectionId;
+    public final int statementId;
+    public final boolean ownStatement;
+    public final Meta.Signature signature;
+    public final Meta.Frame firstFrame;
+    public final long updateCount;
+    public final RpcMetadataResponse rpcMetadata;
+
+    ResultSetResponse() {
+      connectionId = null;
+      statementId = 0;
+      ownStatement = false;
+      signature = null;
+      firstFrame = null;
+      updateCount = 0;
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public ResultSetResponse(
+        @JsonProperty("connectionId") String connectionId,
+        @JsonProperty("statementId") int statementId,
+        @JsonProperty("ownStatement") boolean ownStatement,
+        @JsonProperty("signature") Meta.Signature signature,
+        @JsonProperty("firstFrame") Meta.Frame firstFrame,
+        @JsonProperty("updateCount") long updateCount,
+        @JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.connectionId = connectionId;
+      this.statementId = statementId;
+      this.ownStatement = ownStatement;
+      this.signature = signature;
+      this.firstFrame = firstFrame;
+      this.updateCount = updateCount;
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override ResultSetResponse deserialize(Message genericMsg) {
+      final Responses.ResultSetResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.ResultSetResponse.class);
+
+      return fromProto(msg);
+    }
+
+    static ResultSetResponse fromProto(Responses.ResultSetResponse msg) {
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      Meta.Signature signature = null;
+      if (msg.hasField(SIGNATURE_DESCRIPTOR)) {
+        signature = Meta.Signature.fromProto(msg.getSignature());
+      }
+
+      Meta.Frame frame = null;
+      if (msg.hasField(FIRST_FRAME_DESCRIPTOR)) {
+        frame = Meta.Frame.fromProto(msg.getFirstFrame());
+      }
+
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new ResultSetResponse(connectionId, msg.getStatementId(), msg.getOwnStatement(),
+          signature, frame, msg.getUpdateCount(), metadata);
+    }
+
+    @Override Responses.ResultSetResponse serialize() {
+      Responses.ResultSetResponse.Builder builder = Responses.ResultSetResponse.newBuilder();
+
+      builder.setStatementId(statementId).setOwnStatement(ownStatement).setUpdateCount(updateCount);
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      if (null != signature) {
+        builder.setSignature(signature.toProto());
+      }
+
+      if (null != firstFrame) {
+        builder.setFirstFrame(firstFrame.toProto());
+      }
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, firstFrame);
+      result = p(result, ownStatement);
+      result = p(result, signature);
+      result = p(result, statementId);
+      result = p(result, updateCount);
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof ResultSetResponse
+          && statementId == ((ResultSetResponse) o).statementId
+          && ownStatement == ((ResultSetResponse) o).ownStatement
+          && updateCount == ((ResultSetResponse) o).updateCount
+          && Objects.equals(connectionId, ((ResultSetResponse) o).connectionId)
+          && Objects.equals(firstFrame, ((ResultSetResponse) o).firstFrame)
+          && Objects.equals(signature, ((ResultSetResponse) o).signature)
+          && Objects.equals(rpcMetadata, ((ResultSetResponse) o).rpcMetadata);
+    }
+  }
+
+  /** Request for
+   * {@link Meta#prepareAndExecute(Meta.StatementHandle, String, long, Meta.PrepareCallback)}. */
+  class PrepareAndExecuteRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.
+        PrepareAndExecuteRequest.getDescriptor().findFieldByNumber(
+            Requests.PrepareAndExecuteRequest.CONNECTION_ID_FIELD_NUMBER);
+    private static final FieldDescriptor SQL_DESCRIPTOR = Requests.
+        PrepareAndExecuteRequest.getDescriptor().findFieldByNumber(
+            Requests.PrepareAndExecuteRequest.SQL_FIELD_NUMBER);
+
+    public final String connectionId;
+    public final String sql;
+    public final long maxRowCount;
+    public final int statementId;
+
+    PrepareAndExecuteRequest() {
+      connectionId = null;
+      sql = null;
+      maxRowCount = 0;
+      statementId = 0;
+    }
+
+    @JsonCreator
+    public PrepareAndExecuteRequest(
+        @JsonProperty("connectionId") String connectionId,
+        @JsonProperty("statementId") int statementId,
+        @JsonProperty("sql") String sql,
+        @JsonProperty("maxRowCount") long maxRowCount) {
+      this.connectionId = connectionId;
+      this.statementId = statementId;
+      this.sql = sql;
+      this.maxRowCount = maxRowCount;
+    }
+
+    @Override ExecuteResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override PrepareAndExecuteRequest deserialize(Message genericMsg) {
+      final Requests.PrepareAndExecuteRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.PrepareAndExecuteRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      String sql = null;
+      if (msg.hasField(SQL_DESCRIPTOR)) {
+        sql = msg.getSql();
+      }
+
+      return new PrepareAndExecuteRequest(connectionId, msg.getStatementId(), sql,
+          msg.getMaxRowCount());
+    }
+
+    @Override Requests.PrepareAndExecuteRequest serialize() {
+      Requests.PrepareAndExecuteRequest.Builder builder = Requests.PrepareAndExecuteRequest
+          .newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+      if (null != sql) {
+        builder.setSql(sql);
+      }
+      builder.setStatementId(statementId);
+      builder.setMaxRowCount(maxRowCount);
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, maxRowCount);
+      result = p(result, sql);
+      result = p(result, statementId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof PrepareAndExecuteRequest
+          && statementId == ((PrepareAndExecuteRequest) o).statementId
+          && maxRowCount == ((PrepareAndExecuteRequest) o).maxRowCount
+          && Objects.equals(connectionId, ((PrepareAndExecuteRequest) o).connectionId)
+          && Objects.equals(sql, ((PrepareAndExecuteRequest) o).sql);
+    }
+  }
+
+  /** Request for
+   * {@link org.apache.calcite.avatica.Meta#execute}. */
+  class ExecuteRequest extends Request {
+    private static final FieldDescriptor STATEMENT_HANDLE_DESCRIPTOR = Requests.ExecuteRequest.
+        getDescriptor().findFieldByNumber(Requests.ExecuteRequest.STATEMENTHANDLE_FIELD_NUMBER);
+    public final Meta.StatementHandle statementHandle;
+    public final List<TypedValue> parameterValues;
+    public final long maxRowCount;
+
+    ExecuteRequest() {
+      statementHandle = null;
+      parameterValues = null;
+      maxRowCount = 0;
+    }
+
+    @JsonCreator
+    public ExecuteRequest(
+        @JsonProperty("statementHandle") Meta.StatementHandle statementHandle,
+        @JsonProperty("parameterValues") List<TypedValue> parameterValues,
+        @JsonProperty("maxRowCount") long maxRowCount) {
+      this.statementHandle = statementHandle;
+      this.parameterValues = parameterValues;
+      this.maxRowCount = maxRowCount;
+    }
+
+    @Override ExecuteResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override ExecuteRequest deserialize(Message genericMsg) {
+      final Requests.ExecuteRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.ExecuteRequest.class);
+
+      Meta.StatementHandle statemetnHandle = null;
+      if (msg.hasField(STATEMENT_HANDLE_DESCRIPTOR)) {
+        statemetnHandle = Meta.StatementHandle.fromProto(msg.getStatementHandle());
+      }
+
+      List<TypedValue> values = null;
+      if (msg.getHasParameterValues()) {
+        values = new ArrayList<>(msg.getParameterValuesCount());
+        for (Common.TypedValue valueProto : msg.getParameterValuesList()) {
+          values.add(TypedValue.fromProto(valueProto));
+        }
+      }
+
+      return new ExecuteRequest(statemetnHandle, values, msg.getMaxRowCount());
+    }
+
+    @Override Requests.ExecuteRequest serialize() {
+      Requests.ExecuteRequest.Builder builder = Requests.ExecuteRequest.newBuilder();
+
+      if (null != statementHandle) {
+        builder.setStatementHandle(statementHandle.toProto());
+      }
+
+      if (null != parameterValues) {
+        builder.setHasParameterValues(true);
+        for (TypedValue paramValue : parameterValues) {
+          if (paramValue == null) {
+            builder.addParameterValues(TypedValue.NULL.toProto());
+          } else {
+            builder.addParameterValues(paramValue.toProto());
+          }
+        }
+      } else {
+        builder.setHasParameterValues(false);
+      }
+
+      builder.setMaxRowCount(maxRowCount);
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, statementHandle);
+      result = p(result, parameterValues);
+      result = p(result, maxRowCount);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof ExecuteRequest
+          && maxRowCount == ((ExecuteRequest) o).maxRowCount
+          && Objects.equals(statementHandle, ((ExecuteRequest) o).statementHandle)
+          && Objects.equals(parameterValues, ((ExecuteRequest) o).parameterValues);
+    }
+  }
+
+  /** Response to a
+   * {@link org.apache.calcite.avatica.remote.Service.PrepareAndExecuteRequest}. */
+  class ExecuteResponse extends Response {
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.ExecuteResponse.
+        getDescriptor().findFieldByNumber(Responses.ExecuteResponse.METADATA_FIELD_NUMBER);
+    public final List<ResultSetResponse> results;
+    public boolean missingStatement = false;
+    public final RpcMetadataResponse rpcMetadata;
+
+    ExecuteResponse() {
+      results = null;
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public ExecuteResponse(@JsonProperty("resultSets") List<ResultSetResponse> results,
+        @JsonProperty("missingStatement") boolean missingStatement,
+        @JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.results = results;
+      this.missingStatement = missingStatement;
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override ExecuteResponse deserialize(Message genericMsg) {
+      final Responses.ExecuteResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.ExecuteResponse.class);
+
+      List<Responses.ResultSetResponse> msgResults = msg.getResultsList();
+      List<ResultSetResponse> copiedResults = new ArrayList<>(msgResults.size());
+
+      for (Responses.ResultSetResponse msgResult : msgResults) {
+        copiedResults.add(ResultSetResponse.fromProto(msgResult));
+      }
+
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new ExecuteResponse(copiedResults, msg.getMissingStatement(), metadata);
+    }
+
+    @Override Responses.ExecuteResponse serialize() {
+      Responses.ExecuteResponse.Builder builder = Responses.ExecuteResponse.newBuilder();
+
+      if (null != results) {
+        for (ResultSetResponse result : results) {
+          builder.addResults(result.serialize());
+        }
+      }
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      return builder.setMissingStatement(missingStatement).build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, results);
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof ExecuteResponse
+          && Objects.equals(results, ((ExecuteResponse) o).results)
+          && Objects.equals(rpcMetadata, ((ExecuteResponse) o).rpcMetadata);
+    }
+  }
+
+  /** Request for
+   * {@link Meta#prepare(Meta.ConnectionHandle, String, long)}. */
+  class PrepareRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.PrepareRequest.
+        getDescriptor().findFieldByNumber(Requests.PrepareRequest.CONNECTION_ID_FIELD_NUMBER);
+    private static final FieldDescriptor SQL_DESCRIPTOR = Requests.PrepareRequest.
+        getDescriptor().findFieldByNumber(Requests.PrepareRequest.SQL_FIELD_NUMBER);
+    public final String connectionId;
+    public final String sql;
+    public final long maxRowCount;
+
+    PrepareRequest() {
+      connectionId = null;
+      sql = null;
+      maxRowCount = 0;
+    }
+
+    @JsonCreator
+    public PrepareRequest(
+        @JsonProperty("connectionId") String connectionId,
+        @JsonProperty("sql") String sql,
+        @JsonProperty("maxRowCount") long maxRowCount) {
+      this.connectionId = connectionId;
+      this.sql = sql;
+      this.maxRowCount = maxRowCount;
+    }
+
+    @Override PrepareResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override PrepareRequest deserialize(Message genericMsg) {
+      final Requests.PrepareRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.PrepareRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      String sql = null;
+      if (msg.hasField(SQL_DESCRIPTOR)) {
+        sql = msg.getSql();
+      }
+
+      return new PrepareRequest(connectionId, sql, msg.getMaxRowCount());
+    }
+
+    @Override Requests.PrepareRequest serialize() {
+      Requests.PrepareRequest.Builder builder = Requests.PrepareRequest.newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      if (null != sql) {
+        builder.setSql(sql);
+      }
+
+      return builder.setMaxRowCount(maxRowCount).build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, maxRowCount);
+      result = p(result, sql);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof PrepareRequest
+          && maxRowCount == ((PrepareRequest) o).maxRowCount
+          && Objects.equals(connectionId, ((PrepareRequest) o).connectionId)
+          && Objects.equals(sql, ((PrepareRequest) o).sql);
+    }
+  }
+
+  /** Response from
+   * {@link org.apache.calcite.avatica.remote.Service.PrepareRequest}. */
+  class PrepareResponse extends Response {
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.PrepareResponse.
+        getDescriptor().findFieldByNumber(Responses.PrepareResponse.METADATA_FIELD_NUMBER);
+    public final Meta.StatementHandle statement;
+    public final RpcMetadataResponse rpcMetadata;
+
+    PrepareResponse() {
+      statement = null;
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public PrepareResponse(
+        @JsonProperty("statement") Meta.StatementHandle statement,
+        @JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.statement = statement;
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override PrepareResponse deserialize(Message genericMsg) {
+      final Responses.PrepareResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.PrepareResponse.class);
+
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new PrepareResponse(Meta.StatementHandle.fromProto(msg.getStatement()), metadata);
+    }
+
+    @Override Responses.PrepareResponse serialize() {
+      Responses.PrepareResponse.Builder builder = Responses.PrepareResponse.newBuilder();
+
+      if (null != statement) {
+        builder.setStatement(statement.toProto());
+      }
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, statement);
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof PrepareResponse
+          && Objects.equals(statement, ((PrepareResponse) o).statement)
+          && Objects.equals(rpcMetadata, ((PrepareResponse) o).rpcMetadata);
+    }
+  }
+
+  /** Request for
+   * {@link Meta#fetch}. */
+  class FetchRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.FetchRequest.
+        getDescriptor().findFieldByNumber(Requests.FetchRequest.CONNECTION_ID_FIELD_NUMBER);
+    public final String connectionId;
+    public final int statementId;
+    public final long offset;
+    /** Maximum number of rows to be returned in the frame. Negative means no
+     * limit. */
+    public final int fetchMaxRowCount;
+
+    FetchRequest() {
+      connectionId = null;
+      statementId = 0;
+      offset = 0;
+      fetchMaxRowCount = 0;
+    }
+
+    @JsonCreator
+    public FetchRequest(
+        @JsonProperty("connectionId") String connectionId,
+        @JsonProperty("statementId") int statementId,
+        @JsonProperty("offset") long offset,
+        @JsonProperty("fetchMaxRowCount") int fetchMaxRowCount) {
+      this.connectionId = connectionId;
+      this.statementId = statementId;
+      this.offset = offset;
+      this.fetchMaxRowCount = fetchMaxRowCount;
+    }
+
+    @Override FetchResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override FetchRequest deserialize(Message genericMsg) {
+      final Requests.FetchRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.FetchRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      return new FetchRequest(connectionId, msg.getStatementId(), msg.getOffset(),
+          msg.getFetchMaxRowCount());
+    }
+
+    @Override Requests.FetchRequest serialize() {
+      Requests.FetchRequest.Builder builder = Requests.FetchRequest.newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      builder.setStatementId(statementId);
+      builder.setOffset(offset);
+      builder.setFetchMaxRowCount(fetchMaxRowCount);
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, fetchMaxRowCount);
+      result = p(result, offset);
+      result = p(result, statementId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof FetchRequest
+          && statementId == ((FetchRequest) o).statementId
+          && offset == ((FetchRequest) o).offset
+          && fetchMaxRowCount == ((FetchRequest) o).fetchMaxRowCount
+          && Objects.equals(connectionId, ((FetchRequest) o).connectionId);
+    }
+  }
+
+  /** Response from
+   * {@link org.apache.calcite.avatica.remote.Service.FetchRequest}. */
+  class FetchResponse extends Response {
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.FetchResponse.
+        getDescriptor().findFieldByNumber(Responses.FetchResponse.METADATA_FIELD_NUMBER);
+    public final Meta.Frame frame;
+    public boolean missingStatement = false;
+    public boolean missingResults = false;
+    public final RpcMetadataResponse rpcMetadata;
+
+    FetchResponse() {
+      frame = null;
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public FetchResponse(@JsonProperty("frame") Meta.Frame frame,
+        @JsonProperty("missingStatement") boolean missingStatement,
+        @JsonProperty("missingResults") boolean missingResults,
+        @JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.frame = frame;
+      this.missingStatement = missingStatement;
+      this.missingResults = missingResults;
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override FetchResponse deserialize(Message genericMsg) {
+      final Responses.FetchResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.FetchResponse.class);
+
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new FetchResponse(Meta.Frame.fromProto(msg.getFrame()), msg.getMissingStatement(),
+          msg.getMissingResults(), metadata);
+    }
+
+    @Override Responses.FetchResponse serialize() {
+      Responses.FetchResponse.Builder builder = Responses.FetchResponse.newBuilder();
+
+      if (null != frame) {
+        builder.setFrame(frame.toProto());
+      }
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      return builder.setMissingStatement(missingStatement)
+          .setMissingResults(missingResults).build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, frame);
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof FetchResponse
+          && Objects.equals(frame, ((FetchResponse) o).frame)
+          && Objects.equals(rpcMetadata, ((FetchResponse) o).rpcMetadata)
+          && missingStatement == ((FetchResponse) o).missingStatement;
+    }
+  }
+
+  /** Request for
+   * {@link org.apache.calcite.avatica.Meta#createStatement(org.apache.calcite.avatica.Meta.ConnectionHandle)}. */
+  class CreateStatementRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.CreateStatementRequest.
+        getDescriptor().findFieldByNumber(
+            Requests.CreateStatementRequest.CONNECTION_ID_FIELD_NUMBER);
+    public final String connectionId;
+
+    CreateStatementRequest() {
+      connectionId = null;
+    }
+
+    @JsonCreator
+    public CreateStatementRequest(
+        @JsonProperty("signature") String connectionId) {
+      this.connectionId = connectionId;
+    }
+
+    @Override CreateStatementResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override CreateStatementRequest deserialize(Message genericMsg) {
+      final Requests.CreateStatementRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.CreateStatementRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      return new CreateStatementRequest(connectionId);
+    }
+
+    @Override Requests.CreateStatementRequest serialize() {
+      Requests.CreateStatementRequest.Builder builder = Requests.CreateStatementRequest
+          .newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof CreateStatementRequest
+          && Objects.equals(connectionId, ((CreateStatementRequest) o).connectionId);
+    }
+  }
+
+  /** Response from
+   * {@link org.apache.calcite.avatica.remote.Service.CreateStatementRequest}. */
+  class CreateStatementResponse extends Response {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Responses.
+        CreateStatementResponse.getDescriptor().findFieldByNumber(
+            Responses.CreateStatementResponse.CONNECTION_ID_FIELD_NUMBER);
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.
+        CreateStatementResponse.getDescriptor().findFieldByNumber(
+            Responses.CreateStatementResponse.METADATA_FIELD_NUMBER);
+    public final String connectionId;
+    public final int statementId;
+    public final RpcMetadataResponse rpcMetadata;
+
+    CreateStatementResponse() {
+      connectionId = null;
+      statementId = 0;
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public CreateStatementResponse(
+        @JsonProperty("connectionId") String connectionId,
+        @JsonProperty("statementId") int statementId,
+        @JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.connectionId = connectionId;
+      this.statementId = statementId;
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override CreateStatementResponse deserialize(Message genericMsg) {
+      final Responses.CreateStatementResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.CreateStatementResponse.class);
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new CreateStatementResponse(connectionId, msg.getStatementId(), metadata);
+    }
+
+    @Override Responses.CreateStatementResponse serialize() {
+      Responses.CreateStatementResponse.Builder builder = Responses.CreateStatementResponse
+          .newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      builder.setStatementId(statementId);
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, statementId);
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof CreateStatementResponse
+          && statementId == ((CreateStatementResponse) o).statementId
+          && Objects.equals(connectionId, ((CreateStatementResponse) o).connectionId)
+          && Objects.equals(rpcMetadata, ((CreateStatementResponse) o).rpcMetadata);
+    }
+  }
+
+  /** Request for
+   * {@link org.apache.calcite.avatica.Meta#closeStatement(org.apache.calcite.avatica.Meta.StatementHandle)}. */
+  class CloseStatementRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.CloseStatementRequest.
+        getDescriptor().findFieldByNumber(
+            Requests.CloseStatementRequest.CONNECTION_ID_FIELD_NUMBER);
+    public final String connectionId;
+    public final int statementId;
+
+    CloseStatementRequest() {
+      connectionId = null;
+      statementId = 0;
+    }
+
+    @JsonCreator
+    public CloseStatementRequest(
+        @JsonProperty("connectionId") String connectionId,
+        @JsonProperty("statementId") int statementId) {
+      this.connectionId = connectionId;
+      this.statementId = statementId;
+    }
+
+    @Override CloseStatementResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override CloseStatementRequest deserialize(Message genericMsg) {
+      final Requests.CloseStatementRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.CloseStatementRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      return new CloseStatementRequest(connectionId, msg.getStatementId());
+    }
+
+    @Override Requests.CloseStatementRequest serialize() {
+      Requests.CloseStatementRequest.Builder builder = Requests.CloseStatementRequest.newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      return builder.setStatementId(statementId).build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, statementId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof CloseStatementRequest
+          && statementId == ((CloseStatementRequest) o).statementId
+          && Objects.equals(connectionId, ((CloseStatementRequest) o).connectionId);
+    }
+  }
+
+  /** Response from
+   * {@link org.apache.calcite.avatica.remote.Service.CloseStatementRequest}. */
+  class CloseStatementResponse extends Response {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Responses.
+        CloseStatementResponse.getDescriptor().findFieldByNumber(
+            Responses.CloseStatementResponse.METADATA_FIELD_NUMBER);
+
+    public final RpcMetadataResponse rpcMetadata;
+
+    public CloseStatementResponse() {
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public CloseStatementResponse(@JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override CloseStatementResponse deserialize(Message genericMsg) {
+      final Responses.CloseStatementResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.CloseStatementResponse.class);
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new CloseStatementResponse(metadata);
+    }
+
+    @Override Responses.CloseStatementResponse serialize() {
+      Responses.CloseStatementResponse.Builder builder =
+          Responses.CloseStatementResponse.newBuilder();
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof CloseStatementResponse
+          && Objects.equals(rpcMetadata, ((CloseStatementResponse) o).rpcMetadata);
+    }
+  }
+
+  /** Request for
+   * {@link Meta#openConnection}. */
+  class OpenConnectionRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.OpenConnectionRequest
+        .getDescriptor().findFieldByNumber(
+            Requests.OpenConnectionRequest.CONNECTION_ID_FIELD_NUMBER);
+    public final String connectionId;
+    public final Map<String, String> info;
+
+    public OpenConnectionRequest() {
+      connectionId = null;
+      info = null;
+    }
+
+    @JsonCreator
+    public OpenConnectionRequest(@JsonProperty("connectionId") String connectionId,
+        @JsonProperty("info") Map<String, String> info) {
+      this.connectionId = connectionId;
+      this.info = info;
+    }
+
+    @Override OpenConnectionResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    /**
+     * Serializes the necessary properties into a Map.
+     *
+     * @param props The properties to serialize.
+     * @return A representation of the Properties as a Map.
+     */
+    public static Map<String, String> serializeProperties(Properties props) {
+      Map<String, String> infoAsString = new HashMap<>();
+      for (Map.Entry<Object, Object> entry : props.entrySet()) {
+        // Determine if this is a property we want to forward to the server
+        boolean localProperty = false;
+        for (BuiltInConnectionProperty prop : BuiltInConnectionProperty.values()) {
+          if (prop.camelName().equals(entry.getKey())) {
+            localProperty = true;
+            break;
+          }
+        }
+
+        if (!localProperty) {
+          infoAsString.put(entry.getKey().toString(), entry.getValue().toString());
+        }
+      }
+      return infoAsString;
+    }
+
+    @Override Request deserialize(Message genericMsg) {
+      final Requests.OpenConnectionRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.OpenConnectionRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      Map<String, String> info = msg.getInfo();
+      if (info.isEmpty()) {
+        info = null;
+      }
+
+      return new OpenConnectionRequest(connectionId, info);
+    }
+
+    @Override Message serialize() {
+      Requests.OpenConnectionRequest.Builder builder = Requests.OpenConnectionRequest.newBuilder();
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+      if (null != info) {
+        builder.getMutableInfo().putAll(info);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      result = p(result, info);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof OpenConnectionRequest
+          && Objects.equals(connectionId, ((OpenConnectionRequest) o).connectionId)
+          && Objects.equals(info, ((OpenConnectionRequest) o).info);
+    }
+  }
+
+  /** Response from
+   * {@link org.apache.calcite.avatica.remote.Service.OpenConnectionRequest}. */
+  class OpenConnectionResponse extends Response {
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.OpenConnectionResponse
+        .getDescriptor().findFieldByNumber(
+            Responses.OpenConnectionResponse.METADATA_FIELD_NUMBER);
+    public final RpcMetadataResponse rpcMetadata;
+
+    public OpenConnectionResponse() {
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public OpenConnectionResponse(@JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override OpenConnectionResponse deserialize(Message genericMsg) {
+      final Responses.OpenConnectionResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.OpenConnectionResponse.class);
+
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new OpenConnectionResponse(metadata);
+    }
+
+    @Override Responses.OpenConnectionResponse serialize() {
+      Responses.OpenConnectionResponse.Builder builder =
+          Responses.OpenConnectionResponse.newBuilder();
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof OpenConnectionResponse
+          && Objects.equals(rpcMetadata, ((OpenConnectionResponse) o).rpcMetadata);
+    }
+  }
+
+  /** Request for
+   * {@link Meta#closeConnection(org.apache.calcite.avatica.Meta.ConnectionHandle)}. */
+  class CloseConnectionRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.CloseConnectionRequest
+        .getDescriptor().findFieldByNumber(
+            Requests.CloseConnectionRequest.CONNECTION_ID_FIELD_NUMBER);
+    public final String connectionId;
+
+    CloseConnectionRequest() {
+      connectionId = null;
+    }
+
+    @JsonCreator
+    public CloseConnectionRequest(
+        @JsonProperty("connectionId") String connectionId) {
+      this.connectionId = connectionId;
+    }
+
+    @Override CloseConnectionResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override CloseConnectionRequest deserialize(Message genericMsg) {
+      final Requests.CloseConnectionRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.CloseConnectionRequest.class);
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      return new CloseConnectionRequest(connectionId);
+    }
+
+    @Override Requests.CloseConnectionRequest serialize() {
+      Requests.CloseConnectionRequest.Builder builder = Requests.CloseConnectionRequest
+          .newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connectionId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof CloseConnectionRequest
+          && Objects.equals(connectionId, ((CloseConnectionRequest) o).connectionId);
+    }
+  }
+
+  /** Response from
+   * {@link org.apache.calcite.avatica.remote.Service.CloseConnectionRequest}. */
+  class CloseConnectionResponse extends Response {
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.CloseConnectionResponse
+        .getDescriptor().findFieldByNumber(
+            Responses.CloseConnectionResponse.METADATA_FIELD_NUMBER);
+
+    public final RpcMetadataResponse rpcMetadata;
+
+    public CloseConnectionResponse() {
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public CloseConnectionResponse(@JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override CloseConnectionResponse deserialize(Message genericMsg) {
+      final Responses.CloseConnectionResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.CloseConnectionResponse.class);
+
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new CloseConnectionResponse(metadata);
+    }
+
+    @Override Responses.CloseConnectionResponse serialize() {
+      Responses.CloseConnectionResponse.Builder builder =
+          Responses.CloseConnectionResponse.newBuilder();
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof CloseConnectionResponse
+          && Objects.equals(rpcMetadata, ((CloseConnectionResponse) o).rpcMetadata);
+    }
+  }
+
+  /** Request for {@link Meta#connectionSync(Meta.ConnectionHandle, Meta.ConnectionProperties)}. */
+  class ConnectionSyncRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.ConnectionSyncRequest
+        .getDescriptor().findFieldByNumber(
+            Requests.ConnectionSyncRequest.CONNECTION_ID_FIELD_NUMBER);
+    private static final FieldDescriptor CONN_PROPS_DESCRIPTOR = Requests.ConnectionSyncRequest
+        .getDescriptor().findFieldByNumber(Requests.ConnectionSyncRequest.CONN_PROPS_FIELD_NUMBER);
+
+    public final String connectionId;
+    public final Meta.ConnectionProperties connProps;
+
+    ConnectionSyncRequest() {
+      connectionId = null;
+      connProps = null;
+    }
+
+    @JsonCreator
+    public ConnectionSyncRequest(
+        @JsonProperty("connectionId") String connectionId,
+        @JsonProperty("connProps") Meta.ConnectionProperties connProps) {
+      this.connectionId = connectionId;
+      this.connProps = connProps;
+    }
+
+    @Override ConnectionSyncResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    @Override ConnectionSyncRequest deserialize(Message genericMsg) {
+      final Requests.ConnectionSyncRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.ConnectionSyncRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      Meta.ConnectionProperties connProps = null;
+      if (msg.hasField(CONN_PROPS_DESCRIPTOR)) {
+        connProps = ConnectionPropertiesImpl.fromProto(msg.getConnProps());
+      }
+
+      return new ConnectionSyncRequest(connectionId, connProps);
+    }
+
+    @Override Requests.ConnectionSyncRequest serialize() {
+      Requests.ConnectionSyncRequest.Builder builder = Requests.ConnectionSyncRequest.newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      if (null != connProps) {
+        builder.setConnProps(connProps.toProto());
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connProps);
+      result = p(result, connectionId);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof ConnectionSyncRequest
+          && Objects.equals(connectionId, ((ConnectionSyncRequest) o).connectionId)
+          && Objects.equals(connProps, ((ConnectionSyncRequest) o).connProps);
+    }
+  }
+
+  /** Response for
+   * {@link Meta#connectionSync(Meta.ConnectionHandle, Meta.ConnectionProperties)}. */
+  class ConnectionSyncResponse extends Response {
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.ConnectionSyncResponse
+        .getDescriptor().findFieldByNumber(Responses.ConnectionSyncResponse.METADATA_FIELD_NUMBER);
+    public final Meta.ConnectionProperties connProps;
+    public final RpcMetadataResponse rpcMetadata;
+
+    ConnectionSyncResponse() {
+      connProps = null;
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public ConnectionSyncResponse(@JsonProperty("connProps") Meta.ConnectionProperties connProps,
+        @JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.connProps = connProps;
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override ConnectionSyncResponse deserialize(Message genericMsg) {
+      final Responses.ConnectionSyncResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.ConnectionSyncResponse.class);
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new ConnectionSyncResponse(ConnectionPropertiesImpl.fromProto(msg.getConnProps()),
+          metadata);
+    }
+
+    @Override Responses.ConnectionSyncResponse serialize() {
+      Responses.ConnectionSyncResponse.Builder builder = Responses.ConnectionSyncResponse
+          .newBuilder();
+
+      if (null != connProps) {
+        builder.setConnProps(connProps.toProto());
+      }
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, connProps);
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof ConnectionSyncResponse
+          && Objects.equals(connProps, ((ConnectionSyncResponse) o).connProps)
+          && Objects.equals(rpcMetadata, ((ConnectionSyncResponse) o).rpcMetadata);
+    }
+  }
+
+  /** Response for
+   * {@link Meta#getDatabaseProperties(Meta.ConnectionHandle)}. */
+  class DatabasePropertyResponse extends Response {
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.DatabasePropertyResponse
+        .getDescriptor().findFieldByNumber(
+            Responses.DatabasePropertyResponse.METADATA_FIELD_NUMBER);
+    public final Map<Meta.DatabaseProperty, Object> map;
+    public final RpcMetadataResponse rpcMetadata;
+
+    DatabasePropertyResponse() {
+      map = null;
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public DatabasePropertyResponse(@JsonProperty("map") Map<Meta.DatabaseProperty, Object> map,
+        @JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.map = map;
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    @Override DatabasePropertyResponse deserialize(Message genericMsg) {
+      final Responses.DatabasePropertyResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.DatabasePropertyResponse.class);
+      HashMap<Meta.DatabaseProperty, Object> properties = new HashMap<>();
+      for (Responses.DatabasePropertyElement property : msg.getPropsList()) {
+        final Meta.DatabaseProperty dbProp = Meta.DatabaseProperty.fromProto(property.getKey());
+        final Common.TypedValue value = property.getValue();
+
+        Object obj;
+        switch (dbProp) {
+        // Just need to keep parity with the exposed values on DatabaseProperty
+        case GET_NUMERIC_FUNCTIONS:
+        case GET_STRING_FUNCTIONS:
+        case GET_SYSTEM_FUNCTIONS:
+        case GET_TIME_DATE_FUNCTIONS:
+        case GET_S_Q_L_KEYWORDS:
+          // String
+          if (Common.Rep.STRING != value.getType()) {
+            throw new IllegalArgumentException("Expected STRING, but got " + value.getType());
+          }
+
+          obj = value.getStringValue();
+          break;
+        case GET_DEFAULT_TRANSACTION_ISOLATION:
+          // int
+          if (Common.Rep.INTEGER != value.getType()) {
+            throw new IllegalArgumentException("Expected INTEGER, but got " + value.getType());
+          }
+
+          obj = (int) value.getNumberValue();
+          break;
+        default:
+          throw new RuntimeException("Unhandled DatabaseProperty");
+        }
+
+        properties.put(dbProp, obj);
+      }
+
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new DatabasePropertyResponse(properties, metadata);
+    }
+
+    @Override Responses.DatabasePropertyResponse serialize() {
+      Responses.DatabasePropertyResponse.Builder builder = Responses.DatabasePropertyResponse
+          .newBuilder();
+
+      if (null != map) {
+        for (Entry<Meta.DatabaseProperty, Object> entry : map.entrySet()) {
+          Object obj = entry.getValue();
+
+          Common.TypedValue.Builder valueBuilder = Common.TypedValue.newBuilder();
+          switch (entry.getKey()) {
+          // Just need to keep parity with the exposed values on DatabaseProperty
+          case GET_NUMERIC_FUNCTIONS:
+          case GET_STRING_FUNCTIONS:
+          case GET_SYSTEM_FUNCTIONS:
+          case GET_TIME_DATE_FUNCTIONS:
+          case GET_S_Q_L_KEYWORDS:
+            // String
+            if (!(obj instanceof String)) {
+              throw new RuntimeException("Expected a String, but got " + obj.getClass());
+            }
+
+            valueBuilder.setType(Common.Rep.STRING).setStringValue((String) obj);
+            break;
+          case GET_DEFAULT_TRANSACTION_ISOLATION:
+            // int
+            if (!(obj instanceof Integer)) {
+              throw new RuntimeException("Expected an Integer, but got " + obj.getClass());
+            }
+
+            valueBuilder.setType(Common.Rep.INTEGER).setNumberValue(((Integer) obj).longValue());
+            break;
+          default:
+            throw new RuntimeException("Unhandled DatabaseProperty");
+          }
+
+          builder.addProps(Responses.DatabasePropertyElement.newBuilder()
+              .setKey(entry.getKey().toProto()).setValue(valueBuilder.build()));
+        }
+      }
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      return builder.build();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, map);
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return o == this
+          || o instanceof DatabasePropertyResponse
+          && Objects.equals(map, ((DatabasePropertyResponse) o).map)
+          && Objects.equals(rpcMetadata, ((DatabasePropertyResponse) o).rpcMetadata);
+    }
+  }
+
+  /**
+   * Response for any request that the server failed to successfully perform.
+   * It is used internally by the transport layers to format errors for
+   * transport over the wire. Thus, {@link Service#apply} will never return
+   * an ErrorResponse.
+   */
+  public class ErrorResponse extends Response {
+    private static final FieldDescriptor ERROR_MESSAGE_DESCRIPTOR = Responses.ErrorResponse
+        .getDescriptor().findFieldByNumber(
+            Responses.ErrorResponse.ERROR_MESSAGE_FIELD_NUMBER);
+    private static final FieldDescriptor SQL_DESCRIPTOR = Responses.ErrorResponse
+        .getDescriptor().findFieldByNumber(
+            Responses.ErrorResponse.SQL_STATE_FIELD_NUMBER);
+    private static final FieldDescriptor SEVERITY_DESCRIPTOR = Responses.ErrorResponse
+        .getDescriptor().findFieldByNumber(
+            Responses.ErrorResponse.SEVERITY_FIELD_NUMBER);
+    private static final FieldDescriptor METADATA_DESCRIPTOR = Responses.ErrorResponse
+        .getDescriptor().findFieldByNumber(
+            Responses.ErrorResponse.METADATA_FIELD_NUMBER);
+
+    public static final int UNKNOWN_ERROR_CODE = -1;
+    public static final int MISSING_CONNECTION_ERROR_CODE = 1;
+
+    public static final String UNKNOWN_SQL_STATE = "00000";
+
+    public final List<String> exceptions;
+    public final String errorMessage;
+    public final int errorCode;
+    public final String sqlState;
+    public final AvaticaSeverity severity;
+    public final RpcMetadataResponse rpcMetadata;
+
+    ErrorResponse() {
+      exceptions = Collections.singletonList("Unhandled exception");
+      errorMessage = "Unknown message";
+      errorCode = -1;
+      sqlState = UNKNOWN_SQL_STATE;
+      severity = AvaticaSeverity.UNKNOWN;
+      rpcMetadata = null;
+    }
+
+    @JsonCreator
+    public ErrorResponse(@JsonProperty("exceptions") List<String> exceptions,
+        @JsonProperty("errorMessage") String errorMessage,
+        @JsonProperty("errorCode") int errorCode,
+        @JsonProperty("sqlState") String sqlState,
+        @JsonProperty("severity") AvaticaSeverity severity,
+        @JsonProperty("rpcMetadata") RpcMetadataResponse rpcMetadata) {
+      this.exceptions = exceptions;
+      this.errorMessage = errorMessage;
+      this.errorCode = errorCode;
+      this.sqlState = sqlState;
+      this.severity = severity;
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    protected ErrorResponse(Exception e, String errorMessage, int code, String sqlState,
+        AvaticaSeverity severity, RpcMetadataResponse rpcMetadata) {
+      this(errorMessage, code, sqlState, severity, toStackTraces(e), rpcMetadata);
+    }
+
+    protected ErrorResponse(String errorMessage, int code, String sqlState,
+        AvaticaSeverity severity, List<String> exceptions, RpcMetadataResponse rpcMetadata) {
+      this.exceptions = exceptions;
+      this.errorMessage = errorMessage;
+      this.errorCode = code;
+      this.sqlState = sqlState;
+      this.severity = severity;
+      this.rpcMetadata = rpcMetadata;
+    }
+
+    static List<String> toStackTraces(Exception e) {
+      List<String> stackTraces = new ArrayList<>();
+      stackTraces.add(toString(e));
+      if (e instanceof SQLException) {
+        SQLException next = ((SQLException) e).getNextException();
+        while (null != next) {
+          stackTraces.add(toString(next));
+          next = next.getNextException();
+        }
+      }
+      return stackTraces;
+    }
+
+    static String toString(Exception e) {
+      //noinspection ThrowableResultOfMethodCallIgnored
+      Objects.requireNonNull(e);
+      StringWriter sw = new StringWriter();
+      e.printStackTrace(new PrintWriter(sw));
+      return sw.toString();
+    }
+
+    @Override ErrorResponse deserialize(Message genericMsg) {
+      final Responses.ErrorResponse msg = ProtobufService.castProtobufMessage(genericMsg,
+          Responses.ErrorResponse.class);
+      List<String> exceptions = null;
+      if (msg.getHasExceptions()) {
+        exceptions = msg.getExceptionsList();
+      }
+
+      String errorMessage = null;
+      if (msg.hasField(ERROR_MESSAGE_DESCRIPTOR)) {
+        errorMessage = msg.getErrorMessage();
+      }
+
+      String sqlState = null;
+      if (msg.hasField(SQL_DESCRIPTOR)) {
+        sqlState = msg.getSqlState();
+      }
+
+      AvaticaSeverity severity = null;
+      if (msg.hasField(SEVERITY_DESCRIPTOR)) {
+        severity = AvaticaSeverity.fromProto(msg.getSeverity());
+      }
+
+      RpcMetadataResponse metadata = null;
+      if (msg.hasField(METADATA_DESCRIPTOR)) {
+        metadata = RpcMetadataResponse.fromProto(msg.getMetadata());
+      }
+
+      return new ErrorResponse(exceptions, errorMessage, msg.getErrorCode(), sqlState, severity,
+          metadata);
+    }
+
+    @Override Responses.ErrorResponse serialize() {
+      Responses.ErrorResponse.Builder builder = Responses.ErrorResponse.newBuilder();
+
+      if (null != rpcMetadata) {
+        builder.setMetadata(rpcMetadata.serialize());
+      }
+
+      if (null != exceptions) {
+        builder.setHasExceptions(true);
+        builder.addAllExceptions(exceptions);
+      } else {
+        builder.setHasExceptions(false);
+      }
+
+      if (null != errorMessage) {
+        builder.setErrorMessage(errorMessage);
+      }
+
+      if (null != sqlState) {
+        builder.setSqlState(sqlState);
+      }
+
+      if (null != severity) {
+        builder.setSeverity(severity.toProto());
+      }
+
+      return builder.setErrorCode(errorCode).build();
+    }
+
+    @Override public String toString() {
+      StringBuilder sb = new StringBuilder(32);
+      sb.append("ErrorResponse[errorCode=").append(errorCode)
+          .append(", sqlState=").append(sqlState)
+          .append(", severity=").append(severity)
+          .append(", errorMessage=").append(errorMessage)
+          .append(", exceptions=").append(exceptions);
+      return sb.toString();
+    }
+
+    @Override public int hashCode() {
+      int result = 1;
+      result = p(result, exceptions);
+      result = p(result, errorMessage);
+      result = p(result, errorCode);
+      result = p(result, sqlState);
+      result = p(result, severity);
+      result = p(result, rpcMetadata);
+      return result;
+    }
+
+    @Override public boolean equals(Object o) {
+      return this == o
+          || o instanceof ErrorResponse
+          && errorCode == ((ErrorResponse) o).errorCode
+          && severity == ((ErrorResponse) o).severity
+          && Objects.equals(exceptions, ((ErrorResponse) o).exceptions)
+          && Objects.equals(errorMessage, ((ErrorResponse) o).errorMessage)
+          && Objects.equals(sqlState, ((ErrorResponse) o).sqlState)
+          && Objects.equals(rpcMetadata, ((ErrorResponse) o).rpcMetadata);
+    }
+
+    public AvaticaClientRuntimeException toException() {
+      return new AvaticaClientRuntimeException("Remote driver error: " + errorMessage, errorCode,
+          sqlState, severity, exceptions, rpcMetadata);
+    }
+  }
+
+  /**
+   * Request for {@link Service#apply(SyncResultsRequest)}
+   */
+  class SyncResultsRequest extends Request {
+    private static final FieldDescriptor CONNECTION_ID_DESCRIPTOR = Requests.SyncResultsRequest
+        .getDescriptor().findFieldByNumber(Requests.SyncResultsRequest.CONNECTION_ID_FIELD_NUMBER);
+    private static final FieldDescriptor STATEMENT_ID_DESCRIPTOR = Requests.SyncResultsRequest
+        .getDescriptor().findFieldByNumber(Requests.SyncResultsRequest.STATEMENT_ID_FIELD_NUMBER);
+    private static final FieldDescriptor STATE_DESCRIPTOR = Requests.SyncResultsRequest
+        .getDescriptor().findFieldByNumber(Requests.SyncResultsRequest.STATE_FIELD_NUMBER);
+    private static final FieldDescriptor OFFSET_DESCRIPTOR = Requests.SyncResultsRequest
+        .getDescriptor().findFieldByNumber(Requests.SyncResultsRequest.OFFSET_FIELD_NUMBER);
+    public final String connectionId;
+    public final int statementId;
+    public final QueryState state;
+    public final long offset;
+
+    SyncResultsRequest() {
+      this.connectionId = null;
+      this.statementId = 0;
+      this.state = null;
+      this.offset = 0L;
+    }
+
+    public SyncResultsRequest(@JsonProperty("connectionId") String connectionId,
+        @JsonProperty("statementId") int statementId, @JsonProperty("state") QueryState state,
+        @JsonProperty("offset") long offset) {
+      this.connectionId = connectionId;
+      this.statementId = statementId;
+      this.state = state;
+      this.offset = offset;
+    }
+
+    SyncResultsResponse accept(Service service) {
+      return service.apply(this);
+    }
+
+    Request deserialize(Message genericMsg) {
+      final Requests.SyncResultsRequest msg = ProtobufService.castProtobufMessage(genericMsg,
+          Requests.SyncResultsRequest.class);
+
+      String connectionId = null;
+      if (msg.hasField(CONNECTION_ID_DESCRIPTOR)) {
+        connectionId = msg.getConnectionId();
+      }
+
+      int statementId = 0;
+      if (msg.hasField(STATEMENT_ID_DESCRIPTOR)) {
+        statementId = msg.getStatementId();
+      }
+
+      Common.QueryState state = null;
+      if (msg.hasField(STATE_DESCRIPTOR)) {
+        state = msg.getState();
+      }
+
+      long offset = 0;
+      if (msg.hasField(OFFSET_DESCRIPTOR)) {
+        offset = msg.getOffset();
+      }
+
+      return new SyncResultsRequest(connectionId, statementId,
+          null == state ? null : QueryState.fromProto(msg.getState()), offset);
+    }
+
+    Requests.SyncResultsRequest serialize() {
+      Requests.SyncResultsRequest.Builder builder = Requests.SyncResultsRequest.newBuilder();
+
+      if (null != connectionId) {
+        builder.setConnectionId(connectionId);
+      }
+
+      if (null != state) {
+        builder.setState(state.toProto());
+      }

<TRUNCATED>