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:08 UTC
[30/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/test/java/org/apache/calcite/avatica/remote/ProtobufSerializationTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufSerializationTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufSerializationTest.java
new file mode 100644
index 0000000..cd8a329
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufSerializationTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.ColumnMetaData.Rep;
+import org.apache.calcite.avatica.Meta.Signature;
+import org.apache.calcite.avatica.Meta.StatementHandle;
+import org.apache.calcite.avatica.proto.Common.WireMessage;
+import org.apache.calcite.avatica.proto.Requests;
+import org.apache.calcite.avatica.remote.Service.Request;
+
+import com.google.protobuf.HBaseZeroCopyByteString;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Protobuf serialization tests.
+ */
+public class ProtobufSerializationTest {
+
+ private Signature getSignature() {
+ return null;
+ }
+
+ private List<TypedValue> getTypedValues() {
+ List<TypedValue> paramValues =
+ Arrays.asList(TypedValue.create(Rep.BOOLEAN.name(), Boolean.TRUE),
+ TypedValue.create(Rep.STRING.name(), "string"));
+ return paramValues;
+ }
+
+ @Test public void testExecuteSerialization() throws Exception {
+ Service.ExecuteRequest executeRequest = new Service.ExecuteRequest(
+ new StatementHandle("connection", 12345, getSignature()), getTypedValues(), 0);
+
+ Requests.ExecuteRequest pbExecuteRequest = executeRequest.serialize();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+ pbExecuteRequest.writeTo(baos);
+
+ byte[] serialized = baos.toByteArray();
+ baos.reset();
+ WireMessage wireMsg = WireMessage.newBuilder().setName(Requests.ExecuteRequest.class.getName())
+ .setWrappedMessage(HBaseZeroCopyByteString.wrap(serialized)).build();
+ wireMsg.writeTo(baos);
+ serialized = baos.toByteArray();
+
+ ProtobufTranslation translator = new ProtobufTranslationImpl();
+
+ Request newRequest = translator.parseRequest(serialized);
+
+ Assert.assertEquals(executeRequest, newRequest);
+ }
+
+}
+
+// End ProtobufSerializationTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufServiceTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufServiceTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufServiceTest.java
new file mode 100644
index 0000000..a29ee34
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufServiceTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.proto.Requests;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * Test class for ProtobufService.
+ */
+public class ProtobufServiceTest {
+
+ @Test public void testCastProtobufMessage() {
+ final Requests.CommitRequest commitReq =
+ Requests.CommitRequest.newBuilder().setConnectionId("cnxn1").build();
+ final Requests.RollbackRequest rollbackReq =
+ Requests.RollbackRequest.newBuilder().setConnectionId("cnxn1").build();
+
+ assertEquals(commitReq,
+ ProtobufService.castProtobufMessage(commitReq, Requests.CommitRequest.class));
+ assertEquals(rollbackReq,
+ ProtobufService.castProtobufMessage(rollbackReq, Requests.RollbackRequest.class));
+
+ try {
+ ProtobufService.castProtobufMessage(commitReq, Requests.RollbackRequest.class);
+ fail("Should have seen IllegalArgumentException casting CommitRequest into RollbackRequest");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+
+ try {
+ ProtobufService.castProtobufMessage(rollbackReq, Requests.CommitRequest.class);
+ fail("Should have seen IllegalArgumentException casting RollbackRequest into CommitRequest");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+ }
+}
+
+// End ProtobufServiceTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufTranslationImplTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufTranslationImplTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufTranslationImplTest.java
new file mode 100644
index 0000000..c75bdb0
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/ProtobufTranslationImplTest.java
@@ -0,0 +1,376 @@
+/*
+ * 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.AvaticaParameter;
+import org.apache.calcite.avatica.AvaticaSeverity;
+import org.apache.calcite.avatica.ColumnMetaData;
+import org.apache.calcite.avatica.ColumnMetaData.ArrayType;
+import org.apache.calcite.avatica.ColumnMetaData.Rep;
+import org.apache.calcite.avatica.ColumnMetaData.ScalarType;
+import org.apache.calcite.avatica.ConnectionPropertiesImpl;
+import org.apache.calcite.avatica.Meta;
+import org.apache.calcite.avatica.Meta.Frame;
+import org.apache.calcite.avatica.Meta.Signature;
+import org.apache.calcite.avatica.Meta.Style;
+import org.apache.calcite.avatica.MetaImpl;
+import org.apache.calcite.avatica.QueryState;
+import org.apache.calcite.avatica.remote.Service.CatalogsRequest;
+import org.apache.calcite.avatica.remote.Service.CloseConnectionRequest;
+import org.apache.calcite.avatica.remote.Service.CloseConnectionResponse;
+import org.apache.calcite.avatica.remote.Service.CloseStatementRequest;
+import org.apache.calcite.avatica.remote.Service.CloseStatementResponse;
+import org.apache.calcite.avatica.remote.Service.ColumnsRequest;
+import org.apache.calcite.avatica.remote.Service.CommitRequest;
+import org.apache.calcite.avatica.remote.Service.CommitResponse;
+import org.apache.calcite.avatica.remote.Service.ConnectionSyncRequest;
+import org.apache.calcite.avatica.remote.Service.ConnectionSyncResponse;
+import org.apache.calcite.avatica.remote.Service.CreateStatementRequest;
+import org.apache.calcite.avatica.remote.Service.CreateStatementResponse;
+import org.apache.calcite.avatica.remote.Service.DatabasePropertyRequest;
+import org.apache.calcite.avatica.remote.Service.DatabasePropertyResponse;
+import org.apache.calcite.avatica.remote.Service.ErrorResponse;
+import org.apache.calcite.avatica.remote.Service.ExecuteResponse;
+import org.apache.calcite.avatica.remote.Service.FetchRequest;
+import org.apache.calcite.avatica.remote.Service.FetchResponse;
+import org.apache.calcite.avatica.remote.Service.OpenConnectionRequest;
+import org.apache.calcite.avatica.remote.Service.OpenConnectionResponse;
+import org.apache.calcite.avatica.remote.Service.PrepareAndExecuteRequest;
+import org.apache.calcite.avatica.remote.Service.PrepareRequest;
+import org.apache.calcite.avatica.remote.Service.PrepareResponse;
+import org.apache.calcite.avatica.remote.Service.Request;
+import org.apache.calcite.avatica.remote.Service.Response;
+import org.apache.calcite.avatica.remote.Service.ResultSetResponse;
+import org.apache.calcite.avatica.remote.Service.RollbackRequest;
+import org.apache.calcite.avatica.remote.Service.RollbackResponse;
+import org.apache.calcite.avatica.remote.Service.RpcMetadataResponse;
+import org.apache.calcite.avatica.remote.Service.SchemasRequest;
+import org.apache.calcite.avatica.remote.Service.SyncResultsRequest;
+import org.apache.calcite.avatica.remote.Service.SyncResultsResponse;
+import org.apache.calcite.avatica.remote.Service.TableTypesRequest;
+import org.apache.calcite.avatica.remote.Service.TablesRequest;
+import org.apache.calcite.avatica.remote.Service.TypeInfoRequest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.sql.DatabaseMetaData;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests serialization of requests and response objects.
+ *
+ * @param <T> The object class being tested
+ */
+@RunWith(Parameterized.class)
+public class ProtobufTranslationImplTest<T> {
+
+ /**
+ * Simple function definition that acts as an identity.
+ *
+ * @param <A> Argument type
+ */
+ private interface IdentityFunction<A> {
+ A apply(A obj) throws IOException;
+ }
+
+ /**
+ * Identity function that accepts a request, serializes it to protobuf, and converts it back.
+ */
+ private static class RequestFunc implements IdentityFunction<Request> {
+ private final ProtobufTranslation translation;
+
+ public RequestFunc(ProtobufTranslation translation) {
+ this.translation = translation;
+ }
+
+ public Request apply(Request request) throws IOException {
+ // Serialize and then re-parse the request
+ return translation.parseRequest(translation.serializeRequest(request));
+ }
+ }
+
+ /**
+ * Identity function that accepts a response, serializes it to protobuf, and converts it back.
+ */
+ private static class ResponseFunc implements IdentityFunction<Response> {
+ private final ProtobufTranslation translation;
+
+ public ResponseFunc(ProtobufTranslation translation) {
+ this.translation = translation;
+ }
+
+ public Response apply(Response response) throws IOException {
+ // Serialize and then re-pare the response
+ return translation.parseResponse(translation.serializeResponse(response));
+ }
+ }
+
+ @Parameters
+ public static List<Object[]> parameters() {
+ List<Object[]> params = new ArrayList<>();
+
+ // The impl we're testing
+ ProtobufTranslationImpl translation = new ProtobufTranslationImpl();
+
+ // Identity transformation for Requests
+ RequestFunc requestFunc = new RequestFunc(translation);
+ // Identity transformation for Responses
+ ResponseFunc responseFunc = new ResponseFunc(translation);
+
+ List<Request> requests = getRequests();
+ List<Request> requestsWithNulls = getRequestsWithNulls();
+ List<Response> responses = getResponses();
+
+ // Requests
+ for (Request request : requests) {
+ params.add(new Object[] {request, requestFunc});
+ }
+
+ // Requests with nulls in parameters
+ for (Request request : requestsWithNulls) {
+ params.add(new Object[] {request, requestFunc});
+ }
+
+ // Responses
+ for (Response response : responses) {
+ params.add(new Object[] {response, responseFunc});
+ }
+
+ return params;
+ }
+
+ /**
+ * Generates a collection of Requests whose serialization will be tested.
+ */
+ private static List<Request> getRequests() {
+ LinkedList<Request> requests = new LinkedList<>();
+
+ requests.add(new CatalogsRequest());
+ requests.add(new DatabasePropertyRequest());
+ requests.add(new SchemasRequest("connectionId", "catalog", "schemaPattern"));
+ requests.add(
+ new TablesRequest("connectionId", "catalog", "schemaPattern", "tableNamePattern",
+ Arrays.asList("STRING", "BOOLEAN", "INT")));
+ requests.add(new TableTypesRequest());
+ requests.add(
+ new ColumnsRequest("connectionId", "catalog", "schemaPattern", "tableNamePattern",
+ "columnNamePattern"));
+ requests.add(new TypeInfoRequest());
+ requests.add(
+ new PrepareAndExecuteRequest("connectionId", Integer.MAX_VALUE, "sql",
+ Long.MAX_VALUE));
+ requests.add(new PrepareRequest("connectionId", "sql", Long.MAX_VALUE));
+
+ List<TypedValue> paramValues =
+ Arrays.asList(TypedValue.create(Rep.BOOLEAN.name(), Boolean.TRUE),
+ TypedValue.create(Rep.STRING.name(), "string"));
+ FetchRequest fetchRequest = new FetchRequest("connectionId", Integer.MAX_VALUE,
+ Long.MAX_VALUE, Integer.MAX_VALUE);
+ requests.add(fetchRequest);
+
+ requests.add(new CreateStatementRequest("connectionId"));
+ requests.add(new CloseStatementRequest("connectionId", Integer.MAX_VALUE));
+ Map<String, String> info = new HashMap<>();
+ info.put("param1", "value1");
+ info.put("param2", "value2");
+ requests.add(new OpenConnectionRequest("connectionId", info));
+ requests.add(new CloseConnectionRequest("connectionId"));
+ requests.add(
+ new ConnectionSyncRequest("connectionId",
+ new ConnectionPropertiesImpl(Boolean.FALSE, Boolean.FALSE,
+ Integer.MAX_VALUE, "catalog", "schema")));
+
+ requests.add(new SyncResultsRequest("connectionId", 12345, getSqlQueryState(), 150));
+ requests.add(new SyncResultsRequest("connectionId2", 54321, getMetadataQueryState1(), 0));
+ requests.add(new SyncResultsRequest("connectionId3", 5, getMetadataQueryState2(), 10));
+
+ requests.add(new CommitRequest("connectionId"));
+ requests.add(new RollbackRequest("connectionId"));
+
+ return requests;
+ }
+
+ private static QueryState getSqlQueryState() {
+ return new QueryState("SELECT * from TABLE");
+ }
+
+ private static QueryState getMetadataQueryState1() {
+ return new QueryState(MetaDataOperation.GET_COLUMNS, new Object[] {
+ "",
+ null,
+ "%",
+ "%"
+ });
+ }
+
+ private static QueryState getMetadataQueryState2() {
+ return new QueryState(MetaDataOperation.GET_CATALOGS, new Object[0]);
+ }
+
+ private static List<Request> getRequestsWithNulls() {
+ LinkedList<Request> requests = new LinkedList<>();
+
+ // We're pretty fast and loose on what can be null.
+ requests.add(new SchemasRequest(null, null, null));
+ // Repeated fields default to an empty list
+ requests.add(new TablesRequest(null, null, null, null, Collections.<String>emptyList()));
+ requests.add(new ColumnsRequest(null, null, null, null, null));
+ requests.add(new PrepareAndExecuteRequest(null, 0, null, 0));
+ requests.add(new PrepareRequest(null, null, 0));
+ requests.add(new CreateStatementRequest(null));
+ requests.add(new CloseStatementRequest(null, 0));
+ requests.add(new OpenConnectionRequest(null, null));
+ requests.add(new CloseConnectionRequest(null));
+ requests.add(new ConnectionSyncRequest(null, null));
+
+ return requests;
+ }
+
+ private static ColumnMetaData getArrayColumnMetaData(ScalarType componentType, int index,
+ String name) {
+ ArrayType arrayType = ColumnMetaData.array(componentType, "Array", Rep.ARRAY);
+ return new ColumnMetaData(
+ index, false, true, false, false, DatabaseMetaData.columnNullable,
+ true, -1, name, name, null,
+ 0, 0, null, null, arrayType, true, false, false,
+ "ARRAY");
+ }
+
+ /**
+ * Generates a collection of Responses whose serialization will be tested.
+ */
+ private static List<Response> getResponses() {
+ final RpcMetadataResponse rpcMetadata = new RpcMetadataResponse("localhost:8765");
+ LinkedList<Response> responses = new LinkedList<>();
+
+ // Nested classes (Signature, ColumnMetaData, CursorFactory, etc) are implicitly getting tested)
+
+ // Stub out the metadata for a row
+ ScalarType arrayComponentType = ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER);
+ ColumnMetaData arrayColumnMetaData = getArrayColumnMetaData(arrayComponentType, 2, "counts");
+ List<ColumnMetaData> columns =
+ Arrays.asList(MetaImpl.columnMetaData("str", 0, String.class),
+ MetaImpl.columnMetaData("count", 1, Integer.class),
+ arrayColumnMetaData);
+ List<AvaticaParameter> params =
+ Arrays.asList(
+ new AvaticaParameter(false, 10, 0, Types.VARCHAR, "VARCHAR",
+ String.class.getName(), "str"));
+ Meta.CursorFactory cursorFactory = Meta.CursorFactory.create(Style.LIST, Object.class,
+ Arrays.asList("str", "count", "counts"));
+ // The row values
+ List<Object> rows = new ArrayList<>();
+ rows.add(new Object[] {"str_value1", 50, Arrays.asList(1, 2, 3)});
+ rows.add(new Object[] {"str_value2", 100, Arrays.asList(1)});
+
+ // Create the signature and frame using the metadata and values
+ Signature signature = Signature.create(columns, "sql", params, cursorFactory,
+ Meta.StatementType.SELECT);
+ Frame frame = Frame.create(Integer.MAX_VALUE, true, rows);
+
+ // And then create a ResultSetResponse
+ ResultSetResponse results1 = new ResultSetResponse("connectionId", Integer.MAX_VALUE, true,
+ signature, frame, Long.MAX_VALUE, rpcMetadata);
+ responses.add(results1);
+
+ responses.add(new CloseStatementResponse(rpcMetadata));
+
+ ConnectionPropertiesImpl connProps = new ConnectionPropertiesImpl(false, true,
+ Integer.MAX_VALUE, "catalog", "schema");
+ responses.add(new ConnectionSyncResponse(connProps, rpcMetadata));
+
+ responses.add(new OpenConnectionResponse(rpcMetadata));
+ responses.add(new CloseConnectionResponse(rpcMetadata));
+
+ responses.add(new CreateStatementResponse("connectionId", Integer.MAX_VALUE, rpcMetadata));
+
+ Map<Meta.DatabaseProperty, Object> propertyMap = new HashMap<>();
+ for (Meta.DatabaseProperty prop : Meta.DatabaseProperty.values()) {
+ propertyMap.put(prop, prop.defaultValue);
+ }
+ responses.add(new DatabasePropertyResponse(propertyMap, rpcMetadata));
+
+ responses.add(
+ new ExecuteResponse(Arrays.asList(results1, results1, results1), false, rpcMetadata));
+ responses.add(new FetchResponse(frame, false, false, rpcMetadata));
+ responses.add(new FetchResponse(frame, true, true, rpcMetadata));
+ responses.add(new FetchResponse(frame, false, true, rpcMetadata));
+ responses.add(
+ new PrepareResponse(
+ new Meta.StatementHandle("connectionId", Integer.MAX_VALUE, signature),
+ rpcMetadata));
+
+ StringWriter sw = new StringWriter();
+ new Exception().printStackTrace(new PrintWriter(sw));
+ responses.add(
+ new ErrorResponse(Collections.singletonList(sw.toString()), "Test Error Message",
+ ErrorResponse.UNKNOWN_ERROR_CODE, ErrorResponse.UNKNOWN_SQL_STATE,
+ AvaticaSeverity.WARNING, rpcMetadata));
+
+ // No more results, statement not missing
+ responses.add(new SyncResultsResponse(false, false, rpcMetadata));
+ // Missing statement, no results
+ responses.add(new SyncResultsResponse(false, true, rpcMetadata));
+ // More results, no missing statement
+ responses.add(new SyncResultsResponse(true, false, rpcMetadata));
+
+ // Some tests to make sure ErrorResponse doesn't fail.
+ responses.add(new ErrorResponse((List<String>) null, null, 0, null, null, null));
+ responses.add(
+ new ErrorResponse(Arrays.asList("stacktrace1", "stacktrace2"), null, 0, null, null, null));
+
+ responses.add(new CommitResponse());
+ responses.add(new RollbackResponse());
+
+ return responses;
+ }
+
+ private final T object;
+ private final IdentityFunction<T> function;
+
+ public ProtobufTranslationImplTest(T object, IdentityFunction<T> func) {
+ this.object = object;
+ this.function = func;
+ }
+
+ @Test
+ public void testSerialization() throws Exception {
+ // Function acts as opposite sides of the transport.
+ // An object (a request or response) starts on one side
+ // of the transport, serialized, "sent" over the transport
+ // and then reconstituted. The object on either side should
+ // be equivalent.
+ assertEquals(object, this.function.apply(object));
+ }
+}
+
+// End ProtobufTranslationImplTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java
new file mode 100644
index 0000000..28fe6f6
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.ColumnMetaData.Rep;
+import org.apache.calcite.avatica.util.ByteString;
+
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test serialization of TypedValue.
+ */
+public class TypedValueTest {
+
+ private void serializeAndEqualityCheck(TypedValue value) {
+ TypedValue copy = TypedValue.fromProto(value.toProto());
+
+ assertEquals(value.type, copy.type);
+ assertEquals(value.value, copy.value);
+ }
+
+ @Test
+ public void testBoolean() {
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.PRIMITIVE_BOOLEAN, true));
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.BOOLEAN, Boolean.TRUE));
+ }
+
+ @Test
+ public void testByte() {
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.PRIMITIVE_BYTE, (byte) 4));
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.BYTE, Byte.valueOf((byte) 4)));
+ }
+
+ @Test
+ public void testShort() {
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.PRIMITIVE_SHORT, (short) 42));
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.SHORT, Short.valueOf((short) 42)));
+ }
+
+ @Test
+ public void testInteger() {
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.PRIMITIVE_INT, (int) 42000));
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.INTEGER, Integer.valueOf((int) 42000)));
+ }
+
+ @Test
+ public void testLong() {
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.PRIMITIVE_LONG, Long.MAX_VALUE));
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.LONG, Long.valueOf(Long.MAX_VALUE)));
+ }
+
+ @Test
+ public void testFloat() {
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.PRIMITIVE_FLOAT, 3.14159f));
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.FLOAT, Float.valueOf(3.14159f)));
+ }
+
+ @Test
+ public void testDouble() {
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.PRIMITIVE_DOUBLE, Double.MAX_VALUE));
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.DOUBLE, Double.valueOf(Double.MAX_VALUE)));
+ }
+
+ @Test
+ public void testChar() {
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.PRIMITIVE_CHAR, 'c'));
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.CHARACTER, Character.valueOf('c')));
+ }
+
+ @Test
+ public void testString() {
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.STRING, "qwertyasdf"));
+ }
+
+ @Test
+ public void testByteString() {
+ serializeAndEqualityCheck(
+ TypedValue.ofLocal(Rep.BYTE_STRING,
+ new ByteString("qwertyasdf".getBytes(StandardCharsets.UTF_8))));
+ }
+
+ @Test
+ public void testSqlDate() {
+ // days since epoch
+ serializeAndEqualityCheck(TypedValue.ofLocal(Rep.JAVA_SQL_DATE, 25));
+ }
+
+ @Test
+ public void testUtilDate() {
+ serializeAndEqualityCheck(
+ TypedValue.ofLocal(Rep.JAVA_UTIL_DATE, System.currentTimeMillis()));
+ }
+
+ @Test
+ public void testSqlTime() {
+ // millis since epoch
+ serializeAndEqualityCheck(
+ TypedValue.ofLocal(Rep.JAVA_SQL_TIME, 42 * 1024 * 1024));
+ }
+
+ @Test
+ public void testSqlTimestamp() {
+ serializeAndEqualityCheck(
+ TypedValue.ofLocal(Rep.JAVA_SQL_TIMESTAMP, 42L * 1024 * 1024 * 1024));
+ }
+}
+
+// End TypedValueTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaClientRuntimeExceptionTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaClientRuntimeExceptionTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaClientRuntimeExceptionTest.java
new file mode 100644
index 0000000..411f29c
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaClientRuntimeExceptionTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.test;
+
+import org.apache.calcite.avatica.AvaticaClientRuntimeException;
+import org.apache.calcite.avatica.AvaticaSeverity;
+import org.apache.calcite.avatica.remote.Service.RpcMetadataResponse;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test class for {@link AvaticaClientRuntimeException}.
+ */
+public class AvaticaClientRuntimeExceptionTest {
+
+ @Test public void testGetters() {
+ final String errorMsg = "My error message";
+ final int errorCode = 10;
+ final String sqlState = "abc12";
+ final AvaticaSeverity severity = AvaticaSeverity.ERROR;
+ final List<String> stacktraces = Arrays.asList("my stack trace");
+ final RpcMetadataResponse metadata = new RpcMetadataResponse("localhost:8765");
+ AvaticaClientRuntimeException e = new AvaticaClientRuntimeException(errorMsg, errorCode,
+ sqlState, severity, stacktraces, metadata);
+ assertEquals(errorMsg, e.getMessage());
+ assertEquals(errorCode, e.getErrorCode());
+ assertEquals(severity, e.getSeverity());
+ assertEquals(stacktraces, e.getServerExceptions());
+ assertEquals(metadata, e.getRpcMetadata());
+ }
+
+}
+
+// End AvaticaClientRuntimeExceptionTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaSeverityTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaSeverityTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaSeverityTest.java
new file mode 100644
index 0000000..945f959
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaSeverityTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.test;
+
+import org.apache.calcite.avatica.AvaticaSeverity;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for {@link AvaticaSeverity}.
+ */
+public class AvaticaSeverityTest {
+
+ @Test
+ public void testProtobufSerialization() {
+ for (AvaticaSeverity severity : AvaticaSeverity.values()) {
+ assertEquals(severity, AvaticaSeverity.fromProto(severity.toProto()));
+ }
+ }
+
+}
+
+// End AvaticaSeverityTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaSqlExceptionTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaSqlExceptionTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaSqlExceptionTest.java
new file mode 100644
index 0000000..3d7b5b0
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaSqlExceptionTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.test;
+
+import org.apache.calcite.avatica.AvaticaSqlException;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link AvaticaSqlException}.
+ */
+public class AvaticaSqlExceptionTest {
+
+ @Test public void testGetters() {
+ final String msg = "My query failed!";
+ final int code = 42;
+ final String sql = "SELECT foo FROM bar;";
+ final String stacktrace = "My Stack Trace";
+ final String server = "localhost:8765";
+
+ AvaticaSqlException e = new AvaticaSqlException(msg, sql, code, Arrays.asList(stacktrace),
+ server);
+ assertTrue(e.getMessage().contains(msg));
+ assertEquals(code, e.getErrorCode());
+ assertEquals(sql, e.getSQLState());
+ assertEquals(1, e.getStackTraces().size());
+ assertEquals(stacktrace, e.getStackTraces().get(0));
+ assertEquals(server, e.getRemoteServer());
+ }
+
+}
+
+// End AvaticaSqlExceptionTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaUtilsTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaUtilsTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaUtilsTest.java
new file mode 100644
index 0000000..850cbfd
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaUtilsTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.test;
+
+import org.apache.calcite.avatica.AvaticaUtils;
+
+import org.junit.Test;
+
+import java.math.BigInteger;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * Unit test for Avatica utilities.
+ */
+public class AvaticaUtilsTest {
+ @Test public void testInstantiatePlugin() {
+ final String s =
+ AvaticaUtils.instantiatePlugin(String.class, "java.lang.String");
+ assertThat(s, is(""));
+
+ // No default constructor or INSTANCE member
+ try {
+ final Integer i =
+ AvaticaUtils.instantiatePlugin(Integer.class, "java.lang.Integer");
+ fail("expected error, got " + i);
+ } catch (Throwable e) {
+ assertThat(e.getMessage(),
+ is("Property 'java.lang.Integer' not valid for plugin type java.lang.Integer"));
+ }
+
+ final BigInteger b =
+ AvaticaUtils.instantiatePlugin(BigInteger.class, "java.math.BigInteger#ONE");
+ assertThat(b, is(BigInteger.ONE));
+
+ try {
+ final BigInteger b2 =
+ AvaticaUtils.instantiatePlugin(BigInteger.class,
+ "java.math.BigInteger.ONE");
+ fail("expected error, got " + b2);
+ } catch (Throwable e) {
+ assertThat(e.getMessage(),
+ is("Property 'java.math.BigInteger.ONE' not valid for plugin type java.math.BigInteger"));
+ }
+ }
+
+ /** Unit test for
+ * {@link org.apache.calcite.avatica.AvaticaUtils#unique(java.lang.String)}. */
+ @Test public void testUnique() {
+ // Below, the "probably" comments indicate the strings that will be
+ // generated the first time you run the test.
+ final Set<String> list = new LinkedHashSet<>();
+ list.add(AvaticaUtils.unique("a")); // probably "a"
+ assertThat(list.size(), is(1));
+ list.add(AvaticaUtils.unique("a")); // probably "a_1"
+ assertThat(list.size(), is(2));
+ list.add(AvaticaUtils.unique("b")); // probably "b"
+ assertThat(list.size(), is(3));
+ list.add(AvaticaUtils.unique("a_1")); // probably "a_1_3"
+ assertThat(list.size(), is(4));
+ list.add(AvaticaUtils.unique("A")); // probably "A"
+ assertThat(list.size(), is(5));
+ list.add(AvaticaUtils.unique("a")); // probably "a_5"
+ assertThat(list.size(), is(6));
+ }
+}
+
+// End AvaticaUtilsTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/test/ConnectStringParserTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/test/ConnectStringParserTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/test/ConnectStringParserTest.java
new file mode 100644
index 0000000..cdc8d8a
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/test/ConnectStringParserTest.java
@@ -0,0 +1,255 @@
+/*
+ * 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.test;
+
+import org.apache.calcite.avatica.ConnectStringParser;
+
+import org.junit.Test;
+
+import java.sql.SQLException;
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+/**
+ * Unit test for JDBC connect string parser, {@link ConnectStringParser}. The
+ * ConnectStringParser is adapted from code in Mondrian, but most of the tests
+ * below were unfortunately "reinvented" prior to having the Mondrian unit tests
+ * in hand.
+ */
+public class ConnectStringParserTest {
+ /**
+ * Tests simple connect string. Adapted from Mondrian tests.
+ */
+ @Test public void testSimpleStrings() throws Throwable {
+ Properties props = ConnectStringParser.parse("foo=x;bar=y;foo=z");
+ assertEquals(
+ "bar",
+ "y",
+ props.get("bar"));
+ assertNull(
+ "BAR",
+ props.get("BAR")); // case-sensitive, unlike Mondrian
+ assertEquals(
+ "last foo",
+ "z",
+ props.get("foo"));
+ assertNull(
+ "key=\" bar\"",
+ props.get(" bar"));
+ assertNull(
+ "bogus key",
+ props.get("kipper"));
+ assertEquals(
+ "param count",
+ 2,
+ props.size());
+
+ String synth = ConnectStringParser.getParamString(props);
+ Properties synthProps = ConnectStringParser.parse(synth);
+ assertEquals("reversible", props, synthProps);
+ }
+
+ /**
+ * Tests complex connect strings. Adapted directly from Mondrian tests.
+ */
+ @Test public void testComplexStrings() throws Throwable {
+ Properties props =
+ ConnectStringParser.parse("normalProp=value;"
+ + "emptyValue=;"
+ + " spaceBeforeProp=abc;"
+ + " spaceBeforeAndAfterProp =def;"
+ + " space in prop = foo bar ;"
+ + "equalsInValue=foo=bar;"
+ + "semiInProp;Name=value;"
+ + " singleQuotedValue = 'single quoted value ending in space ' ;"
+ + " doubleQuotedValue = "
+ + "\"=double quoted value preceded by equals\" ;"
+ + " singleQuotedValueWithSemi = 'one; two';"
+ + " singleQuotedValueWithSpecials = 'one; two \"three''four=five'");
+
+ assertEquals(
+ "param count",
+ 11,
+ props.size());
+
+ String value;
+ value = (String) props.get("normalProp");
+ assertEquals("value", value);
+ value = (String) props.get("emptyValue");
+ assertEquals("", value); // empty string, not null!
+ value = (String) props.get("spaceBeforeProp");
+ assertEquals("abc", value);
+ value = (String) props.get("spaceBeforeAndAfterProp");
+ assertEquals("def", value);
+ value = (String) props.get("space in prop");
+ assertEquals(value, "foo bar");
+ value = (String) props.get("equalsInValue");
+ assertEquals("foo=bar", value);
+ value = (String) props.get("semiInProp;Name");
+ assertEquals("value", value);
+ value = (String) props.get("singleQuotedValue");
+ assertEquals("single quoted value ending in space ", value);
+ value = (String) props.get("doubleQuotedValue");
+ assertEquals("=double quoted value preceded by equals", value);
+ value = (String) props.get("singleQuotedValueWithSemi");
+ assertEquals(value, "one; two");
+ value = (String) props.get("singleQuotedValueWithSpecials");
+ assertEquals(value, "one; two \"three'four=five");
+ }
+
+ /**
+ * Tests for specific errors thrown by the parser.
+ */
+ @Test public void testConnectStringErrors() throws Throwable {
+ // force some parsing errors
+ try {
+ ConnectStringParser.parse("key='can't parse'");
+ fail("quoted value ended too soon");
+ } catch (SQLException e) {
+ assertExceptionMatches(e, ".*quoted value ended.*position 9.*");
+ }
+
+ try {
+ ConnectStringParser.parse("key='\"can''t parse\"");
+ fail("unterminated quoted value");
+ } catch (SQLException e) {
+ assertExceptionMatches(e, ".*unterminated quoted value.*");
+ }
+ }
+
+ /**
+ * Tests most of the examples from the <a
+ * href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/oledb/htm/oledbconnectionstringsyntax.asp">
+ * OLE DB spec</a>. Omitted are cases for Window handles, returning multiple
+ * values, and special handling of "Provider" keyword.
+ */
+ @Test public void testOleDbExamples() throws Throwable {
+ // test the parser with examples from OLE DB documentation
+ Quad[] quads = {
+ // {reason for test, key, val, string to parse},
+ new Quad(
+ "printable chars",
+ "Jet OLE DB:System Database", "c:\\system.mda",
+ "Jet OLE DB:System Database=c:\\system.mda"),
+ new Quad(
+ "key embedded semi",
+ "Authentication;Info", "Column 5",
+ "Authentication;Info=Column 5"),
+ new Quad(
+ "key embedded equal",
+ "Verification=Security", "True",
+ "Verification==Security=True"),
+ new Quad(
+ "key many equals",
+ "Many==One", "Valid",
+ "Many====One=Valid"),
+ new Quad(
+ "key too many equal",
+ "TooMany=", "False",
+ "TooMany===False"),
+ new Quad(
+ "value embedded quote and semi",
+ "ExtProps", "Data Source='localhost';Key Two='value 2'",
+ "ExtProps=\"Data Source='localhost';Key Two='value 2'\""),
+ new Quad(
+ "value embedded double quote and semi",
+ "ExtProps", "Integrated Security=\"SSPI\";Key Two=\"value 2\"",
+ "ExtProps='Integrated Security=\"SSPI\";Key Two=\"value 2\"'"),
+ new Quad(
+ "value double quoted",
+ "DataSchema", "\"MyCustTable\"",
+ "DataSchema='\"MyCustTable\"'"),
+ new Quad(
+ "value single quoted",
+ "DataSchema", "'MyCustTable'",
+ "DataSchema=\"'MyCustTable'\""),
+ new Quad(
+ "value double quoted double trouble",
+ "Caption", "\"Company's \"new\" customer\"",
+ "Caption=\"\"\"Company's \"\"new\"\" customer\"\"\""),
+ new Quad(
+ "value single quoted double trouble",
+ "Caption", "\"Company's \"new\" customer\"",
+ "Caption='\"Company''s \"new\" customer\"'"),
+ new Quad(
+ "embedded blanks and trim",
+ "My Keyword", "My Value",
+ " My Keyword = My Value ;MyNextValue=Value"),
+ new Quad(
+ "value single quotes preserve blanks",
+ "My Keyword", " My Value ",
+ " My Keyword =' My Value ';MyNextValue=Value"),
+ new Quad(
+ "value double quotes preserve blanks",
+ "My Keyword", " My Value ",
+ " My Keyword =\" My Value \";MyNextValue=Value"),
+ new Quad(
+ "last redundant key wins",
+ "SomeKey", "NextValue",
+ "SomeKey=FirstValue;SomeKey=NextValue"),
+ };
+ for (Quad quad : quads) {
+ Properties props = ConnectStringParser.parse(quad.str);
+
+ assertEquals(quad.why, quad.val, props.get(quad.key));
+ String synth = ConnectStringParser.getParamString(props);
+
+ try {
+ assertEquals("reversible " + quad.why, quad.str, synth);
+ } catch (Throwable e) {
+ // it's OK that the strings don't match as long as the
+ // two strings parse out the same way and are thus
+ // "semantically reversible"
+ Properties synthProps = ConnectStringParser.parse(synth);
+ assertEquals("equivalent " + quad.why, props, synthProps);
+ }
+ }
+ }
+
+ static void assertExceptionMatches(
+ Throwable e,
+ String expectedPattern) {
+ if (e == null) {
+ fail("Expected an error which matches pattern '" + expectedPattern + "'");
+ }
+ String msg = e.toString();
+ if (!msg.matches(expectedPattern)) {
+ fail("Got a different error '" + msg + "' than expected '"
+ + expectedPattern + "'");
+ }
+ }
+
+ /** Collection of values comprising a test. */
+ static class Quad {
+ private final String why;
+ private final String key;
+ private final String val;
+ private final String str;
+
+ Quad(String why, String key, String val, String str) {
+ this.why = why;
+ this.key = key;
+ this.val = val;
+ this.str = str;
+ }
+ }
+}
+
+// End ConnectStringParserTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/test/JsonHandlerTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/test/JsonHandlerTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/test/JsonHandlerTest.java
new file mode 100644
index 0000000..57cf60a
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/test/JsonHandlerTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.test;
+
+import org.apache.calcite.avatica.AvaticaParameter;
+import org.apache.calcite.avatica.ColumnMetaData;
+import org.apache.calcite.avatica.Meta;
+import org.apache.calcite.avatica.Meta.CursorFactory;
+import org.apache.calcite.avatica.metrics.noop.NoopMetricsSystem;
+import org.apache.calcite.avatica.remote.JsonHandler;
+import org.apache.calcite.avatica.remote.JsonService;
+import org.apache.calcite.avatica.remote.LocalJsonService;
+import org.apache.calcite.avatica.remote.Service;
+import org.apache.calcite.avatica.remote.TypedValue;
+
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.UUID;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests JSON encoding/decoding in the remote service.
+ */
+public class JsonHandlerTest {
+
+ private static final Random RANDOM = new Random();
+
+ /**
+ * Implementation of {@link org.apache.calcite.avatica.remote.Service}
+ * that does nothing.
+ */
+ public static class NoopService implements Service {
+ @Override public ResultSetResponse apply(CatalogsRequest request) {
+ return null;
+ }
+
+ @Override public ResultSetResponse apply(SchemasRequest request) {
+ return null;
+ }
+
+ @Override public ResultSetResponse apply(TablesRequest request) {
+ return null;
+ }
+
+ @Override public ResultSetResponse apply(TableTypesRequest request) {
+ return null;
+ }
+
+ @Override public ResultSetResponse apply(TypeInfoRequest request) {
+ return null;
+ }
+
+ @Override public ResultSetResponse apply(ColumnsRequest request) {
+ return null;
+ }
+
+ @Override public PrepareResponse apply(PrepareRequest request) {
+ return null;
+ }
+
+ @Override public ExecuteResponse apply(PrepareAndExecuteRequest request) {
+ return null;
+ }
+
+ @Override public FetchResponse apply(FetchRequest request) {
+ return null;
+ }
+
+ @Override public CreateStatementResponse apply(CreateStatementRequest request) {
+ return null;
+ }
+
+ @Override public CloseStatementResponse apply(CloseStatementRequest request) {
+ return null;
+ }
+
+ @Override public OpenConnectionResponse apply(OpenConnectionRequest request) {
+ return null;
+ }
+
+ @Override public CloseConnectionResponse apply(CloseConnectionRequest request) {
+ return null;
+ }
+
+ @Override public ConnectionSyncResponse apply(ConnectionSyncRequest request) {
+ return null;
+ }
+
+ @Override public DatabasePropertyResponse apply(DatabasePropertyRequest request) {
+ return null;
+ }
+
+ @Override public SyncResultsResponse apply(SyncResultsRequest request) {
+ return null;
+ }
+
+ @Override public ExecuteResponse apply(ExecuteRequest request) {
+ return null;
+ }
+
+ @Override public void setRpcMetadata(RpcMetadataResponse metadata) {}
+
+ @Override public CommitResponse apply(CommitRequest request) {
+ return null;
+ }
+
+ @Override public RollbackResponse apply(RollbackRequest request) {
+ return null;
+ }
+ }
+
+ /**
+ * Instrumented subclass of {@link org.apache.calcite.avatica.test.JsonHandlerTest.NoopService}
+ * that checks the parameter values passed to the "execute" request.
+ *
+ * <p>Note: parameter values for "fetch" request deprecated.
+ */
+ public static class ParameterValuesCheckingService extends NoopService {
+
+ final List<TypedValue> expectedParameterValues;
+
+ public ParameterValuesCheckingService(List<TypedValue> epv) {
+ expectedParameterValues = epv;
+ }
+
+ @Override public ExecuteResponse apply(ExecuteRequest request) {
+ expectedParameterValues.addAll(request.parameterValues);
+
+ final Meta.Signature signature =
+ new Meta.Signature(Collections.<ColumnMetaData>emptyList(),
+ "SELECT 1 FROM VALUE()",
+ Collections.<AvaticaParameter>emptyList(),
+ Collections.<String, Object>emptyMap(),
+ CursorFactory.LIST, Meta.StatementType.SELECT);
+
+ final Service.ResultSetResponse resultSetResponse =
+ new Service.ResultSetResponse(UUID.randomUUID().toString(),
+ RANDOM.nextInt(), false, signature, Meta.Frame.EMPTY, -1L, null);
+
+ return new Service.ExecuteResponse(
+ Collections.singletonList(resultSetResponse), false, null);
+ }
+ }
+
+ @Test public void testExecuteRequestWithNumberParameter() {
+ final List<TypedValue> expectedParameterValues = new ArrayList<>();
+ final Service service = new ParameterValuesCheckingService(expectedParameterValues);
+ final JsonService jsonService = new LocalJsonService(service);
+ final JsonHandler jsonHandler = new JsonHandler(jsonService, NoopMetricsSystem.getInstance());
+
+ final List<TypedValue> parameterValues = Arrays.asList(
+ TypedValue.create("NUMBER", new BigDecimal("123")),
+ TypedValue.create("STRING", "calcite"));
+
+ jsonHandler.apply(
+ "{'request':'execute',"
+ + "'parameterValues':[{'type':'NUMBER','value':123},"
+ + "{'type':'STRING','value':'calcite'}]}");
+ assertThat(expectedParameterValues.size(), is(2));
+ assertThat(expectedParameterValues.get(0), is(parameterValues.get(0)));
+ assertThat(expectedParameterValues.get(1), is(parameterValues.get(1)));
+ }
+}
+
+// End JsonHandlerTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/test/package-info.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/test/package-info.java b/avatica/core/src/test/java/org/apache/calcite/avatica/test/package-info.java
new file mode 100644
index 0000000..501bb9f
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/test/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/**
+ * Avatica tests.
+ */
+@PackageMarker
+package org.apache.calcite.avatica.test;
+
+import org.apache.calcite.avatica.util.PackageMarker;
+
+// End package-info.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/util/NumberAccessorTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/util/NumberAccessorTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/util/NumberAccessorTest.java
new file mode 100644
index 0000000..4f8e51f
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/util/NumberAccessorTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.util;
+
+import org.apache.calcite.avatica.util.AbstractCursor.Getter;
+import org.apache.calcite.avatica.util.AbstractCursor.NumberAccessor;
+
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test logic for the NumberAccessor.
+ */
+public class NumberAccessorTest {
+
+ @Test
+ public void testBigDecimalZeroScale() {
+ final BigDecimal orig = new BigDecimal(BigInteger.valueOf(137L), 1);
+ NumberAccessor accessor = new AbstractCursor.NumberAccessor(
+ new Getter() {
+ @Override public Object getObject() {
+ return orig;
+ }
+
+ @Override public boolean wasNull() {
+ return false;
+ }
+ },
+ 0);
+
+ assertEquals(orig, accessor.getBigDecimal(0));
+ }
+
+}
+
+// End NumberAccessorTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/core/src/test/java/org/apache/calcite/avatica/util/UnsynchronizedBufferTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/util/UnsynchronizedBufferTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/util/UnsynchronizedBufferTest.java
new file mode 100644
index 0000000..a448d3e
--- /dev/null
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/util/UnsynchronizedBufferTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.util;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for the UnsynchronizedBuffer.
+ */
+public class UnsynchronizedBufferTest {
+
+ @Test public void testArrayResizing() {
+ int size = 64;
+ int expected = 128;
+ for (int i = 0; i < 10; i++) {
+ // We keep being one byte short to contain this message
+ int next = UnsynchronizedBuffer.nextArraySize(size + 1);
+ assertEquals(expected, next);
+ size = next;
+ expected *= 2;
+ }
+ }
+}
+
+// End UnsynchronizedBufferTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/pom.xml
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/pom.xml b/avatica/metrics-dropwizardmetrics3/pom.xml
new file mode 100644
index 0000000..4966c5b
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.calcite.avatica</groupId>
+ <artifactId>calcite-avatica-parent</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>calcite-avatica-metrics-dropwizardmetrics3</artifactId>
+ <packaging>jar</packaging>
+ <name>Calcite Avatica Dropwizard Metrics 3</name>
+ <description>An implementation of Avatica Metrics using Dropwizard Metrics.</description>
+
+ <properties>
+ <top.dir>${project.basedir}/..</top.dir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.calcite</groupId>
+ <artifactId>calcite-avatica-metrics</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.dropwizard.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ <!-- Avoid specifying version in dependencyManagement in support of other avatica-metrics impls -->
+ <version>${dropwizard-metrics3.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <versionRange>[2.12.1,)</versionRange>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <!-- Parent module has the same plugin and does the work of
+ generating -sources.jar for each project. But without the
+ plugin declared here, IDEs don't know the sources are
+ available. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>jar-no-fork</goal>
+ <goal>test-jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-remote-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>non-root-resources</id>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardCounter.java
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardCounter.java b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardCounter.java
new file mode 100644
index 0000000..4204ebf
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardCounter.java
@@ -0,0 +1,51 @@
+/*
+ * 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.metrics.dropwizard3;
+
+import com.codahale.metrics.Counter;
+
+import java.util.Objects;
+
+/**
+ * Dropwizard Metrics implementation of {@link org.apache.calcite.avatica.metrics.Counter}.
+ */
+public class DropwizardCounter implements org.apache.calcite.avatica.metrics.Counter {
+
+ private final Counter counter;
+
+ public DropwizardCounter(Counter counter) {
+ this.counter = Objects.requireNonNull(counter);
+ }
+
+ @Override public void increment() {
+ this.counter.inc();
+ }
+
+ @Override public void increment(long n) {
+ this.counter.inc(n);
+ }
+
+ @Override public void decrement() {
+ this.counter.dec();
+ }
+
+ @Override public void decrement(long n) {
+ this.counter.dec(n);
+ }
+}
+
+// End DropwizardCounter.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardGauge.java
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardGauge.java b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardGauge.java
new file mode 100644
index 0000000..5f4b776
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardGauge.java
@@ -0,0 +1,39 @@
+/*
+ * 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.metrics.dropwizard3;
+
+import com.codahale.metrics.Gauge;
+
+/**
+ * Dropwizard Metrics implementation of {@link org.apache.calcite.avatica.metrics.Gauge}.
+ *
+ * @param <T> The value the gauge returns.
+ */
+public class DropwizardGauge<T> implements Gauge<T> {
+
+ private final org.apache.calcite.avatica.metrics.Gauge<T> gauge;
+
+ public DropwizardGauge(org.apache.calcite.avatica.metrics.Gauge<T> gauge) {
+ this.gauge = gauge;
+ }
+
+ @Override public T getValue() {
+ return gauge.getValue();
+ }
+}
+
+// End DropwizardGauge.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardHistogram.java
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardHistogram.java b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardHistogram.java
new file mode 100644
index 0000000..266f130
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardHistogram.java
@@ -0,0 +1,43 @@
+/*
+ * 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.metrics.dropwizard3;
+
+import com.codahale.metrics.Histogram;
+
+import java.util.Objects;
+
+/**
+ * Dropwizard metrics implementation of {@link org.apache.calcite.avatica.metrics.Histogram}.
+ */
+public class DropwizardHistogram implements org.apache.calcite.avatica.metrics.Histogram {
+
+ private final Histogram histogram;
+
+ public DropwizardHistogram(Histogram histogram) {
+ this.histogram = Objects.requireNonNull(histogram);
+ }
+
+ @Override public void update(int value) {
+ histogram.update(value);
+ }
+
+ @Override public void update(long value) {
+ histogram.update(value);
+ }
+}
+
+// End DropwizardHistogram.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMeter.java
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMeter.java b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMeter.java
new file mode 100644
index 0000000..ab8fafc
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMeter.java
@@ -0,0 +1,43 @@
+/*
+ * 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.metrics.dropwizard3;
+
+import com.codahale.metrics.Meter;
+
+import java.util.Objects;
+
+/**
+ * Dropwizard metrics implementation of {@link org.apache.calcite.avatica.metrics.Meter}.
+ */
+public class DropwizardMeter implements org.apache.calcite.avatica.metrics.Meter {
+
+ private final Meter meter;
+
+ public DropwizardMeter(Meter meter) {
+ this.meter = Objects.requireNonNull(meter);
+ }
+
+ @Override public void mark() {
+ this.meter.mark();
+ }
+
+ @Override public void mark(long count) {
+ this.meter.mark(count);
+ }
+}
+
+// End DropwizardMeter.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystem.java
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystem.java b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystem.java
new file mode 100644
index 0000000..6aa71b9
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystem.java
@@ -0,0 +1,62 @@
+/*
+ * 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.metrics.dropwizard3;
+
+import org.apache.calcite.avatica.metrics.Counter;
+import org.apache.calcite.avatica.metrics.Gauge;
+import org.apache.calcite.avatica.metrics.Histogram;
+import org.apache.calcite.avatica.metrics.Meter;
+import org.apache.calcite.avatica.metrics.MetricsSystem;
+import org.apache.calcite.avatica.metrics.Timer;
+
+import com.codahale.metrics.MetricRegistry;
+
+import java.util.Objects;
+
+/**
+ * Dropwizard Metrics implementation of {@link MetricsSystem}.
+ */
+public class DropwizardMetricsSystem implements MetricsSystem {
+
+ private final MetricRegistry registry;
+
+ public DropwizardMetricsSystem(MetricRegistry registry) {
+ this.registry = Objects.requireNonNull(registry);
+ }
+
+ @Override public Timer getTimer(String name) {
+ return new DropwizardTimer(registry.timer(name));
+ }
+
+ @Override public Histogram getHistogram(String name) {
+ return new DropwizardHistogram(registry.histogram(name));
+ }
+
+ @Override public Meter getMeter(String name) {
+ return new DropwizardMeter(registry.meter(name));
+ }
+
+ @Override public Counter getCounter(String name) {
+ return new DropwizardCounter(registry.counter(name));
+ }
+
+ @Override public <T> void register(String name, Gauge<T> gauge) {
+ registry.register(name, new DropwizardGauge<T>(gauge));
+ }
+}
+
+// End DropwizardMetricsSystem.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystemConfiguration.java
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystemConfiguration.java b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystemConfiguration.java
new file mode 100644
index 0000000..f4c9234
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystemConfiguration.java
@@ -0,0 +1,42 @@
+/*
+ * 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.metrics.dropwizard3;
+
+import org.apache.calcite.avatica.metrics.MetricsSystemConfiguration;
+
+import com.codahale.metrics.MetricRegistry;
+
+import java.util.Objects;
+
+/**
+ * A container which provides a {@link MetricRegistry} to a {@link DropwizardMetricsSystem}.
+ */
+public class DropwizardMetricsSystemConfiguration implements
+ MetricsSystemConfiguration<MetricRegistry> {
+
+ private final MetricRegistry registry;
+
+ public DropwizardMetricsSystemConfiguration(MetricRegistry registry) {
+ this.registry = Objects.requireNonNull(registry);
+ }
+
+ @Override public MetricRegistry get() {
+ return registry;
+ }
+}
+
+// End DropwizardMetricsSystemConfiguration.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystemFactory.java
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystemFactory.java b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystemFactory.java
new file mode 100644
index 0000000..1480db6
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardMetricsSystemFactory.java
@@ -0,0 +1,42 @@
+/*
+ * 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.metrics.dropwizard3;
+
+import org.apache.calcite.avatica.metrics.MetricsSystemConfiguration;
+import org.apache.calcite.avatica.metrics.MetricsSystemFactory;
+
+/**
+ * A {@link MetricsSystemFactory} for {@link DropwizardMetricsSystem}.
+ */
+public class DropwizardMetricsSystemFactory implements MetricsSystemFactory {
+
+ @Override public DropwizardMetricsSystem create(MetricsSystemConfiguration<?> config) {
+ // Verify we got configuration this factory can use
+ if (config instanceof DropwizardMetricsSystemConfiguration) {
+ DropwizardMetricsSystemConfiguration typedConfig =
+ (DropwizardMetricsSystemConfiguration) config;
+
+ return new DropwizardMetricsSystem(typedConfig.get());
+ }
+
+ throw new IllegalStateException("Expected instance of "
+ + DropwizardMetricsSystemConfiguration.class.getName() + " but got "
+ + (null == config ? "null" : config.getClass().getName()));
+ }
+}
+
+// End DropwizardMetricsSystemFactory.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardTimer.java
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardTimer.java b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardTimer.java
new file mode 100644
index 0000000..850f9a6
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/DropwizardTimer.java
@@ -0,0 +1,54 @@
+/*
+ * 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.metrics.dropwizard3;
+
+import com.codahale.metrics.Timer;
+
+import java.util.Objects;
+
+/**
+ * Dropwizard Metrics implementation of {@link org.apache.calcite.avatica.metrics.Timer}.
+ */
+public class DropwizardTimer implements org.apache.calcite.avatica.metrics.Timer {
+
+ private final Timer timer;
+
+ public DropwizardTimer(Timer timer) {
+ this.timer = Objects.requireNonNull(timer);
+ }
+
+ @Override public DropwizardContext start() {
+ return new DropwizardContext(timer.time());
+ }
+
+ /**
+ * Dropwizard Metrics implementation of {@link org.apache.calcite.avatica.metrics.Timer.Context}
+ */
+ public class DropwizardContext implements org.apache.calcite.avatica.metrics.Timer.Context {
+ private final com.codahale.metrics.Timer.Context context;
+
+ public DropwizardContext(com.codahale.metrics.Timer.Context context) {
+ this.context = Objects.requireNonNull(context);
+ }
+
+ @Override public void close() {
+ this.context.stop();
+ }
+ }
+}
+
+// End DropwizardTimer.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/package-info.java
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/package-info.java b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/package-info.java
new file mode 100644
index 0000000..f88df93
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/java/org/apache/calcite/avatica/metrics/dropwizard3/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/**
+ * Dropwizard-Metrics (v3) implementation of the Avatica Metrics framework.
+ */
+@PackageMarker
+package org.apache.calcite.avatica.metrics.dropwizard3;
+
+import org.apache.calcite.avatica.metrics.PackageMarker;
+
+// End package-info.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/5cee486f/avatica/metrics-dropwizardmetrics3/src/main/resources/META-INF/services/org.apache.calcite.avatica.metrics.MetricsSystemFactory
----------------------------------------------------------------------
diff --git a/avatica/metrics-dropwizardmetrics3/src/main/resources/META-INF/services/org.apache.calcite.avatica.metrics.MetricsSystemFactory b/avatica/metrics-dropwizardmetrics3/src/main/resources/META-INF/services/org.apache.calcite.avatica.metrics.MetricsSystemFactory
new file mode 100644
index 0000000..25b64a8
--- /dev/null
+++ b/avatica/metrics-dropwizardmetrics3/src/main/resources/META-INF/services/org.apache.calcite.avatica.metrics.MetricsSystemFactory
@@ -0,0 +1,2 @@
+org.apache.calcite.avatica.metrics.dropwizard3.DropwizardMetricsSystemFactory
+