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/05/09 15:37:15 UTC

[1/2] calcite git commit: [CALCITE-1190] Avatica TCK for cross-version compatibility testing

Repository: calcite
Updated Branches:
  refs/heads/master 9deff987b -> 2197f7dc3


http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/resources/META-INF/LICENSE
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/resources/META-INF/LICENSE b/avatica/tck/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..0720b21
--- /dev/null
+++ b/avatica/tck/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,251 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
+
+
+
+
+-----------------------------------------------------------------------
+
+APACHE CALCITE AVATICA SUBCOMPONENTS:
+
+The Apache Calcite Avatica project contains subcomponents with separate copyright
+notices and license terms. Your use of the source code for the these
+subcomponents is subject to the terms and conditions of the following
+licenses.
+
+-----------------------------------------------------------------------
+ 3-clause BSD license
+-----------------------------------------------------------------------
+
+The Apache Calcite Avatica project bundles HSQLDB, which is available
+under the following "3-clause BSD" license:
+
+    Copyright (c) 2001-2016, The HSQL Development Group
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+    
+    Neither the name of the HSQL Development Group nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
+    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/resources/example_config.yml
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/resources/example_config.yml b/avatica/tck/src/main/resources/example_config.yml
new file mode 100644
index 0000000..b6b255e
--- /dev/null
+++ b/avatica/tck/src/main/resources/example_config.yml
@@ -0,0 +1,38 @@
+# 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.
+---
+# https://repository.apache.org/content/repositories/snapshots/org/apache/calcite/avatica/avatica-tck/1.8.0-SNAPSHOT
+tck_jar: /home/user/avatica-tck-1.8.0-SNAPSHOT-shaded.jar
+
+# Global template, can be overriden in each version. <url> is automatically replaced by the framework
+client_url_template: jdbc:avatica:remote;url=<url>;serialization=PROTOBUF
+
+# Specifies all versions to be tested against one another
+versions:
+  # The user _must_ fill in the port number for the Avatica server for each version
+  v1.6.0:
+    # https://repository.apache.org/content/repositories/releases/org/apache/calcite/calcite-avatica/1.6.0/calcite-avatica-1.6.0.jar
+    client_jar: /home/user/calcite-avatica-1.6.0.jar
+    server_url: http://localhost:XXXXX
+
+  v1.7.1:
+    # https://repository.apache.org/content/repositories/releases/org/apache/calcite/avatica/avatica/1.7.1/avatica-1.7.1.jar
+    client_jar: /home/user/avatica-1.7.1.jar
+    server_url: http://localhost:XXXXX
+
+  v1.8.0-SNAPSHOT:
+    # https://repository.apache.org/content/repositories/snapshots/org/apache/calcite/avatica/avatica/1.8.0-SNAPSHOT/
+    client_jar: /home/user/avatica-1.8.0-SNAPSHOT.jar
+    server_url: http://localhost:XXXXX

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/resources/log4j.properties b/avatica/tck/src/main/resources/log4j.properties
new file mode 100644
index 0000000..68a9cc2
--- /dev/null
+++ b/avatica/tck/src/main/resources/log4j.properties
@@ -0,0 +1,24 @@
+# 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.
+
+# Root logger is configured at INFO and is sent to A1
+log4j.rootLogger=INFO, A1
+
+# A1 goes to the console
+log4j.appender.A1=org.apache.calcite.avatica.tck.shaded.org.apache.log4j.ConsoleAppender
+
+# Set the pattern for each log message
+log4j.appender.A1.layout=org.apache.calcite.avatica.tck.shaded.org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c{2} - %m%n
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/ruby/test_runner.rb
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/ruby/test_runner.rb b/avatica/tck/src/main/ruby/test_runner.rb
new file mode 100755
index 0000000..e0b9d73
--- /dev/null
+++ b/avatica/tck/src/main/ruby/test_runner.rb
@@ -0,0 +1,125 @@
+#!/usr/bin/env ruby
+
+# 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.
+
+require 'logger'
+require 'yaml'
+
+PASSED = "\033[32mPassed\033[0m"
+FAILED = "\033[31mFailed\033[0m"
+
+VERSIONS_KEY = 'versions'
+CLIENT_JAR_KEY = 'client_jar'
+SERVER_URL_KEY = 'server_url'
+CLIENT_URL_TEMPLATE_KEY = 'client_url_template'
+
+TCK_JAR_KEY = 'tck_jar'
+
+# Special key for the client URL template to substitute the server's url
+URL_REPLACEMENT_HOLDER = '<url>'
+
+LOG = Logger.new(STDOUT)
+LOG.level = Logger::WARN
+
+
+def usage()
+  puts "usage: test_runner.rb configuration.yml"
+end
+
+def run_test(tck_jar, client, server)
+  client_jar = client[:config][CLIENT_JAR_KEY]
+  client_url = client[:config][CLIENT_URL_TEMPLATE_KEY]
+  server_url = server[:config][SERVER_URL_KEY]
+
+  puts "\nRunning #{client[:name]} against #{server[:name]}"
+
+  if server_url.end_with? 'X'
+    LOG.error("Fill in the port for server version '#{server_url}' in the YAML configuration file")
+    return false
+  end
+
+  # Make a copy here to be sure to not affect other tests
+  LOG.debug("Updating server url #{server_url} in #{client_url}")
+  client_url = client_url.gsub(URL_REPLACEMENT_HOLDER, server_url)
+
+  cmd = "java -cp '#{tck_jar}:#{client_jar}' org.apache.calcite.avatica.tck.TestRunner -u '#{client_url}'"
+  puts "Java command: '#{cmd}'"
+  success = system(cmd)
+
+  puts "Test of #{client[:name]} against #{server[:name]} " + (success ? PASSED : FAILED)
+  return success
+end
+
+unless ARGV.size == 1
+  usage()
+  raise ArgumentError.new('YAML configuration file is required as the only argument')
+end
+
+# Parse the configuration file
+config_file = ARGV[0]
+config = YAML.load_file(config_file)
+
+# The Avatica TCK jar
+tck_jar = config[TCK_JAR_KEY]
+if tck_jar.nil?
+  raise "Configuration file does not contain '#{TCK_JAR_KEY}' key"
+end
+
+# A client url template specified globally, can be overriden in the version
+global_url_template = config[CLIENT_URL_TEMPLATE_KEY]
+
+# Map of version name to jar/configuration
+all_versions = config[VERSIONS_KEY]
+if all_versions.nil?
+  raise "Configuration file does not contain '#{VERSIONS_KEY}' key"
+end
+
+# Push down the global client url template to each version when applicable
+all_versions.each do |version|
+  if version.length != 2
+    LOG.warn("Unexpected number of arguments for version: #{version.to_s}")
+  end
+  version_config = version[1]
+  if version_config[CLIENT_URL_TEMPLATE_KEY].nil? and not global_url_template.nil?
+    version_config[CLIENT_URL_TEMPLATE_KEY] = global_url_template
+  end
+end
+
+# Convert from a hash to an array of pairs
+all_versions = all_versions.collect{ |k,v| {:name=>k, :config=>v} }
+
+# Compute the "identity" mapping as a sanity check
+identity_versions = all_versions.collect {|x| [x, x]}
+
+# Create a cartesian product of the pairs, dropping entries where the pairs are equal
+all_pairs = all_versions.product(all_versions).select {|x| x[0][:name] != x[1][:name]}
+
+puts "Running identity test as a sanity check (client and server at the same version)"
+
+identity_outcomes = identity_versions.collect{|pair| {:client => pair[0][:name], :server=>pair[1][:name], :result=>run_test(tck_jar, pair[0], pair[1])}}
+
+puts "\nRunning cross-version tests"
+
+# Run the TCK against each pair
+outcomes = all_pairs.collect{|pair| {:client=>pair[0][:name], :server=>pair[1][:name], :result=>run_test(tck_jar, pair[0], pair[1])}}
+
+puts "\n-------------------------------------\nSummary:\n\n"
+
+puts "Identity test scenarios (ran #{identity_outcomes.size})\n\n"
+identity_outcomes.each{|outcome| puts "Testing identity for version #{outcome[:client]}: #{(outcome[:result] ? PASSED : FAILED)}"}
+
+puts "\nAll test scenarios (ran #{all_pairs.size})\n\n"
+outcomes.each{|outcome| puts "Testing client #{outcome[:client]} against server #{outcome[:server]}: #{(outcome[:result] ? PASSED : FAILED)}"}


[2/2] calcite git commit: [CALCITE-1190] Avatica TCK for cross-version compatibility testing

Posted by el...@apache.org.
[CALCITE-1190] Avatica TCK for cross-version compatibility testing

Also includes a standalone Avatica server implementation which
uses HSQLDB to simplify testing. README and site updated with
more information about compatibility and the TCK.

Closes apache/calcite#227


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/2197f7dc
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/2197f7dc
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/2197f7dc

Branch: refs/heads/master
Commit: 2197f7dc34035f63c50b12eeebf4758d44e09c43
Parents: 9deff98
Author: Josh Elser <el...@apache.org>
Authored: Mon May 9 11:24:46 2016 -0400
Committer: Josh Elser <el...@apache.org>
Committed: Mon May 9 11:30:15 2016 -0400

----------------------------------------------------------------------
 avatica/pom.xml                                 |  13 +
 avatica/site/_data/docs.yml                     |   1 +
 avatica/site/_docs/compatibility.md             | 105 +++++++
 avatica/standalone-server/.gitignore            |   1 +
 avatica/standalone-server/pom.xml               | 195 +++++++++++++
 .../calcite/avatica/hsqldb/HsqldbServer.java    | 134 +++++++++
 .../calcite/avatica/hsqldb/package-info.java    |  26 ++
 .../src/main/resources/META-INF/LICENSE         | 251 +++++++++++++++++
 .../resources/META-INF/services/java.sql.Driver |   1 +
 .../src/main/resources/log4j.properties         |  24 ++
 avatica/tck/.gitignore                          |   1 +
 avatica/tck/README.md                           |  80 ++++++
 avatica/tck/pom.xml                             | 223 +++++++++++++++
 .../calcite/avatica/tck/PackageMarker.java      |  37 +++
 .../apache/calcite/avatica/tck/TestRunner.java  | 274 +++++++++++++++++++
 .../calcite/avatica/tck/package-info.java       |  24 ++
 .../calcite/avatica/tck/tests/BaseTckTest.java  |  56 ++++
 .../calcite/avatica/tck/tests/InsertTest.java   | 213 ++++++++++++++
 .../calcite/avatica/tck/tests/MetadataTest.java | 132 +++++++++
 .../calcite/avatica/tck/tests/package-info.java |  26 ++
 avatica/tck/src/main/resources/META-INF/LICENSE | 251 +++++++++++++++++
 .../tck/src/main/resources/example_config.yml   |  38 +++
 avatica/tck/src/main/resources/log4j.properties |  24 ++
 avatica/tck/src/main/ruby/test_runner.rb        | 125 +++++++++
 24 files changed, 2255 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/pom.xml
----------------------------------------------------------------------
diff --git a/avatica/pom.xml b/avatica/pom.xml
index 64719db..e258476 100644
--- a/avatica/pom.xml
+++ b/avatica/pom.xml
@@ -76,6 +76,7 @@ limitations under the License.
     <hydromatic-toolbox.version>0.3</hydromatic-toolbox.version>
     <jackson.version>2.6.3</jackson.version>
     <jcip-annotations.version>1.0-1</jcip-annotations.version>
+    <jcommander.version>1.48</jcommander.version>
     <jetty.version>9.2.15.v20160210</jetty.version>
     <junit.version>4.12</junit.version>
     <kerby.version>1.0.0-RC2</kerby.version>
@@ -112,6 +113,8 @@ limitations under the License.
     <module>metrics-dropwizardmetrics3</module>
     <module>noop-driver</module>
     <module>server</module>
+    <module>tck</module>
+    <module>standalone-server</module>
   </modules>
 
   <!-- No dependencies here. Declare dependency VERSIONS in
@@ -139,6 +142,11 @@ limitations under the License.
       </dependency>
       <dependency>
         <groupId>org.apache.calcite.avatica</groupId>
+        <artifactId>avatica-tck</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.calcite.avatica</groupId>
         <artifactId>avatica-server</artifactId>
         <version>${project.version}</version>
       </dependency>
@@ -151,6 +159,11 @@ limitations under the License.
 
       <!-- Now third-party dependencies, sorted by groupId and artifactId. -->
       <dependency>
+        <groupId>com.beust</groupId>
+        <artifactId>jcommander</artifactId>
+        <version>${jcommander.version}</version>
+      </dependency>
+      <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-core</artifactId>
         <version>${jackson.version}</version>

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/site/_data/docs.yml
----------------------------------------------------------------------
diff --git a/avatica/site/_data/docs.yml b/avatica/site/_data/docs.yml
index 787588d..4b63d20 100644
--- a/avatica/site/_data/docs.yml
+++ b/avatica/site/_data/docs.yml
@@ -27,6 +27,7 @@
   - protobuf_reference
   - howto
   - security
+  - compatibility
 
 - title: Meta
   docs:

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/site/_docs/compatibility.md
----------------------------------------------------------------------
diff --git a/avatica/site/_docs/compatibility.md b/avatica/site/_docs/compatibility.md
new file mode 100644
index 0000000..18ae3a6
--- /dev/null
+++ b/avatica/site/_docs/compatibility.md
@@ -0,0 +1,105 @@
+---
+layout: docs
+title: Compatibility
+sidebar_title: Compatibility
+permalink: /docs/compatibility.html
+---
+
+<!--
+{% comment %}
+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.
+{% endcomment %}
+-->
+
+Given Avatica's client-server model, it is no surprise that compatibility is
+important to the users and developers of Apache Calcite Avatica. This document
+defines what guarantees are made by Avatica with respect to compatibility
+between Avatica client and server across versions. This document is still a work
+in progress with many areas still requiring definition. Contributions are always
+welcome.
+
+## Avatica Technology Compatibility Kit (TCK)
+
+The [Avatica TCK project][github-tck] is a framework designed to automatically
+test an Avatica client against an Avatica server. A collection of JUnit tests,
+a YAML configuration file, and a Ruby script defines the TCK.
+The JUnit tests invoke specific portions of both the client and
+server components of Avatica to verify that they work as expected. The Ruby
+script uses the YAML configuration file to define the set of
+client and server version pairs to run the JUnit tests against.
+
+In the YAML configuration file, a name (e.g. `1.6.0`) and the following three
+items define an Avatica version:
+
+1. A filesystem path to an Avatica client jar (e.g. groupId=org.apache.calcite.avatica, artifactId=avatica)
+2. A URL to a running instance of an Avatica server
+3. A JDBC URL template to the Avatica server for the Avatica client JDBC driver.
+
+Users of the TCK define the collection of versions (defined by the above
+information) and the location of the [avatica-tck][github-tck] jar by a YAML
+configuration file. An [example YAML configuration file][github-tck-yml-file] is
+bundled with the project.
+
+Traditionally, Avatica does not provide any implementation of the Avatica server
+as the value in Avatica is recognized in the integrating project (e.g. Apache
+Drill or Apache Phoenix). However, for the purposes of compatibility testing, it
+makes sense that Avatica provides a standalone server instance.  A new artifact
+is introduced to Avatica with the original TCK codebase called
+[avatica-standalone-server][github-standalone-server].  This artifact is a
+runnable jar (e.g. `java -jar`) which starts an instance of the Avatica server
+on a random port using the in-memory [HSQLDB database](http://hsqldb.org/). This
+artifacts makes it extremely simple to start a version of the Avatica server for
+the specific version of Avatica to be tested.
+
+As mentioned, the Ruby script is the entry point for the TCK. Invoking the Ruby
+script which prints a summary of testing each specified version against itself and
+all other versions in the YAML configuration. An example summary is presented
+below which is the result of testing versions 1.6.0, 1.7.1 and 1.8.0-SNAPSHOT:
+
+```
+Summary:
+
+Identity test scenarios (ran 3)
+
+Testing identity for version v1.6.0: Passed
+Testing identity for version v1.7.1: Passed
+Testing identity for version v1.8.0-SNAPSHOT: Failed
+
+All test scenarios (ran 6)
+
+Testing client v1.6.0 against server v1.7.1: Passed
+Testing client v1.6.0 against server v1.8.0-SNAPSHOT: Failed
+Testing client v1.7.1 against server v1.6.0: Passed
+Testing client v1.7.1 against server v1.8.0-SNAPSHOT: Failed
+Testing client v1.8.0-SNAPSHOT against server v1.6.0: Failed
+Testing client v1.8.0-SNAPSHOT against server v1.7.1: Failed
+```
+
+It is not always expected that all tested version-pairs will pass unless the
+test is written with specific knowledge about past bugs in Avatica itself. While
+Avatica tries to handle all of these edge cases implicitly, it is not always
+feasible or desirable to do so. Adding new test cases is as easy as writing a
+JUnit test case in the [TCK module][github-tck-tests], but there is presently no
+automation around verifying the test cases as a part of the Maven build.
+
+For more information on running this TCK, including specific instructions for
+running the TCK, reference the provided [README][github-tck-readme] file.
+
+[github-tck]: https://github.com/apache/calcite/tree/master/avatica/tck
+[github-tck-tests]: https://github.com/apache/calcite/tree/master/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests
+[github-standalone-server]: https://github.com/apache/calcite/tree/master/avatica/standalone-server
+[github-tck-readme]: https://github.com/apache/calcite/tree/master/avatica/tck/README.md
+[github-tck-yml-file]: https://github.com/apache/calcite/tree/master/avatica/tck/src/main/resources/example_config.yml

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/standalone-server/.gitignore
----------------------------------------------------------------------
diff --git a/avatica/standalone-server/.gitignore b/avatica/standalone-server/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/avatica/standalone-server/.gitignore
@@ -0,0 +1 @@
+/target/

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/standalone-server/pom.xml
----------------------------------------------------------------------
diff --git a/avatica/standalone-server/pom.xml b/avatica/standalone-server/pom.xml
new file mode 100644
index 0000000..5a11086
--- /dev/null
+++ b/avatica/standalone-server/pom.xml
@@ -0,0 +1,195 @@
+<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>avatica-parent</artifactId>
+    <version>1.8.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>avatica-standalone-server</artifactId>
+  <name>Avatica Standalone Server</name>
+  <description>A Stadnalone Avatica Server Implementation</description>
+
+  <properties>
+    <top.dir>${project.basedir}/..</top.dir>
+  </properties>
+
+  <dependencies>
+    <!-- Sorted by groupId, artifactId; calcite dependencies first. Put versions
+         in dependencyManagement in the root POM, not here. -->
+    <dependency>
+      <groupId>org.apache.calcite.avatica</groupId>
+      <artifactId>avatica</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.calcite.avatica</groupId>
+      <artifactId>avatica-server</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.beust</groupId>
+      <artifactId>jcommander</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>net.hydromatic</groupId>
+      <artifactId>scott-data-hsqldb</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.hsqldb</groupId>
+      <artifactId>hsqldb</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+    </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-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>analyze</id>
+            <goals>
+              <goal>analyze-only</goal>
+            </goals>
+            <configuration>
+              <failOnWarning>true</failOnWarning>
+              <!-- ignore "unused but declared" warnings -->
+              <ignoredUnusedDeclaredDependencies>
+                <ignoredUnusedDeclaredDependency>net.hydromatic:scott-data-hsqldb</ignoredUnusedDeclaredDependency>
+                <ignoredUnusedDeclaredDependency>org.hsqldb:hsqldb</ignoredUnusedDeclaredDependency>
+                <ignoredUnusedDeclaredDependency>org.slf4j:slf4j-log4j12</ignoredUnusedDeclaredDependency>
+                <ignoredUnusedDeclaredDependency>org.slf4j:slf4j-api</ignoredUnusedDeclaredDependency>
+              </ignoredUnusedDeclaredDependencies>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <!-- Create a standalone JAR capable of running the server -->
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <artifactSet>
+                <excludes>
+                  <exclude>com.google.protobuf:protobuf-java</exclude>
+                  <exclude>org.apache.httpcomponents:*</exclude>
+                  <exclude>commons-codec:commons-codec</exclude>
+                </excludes>
+                </artifactSet>
+              <createDependencyReducedPom>false</createDependencyReducedPom>
+              <relocations>
+                <relocation>
+                  <pattern>com.beust</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.hsqldb.shaded.com.beust</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>com.fasterxml</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.hsqldb.shaded.com.fasterxml</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>com.google.common</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.hsqldb.shaded.com.google.common</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>javax.servlet</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.hsqldb.shaded.javax.servlet</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>net.hydromatic</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.hsqldb.shaded.net.hydromatic</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>org.apache.log4j</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.hsqldb.shaded.org.apache.log4j</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>org.eclipse.jetty</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.hsqldb.shaded.org.eclipse.jetty</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>org.hsqldb</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.hsqldb.shaded.org.hsqldb</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>org.slf4j</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.hsqldb.shaded.org.slf4j</shadedPattern>
+                </relocation>
+              </relocations>
+              <shadedArtifactAttached>true</shadedArtifactAttached>
+              <transformers>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
+                    <addHeader>false</addHeader>
+                </transformer>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
+                  <resources>
+                    <resource>LICENSE.txt</resource>
+                  </resources>
+                </transformer>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                  <mainClass>org.apache.calcite.avatica.hsqldb.HsqldbServer</mainClass>
+                </transformer>
+              </transformers>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/HsqldbServer.java
----------------------------------------------------------------------
diff --git a/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/HsqldbServer.java b/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/HsqldbServer.java
new file mode 100644
index 0000000..dbd632c
--- /dev/null
+++ b/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/HsqldbServer.java
@@ -0,0 +1,134 @@
+/*
+ * 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.hsqldb;
+
+import org.apache.calcite.avatica.jdbc.JdbcMeta;
+import org.apache.calcite.avatica.remote.Driver.Serialization;
+import org.apache.calcite.avatica.remote.LocalService;
+import org.apache.calcite.avatica.server.HttpServer;
+
+import com.beust.jcommander.IStringConverter;
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+
+import net.hydromatic.scott.data.hsqldb.ScottHsqldb;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An Avatica server for HSQLDB.
+ */
+public class HsqldbServer {
+  private static final Logger LOG = LoggerFactory.getLogger(HsqldbServer.class);
+
+  @Parameter(names = { "-p", "--port" }, required = false,
+      description = "Port the server should bind")
+  private int port = 0;
+
+  @Parameter(names = { "-s", "--serialization" }, required = false,
+      description = "Serialization method to use", converter = SerializationConverter.class)
+  private Serialization serialization = Serialization.PROTOBUF;
+
+  private HttpServer server;
+
+  public void start() {
+    if (null != server) {
+      LOG.error("The server was already started");
+      System.exit(ExitCodes.ALREADY_STARTED.ordinal());
+      return;
+    }
+
+    try {
+      // Set up Julian's ScottDB for HSQLDB
+      JdbcMeta meta = new JdbcMeta(ScottHsqldb.URI, ScottHsqldb.USER, ScottHsqldb.PASSWORD);
+      LocalService service = new LocalService(meta);
+
+      // Construct the server
+      this.server = new HttpServer.Builder()
+          .withHandler(service, serialization)
+          .withPort(port)
+          .build();
+
+      // Then start it
+      server.start();
+
+      LOG.info("Started Avatica server on port {} with serialization {}", server.getPort(),
+          serialization);
+    } catch (Exception e) {
+      LOG.error("Failed to start Avatica server", e);
+      System.exit(ExitCodes.START_FAILED.ordinal());
+    }
+  }
+
+  public void stop() {
+    if (null != server) {
+      server.stop();
+      server = null;
+    }
+  }
+
+  public void join() throws InterruptedException {
+    server.join();
+  }
+
+  public static void main(String[] args) {
+    final HsqldbServer server = new HsqldbServer();
+    new JCommander(server, args);
+
+    server.start();
+
+    // Try to clean up when the server is stopped.
+    Runtime.getRuntime().addShutdownHook(
+        new Thread(new Runnable() {
+          @Override public void run() {
+            LOG.info("Stopping server");
+            server.stop();
+            LOG.info("Server stopped");
+          }
+        }));
+
+    try {
+      server.join();
+    } catch (InterruptedException e) {
+      // Reset interruption
+      Thread.currentThread().interrupt();
+      // And exit now.
+      return;
+    }
+  }
+
+  /**
+   * Converter from String to Serialization.
+   */
+  private static class SerializationConverter implements IStringConverter<Serialization> {
+    @Override public Serialization convert(String value) {
+      return Serialization.valueOf(value.toUpperCase());
+    }
+  }
+
+  /**
+   * Codes for exit conditions
+   */
+  private enum ExitCodes {
+    NORMAL,
+    ALREADY_STARTED, // 1
+    START_FAILED;    // 2
+  }
+}
+
+// End HsqldbServer.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/package-info.java
----------------------------------------------------------------------
diff --git a/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/package-info.java b/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/package-info.java
new file mode 100644
index 0000000..da97815
--- /dev/null
+++ b/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/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 Server for HSQLDB.
+ */
+@PackageMarker
+package org.apache.calcite.avatica.hsqldb;
+
+import org.apache.calcite.avatica.util.PackageMarker;
+
+// End package-info.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/standalone-server/src/main/resources/META-INF/LICENSE
----------------------------------------------------------------------
diff --git a/avatica/standalone-server/src/main/resources/META-INF/LICENSE b/avatica/standalone-server/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..0720b21
--- /dev/null
+++ b/avatica/standalone-server/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,251 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
+
+
+
+
+-----------------------------------------------------------------------
+
+APACHE CALCITE AVATICA SUBCOMPONENTS:
+
+The Apache Calcite Avatica project contains subcomponents with separate copyright
+notices and license terms. Your use of the source code for the these
+subcomponents is subject to the terms and conditions of the following
+licenses.
+
+-----------------------------------------------------------------------
+ 3-clause BSD license
+-----------------------------------------------------------------------
+
+The Apache Calcite Avatica project bundles HSQLDB, which is available
+under the following "3-clause BSD" license:
+
+    Copyright (c) 2001-2016, The HSQL Development Group
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+    
+    Neither the name of the HSQL Development Group nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
+    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/standalone-server/src/main/resources/META-INF/services/java.sql.Driver
----------------------------------------------------------------------
diff --git a/avatica/standalone-server/src/main/resources/META-INF/services/java.sql.Driver b/avatica/standalone-server/src/main/resources/META-INF/services/java.sql.Driver
new file mode 100644
index 0000000..7b95c3f
--- /dev/null
+++ b/avatica/standalone-server/src/main/resources/META-INF/services/java.sql.Driver
@@ -0,0 +1 @@
+org.apache.calcite.avatica.hsqldb.shaded.org.hsqldb.jdbcDriver
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/standalone-server/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/avatica/standalone-server/src/main/resources/log4j.properties b/avatica/standalone-server/src/main/resources/log4j.properties
new file mode 100644
index 0000000..bc1bda9
--- /dev/null
+++ b/avatica/standalone-server/src/main/resources/log4j.properties
@@ -0,0 +1,24 @@
+# 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.
+
+# Root logger is configured at INFO and is sent to A1
+log4j.rootLogger=INFO, A1
+
+# A1 goes to the console
+log4j.appender.A1=org.apache.calcite.avatica.hsqldb.shaded.org.apache.log4j.ConsoleAppender
+
+# Set the pattern for each log message
+log4j.appender.A1.layout=org.apache.calcite.avatica.hsqldb.shaded.org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c{2} - %m%n
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/.gitignore
----------------------------------------------------------------------
diff --git a/avatica/tck/.gitignore b/avatica/tck/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/avatica/tck/.gitignore
@@ -0,0 +1 @@
+/target/

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/README.md
----------------------------------------------------------------------
diff --git a/avatica/tck/README.md b/avatica/tck/README.md
new file mode 100644
index 0000000..d8025ef
--- /dev/null
+++ b/avatica/tck/README.md
@@ -0,0 +1,80 @@
+<!--
+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.
+-->
+
+# Apache Calcite Avatica Technology Compatibility Kit (TCK)
+
+The Avatica TCK is a framework to test the compatibilty between
+various versions of Avatica clients and servers.
+
+The TCK is configured by a YAML file which specifies a TCK framework
+jar and a list of Avatica client and server versions. Each version
+must specify the path to a client jar, the URL of the server for
+that version, and a template for the JDBC url.
+
+An example YAML configuration file is provided ([example_config.yml][example-config-yml])
+which can be used as a starting point for users to fill out. Most elements are
+straightforward to understand; however, it does require that you provide a URL
+to a running Avatica server for each version to be tested.
+
+## Running a standalone Avatica server
+
+To make it easy to run a standalone Avatica server, an instance of the Avatica
+server running against an in-memory SQL database (HSQLDB) is provided starting
+in version 1.8.0. The `avatica-hsqldb-server-1.8.0-SNAPSHOT-shaded.jar` artifact
+can be used to start an Avatica server on a random port (printed to the console).
+
+  `java -jar avatica-hsqldb-server-1.8.0-SNAPSHOT-shaded.jar`
+
+For convenience in testing against earlier versions of Avatica, the following
+repository can be used to simplify building the same instance of a standalone
+HSQLDB-backed Avatica server https://github.com/joshelser/legacy-avatica-hsqldb-server
+
+Follow the instructions in the [README][legacy-readme] to build a standalone jar
+against a specific version of Calcite/Avatica which can be used as specified above.
+
+## Running the TCK
+
+A ruby script, [test_runner.rb][test-runner-script] is provided which consumes the modified YAML configuration
+file. This script will first run each provided version against itself as a sanity
+check for the tests itself (as the scope of what is implemented in Avatica does
+change over time), and then enumerate all possible combinations of client and server
+version.
+
+  `./test_runner.rb my_tck_config.yml`
+
+For example, if versions 1.6.0, 1.7.1 and 1.8.0-SNAPSHOT are defined in the YAML configuration
+file, the following identity tests will be run from client to server:
+
+* 1.6.0 to 1.6.0
+* 1.7.1 to 1.7.1
+* 1.8.0-SNAPSHOT to 1.8.0-SNAPSHOT
+
+while the following tests will be run for cross-version compatibility:
+
+* 1.6.0 to 1.7.1
+* 1.6.0 to 1.8.0-SNAPSHOT
+* 1.7.1 to 1.6.0
+* 1.7.1 to 1.8.0-SNAPSHOT
+* 1.8.0-SNAPSHOT to 1.6.0
+* 1.8.0-SNAPSHOT to 1.7.1
+
+Any errors encountered will be printed to the terminal. The final output of the script
+will be a summary of both the identity tests and the cross-version tests for easy consumption.
+
+[example-config-yml]: https://github.com/apache/calcite/tree/master/avatica/tck/src/main/resources/example_config.yml
+[legacy-readme]: https://github.com/joshelser/legacy-avatica-hsqldb-server/blob/master/README.md
+[test-runner-script]: https://github.com/apache/calcite/tree/master/avatica/tck/src/main/ruby/test_runner.rb

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/pom.xml
----------------------------------------------------------------------
diff --git a/avatica/tck/pom.xml b/avatica/tck/pom.xml
new file mode 100644
index 0000000..0ddf1de
--- /dev/null
+++ b/avatica/tck/pom.xml
@@ -0,0 +1,223 @@
+<?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>avatica-parent</artifactId>
+    <version>1.8.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>avatica-tck</artifactId>
+  <packaging>jar</packaging>
+  <name>Apache Calcite Avatica Compatibility Kit</name>
+  <description>Library for testing compatibility of Avatica across versions.</description>
+
+  <properties>
+    <top.dir>${project.basedir}/..</top.dir>
+  </properties>
+
+  <dependencies>
+    <!-- Sorted by groupId, artifactId; calcite dependencies first. Put versions
+         in dependencyManagement in the root POM, not here. -->
+    <dependency>
+      <groupId>com.beust</groupId>
+      <artifactId>jcommander</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.hsqldb</groupId>
+      <artifactId>hsqldb</artifactId>
+    </dependency>
+    <!-- As long as we want to run compatibility checks again 1.6.0, we have to include these because
+         they weren't yet provided by the avatica client jar -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+    </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>
+        <!-- Create a standalone JAR capable of running the server -->
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <artifactSet>
+                <excludes>
+                  <exclude>com.google.protobuf:protobuf-java</exclude>
+                  <exclude>org.apache.httpcomponents:*</exclude>
+                  <exclude>commons-codec:commons-codec</exclude>
+                </excludes>
+                </artifactSet>
+              <createDependencyReducedPom>false</createDependencyReducedPom>
+              <relocations>
+                <relocation>
+                  <pattern>com.beust</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.com.beust</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>com.fasterxml</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.com.fasterxml</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>com.google.common</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.com.google.common</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>javax.servlet</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.javax.servlet</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>junit</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.junit</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>net.hydromatic</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.net.hydromatic</shadedPattern>
+                </relocation>
+                <!-- We bundle a log4j.properties file which will be looking in this relocated location -->
+                <relocation>
+                  <pattern>org.apache.log4j</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.org.apache.log4j</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>org.eclipse.jetty</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.org.eclipse.jetty</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>org.hamcrest</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.org.hamcrest</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>org.hsqldb</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.org.hsqldb</shadedPattern>
+                </relocation>
+                <relocation>
+                  <pattern>org.junit</pattern>
+                  <shadedPattern>org.apache.calcite.avatica.tck.shaded.org.junit</shadedPattern>
+                </relocation>
+                <!-- Intentionally not shading slf4j as it would break -->
+              </relocations>
+              <shadedArtifactAttached>true</shadedArtifactAttached>
+              <transformers>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
+                    <addHeader>false</addHeader>
+                </transformer>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
+                  <resources>
+                    <resource>LICENSE.txt</resource>
+                  </resources>
+                </transformer>
+              </transformers>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>analyze</id>
+            <goals>
+              <goal>analyze-only</goal>
+            </goals>
+            <configuration>
+              <failOnWarning>true</failOnWarning>
+              <!-- ignore "unused but declared" warnings -->
+              <ignoredUnusedDeclaredDependencies>
+                <ignoredUnusedDeclaredDependency>org.hamcrest:hamcrest-core</ignoredUnusedDeclaredDependency>
+                <ignoredUnusedDeclaredDependency>org.hsqldb:hsqldb</ignoredUnusedDeclaredDependency>
+                <ignoredUnusedDeclaredDependency>org.slf4j:slf4j-log4j12</ignoredUnusedDeclaredDependency>
+                <ignoredUnusedDeclaredDependency>org.slf4j:slf4j-api</ignoredUnusedDeclaredDependency>
+              </ignoredUnusedDeclaredDependencies>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/PackageMarker.java
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/PackageMarker.java b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/PackageMarker.java
new file mode 100644
index 0000000..cb64e93
--- /dev/null
+++ b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/PackageMarker.java
@@ -0,0 +1,37 @@
+/*
+ * 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.tck;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This is a dummy annotation that forces javac to produce output for
+ * otherwise empty package-info.java.
+ *
+ * <p>The result is maven-compiler-plugin can properly identify the scope of
+ * changed files
+ *
+ * <p>See more details in
+ * <a href="https://jira.codehaus.org/browse/MCOMPILER-205">
+ *   maven-compiler-plugin: incremental compilation broken</a>
+ */
+@Retention(RetentionPolicy.SOURCE)
+public @interface PackageMarker {
+}
+
+// End PackageMarker.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/TestRunner.java
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/TestRunner.java b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/TestRunner.java
new file mode 100644
index 0000000..9ada4a4
--- /dev/null
+++ b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/TestRunner.java
@@ -0,0 +1,274 @@
+/*
+ * 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.tck;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.ClassPath;
+import com.google.common.reflect.ClassPath.ClassInfo;
+
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Modifier;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Entry point for running an Avatica cross-version compatibility test.
+ */
+public class TestRunner implements Runnable {
+  private static final Logger LOG = LoggerFactory.getLogger(TestRunner.class);
+  private static final String ANSI_RESET = "\u001B[0m";
+  private static final String ANSI_RED = "\u001B[31m";
+  private static final String ANSI_GREEN = "\u001B[32m";
+
+  private static Driver driver;
+  private static String driverUrl;
+
+  @Parameter(names = { "-u", "--jdbcUrl" }, description = "JDBC URL for Avatica Driver")
+  private String jdbcUrl;
+
+  private JUnitCore junitCore;
+
+  /**
+   * Returns the {@link Connection} for tests to use.
+   *
+   * @return A JDBC Connection.
+   */
+  public static Connection getConnection() throws SQLException {
+    if (null == driver) {
+      throw new IllegalStateException("JDBC Driver is not initialized");
+    }
+
+    return driver.connect(driverUrl, new Properties());
+  }
+
+  @Override public void run() {
+    // Construct the Connection
+    initializeDriver();
+
+    if (null == driver) {
+      LOG.error("Failed to find driver for {}", jdbcUrl);
+      System.exit(TestRunnerExitCodes.NO_SUCH_DRIVER.ordinal());
+      return;
+    }
+
+    // Initialize JUnit
+    initializeJUnit();
+
+    // Enumerate available test cases
+    final List<Class<?>> testClasses = getAllTestClasses();
+
+    final TestResults globalResults = new TestResults();
+
+    // Run each test case
+    for (Class<?> testClass : testClasses) {
+      runSingleTest(globalResults, testClass);
+    }
+
+    System.out.println(globalResults.summarize());
+
+    if (globalResults.numFailed > 0) {
+      // Tests failed, don't exit normally
+      System.exit(TestRunnerExitCodes.FAILED_TESTS.ordinal());
+    } else {
+      // Exited normally
+      System.exit(TestRunnerExitCodes.NORMAL.ordinal());
+    }
+  }
+
+  /**
+   * Finds all tests to run for the TCK.
+   *
+   * @return A list of test classes to run.
+   */
+  List<Class<?>> getAllTestClasses() {
+    try {
+      ClassPath cp = ClassPath.from(getClass().getClassLoader());
+      ImmutableSet<ClassInfo> classes =
+          cp.getTopLevelClasses("org.apache.calcite.avatica.tck.tests");
+
+      List<Class<?>> testClasses = new ArrayList<>(classes.size());
+      for (ClassInfo classInfo : classes) {
+        if (classInfo.getSimpleName().equals("package-info")) {
+          continue;
+        }
+        Class<?> clz = Class.forName(classInfo.getName());
+        if (Modifier.isAbstract(clz.getModifiers())) {
+          // Ignore abstract classes
+          continue;
+        }
+        testClasses.add(clz);
+      }
+
+      return testClasses;
+    } catch (Exception e) {
+      LOG.error("Failed to instantiate test classes", e);
+      System.exit(TestRunnerExitCodes.TEST_CASE_INSTANTIATION.ordinal());
+      // Unreachable..
+      return null;
+    }
+  }
+
+  void initializeDriver() {
+    try {
+      // Make sure the Avatica Driver gets loaded
+      Class.forName("org.apache.calcite.avatica.remote.Driver");
+      driverUrl = jdbcUrl;
+      driver = DriverManager.getDriver(driverUrl);
+    } catch (SQLException e) {
+      LOG.error("Could not instantiate JDBC Driver with URL: '{}'", jdbcUrl, e);
+      System.exit(TestRunnerExitCodes.BAD_JDBC_URL.ordinal());
+    } catch (ClassNotFoundException e) {
+      LOG.error("Could not load Avatica Driver class", e);
+      System.exit(TestRunnerExitCodes.MISSING_DRIVER_CLASS.ordinal());
+    }
+  }
+
+  /**
+   * Sets up JUnit to run the tests for us.
+   */
+  void initializeJUnit() {
+    junitCore = new JUnitCore();
+
+    junitCore.addListener(new RunListener() {
+      @Override public void testStarted(Description description) throws Exception {
+        LOG.debug("Starting {}", description);
+      }
+
+      @Override public void testFinished(Description description) throws Exception {
+        LOG.debug("{}Finished {}{}", ANSI_GREEN, description, ANSI_RESET);
+      }
+
+      @Override public void testFailure(Failure failure) throws Exception {
+        LOG.info("{}Failed {}{}", ANSI_RED, failure.getDescription(), ANSI_RESET,
+            failure.getException());
+      }
+    });
+  }
+
+  /**
+   * Runs a single test class, adding its results to <code>globalResults</code>.
+   *
+   * @param globalResults A global record of test results.
+   * @param testClass The test class to run.
+   */
+  void runSingleTest(final TestResults globalResults, final Class<?> testClass) {
+    final String className = Objects.requireNonNull(testClass).getName();
+    LOG.info("{}Running {}{}", ANSI_GREEN, className, ANSI_RESET);
+
+    try {
+      Result result = junitCore.run(testClass);
+      globalResults.merge(testClass, result);
+    } catch (Exception e) {
+      // most likely JUnit issues, like no tests to run
+      LOG.error("{}Test failed: {}{}", ANSI_RED, className, ANSI_RESET, e);
+    }
+  }
+
+  public static void main(String[] args) {
+    TestRunner runner = new TestRunner();
+
+    // Parse the args, sets it on runner.
+    new JCommander(runner, args);
+
+    // Run the tests.
+    runner.run();
+  }
+
+  /**
+   * A container to track results from all tests executed.
+   */
+  private static class TestResults {
+    private int numRun = 0;
+    private int numFailed = 0;
+    private int numIgnored = 0;
+    private List<Failure> failures = new ArrayList<>();
+
+    /**
+     * Updates the current state of <code>this</code> with the <code>result</code>.
+     *
+     * @param testClass The test class executed.
+     * @param result The results of the test class execution.
+     * @return <code>this</code>
+     */
+    public TestResults merge(Class<?> testClass, Result result) {
+      LOG.info("Tests run: {}, Failures: {}, Skipped: {}, Time elapsed: {} - in {}",
+          result.getRunCount(), result.getFailureCount(), result.getIgnoreCount(),
+          TimeUnit.SECONDS.convert(result.getRunTime(), TimeUnit.MILLISECONDS),
+          testClass.getName());
+
+      numRun += result.getRunCount();
+      numFailed += result.getFailureCount();
+      numIgnored += result.getIgnoreCount();
+
+      // Collect the failures
+      if (!result.wasSuccessful()) {
+        failures.addAll(result.getFailures());
+      }
+
+      return this;
+    }
+
+    /**
+     * Constructs a human-readable summary of the success/failure of the tests executed.
+     *
+     * @return A summary in the form of a String.
+     */
+    public String summarize() {
+      StringBuilder sb = new StringBuilder(64);
+      sb.append("\nTest Summary: Run: ").append(numRun).append(", Failed: ").append(numFailed);
+      sb.append(", Skipped: ").append(numIgnored);
+      if (numFailed > 0) {
+        sb.append(ANSI_RED).append("\n\nFailures:").append(ANSI_RESET).append("\n\n");
+        for (Failure failure : failures) {
+          sb.append(failure.getTestHeader()).append(" ").append(failure.getMessage()).append("\n");
+        }
+      }
+      return sb.toString();
+    }
+  }
+
+  /**
+   * ExitCodes set by {@link TestRunner}.
+   */
+  private enum TestRunnerExitCodes {
+    // Position is important, ordinal() is used!
+    NORMAL,                  // 0, all tests passed
+    BAD_JDBC_URL,            // 1
+    TEST_CASE_INSTANTIATION, // 2
+    NO_SUCH_DRIVER,          // 3
+    FAILED_TESTS,            // 4
+    MISSING_DRIVER_CLASS;    // 5
+  }
+}
+
+// End TestRunner.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/package-info.java
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/package-info.java b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/package-info.java
new file mode 100644
index 0000000..77c2d16
--- /dev/null
+++ b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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 compatibility framework.
+ */
+@PackageMarker
+package org.apache.calcite.avatica.tck;
+
+// End package-info.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/BaseTckTest.java
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/BaseTckTest.java b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/BaseTckTest.java
new file mode 100644
index 0000000..8799cf1
--- /dev/null
+++ b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/BaseTckTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.tck.tests;
+
+import org.apache.calcite.avatica.tck.TestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+
+import java.sql.Connection;
+
+/**
+ * Base class for TCK tests.
+ */
+public abstract class BaseTckTest {
+
+  @Rule public TestName name = new TestName();
+
+  protected Connection connection;
+
+  @Before public void initializeConnection() throws Exception {
+    connection = TestRunner.getConnection();
+  }
+
+  @After public void closeConnection() throws Exception {
+    if (null != connection) {
+      connection.close();
+    }
+  }
+
+  protected Connection getConnection() {
+    return connection;
+  }
+
+  protected String getTableName() {
+    return getClass().getSimpleName() + "_" + name.getMethodName();
+  }
+}
+
+// End BaseTckTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/InsertTest.java
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/InsertTest.java b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/InsertTest.java
new file mode 100644
index 0000000..11c44d7
--- /dev/null
+++ b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/InsertTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.tck.tests;
+
+import org.junit.Assume;
+import org.junit.Test;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.Statement;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for <code>INSERT</code>.
+ */
+public class InsertTest extends BaseTckTest {
+
+  @Test public void simpleInsert() throws Exception {
+    final String tableName = getTableName();
+    try (Statement stmt = connection.createStatement()) {
+      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
+      String sql = "CREATE TABLE " + tableName
+          + " (pk integer not null primary key, col1 varchar(10))";
+      assertFalse(stmt.execute(sql));
+
+      for (int i = 0; i < 10; i++) {
+        sql = "INSERT INTO " + tableName + " values (" + i + ", '" + i + "')";
+        assertEquals(1, stmt.executeUpdate(sql));
+      }
+
+      ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName);
+      assertNotNull(results);
+      for (int i = 0; i < 10; i++) {
+        assertTrue(results.next());
+        assertEquals(i, results.getInt(1));
+        assertEquals(Integer.toString(i), results.getString(1));
+      }
+      assertFalse(results.next());
+      results.close();
+    }
+  }
+
+  @Test public void preparedStatementInsert() throws Exception {
+    final String tableName = getTableName();
+    final String insertSql = "INSERT INTO " + tableName + " values(?, ?)";
+    try (Statement stmt = connection.createStatement()) {
+      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
+      String sql = "CREATE TABLE " + tableName
+          + " (pk integer not null primary key, col1 varchar(10))";
+      assertFalse(stmt.execute(sql));
+
+      try (PreparedStatement pstmt = connection.prepareStatement(insertSql)) {
+        for (int i = 0; i < 10; i++) {
+          pstmt.setInt(1, i);
+          pstmt.setString(2, "a_" + Integer.toString(i));
+          assertEquals(1, pstmt.executeUpdate());
+        }
+      }
+
+      ResultSet results = stmt.executeQuery("SELECT COUNT(pk) from " + tableName);
+      assertNotNull(results);
+      assertTrue(results.next());
+      assertEquals(10, results.getInt(1));
+
+      results = stmt.executeQuery("SELECT * from " + tableName);
+      assertNotNull(results);
+      for (int i = 0; i < 10; i++) {
+        assertTrue(results.next());
+        assertEquals(i, results.getInt(1));
+        assertEquals("a_" + i, results.getString(2));
+      }
+      assertFalse(results.next());
+      results.close();
+    }
+  }
+
+  @Test public void batchInsert() throws Exception {
+    final String tableName = getTableName();
+    try (Statement stmt = connection.createStatement()) {
+      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
+      String sql = "CREATE TABLE " + tableName
+          + " (pk integer not null primary key, col1 varchar(10))";
+      assertFalse(stmt.execute(sql));
+
+      for (int i = 0; i < 10; i++) {
+        sql = "INSERT INTO " + tableName + " values (" + i + ", '" + i + "')";
+        try {
+          stmt.addBatch(sql);
+        } catch (SQLFeatureNotSupportedException e) {
+          // batch isn't supported in this version, gracefully ignore,
+          Assume.assumeTrue("Batch update is not support by the client", false);
+        }
+      }
+
+      int[] updateCounts = stmt.executeBatch();
+      int[] expectedUpdateCounts = new int[10];
+      Arrays.fill(expectedUpdateCounts, 1);
+      assertArrayEquals(expectedUpdateCounts, updateCounts);
+
+      ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName);
+      assertNotNull(results);
+      for (int i = 0; i < 10; i++) {
+        assertTrue(results.next());
+        assertEquals(i, results.getInt(1));
+        assertEquals(Integer.toString(i), results.getString(1));
+      }
+      assertFalse(results.next());
+      results.close();
+    }
+  }
+
+  @Test public void preparedBatchInsert() throws Exception {
+    final String tableName = getTableName();
+    final String insertSql = "INSERT INTO " + tableName + " values(?, ?)";
+    try (Statement stmt = connection.createStatement()) {
+      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
+      String sql = "CREATE TABLE " + tableName
+          + " (pk integer not null primary key, col1 varchar(10))";
+      assertFalse(stmt.execute(sql));
+
+      try (PreparedStatement pstmt = connection.prepareStatement(insertSql)) {
+        for (int i = 0; i < 10; i++) {
+          pstmt.setInt(1, i);
+          pstmt.setString(2, "a_" + Integer.toString(i));
+          try {
+            pstmt.addBatch();
+          } catch (SQLFeatureNotSupportedException e) {
+            // batch isn't supported in this version, gracefully ignore,
+            Assume.assumeTrue("Batch update is not support by the client", false);
+          }
+        }
+
+        int[] updateCounts = pstmt.executeBatch();
+        int[] expectedUpdateCounts = new int[10];
+        Arrays.fill(expectedUpdateCounts, 1);
+        assertArrayEquals(expectedUpdateCounts, updateCounts);
+      }
+
+      ResultSet results = stmt.executeQuery("SELECT COUNT(pk) from " + tableName);
+      assertNotNull(results);
+      assertTrue(results.next());
+      assertEquals(10, results.getInt(1));
+
+      results = stmt.executeQuery("SELECT * from " + tableName);
+      assertNotNull(results);
+      for (int i = 0; i < 10; i++) {
+        assertTrue(results.next());
+        assertEquals(i, results.getInt(1));
+        assertEquals("a_" + i, results.getString(2));
+      }
+      assertFalse(results.next());
+      results.close();
+    }
+  }
+
+  @Test public void commitAndRollback() throws Exception {
+    final String tableName = getTableName();
+
+    // Disable autoCommit
+    connection.setAutoCommit(false);
+    assertFalse(connection.getAutoCommit());
+
+    try (Statement stmt = connection.createStatement()) {
+      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
+      String sql = "CREATE TABLE " + tableName
+          + " (pk integer not null primary key, col1 varchar(10))";
+      assertFalse(stmt.execute(sql));
+
+      for (int i = 0; i < 10; i++) {
+        sql = "INSERT INTO " + tableName + " values (" + i + ", '" + i + "')";
+        assertEquals(1, stmt.executeUpdate(sql));
+        if (i == 4) {
+          // Rollback after the first 5 updates
+          connection.rollback();
+        }
+      }
+      connection.commit();
+
+      ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName);
+      assertNotNull(results);
+      for (int i = 5; i < 10; i++) {
+        assertTrue(results.next());
+        assertEquals(i, results.getInt(1));
+        assertEquals(Integer.toString(i), results.getString(1));
+      }
+      assertFalse(results.next());
+      results.close();
+    }
+  }
+}
+
+// End InsertTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/MetadataTest.java
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/MetadataTest.java b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/MetadataTest.java
new file mode 100644
index 0000000..9c92ec0
--- /dev/null
+++ b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/MetadataTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.tck.tests;
+
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.sql.Types;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test class for metadata operations (parameter, resultset).
+ */
+public class MetadataTest extends BaseTckTest {
+
+  @Test public void parameterMetadata() throws Exception {
+    final String tableName = getTableName();
+    try (Statement stmt = getConnection().createStatement()) {
+      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
+      String sql = "CREATE TABLE " + tableName + " (pk integer not null primary key, "
+          + "col1 DECIMAL(10, 5), col2 boolean not null)";
+      assertFalse(stmt.execute(sql));
+
+      String insertSql = "INSERT INTO " + tableName + " values(?, ?, ?)";
+      try (PreparedStatement pstmt = getConnection().prepareStatement(insertSql)) {
+        ParameterMetaData params = pstmt.getParameterMetaData();
+        assertEquals(3, params.getParameterCount());
+
+        assertEquals(Types.INTEGER, params.getParameterType(1));
+        assertTrue(params.isSigned(1));
+        assertTrue(ParameterMetaData.parameterNoNulls == params.isNullable(1)
+            || ParameterMetaData.parameterNullableUnknown == params.isNullable(1));
+
+        assertEquals(Types.DECIMAL, params.getParameterType(2));
+        assertTrue(params.isSigned(2));
+        assertTrue(ParameterMetaData.parameterNullable == params.isNullable(2)
+            || ParameterMetaData.parameterNullableUnknown == params.isNullable(2));
+        assertEquals(10, params.getPrecision(2));
+        assertEquals(5, params.getScale(2));
+
+        assertEquals(Types.BOOLEAN, params.getParameterType(3));
+        assertFalse(params.isSigned(3));
+        assertTrue(ParameterMetaData.parameterNoNulls == params.isNullable(3)
+            || ParameterMetaData.parameterNullableUnknown == params.isNullable(3));
+
+        // CALCITE-1103 <1.8.0 server mishandled the protobuf translation from BIG_DECIMAL to NUMBER
+        pstmt.setInt(1, Integer.MAX_VALUE);
+        pstmt.setBigDecimal(2, new BigDecimal("12345.12345"));
+        pstmt.setBoolean(3, true);
+        assertEquals(1, pstmt.executeUpdate());
+
+        pstmt.setInt(1, Integer.MIN_VALUE);
+        pstmt.setBigDecimal(2, new BigDecimal("54321.54321"));
+        pstmt.setBoolean(3, false);
+        assertEquals(1, pstmt.executeUpdate());
+      }
+
+      ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY pk");
+      assertNotNull(results);
+      ResultSetMetaData resultMetadata = results.getMetaData();
+      // Verify result metadata
+      assertEquals(3, resultMetadata.getColumnCount());
+
+      assertTrue(ParameterMetaData.parameterNoNulls == resultMetadata.isNullable(1)
+          || ParameterMetaData.parameterNullableUnknown == resultMetadata.isNullable(1));
+      assertEquals(Types.INTEGER, resultMetadata.getColumnType(1));
+      assertTrue(resultMetadata.isSigned(1));
+
+      assertTrue(ParameterMetaData.parameterNullable == resultMetadata.isNullable(2)
+          || ParameterMetaData.parameterNullableUnknown == resultMetadata.isNullable(2));
+      assertEquals(Types.DECIMAL, resultMetadata.getColumnType(2));
+      assertTrue(resultMetadata.isSigned(2));
+      assertEquals(10, resultMetadata.getPrecision(2));
+      assertEquals(5, resultMetadata.getScale(2));
+
+      assertTrue(ParameterMetaData.parameterNoNulls == resultMetadata.isNullable(3)
+          || ParameterMetaData.parameterNullableUnknown == resultMetadata.isNullable(3));
+      assertEquals(Types.BOOLEAN, resultMetadata.getColumnType(3));
+      assertFalse(resultMetadata.isSigned(3));
+
+      // Verify the results
+      assertTrue(results.next());
+      assertEquals(Integer.MIN_VALUE, results.getInt(1));
+      // CALCITE-1103 protobuf truncated decimal value
+      BigDecimal buggyDecimalValue = new BigDecimal("54321.00000");
+      BigDecimal expectedDecimalValue = new BigDecimal("54321.54321");
+      BigDecimal actualDecimalValue = results.getBigDecimal(2);
+      assertTrue("Unexpected decimal value of " + actualDecimalValue,
+          expectedDecimalValue.equals(actualDecimalValue)
+          || buggyDecimalValue.equals(actualDecimalValue));
+      assertEquals(false, results.getBoolean(3));
+
+      assertTrue(results.next());
+      assertEquals(Integer.MAX_VALUE, results.getInt(1));
+      // CALCITE-1103 protobuf truncated decimal value
+      buggyDecimalValue = new BigDecimal("12345.00000");
+      expectedDecimalValue = new BigDecimal("12345.12345");
+      actualDecimalValue = results.getBigDecimal(2);
+      assertTrue("Unexpected decimal value of " + actualDecimalValue,
+          expectedDecimalValue.equals(actualDecimalValue)
+          || buggyDecimalValue.equals(actualDecimalValue));
+      assertEquals(true, results.getBoolean(3));
+
+      assertFalse(results.next());
+    }
+  }
+}
+
+// End MetadataTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2197f7dc/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/package-info.java
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/package-info.java b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/package-info.java
new file mode 100644
index 0000000..940a1bd
--- /dev/null
+++ b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/tests/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.
+ */
+
+/**
+ * Tests for the Avatica compatibility framework.
+ */
+@PackageMarker
+package org.apache.calcite.avatica.tck.tests;
+
+import org.apache.calcite.avatica.tck.PackageMarker;
+
+// End package-info.java