/*
 * 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;

import org.apache.calcite.avatica.Meta.DatabaseProperty;
import org.apache.calcite.avatica.jdbc.JdbcMeta;
import org.apache.calcite.avatica.remote.JsonService;
import org.apache.calcite.avatica.remote.LocalJsonService;
import org.apache.calcite.avatica.remote.LocalProtobufService;
import org.apache.calcite.avatica.remote.LocalService;
import org.apache.calcite.avatica.remote.ProtobufTranslation;
import org.apache.calcite.avatica.remote.ProtobufTranslationImpl;
import org.apache.calcite.avatica.remote.Service;
import org.apache.calcite.avatica.remote.TypedValue;
import org.apache.calcite.avatica.util.DateTimeUtils;

import com.google.common.cache.Cache;

import net.jcip.annotations.NotThreadSafe;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.Callable;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.core.StringContains.containsString;
import static org.hamcrest.core.StringStartsWith.startsWith;
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.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
 * Unit test for Avatica Remote JDBC driver.
 */
@RunWith(Parameterized.class)
@NotThreadSafe // for testConnectionIsolation
public class RemoteDriverTest {
  private static final Logger LOG = LoggerFactory.getLogger(RemoteDriverTest.class);

  public static final String LJS =
      LocalJdbcServiceFactory.class.getName();

  public static final String QRJS =
      QuasiRemoteJdbcServiceFactory.class.getName();

  public static final String QRPBS =
      QuasiRemotePBJdbcServiceFactory.class.getName();

  private static final ConnectionSpec CONNECTION_SPEC = ConnectionSpec.HSQLDB;

  private static Connection ljs() throws SQLException {
    return DriverManager.getConnection("jdbc:avatica:remote:factory=" + QRJS);
  }

  private static Connection lpbs() throws SQLException {
    return DriverManager.getConnection("jdbc:avatica:remote:factory=" + QRPBS);
  }

  private Connection canon() throws SQLException {
    return DriverManager.getConnection(CONNECTION_SPEC.url,
        CONNECTION_SPEC.username, CONNECTION_SPEC.password);
  }

  /**
   * Interface that allows for alternate ways to access internals to the Connection for testing
   * purposes.
   */
  interface ConnectionInternals {
    /**
     * Reaches into the guts of a quasi-remote connection and pull out the
     * statement map from the other side.
     *
     * <p>TODO: refactor tests to replace reflection with package-local access
     */
    Cache<Integer, Object> getRemoteStatementMap(AvaticaConnection connection) throws Exception;

    /**
     * Reaches into the guts of a quasi-remote connection and pull out the
     * connection map from the other side.
     *
     * <p>TODO: refactor tests to replace reflection with package-local access
     */
    Cache<String, Connection> getRemoteConnectionMap(AvaticaConnection connection) throws Exception;
  }

  // Run each test with the LocalJsonService and LocalProtobufService
  @Parameters(name = "{0}")
  public static List<Object[]> parameters() {
    List<Object[]> connections = new ArrayList<>();

    // Json and Protobuf operations should be equivalent -- tests against one work on the other
    // Each test needs to get a fresh Connection and also access some internals on that Connection.

    connections.add(
        new Object[] {
            "JSON",
            new Callable<Connection>() {
              public Connection call() {
                try {
                  return ljs();
                } catch (SQLException e) {
                  throw new RuntimeException(e);
                }
              }
            },
            new QuasiRemoteJdbcServiceInternals(),
            new Callable<RequestInspection>() {
              public RequestInspection call() throws Exception {
                assert null != QuasiRemoteJdbcServiceFactory.requestInspection;
                return QuasiRemoteJdbcServiceFactory.requestInspection;
              }
            } });

    // TODO write the ConnectionInternals implementation
    connections.add(
        new Object[] {
            "PROTOBUF",
            new Callable<Connection>() {
              public Connection call() {
                try {
                  return lpbs();
                } catch (SQLException e) {
                  throw new RuntimeException(e);
                }
              }
            },
            new QuasiRemoteProtobufJdbcServiceInternals(),
            new Callable<RequestInspection>() {
              public RequestInspection call() throws Exception {
                assert null != QuasiRemotePBJdbcServiceFactory.requestInspection;
                return QuasiRemotePBJdbcServiceFactory.requestInspection;
              }
            } });

    return connections;
  }

  private final Callable<Connection> localConnectionCallable;
  private final ConnectionInternals localConnectionInternals;
  private final Callable<RequestInspection> requestInspectionCallable;

  public RemoteDriverTest(String name, Callable<Connection> localConnectionCallable,
      ConnectionInternals internals, Callable<RequestInspection> requestInspectionCallable) {
    this.localConnectionCallable = localConnectionCallable;
    this.localConnectionInternals = internals;
    this.requestInspectionCallable = requestInspectionCallable;
  }

  private Connection getLocalConnection() {
    try {
      return localConnectionCallable.call();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  private ConnectionInternals getLocalConnectionInternals() {
    return localConnectionInternals;
  }

  private RequestInspection getRequestInspection() {
    try {
      return requestInspectionCallable.call();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /** Executes a lambda for the canonical connection and the local
   * connection. */
  public void eachConnection(ConnectionFunction f, Connection localConn) throws Exception {
    for (int i = 0; i < 2; i++) {
      try (Connection connection = i == 0 ? canon() : localConn) {
        f.apply(connection);
      }
    }
  }

  @Before
  public void before() throws Exception {
    QuasiRemoteJdbcServiceFactory.initService();
    QuasiRemotePBJdbcServiceFactory.initService();
  }

  @Test public void testRegister() throws Exception {
    final Connection connection = getLocalConnection();
    assertThat(connection.isClosed(), is(false));
    connection.close();
    assertThat(connection.isClosed(), is(true));
  }

  @Test public void testIsValid() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      final Connection connection = getLocalConnection();
      try {
        connection.isValid(-1);
        fail("Connection isValid should throw SQLException on negative timeout");
      } catch (SQLException expected) {
        assertEquals("timeout is less than 0", expected.getMessage());
      }

      // Check that connection isValid before and during use
      assertThat(connection.isValid(1), is(true));
      Statement statement = connection.createStatement();
      assertTrue(statement.execute("VALUES 1"));
      assertNotNull(statement.getResultSet());
      assertThat(connection.isValid(1), is(true));
      statement.close();
      assertThat(connection.isValid(1), is(true));

      // Connection should be invalid after being closed
      connection.close();
      assertThat(connection.isValid(1), is(false));
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testDatabaseProperties() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      final Connection connection = getLocalConnection();
      for (Meta.DatabaseProperty p : Meta.DatabaseProperty.values()) {
        switch (p) {
        case GET_NUMERIC_FUNCTIONS:
          assertThat(connection.getMetaData().getNumericFunctions(),
              equalTo("ABS,ACOS,ASIN,ATAN,ATAN2,BITAND,BITOR,BITXOR,"
                  + "CEILING,COS,COT,DEGREES,EXP,FLOOR,LOG,LOG10,MOD,"
                  + "PI,POWER,RADIANS,RAND,ROUND,ROUNDMAGIC,SIGN,SIN,"
                  + "SQRT,TAN,TRUNCATE"));
          break;
        case GET_SYSTEM_FUNCTIONS:
          assertThat(connection.getMetaData().getSystemFunctions(),
              equalTo("DATABASE,IFNULL,USER"));
          break;
        case GET_TIME_DATE_FUNCTIONS:
          assertThat(connection.getMetaData().getTimeDateFunctions(),
              equalTo("CURDATE,CURTIME,DATEDIFF,DAYNAME,DAYOFMONTH,DAYOFWEEK,"
                  + "DAYOFYEAR,HOUR,MINUTE,MONTH,MONTHNAME,NOW,QUARTER,SECOND,"
                  + "SECONDS_SINCE_MIDNIGHT,TIMESTAMPADD,TIMESTAMPDIFF,"
                  + "TO_CHAR,WEEK,YEAR"));
          break;
        case GET_S_Q_L_KEYWORDS:
          assertThat(connection.getMetaData().getSQLKeywords(),
              equalTo("")); // No SQL keywords return for HSQLDB
          break;
        case GET_STRING_FUNCTIONS:
          assertThat(connection.getMetaData().getStringFunctions(),
              equalTo("ASCII,CHAR,CONCAT,DIFFERENCE,HEXTORAW,INSERT,LCASE,"
                  + "LEFT,LENGTH,LOCATE,LTRIM,RAWTOHEX,REPEAT,REPLACE,"
                  + "RIGHT,RTRIM,SOUNDEX,SPACE,SUBSTR,UCASE"));
          break;
        default:
        }
      }
      connection.close();
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testTypeInfo() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      final Connection connection = getLocalConnection();
      final ResultSet resultSet =
          connection.getMetaData().getTypeInfo();
      assertTrue(resultSet.next());
      final ResultSetMetaData metaData = resultSet.getMetaData();
      assertTrue(metaData.getColumnCount() >= 18);
      assertEquals("TYPE_NAME", metaData.getColumnName(1));
      assertEquals("DATA_TYPE", metaData.getColumnName(2));
      assertEquals("PRECISION", metaData.getColumnName(3));
      assertEquals("SQL_DATA_TYPE", metaData.getColumnName(16));
      assertEquals("SQL_DATETIME_SUB", metaData.getColumnName(17));
      assertEquals("NUM_PREC_RADIX", metaData.getColumnName(18));
      resultSet.close();
      connection.close();
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testGetTables() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      final Connection connection = getLocalConnection();
      final ResultSet resultSet =
              connection.getMetaData().getTables(null, "SCOTT", null, null);
      assertEquals(13, resultSet.getMetaData().getColumnCount());
      assertTrue(resultSet.next());
      assertEquals("DEPT", resultSet.getString(3));
      assertTrue(resultSet.next());
      assertEquals("EMP", resultSet.getString(3));
      assertTrue(resultSet.next());
      assertEquals("BONUS", resultSet.getString(3));
      assertTrue(resultSet.next());
      assertEquals("SALGRADE", resultSet.getString(3));
      resultSet.close();
      connection.close();
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Ignore
  @Test public void testNoFactory() throws Exception {
    final Connection connection =
        DriverManager.getConnection("jdbc:avatica:remote:");
    assertThat(connection.isClosed(), is(false));
    final ResultSet resultSet = connection.getMetaData().getSchemas();
    assertFalse(resultSet.next());
    final ResultSetMetaData metaData = resultSet.getMetaData();
    assertEquals(2, metaData.getColumnCount());
    assertEquals("TABLE_SCHEM", metaData.getColumnName(1));
    assertEquals("TABLE_CATALOG", metaData.getColumnName(2));
    resultSet.close();
    connection.close();
    assertThat(connection.isClosed(), is(true));
  }

  @Test public void testStatementExecuteQueryLocal() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      checkStatementExecuteQuery(getLocalConnection(), false);
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testPrepareExecuteQueryLocal() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      checkStatementExecuteQuery(getLocalConnection(), true);
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testInsertDrop() throws Exception {
    final String t = AvaticaUtils.unique("TEST_TABLE2");
    final String create =
        String.format(Locale.ROOT, "create table if not exists %s ("
            + "id int not null, "
            + "msg varchar(3) not null)", t);
    final String insert = String.format(Locale.ROOT,
        "insert into %s values(1, 'foo')", t);
    Connection connection = ljs();
    Statement statement = connection.createStatement();
    statement.execute(create);

    Statement stmt = connection.createStatement();
    int count = stmt.executeUpdate(insert);
    assertThat(count, is(1));
    ResultSet resultSet = stmt.getResultSet();
    assertThat(resultSet, nullValue());

    PreparedStatement pstmt = connection.prepareStatement(insert);
    boolean status = pstmt.execute();
    assertThat(status, is(false));
    int updateCount = pstmt.getUpdateCount();
    assertThat(updateCount, is(1));
  }

  private void checkStatementExecuteQuery(Connection connection,
      boolean prepare) throws SQLException {
    final String sql = "select * from (\n"
        + "  values (1, 'a'), (null, 'b'), (3, 'c')) as t (c1, c2)";
    final Statement statement;
    final ResultSet resultSet;
    final ParameterMetaData parameterMetaData;
    if (prepare) {
      final PreparedStatement ps = connection.prepareStatement(sql);
      statement = ps;
      parameterMetaData = ps.getParameterMetaData();
      resultSet = ps.executeQuery();
    } else {
      statement = connection.createStatement();
      parameterMetaData = null;
      resultSet = statement.executeQuery(sql);
    }
    if (parameterMetaData != null) {
      assertThat(parameterMetaData.getParameterCount(), equalTo(0));
    }
    final ResultSetMetaData metaData = resultSet.getMetaData();
    assertEquals(2, metaData.getColumnCount());
    assertEquals("C1", metaData.getColumnName(1));
    assertEquals("C2", metaData.getColumnName(2));
    assertTrue(resultSet.next());
    assertTrue(resultSet.next());
    assertTrue(resultSet.next());
    assertFalse(resultSet.next());
    resultSet.close();
    statement.close();
    connection.close();
  }

  @Test public void testStatementExecuteLocal() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      checkStatementExecute(getLocalConnection(), false);
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testStatementExecuteFetch() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      // Creating a > 100 rows queries to enable fetch request
      String sql = "select * from emp cross join emp";
      checkExecuteFetch(getLocalConnection(), sql, false, 1);
      // PreparedStatement needed an extra fetch, as the execute will
      // trigger the 1st fetch. Where statement execute will execute direct
      // with results back.
      // 1 fetch, because execute did the first fetch
      checkExecuteFetch(getLocalConnection(), sql, true, 1);
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void checkExecuteFetch(Connection conn, String sql, boolean isPrepare,
      int fetchCountMatch) throws SQLException {
    final Statement exeStatement;
    final ResultSet results;
    getRequestInspection().getRequestLogger().enableAndClear();
    if (isPrepare) {
      PreparedStatement statement = conn.prepareStatement(sql);
      exeStatement = statement;
      results = statement.executeQuery();
    } else {
      Statement statement = conn.createStatement();
      exeStatement = statement;
      results = statement.executeQuery(sql);
    }
    int count = 0;
    int fetchCount = 0;
    while (results.next()) {
      count++;
    }
    results.close();
    exeStatement.close();
    List<String[]> x = getRequestInspection().getRequestLogger().getAndDisable();
    for (String[] pair : x) {
      if (pair[0].contains("\"request\":\"fetch")) {
        fetchCount++;
      }
    }
    assertEquals(count, 196);
    assertEquals(fetchCountMatch, fetchCount);
  }

  @Test public void testStatementExecuteLocalMaxRow() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      checkStatementExecute(getLocalConnection(), false, 2);
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testFetchSize() throws Exception {
    Connection connection = ljs();

    Statement statement = connection.createStatement();
    statement.setFetchSize(101);
    assertEquals(statement.getFetchSize(), 101);

    PreparedStatement preparedStatement =
        connection.prepareStatement("select * from (values (1, 'a')) as tbl1 (c1, c2)");
    preparedStatement.setFetchSize(1);
    assertEquals(preparedStatement.getFetchSize(), 1);
  }

  @Ignore("CALCITE-719: Refactor PreparedStatement to support setMaxRows")
  @Test public void testStatementPrepareExecuteLocalMaxRow() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      checkStatementExecute(getLocalConnection(), true, 2);
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testPrepareExecuteLocal() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      checkStatementExecute(getLocalConnection(), true);
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void checkStatementExecute(Connection connection,
      boolean prepare) throws SQLException {
    checkStatementExecute(connection, prepare, 0);
  }
  private void checkStatementExecute(Connection connection,
      boolean prepare, int maxRowCount) throws SQLException {
    final String sql = "select * from (\n"
        + "  values (1, 'a'), (null, 'b'), (3, 'c')) as t (c1, c2)";
    final Statement statement;
    final ResultSet resultSet;
    final ParameterMetaData parameterMetaData;
    if (prepare) {
      final PreparedStatement ps = connection.prepareStatement(sql);
      statement = ps;
      ps.setMaxRows(maxRowCount);
      parameterMetaData = ps.getParameterMetaData();
      assertTrue(ps.execute());
      resultSet = ps.getResultSet();
    } else {
      statement = connection.createStatement();
      statement.setMaxRows(maxRowCount);
      parameterMetaData = null;
      assertTrue(statement.execute(sql));
      resultSet = statement.getResultSet();
    }
    if (parameterMetaData != null) {
      assertThat(parameterMetaData.getParameterCount(), equalTo(0));
    }
    final ResultSetMetaData metaData = resultSet.getMetaData();
    assertEquals(2, metaData.getColumnCount());
    assertEquals("C1", metaData.getColumnName(1));
    assertEquals("C2", metaData.getColumnName(2));
    for (int i = 0; i < maxRowCount || (maxRowCount == 0 && i < 3); i++) {
      assertTrue(resultSet.next());
    }
    assertFalse(resultSet.next());
    resultSet.close();
    statement.close();
    connection.close();
  }

  @Test public void testCreateInsertUpdateDrop() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    final String t = AvaticaUtils.unique("TEST_TABLE");
    final String drop =
        String.format(Locale.ROOT, "drop table %s if exists", t);
    final String create =
        String.format(Locale.ROOT, "create table %s("
                + "id int not null, "
                + "msg varchar(3) not null)",
            t);
    final String insert = String.format(Locale.ROOT,
        "insert into %s values(1, 'foo')", t);
    final String update =
        String.format(Locale.ROOT, "update %s set msg='bar' where id=1", t);
    try (Connection connection = getLocalConnection();
        Statement statement = connection.createStatement();
        PreparedStatement pstmt = connection.prepareStatement("values 1")) {
      // drop
      assertFalse(statement.execute(drop));
      assertEquals(0, statement.getUpdateCount());
      assertNull(statement.getResultSet());
      try {
        final ResultSet rs = statement.executeQuery(drop);
        fail("expected error, got " + rs);
      } catch (SQLException e) {
        assertThat(e.getMessage(),
            equalTo("Statement did not return a result set"));
      }
      assertEquals(0, statement.executeUpdate(drop));
      assertEquals(0, statement.getUpdateCount());
      assertNull(statement.getResultSet());

      // create
      assertFalse(statement.execute(create));
      assertEquals(0, statement.getUpdateCount());
      assertNull(statement.getResultSet());
      assertFalse(statement.execute(drop)); // tidy up
      try {
        final ResultSet rs = statement.executeQuery(create);
        fail("expected error, got " + rs);
      } catch (SQLException e) {
        assertThat(e.getMessage(),
            equalTo("Statement did not return a result set"));
      }
      assertFalse(statement.execute(drop)); // tidy up
      assertEquals(0, statement.executeUpdate(create));
      assertEquals(0, statement.getUpdateCount());
      assertNull(statement.getResultSet());

      // insert
      assertFalse(statement.execute(insert));
      assertEquals(1, statement.getUpdateCount());
      assertNull(statement.getResultSet());
      try {
        final ResultSet rs = statement.executeQuery(insert);
        fail("expected error, got " + rs);
      } catch (SQLException e) {
        assertThat(e.getMessage(),
            equalTo("Statement did not return a result set"));
      }
      assertEquals(1, statement.executeUpdate(insert));
      assertEquals(1, statement.getUpdateCount());
      assertNull(statement.getResultSet());

      // update
      assertFalse(statement.execute(update));
      assertEquals(3, statement.getUpdateCount());
      assertNull(statement.getResultSet());
      try {
        final ResultSet rs = statement.executeQuery(update);
        fail("expected error, got " + rs);
      } catch (SQLException e) {
        assertThat(e.getMessage(),
            equalTo("Statement did not return a result set"));
      }
      assertEquals(3, statement.executeUpdate(update));
      assertEquals(3, statement.getUpdateCount());
      assertNull(statement.getResultSet());

      final String[] messages = {
          "Cannot call executeQuery(String) on prepared or callable statement",
          "Cannot call execute(String) on prepared or callable statement",
          "Cannot call executeUpdate(String) on prepared or callable statement",
      };
      for (String sql : new String[]{drop, create, insert, update}) {
        for (int i = 0; i <= 2; i++) {
          try {
            Object o;
            switch (i) {
            case 0:
              o = pstmt.executeQuery(sql);
              break;
            case 1:
              o = pstmt.execute(sql);
              break;
            default:
              o = pstmt.executeUpdate(sql);
            }
            fail("expected error, got " + o);
          } catch (SQLException e) {
            assertThat(e.getMessage(), equalTo(messages[i]));
          }
        }
      }
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testTypeHandling() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      final String query = "select * from EMP";
      try (Connection cannon = canon();
          Connection underTest = getLocalConnection();
          Statement s1 = cannon.createStatement();
          Statement s2 = underTest.createStatement()) {
        assertTrue(s1.execute(query));
        assertTrue(s2.execute(query));
        assertResultSetsEqual(s1, s2);
      }
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void assertResultSetsEqual(Statement s1, Statement s2)
      throws SQLException {
    final TimeZone moscowTz = TimeZone.getTimeZone("Europe/Moscow");
    final Calendar moscowCalendar =
        Calendar.getInstance(moscowTz, Locale.ROOT);
    final TimeZone alaskaTz = TimeZone.getTimeZone("America/Anchorage");
    final Calendar alaskaCalendar =
        Calendar.getInstance(alaskaTz, Locale.ROOT);
    try (ResultSet rs1 = s1.getResultSet();
        ResultSet rs2 = s2.getResultSet()) {
      assertEquals(rs1.getMetaData().getColumnCount(),
          rs2.getMetaData().getColumnCount());
      int colCount = rs1.getMetaData().getColumnCount();
      while (rs1.next() && rs2.next()) {
        for (int i = 0; i < colCount; i++) {
          Object o1 = rs1.getObject(i + 1);
          Object o2 = rs2.getObject(i + 1);
          if (o1 instanceof Integer && o2 instanceof Short) {
            // Hsqldb returns Integer for short columns; we prefer Short
            o1 = ((Number) o1).shortValue();
          }
          if (o1 instanceof Integer && o2 instanceof Byte) {
            // Hsqldb returns Integer for tinyint columns; we prefer Byte
            o1 = ((Number) o1).byteValue();
          }
          if (o1 instanceof Date) {
            Date d1 = rs1.getDate(i + 1, moscowCalendar);
            Date d2 = rs2.getDate(i + 1, moscowCalendar);
            assertEquals(d1, d2);
            d1 = rs1.getDate(i + 1, alaskaCalendar);
            d2 = rs2.getDate(i + 1, alaskaCalendar);
            assertEquals(d1, d2);
            d1 = rs1.getDate(i + 1, null);
            d2 = rs2.getDate(i + 1, null);
            assertEquals(d1, d2);
            d1 = rs1.getDate(i + 1);
            d2 = rs2.getDate(i + 1);
            assertEquals(d1, d2);
          }
          if (o1 instanceof Timestamp) {
            Timestamp d1 = rs1.getTimestamp(i + 1, moscowCalendar);
            Timestamp d2 = rs2.getTimestamp(i + 1, moscowCalendar);
            assertEquals(d1, d2);
            d1 = rs1.getTimestamp(i + 1, alaskaCalendar);
            d2 = rs2.getTimestamp(i + 1, alaskaCalendar);
            assertEquals(d1, d2);
            d1 = rs1.getTimestamp(i + 1, null);
            d2 = rs2.getTimestamp(i + 1, null);
            assertEquals(d1, d2);
            d1 = rs1.getTimestamp(i + 1);
            d2 = rs2.getTimestamp(i + 1);
            assertEquals(d1, d2);
          }
          assertEquals(o1, o2);
        }
      }
      assertEquals(rs1.next(), rs2.next());
    }
  }

  /** Callback to set parameters on each prepared statement before
   * each is executed and the result sets compared. */
  interface PreparedStatementFunction {
    void apply(PreparedStatement s1, PreparedStatement s2)
        throws SQLException;
  }

  /** Callback to execute some code against a connection. */
  interface ConnectionFunction {
    void apply(Connection c1) throws Exception;
  }

  @Test public void testSetParameter() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      checkSetParameter("select ? from (values 1)",
          new PreparedStatementFunction() {
            public void apply(PreparedStatement s1, PreparedStatement s2)
                throws SQLException {
              final Date d = new Date(1234567890);
              s1.setDate(1, d);
              s2.setDate(1, d);
            }
          });
      checkSetParameter("select ? from (values 1)",
          new PreparedStatementFunction() {
            public void apply(PreparedStatement s1, PreparedStatement s2)
                throws SQLException {
              final Timestamp ts = new Timestamp(123456789012L);
              s1.setTimestamp(1, ts);
              s2.setTimestamp(1, ts);
            }
          });
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  void checkSetParameter(String query, PreparedStatementFunction fn)
      throws SQLException {
    try (Connection cannon = canon();
         Connection underTest = ljs();
         PreparedStatement s1 = cannon.prepareStatement(query);
         PreparedStatement s2 = underTest.prepareStatement(query)) {
      fn.apply(s1, s2);
      assertTrue(s1.execute());
      assertTrue(s2.execute());
      assertResultSetsEqual(s1, s2);
    }
  }

  @Test public void testStatementLifecycle() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try (AvaticaConnection connection = (AvaticaConnection) getLocalConnection()) {
      Map<Integer, AvaticaStatement> clientMap = connection.statementMap;
      Cache<Integer, Object> serverMap = getLocalConnectionInternals()
          .getRemoteStatementMap(connection);
      // Other tests being run might leave statements in the cache.
      // The lock guards against more statements being cached during the test.
      serverMap.invalidateAll();
      assertEquals(0, clientMap.size());
      assertEquals(0, serverMap.size());
      Statement stmt = connection.createStatement();
      assertEquals(1, clientMap.size());
      assertEquals(1, serverMap.size());
      stmt.close();
      assertEquals(0, clientMap.size());
      assertEquals(0, serverMap.size());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testConnectionIsolation() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      Cache<String, Connection> connectionMap = getLocalConnectionInternals()
          .getRemoteConnectionMap((AvaticaConnection) getLocalConnection());
      // Other tests being run might leave connections in the cache.
      // The lock guards against more connections being cached during the test.
      connectionMap.invalidateAll();

      final String sql = "select * from (values (1, 'a'))";
      assertEquals("connection cache should start empty",
          0, connectionMap.size());
      Connection conn1 = getLocalConnection();
      Connection conn2 = getLocalConnection();
      assertEquals("we now have two connections open",
          2, connectionMap.size());
      PreparedStatement conn1stmt1 = conn1.prepareStatement(sql);
      assertEquals(
          "creating a statement does not cause new connection",
          2, connectionMap.size());
      PreparedStatement conn2stmt1 = conn2.prepareStatement(sql);
      assertEquals(
          "creating a statement does not cause new connection",
          2, connectionMap.size());
      AvaticaPreparedStatement s1 = (AvaticaPreparedStatement) conn1stmt1;
      AvaticaPreparedStatement s2 = (AvaticaPreparedStatement) conn2stmt1;
      assertFalse("connection id's should be unique",
          s1.handle.connectionId.equalsIgnoreCase(s2.handle.connectionId));
      conn2.close();
      assertEquals("closing a connection closes the server-side connection",
          1, connectionMap.size());
      conn1.close();
      assertEquals("closing a connection closes the server-side connection",
          0, connectionMap.size());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testPrepareBindExecuteFetch() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      getRequestInspection().getRequestLogger().enableAndClear();
      checkPrepareBindExecuteFetch(getLocalConnection());
      List<String[]> x = getRequestInspection().getRequestLogger().getAndDisable();
      for (String[] pair : x) {
        System.out.println(pair[0] + "=" + pair[1]);
      }
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void checkPrepareBindExecuteFetch(Connection connection)
      throws SQLException {
    final String sql = "select cast(? as integer) * 3 as c, 'x' as x\n"
        + "from (values (1, 'a'))";
    final PreparedStatement ps =
        connection.prepareStatement(sql);
    final ResultSetMetaData metaData = ps.getMetaData();
    assertEquals(2, metaData.getColumnCount());
    assertEquals("C", metaData.getColumnName(1));
    assertEquals("X", metaData.getColumnName(2));
    try {
      final ResultSet resultSet = ps.executeQuery();
      fail("expected error, got " + resultSet);
    } catch (SQLException e) {
      LOG.info("Caught expected error", e);
      assertThat(e.getMessage(),
          containsString("exception while executing query: unbound parameter"));
    }

    final ParameterMetaData parameterMetaData = ps.getParameterMetaData();
    assertThat(parameterMetaData.getParameterCount(), equalTo(1));

    ps.setInt(1, 10);
    final ResultSet resultSet = ps.executeQuery();
    assertTrue(resultSet.next());
    assertThat(resultSet.getInt(1), equalTo(30));
    assertFalse(resultSet.next());
    resultSet.close();

    ps.setInt(1, 20);
    final ResultSet resultSet2 = ps.executeQuery();
    assertFalse(resultSet2.isClosed());
    assertTrue(resultSet2.next());
    assertThat(resultSet2.getInt(1), equalTo(60));
    assertThat(resultSet2.wasNull(), is(false));
    assertFalse(resultSet2.next());
    resultSet2.close();

    ps.setObject(1, null);
    final ResultSet resultSet3 = ps.executeQuery();
    assertTrue(resultSet3.next());
    assertThat(resultSet3.getInt(1), equalTo(0));
    assertThat(resultSet3.wasNull(), is(true));
    assertFalse(resultSet3.next());
    resultSet3.close();

    ps.close();
    connection.close();
  }

  @Test public void testPrepareBindExecuteFetchVarbinary() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      final Connection connection = getLocalConnection();
      final String sql = "select x'de' || ? as c from (values (1, 'a'))";
      final PreparedStatement ps =
          connection.prepareStatement(sql);
      final ParameterMetaData parameterMetaData = ps.getParameterMetaData();
      assertThat(parameterMetaData.getParameterCount(), equalTo(1));

      ps.setBytes(1, new byte[]{65, 0, 66});
      final ResultSet resultSet = ps.executeQuery();
      assertTrue(resultSet.next());
      assertThat(resultSet.getBytes(1),
          equalTo(new byte[]{(byte) 0xDE, 65, 0, 66}));
      resultSet.close();
      ps.close();
      connection.close();
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testPrepareBindExecuteFetchDate() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              checkPrepareBindExecuteFetchDate(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void checkPrepareBindExecuteFetchDate(Connection connection) throws Exception {
    final String sql0 =
        "select cast(? as varchar(20)) as c\n"
            + "from (values (1, 'a'))";

    final Date date = Date.valueOf("2015-04-08");
    final long time = date.getTime();

    PreparedStatement ps;
    ParameterMetaData parameterMetaData;
    ResultSet resultSet;

    ps = connection.prepareStatement(sql0);
    parameterMetaData = ps.getParameterMetaData();
    assertThat(parameterMetaData.getParameterCount(), equalTo(1));
    ps.setDate(1, date);
    resultSet = ps.executeQuery();
    assertThat(resultSet.next(), is(true));
    assertThat(resultSet.getString(1), is("2015-04-08"));

    ps.setTimestamp(1, new Timestamp(time));
    resultSet = ps.executeQuery();
    assertThat(resultSet.next(), is(true));
    assertThat(resultSet.getString(1), is("2015-04-08 00:00:00.0"));

    ps.setTime(1, new Time(time));
    resultSet = ps.executeQuery();
    assertThat(resultSet.next(), is(true));
    assertThat(resultSet.getString(1), is("00:00:00"));
    ps.close();
    connection.close();
  }

  @Test public void testDatabaseProperty() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              checkDatabaseProperty(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void checkDatabaseProperty(Connection connection)
      throws SQLException {
    final DatabaseMetaData metaData = connection.getMetaData();
    assertThat(metaData.getSQLKeywords(), equalTo(""));
    assertThat(metaData.getStringFunctions(),
        equalTo("ASCII,CHAR,CONCAT,DIFFERENCE,HEXTORAW,INSERT,LCASE,LEFT,"
            + "LENGTH,LOCATE,LTRIM,RAWTOHEX,REPEAT,REPLACE,RIGHT,RTRIM,SOUNDEX,"
            + "SPACE,SUBSTR,UCASE"));
    assertThat(metaData.getDefaultTransactionIsolation(),
        equalTo(Connection.TRANSACTION_READ_COMMITTED));
  }

  @Test public void testBatchExecute() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              executeBatchUpdate(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void executeBatchUpdate(Connection conn) throws Exception {
    final int numRows = 10;
    try (Statement stmt = conn.createStatement()) {
      final String tableName = AvaticaUtils.unique("BATCH_EXECUTE");
      LOG.info("Creating table {}", tableName);
      final String createCommand = String.format(Locale.ROOT,
          "create table if not exists %s ("
              + "id int not null, "
              + "msg varchar(10) not null)", tableName);
      assertFalse("Failed to create table", stmt.execute(createCommand));

      final String updatePrefix =
          String.format(Locale.ROOT, "INSERT INTO %s values(", tableName);
      for (int i = 0; i < numRows;  i++) {
        stmt.addBatch(updatePrefix + i + ", '" + Integer.toString(i) + "')");
      }

      int[] updateCounts = stmt.executeBatch();
      assertEquals("Unexpected number of update counts returned", numRows, updateCounts.length);
      for (int i = 0; i < updateCounts.length; i++) {
        assertEquals("Unexpected update count at index " + i, 1, updateCounts[i]);
      }

      ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id asc");
      assertNotNull("ResultSet was null", rs);
      for (int i = 0; i < numRows; i++) {
        assertTrue("ResultSet should have a result", rs.next());
        assertEquals("Wrong integer value for row " + i, i, rs.getInt(1));
        assertEquals("Wrong string value for row " + i, Integer.toString(i), rs.getString(2));
      }
      assertFalse("ResultSet should have no more records", rs.next());
    }
  }

  @Test public void testPreparedBatches() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              executePreparedBatchUpdate(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void executePreparedBatchUpdate(Connection conn) throws Exception {
    final int numRows = 10;
    final String tableName = AvaticaUtils.unique("PREPARED_BATCH_EXECUTE");
    LOG.info("Creating table {}", tableName);
    try (Statement stmt = conn.createStatement()) {
      final String createCommand =
          String.format(Locale.ROOT, "create table if not exists %s ("
              + "id int not null, "
              + "msg varchar(10) not null)", tableName);
      assertFalse("Failed to create table", stmt.execute(createCommand));
    }

    final String insertSql =
        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
    try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
      // Add batches with the prepared statement
      for (int i = 0; i < numRows; i++) {
        pstmt.setInt(1, i);
        pstmt.setString(2, Integer.toString(i));
        pstmt.addBatch();
      }

      int[] updateCounts = pstmt.executeBatch();
      assertEquals("Unexpected number of update counts returned", numRows, updateCounts.length);
      for (int i = 0; i < updateCounts.length; i++) {
        assertEquals("Unexpected update count at index " + i, 1, updateCounts[i]);
      }
    }

    try (Statement stmt = conn.createStatement()) {
      ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id asc");
      assertNotNull("ResultSet was null", rs);
      for (int i = 0; i < numRows; i++) {
        assertTrue("ResultSet should have a result", rs.next());
        assertEquals("Wrong integer value for row " + i, i, rs.getInt(1));
        assertEquals("Wrong string value for row " + i, Integer.toString(i), rs.getString(2));
      }
      assertFalse("ResultSet should have no more records", rs.next());
    }
  }

  @Test public void testPreparedInsert() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              executePreparedInsert(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void executePreparedInsert(Connection conn) throws Exception {
    final int numRows = 10;
    final String tableName = AvaticaUtils.unique("PREPARED_INSERT_EXECUTE");
    LOG.info("Creating table {}", tableName);
    try (Statement stmt = conn.createStatement()) {
      final String createCommand =
          String.format(Locale.ROOT, "create table if not exists %s ("
              + "id int not null, "
              + "msg varchar(10) not null)", tableName);
      assertFalse("Failed to create table", stmt.execute(createCommand));
    }

    final String insertSql =
        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
    try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
      // Add batches with the prepared statement
      for (int i = 0; i < numRows; i++) {
        pstmt.setInt(1, i);
        pstmt.setString(2, Integer.toString(i));
        assertEquals(1, pstmt.executeUpdate());
      }
    }

    try (Statement stmt = conn.createStatement()) {
      ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id asc");
      assertNotNull("ResultSet was null", rs);
      for (int i = 0; i < numRows; i++) {
        assertTrue("ResultSet should have a result", rs.next());
        assertEquals("Wrong integer value for row " + i, i, rs.getInt(1));
        assertEquals("Wrong string value for row " + i, Integer.toString(i), rs.getString(2));
      }
      assertFalse("ResultSet should have no more records", rs.next());
    }
  }

  @Test public void testPreparedInsertWithNulls() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              executePreparedInsertWithNulls(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void executePreparedInsertWithNulls(Connection conn) throws Exception {
    final int numRows = 10;
    final String tableName = AvaticaUtils.unique("PREPARED_INSERT_EXECUTE_NULLS");
    LOG.info("Creating table {}", tableName);
    try (Statement stmt = conn.createStatement()) {
      final String createCommand =
          String.format(Locale.ROOT, "create table if not exists %s ("
              + "id int not null, "
              + "msg varchar(10))", tableName);
      assertFalse("Failed to create table", stmt.execute(createCommand));
    }

    final String insertSql =
        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
    try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
      // Add batches with the prepared statement
      for (int i = 0; i < numRows; i++) {
        pstmt.setInt(1, i);
        // Even inserts are non-null, odd are null
        if (0 == i % 2) {
          pstmt.setString(2, Integer.toString(i));
        } else {
          pstmt.setNull(2, Types.VARCHAR);
        }
        assertEquals(1, pstmt.executeUpdate());
      }
    }

    try (Statement stmt = conn.createStatement()) {
      ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id asc");
      assertNotNull("ResultSet was null", rs);
      for (int i = 0; i < numRows; i++) {
        assertTrue("ResultSet should have a result", rs.next());
        assertEquals("Wrong integer value for row " + i, i, rs.getInt(1));
        if (0 == i % 2) {
          assertEquals("Wrong string value for row " + i, Integer.toString(i), rs.getString(2));
        } else {
          assertNull("Expected null value for row " + i, rs.getString(2));
        }
      }
      assertFalse("ResultSet should have no more records", rs.next());
    }
  }

  @Test public void testBatchInsertWithNulls() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              executeBatchInsertWithNulls(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void executeBatchInsertWithNulls(Connection conn) throws Exception {
    final int numRows = 10;
    final String tableName = AvaticaUtils.unique("BATCH_INSERT_EXECUTE_NULLS");
    LOG.info("Creating table {}", tableName);
    try (Statement stmt = conn.createStatement()) {
      final String createCommand =
          String.format(Locale.ROOT, "create table if not exists %s ("
              + "id int not null, "
              + "msg varchar(10))", tableName);
      assertFalse("Failed to create table", stmt.execute(createCommand));
    }

    final String insertSql =
        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
    try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
      // Add batches with the prepared statement
      for (int i = 0; i < numRows; i++) {
        pstmt.setInt(1, i);
        // Even inserts are non-null, odd are null
        if (0 == i % 2) {
          pstmt.setString(2, Integer.toString(i));
        } else {
          pstmt.setNull(2, Types.VARCHAR);
        }
        pstmt.addBatch();
      }
      // Verify that all updates were successful
      int[] updateCounts = pstmt.executeBatch();
      assertEquals(numRows, updateCounts.length);
      int[] expectedCounts = new int[numRows];
      Arrays.fill(expectedCounts, 1);
      assertArrayEquals(expectedCounts, updateCounts);
    }

    try (Statement stmt = conn.createStatement()) {
      ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id asc");
      assertNotNull("ResultSet was null", rs);
      for (int i = 0; i < numRows; i++) {
        assertTrue("ResultSet should have a result", rs.next());
        assertEquals("Wrong integer value for row " + i, i, rs.getInt(1));
        if (0 == i % 2) {
          assertEquals("Wrong string value for row " + i, Integer.toString(i), rs.getString(2));
        } else {
          assertNull("Expected null value for row " + i, rs.getString(2));
        }
      }
      assertFalse("ResultSet should have no more records", rs.next());
    }
  }

  @Test public void preparedStatementParameterCopies() throws Exception {
    // When implementing the JDBC batch APIs, it's important that we are copying the
    // TypedValues and caching them in the AvaticaPreparedStatement. Otherwise, when we submit
    // the batch, the parameter values for the last update added will be reflected in all previous
    // updates added to the batch.
    ConnectionSpec.getDatabaseLock().lock();
    try {
      final String tableName = AvaticaUtils.unique("PREPAREDSTATEMENT_VALUES");
      final Connection conn = getLocalConnection();
      try (Statement stmt = conn.createStatement()) {
        final String sql = "CREATE TABLE " + tableName
            + " (id varchar(1) not null, col1 varchar(1) not null)";
        assertFalse(stmt.execute(sql));
      }
      try (final PreparedStatement pstmt =
          conn.prepareStatement("INSERT INTO " + tableName + " values(?, ?)")) {
        pstmt.setString(1, "a");
        pstmt.setString(2, "b");

        @SuppressWarnings("resource")
        AvaticaPreparedStatement apstmt = (AvaticaPreparedStatement) pstmt;
        TypedValue[] slots = apstmt.slots;

        assertEquals("Unexpected number of values", 2, slots.length);

        List<TypedValue> valuesReference = apstmt.getParameterValues();
        assertEquals(2, valuesReference.size());
        assertEquals(slots[0], valuesReference.get(0));
        assertEquals(slots[1], valuesReference.get(1));
        List<TypedValue> copiedValues = apstmt.copyParameterValues();
        assertEquals(2, valuesReference.size());
        assertEquals(slots[0], copiedValues.get(0));
        assertEquals(slots[1], copiedValues.get(1));

        slots[0] = null;
        slots[1] = null;

        // Modifications to the array are reflected in the List from getParameterValues()
        assertNull(valuesReference.get(0));
        assertNull(valuesReference.get(1));
        // copyParameterValues() copied the underlying array, so updates to slots is not reflected
        assertNotNull(copiedValues.get(0));
        assertNotNull(copiedValues.get(1));
      }
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testBatchInsertWithDates() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              executeBatchInsertWithDates(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void executeBatchInsertWithDates(Connection conn) throws Exception {
    final Calendar calendar = DateTimeUtils.calendar();
    long now = calendar.getTime().getTime();
    final int numRows = 10;
    final String tableName = AvaticaUtils.unique("BATCH_INSERT_EXECUTE_DATES");
    LOG.info("Creating table {}", tableName);
    try (Statement stmt = conn.createStatement()) {
      final String dropCommand =
          String.format(Locale.ROOT, "drop table if exists %s", tableName);
      assertFalse("Failed to drop table", stmt.execute(dropCommand));
      final String createCommand =
          String.format(Locale.ROOT, "create table %s ("
              + "id char(15) not null, "
              + "created_date date not null, "
              + "val_string varchar)", tableName);
      assertFalse("Failed to create table", stmt.execute(createCommand));
    }

    final String insertSql =
        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?, ?)", tableName);
    try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
      // Add batches with the prepared statement
      for (int i = 0; i < numRows; i++) {
        pstmt.setString(1, Integer.toString(i));
        pstmt.setDate(2, new Date(now + i), calendar);
        pstmt.setString(3, UUID.randomUUID().toString());
        pstmt.addBatch();
      }
      // Verify that all updates were successful
      int[] updateCounts = pstmt.executeBatch();
      assertEquals(numRows, updateCounts.length);
      int[] expectedCounts = new int[numRows];
      Arrays.fill(expectedCounts, 1);
      assertArrayEquals(expectedCounts, updateCounts);
    }

    try (Statement stmt = conn.createStatement()) {
      ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id asc");
      assertNotNull("ResultSet was null", rs);
      for (int i = 0; i < numRows; i++) {
        assertTrue("ResultSet should have a result", rs.next());
        assertEquals("Wrong value for row " + i, Integer.toString(i), rs.getString(1).trim());

        Date actual = rs.getDate(2, calendar);
        calendar.setTime(actual);
        int actualDay = calendar.get(Calendar.DAY_OF_MONTH);
        int actualMonth = calendar.get(Calendar.MONTH);
        int actualYear = calendar.get(Calendar.YEAR);

        Date expected = new Date(now + i);
        calendar.setTime(expected);
        int expectedDay = calendar.get(Calendar.DAY_OF_MONTH);
        int expectedMonth = calendar.get(Calendar.MONTH);
        int expectedYear = calendar.get(Calendar.YEAR);
        assertEquals("Wrong day for row " + i, expectedDay, actualDay);
        assertEquals("Wrong month for row " + i, expectedMonth, actualMonth);
        assertEquals("Wrong year for row " + i, expectedYear, actualYear);

        assertNotNull("Non-null string for row " + i, rs.getString(3));
      }
      assertFalse("ResultSet should have no more records", rs.next());
    }
  }

  @Test public void testDatabaseMetaData() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try (Connection conn = getLocalConnection()) {
      DatabaseMetaData metadata = conn.getMetaData();
      assertTrue(metadata.isWrapperFor(AvaticaSpecificDatabaseMetaData.class));
      assertTrue(metadata.isWrapperFor(Properties.class));
      Properties props = metadata.unwrap(Properties.class);
      assertNotNull(props);

      final Object productName = props.get(DatabaseProperty.GET_DATABASE_PRODUCT_NAME.name());
      assertThat(productName, instanceOf(String.class));
      assertThat((String) productName, startsWith("HSQL"));

      final Object driverName = props.get(DatabaseProperty.GET_DRIVER_NAME.name());
      assertThat(driverName, instanceOf(String.class));
      assertThat((String) driverName, startsWith("HSQL"));

      final Object driverVersion = props.get(DatabaseProperty.GET_DRIVER_VERSION.name());
      final Object driverMinVersion = props.get(DatabaseProperty.GET_DRIVER_MINOR_VERSION.name());
      final Object driverMajVersion = props.get(DatabaseProperty.GET_DRIVER_MAJOR_VERSION.name());
      assertThat(driverVersion, instanceOf(String.class));
      assertThat(driverMinVersion, instanceOf(String.class));
      assertThat(driverMajVersion, instanceOf(String.class));
      assertThat((String) driverVersion, startsWith(driverMajVersion + "." + driverMinVersion));
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testMetaDataCanHaveEmptyStringArgument() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try (Connection conn = getLocalConnection();
        Statement stmt = conn.createStatement()) {
      DatabaseMetaData meta = conn.getMetaData();

      ResultSet rs = meta.getSchemas("PUBLIC", null);
      assertTrue(rs.next());
      rs.close();

      //Test for CALCITE-4138
      rs = meta.getSchemas("PUBLIC", "");
      assertFalse(rs.next());
      rs.close();
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testUnicodeColumnNames() throws Exception {
    final String tableName = "unicodeColumn";
    final String columnName = "\u041d\u043e\u043c\u0435\u0440\u0422\u0435\u043b"
        + "\u0435\u0444\u043e\u043d\u0430"; // PhoneNumber in Russian
    ConnectionSpec.getDatabaseLock().lock();
    try (Connection conn = getLocalConnection();
        Statement stmt = conn.createStatement()) {
      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
      final String sql = "CREATE TABLE " + tableName + "(" + columnName + " integer)";
      assertFalse(stmt.execute(sql));
      final ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName);
      assertNotNull(results);
      ResultSetMetaData metadata = results.getMetaData();
      assertNotNull(metadata);
      String actualColumnName = metadata.getColumnName(1);
      // HSQLDB is going to upper-case the column name
      assertEquals(columnName.toUpperCase(Locale.ROOT), actualColumnName);
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  @Test public void testBigDecimalPrecision() throws Exception {
    final String tableName = "decimalPrecision";
    // DECIMAL(25,5), 20 before, 5 after
    BigDecimal decimal = new BigDecimal("12345123451234512345.09876");
    try (Connection conn = getLocalConnection();
        Statement stmt = conn.createStatement()) {
      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
      assertFalse(stmt.execute("CREATE TABLE " + tableName + " (col1 DECIMAL(25,5))"));

      // Insert a single decimal
      try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + tableName
          + " values (?)")) {
        pstmt.setBigDecimal(1, decimal);
        assertEquals(1, pstmt.executeUpdate());
      }

      ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName);
      assertNotNull(results);
      assertTrue(results.next());
      BigDecimal actualDecimal = results.getBigDecimal(1);
      assertEquals(decimal, actualDecimal);
    }
  }

  @Test public void testPreparedClearBatches() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              executePreparedBatchClears(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void executePreparedBatchClears(Connection conn) throws Exception {
    final int numRows = 10;
    final String tableName = AvaticaUtils.unique("BATCH_CLEARS");
    LOG.info("Creating table {}", tableName);
    try (Statement stmt = conn.createStatement()) {
      final String createCommand =
          String.format(Locale.ROOT, "create table if not exists %s ("
              + "id int not null, "
              + "msg varchar(10) not null)", tableName);
      assertFalse("Failed to create table", stmt.execute(createCommand));
    }

    final String insertSql =
        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
    try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
      // Add batches with the prepared statement
      for (int i = 0; i < numRows; i++) {
        pstmt.setInt(1, i);
        pstmt.setString(2, Integer.toString(i));
        pstmt.addBatch();

        if (numRows / 2 - 1 == i) {
          // Clear the first 5 entries in the batch
          pstmt.clearBatch();
        }
      }

      int[] updateCounts = pstmt.executeBatch();
      assertEquals("Unexpected number of update counts returned", numRows / 2, updateCounts.length);
      for (int i = 0; i < updateCounts.length; i++) {
        assertEquals("Unexpected update count at index " + i, 1, updateCounts[i]);
      }
    }

    try (Statement stmt = conn.createStatement()) {
      ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id asc");
      assertNotNull("ResultSet was null", rs);
      for (int i = 0 + (numRows / 2); i < numRows; i++) {
        assertTrue("ResultSet should have a result", rs.next());
        assertEquals("Wrong integer value for row " + i, i, rs.getInt(1));
        assertEquals("Wrong string value for row " + i, Integer.toString(i), rs.getString(2));
      }
      assertFalse("ResultSet should have no more records", rs.next());
    }
  }

  @Test public void testBatchClear() throws Exception {
    ConnectionSpec.getDatabaseLock().lock();
    try {
      eachConnection(
          new ConnectionFunction() {
            public void apply(Connection c1) throws Exception {
              executeBatchClear(c1);
            }
          }, getLocalConnection());
    } finally {
      ConnectionSpec.getDatabaseLock().unlock();
    }
  }

  private void executeBatchClear(Connection conn) throws Exception {
    final int numRows = 10;
    try (Statement stmt = conn.createStatement()) {
      final String tableName = AvaticaUtils.unique("BATCH_EXECUTE");
      LOG.info("Creating table {}", tableName);
      final String createCommand =
          String.format(Locale.ROOT, "create table if not exists %s ("
              + "id int not null, "
              + "msg varchar(10) not null)", tableName);
      assertFalse("Failed to create table", stmt.execute(createCommand));

      final String updatePrefix =
          String.format(Locale.ROOT, "INSERT INTO %s values(", tableName);
      for (int i = 0; i < numRows;  i++) {
        stmt.addBatch(updatePrefix + i + ", '" + Integer.toString(i) + "')");
        if (numRows / 2 - 1 == i) {
          stmt.clearBatch();
        }
      }

      int[] updateCounts = stmt.executeBatch();
      assertEquals("Unexpected number of update counts returned", numRows / 2, updateCounts.length);
      for (int i = 0; i < updateCounts.length; i++) {
        assertEquals("Unexpected update count at index " + i, 1, updateCounts[i]);
      }

      ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY id asc");
      assertNotNull("ResultSet was null", rs);
      for (int i = 0 + (numRows / 2); i < numRows; i++) {
        assertTrue("ResultSet should have a result", rs.next());
        assertEquals("Wrong integer value for row " + i, i, rs.getInt(1));
        assertEquals("Wrong string value for row " + i, Integer.toString(i), rs.getString(2));
      }
      assertFalse("ResultSet should have no more records", rs.next());
    }
  }

  @Test public void testDecimalParameters() throws Exception {
    final String tableName = "decimalParameters";
    BigDecimal decimal = new BigDecimal("123451234512345");
    try (Connection conn = getLocalConnection();
        Statement stmt = conn.createStatement()) {
      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
      String sql = "CREATE TABLE " + tableName + " (keycolumn VARCHAR(5), column1 DECIMAL(15,0))";
      assertFalse(stmt.execute(sql));

      // Insert a single decimal
      try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + tableName
          + " values (?, ?)")) {
        ParameterMetaData metadata = pstmt.getParameterMetaData();
        assertNotNull(metadata);
        assertEquals(5, metadata.getPrecision(1));
        assertEquals(0, metadata.getScale(1));
        assertEquals(15, metadata.getPrecision(2));
        assertEquals(0, metadata.getScale(2));

        pstmt.setString(1, "asdfg");
        pstmt.setBigDecimal(2, decimal);
        assertEquals(1, pstmt.executeUpdate());
      }

      ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName);
      assertNotNull(results);
      assertTrue(results.next());
      BigDecimal actualDecimal = results.getBigDecimal(2);
      assertEquals(decimal, actualDecimal);

      ResultSetMetaData resultMetadata = results.getMetaData();
      assertNotNull(resultMetadata);
      assertEquals(15, resultMetadata.getPrecision(2));
      assertEquals(0, resultMetadata.getScale(2));
    }
  }

  @Test public void testSignedParameters() throws Exception {
    final String tableName = "signedParameters";
    try (Connection conn = getLocalConnection();
        Statement stmt = conn.createStatement()) {
      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
      String sql = "CREATE TABLE " + tableName + " (keycolumn VARCHAR(5), column1 integer)";
      assertFalse(stmt.execute(sql));

      // Insert a single decimal
      try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + tableName
          + " values (?, ?)")) {
        ParameterMetaData metadata = pstmt.getParameterMetaData();
        assertNotNull(metadata);
        assertFalse("Varchar should not be signed", metadata.isSigned(1));
        assertTrue("Integer should be signed", metadata.isSigned(2));

        pstmt.setString(1, "asdfg");
        pstmt.setInt(2, 10);
        assertEquals(1, pstmt.executeUpdate());
      }

      ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName);
      assertNotNull(results);
      assertTrue(results.next());
      assertEquals("asdfg", results.getString(1));
      assertEquals(10, results.getInt(2));

      ResultSetMetaData resultMetadata = results.getMetaData();
      assertNotNull(resultMetadata);
      assertFalse("Varchar should not be signed", resultMetadata.isSigned(1));
      assertTrue("Integer should be signed", resultMetadata.isSigned(2));
    }
  }

  @Test public void testDateParameterWithGMT0() throws Exception {
    final String tableName = "dateParameters";
    try (Connection conn = getLocalConnection();
         Statement stmt = conn.createStatement()) {
      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
      String sql = "CREATE TABLE " + tableName + " (keycolumn VARCHAR(5), column1 date)";
      assertFalse(stmt.execute(sql));
      TimeZone tzUtc = TimeZone.getTimeZone("UTC");
      Calendar cUtc = Calendar.getInstance(tzUtc, Locale.ROOT);
      cUtc.set(Calendar.YEAR, 1970);
      cUtc.set(Calendar.MONTH, Calendar.JANUARY);
      cUtc.set(Calendar.DAY_OF_MONTH, 1);
      cUtc.set(Calendar.HOUR_OF_DAY, 0);
      cUtc.set(Calendar.MINUTE, 0);
      cUtc.set(Calendar.SECOND, 0);
      cUtc.set(Calendar.MILLISECOND, 0);
      Date inputDate = new Date(cUtc.getTimeInMillis());
      // Insert a single date
      try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + tableName
              + " values (?, ?)")) {
        ParameterMetaData metadata = pstmt.getParameterMetaData();
        assertNotNull(metadata);

        pstmt.setString(1, "asdfg");
        pstmt.setDate(2, inputDate, cUtc);
        assertEquals(1, pstmt.executeUpdate());
      }

      ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName);
      assertNotNull(results);
      assertTrue(results.next());
      assertEquals("asdfg", results.getString(1));
      Date outputDate = results.getDate(2, cUtc);
      assertEquals(inputDate.getTime(), outputDate.getTime());
      assertEquals(0, outputDate.getTime());
    }
  }

  @Test public void testDateParameterWithGMTN() throws Exception {
    final String tableName = "dateParameters";
    try (Connection conn = getLocalConnection();
         Statement stmt = conn.createStatement()) {
      assertFalse(stmt.execute("DROP TABLE IF EXISTS " + tableName));
      String sql = "CREATE TABLE " + tableName + " (keycolumn VARCHAR(5), column1 date)";
      assertFalse(stmt.execute(sql));
      TimeZone tzUtc = TimeZone.getTimeZone("GMT+8");
      Calendar cUtc = Calendar.getInstance(tzUtc, Locale.ROOT);
      cUtc.set(Calendar.YEAR, 1970);
      cUtc.set(Calendar.MONTH, Calendar.JANUARY);
      cUtc.set(Calendar.DAY_OF_MONTH, 1);
      cUtc.set(Calendar.HOUR_OF_DAY, 0);
      cUtc.set(Calendar.MINUTE, 0);
      cUtc.set(Calendar.SECOND, 0);
      cUtc.set(Calendar.MILLISECOND, 0);
      Date inputDate = new Date(cUtc.getTimeInMillis());
      // Insert a single date
      try (PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + tableName
              + " values (?, ?)")) {
        ParameterMetaData metadata = pstmt.getParameterMetaData();
        assertNotNull(metadata);

        pstmt.setString(1, "gfdsa");
        pstmt.setDate(2, inputDate, cUtc);
        assertEquals(1, pstmt.executeUpdate());
      }

      ResultSet results = stmt.executeQuery("SELECT * FROM " + tableName);
      assertNotNull(results);
      assertTrue(results.next());
      assertEquals("gfdsa", results.getString(1));
      Date outputDate = results.getDate(2, cUtc);
      assertEquals(inputDate.getTime(), outputDate.getTime());
      assertEquals(-28800000, outputDate.getTime());
    }
  }

  /**
   * Factory that creates a service based on a local JDBC connection.
   */
  public static class LocalJdbcServiceFactory implements Service.Factory {
    @Override public Service create(AvaticaConnection connection) {
      try {
        return new LocalService(
            new JdbcMeta(CONNECTION_SPEC.url, CONNECTION_SPEC.username,
                CONNECTION_SPEC.password));
      } catch (SQLException e) {
        throw new RuntimeException(e);
      }
    }
  }

  /**
   * Factory that creates a fully-local Protobuf service.
   */
  public static class QuasiRemotePBJdbcServiceFactory implements Service.Factory {
    private static Service service;

    private static RequestInspection requestInspection;

    static void initService() {
      try {
        final JdbcMeta jdbcMeta = new JdbcMeta(CONNECTION_SPEC.url,
            CONNECTION_SPEC.username, CONNECTION_SPEC.password);
        final LocalService localService = new LocalService(jdbcMeta);
        service = new LoggingLocalProtobufService(localService, new ProtobufTranslationImpl());
        requestInspection = (RequestInspection) service;
      } catch (SQLException e) {
        throw new RuntimeException(e);
      }
    }

    @Override public Service create(AvaticaConnection connection) {
      assert null != service;
      return service;
    }
  }

  /**
   * Proxy that logs all requests passed into the {@link LocalProtobufService}.
   */
  public static class LoggingLocalProtobufService extends LocalProtobufService
      implements RequestInspection {
    private static final ThreadLocal<RequestLogger> THREAD_LOG =
        new ThreadLocal<RequestLogger>() {
          @Override protected RequestLogger initialValue() {
            return new RequestLogger();
          }
        };

    public LoggingLocalProtobufService(Service service, ProtobufTranslation translation) {
      super(service, translation);
    }

    @Override public RequestLogger getRequestLogger() {
      return THREAD_LOG.get();
    }

    @Override public Response _apply(Request request) {
      final RequestLogger logger = THREAD_LOG.get();
      try {
        String jsonRequest = JsonService.MAPPER.writeValueAsString(request);
        logger.requestStart(jsonRequest);

        Response response = super._apply(request);

        String jsonResponse = JsonService.MAPPER.writeValueAsString(response);
        logger.requestEnd(jsonRequest, jsonResponse);

        return response;
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
  }

  /**
   * Factory that creates a service based on a local JDBC connection.
   */
  public static class QuasiRemoteJdbcServiceFactory implements Service.Factory {

    /** a singleton instance that is recreated for each test */
    private static Service service;

    private static RequestInspection requestInspection;

    static void initService() {
      try {
        final JdbcMeta jdbcMeta = new JdbcMeta(CONNECTION_SPEC.url,
            CONNECTION_SPEC.username, CONNECTION_SPEC.password);
        final LocalService localService = new LocalService(jdbcMeta);
        service = new LoggingLocalJsonService(localService);
        requestInspection = (RequestInspection) service;
      } catch (SQLException e) {
        throw new RuntimeException(e);
      }
    }

    @Override public Service create(AvaticaConnection connection) {
      assert service != null;
      return service;
    }
  }

  /**
   * Implementation that reaches into current connection state via reflection to extract certain
   * internal information.
   */
  public static class QuasiRemoteJdbcServiceInternals implements ConnectionInternals {

    @Override public Cache<Integer, Object>
    getRemoteStatementMap(AvaticaConnection connection) throws Exception {
      Field metaF = AvaticaConnection.class.getDeclaredField("meta");
      metaF.setAccessible(true);
      Meta clientMeta = (Meta) metaF.get(connection);
      Field remoteMetaServiceF = clientMeta.getClass().getDeclaredField("service");
      remoteMetaServiceF.setAccessible(true);
      LocalJsonService remoteMetaService = (LocalJsonService) remoteMetaServiceF.get(clientMeta);
      // Use the explicitly class to avoid issues with LoggingLocalJsonService
      Field remoteMetaServiceServiceF = LocalJsonService.class.getDeclaredField("service");
      remoteMetaServiceServiceF.setAccessible(true);
      LocalService remoteMetaServiceService =
          (LocalService) remoteMetaServiceServiceF.get(remoteMetaService);
      Field remoteMetaServiceServiceMetaF =
          remoteMetaServiceService.getClass().getDeclaredField("meta");
      remoteMetaServiceServiceMetaF.setAccessible(true);
      JdbcMeta serverMeta = (JdbcMeta) remoteMetaServiceServiceMetaF.get(remoteMetaServiceService);
      Field jdbcMetaStatementMapF = JdbcMeta.class.getDeclaredField("statementCache");
      jdbcMetaStatementMapF.setAccessible(true);
      //noinspection unchecked
      @SuppressWarnings("unchecked")
      Cache<Integer, Object> cache = (Cache<Integer, Object>) jdbcMetaStatementMapF.get(serverMeta);
      return cache;
    }

    @Override public Cache<String, Connection>
    getRemoteConnectionMap(AvaticaConnection connection) throws Exception {
      Field metaF = AvaticaConnection.class.getDeclaredField("meta");
      metaF.setAccessible(true);
      Meta clientMeta = (Meta) metaF.get(connection);
      Field remoteMetaServiceF = clientMeta.getClass().getDeclaredField("service");
      remoteMetaServiceF.setAccessible(true);
      LocalJsonService remoteMetaService = (LocalJsonService) remoteMetaServiceF.get(clientMeta);
      // Get the field explicitly off the correct class to avoid LocalLoggingJsonService.class
      Field remoteMetaServiceServiceF = LocalJsonService.class.getDeclaredField("service");
      remoteMetaServiceServiceF.setAccessible(true);
      LocalService remoteMetaServiceService =
          (LocalService) remoteMetaServiceServiceF.get(remoteMetaService);
      Field remoteMetaServiceServiceMetaF =
          remoteMetaServiceService.getClass().getDeclaredField("meta");
      remoteMetaServiceServiceMetaF.setAccessible(true);
      JdbcMeta serverMeta = (JdbcMeta) remoteMetaServiceServiceMetaF.get(remoteMetaServiceService);
      Field jdbcMetaConnectionCacheF = JdbcMeta.class.getDeclaredField("connectionCache");
      jdbcMetaConnectionCacheF.setAccessible(true);
      //noinspection unchecked
      @SuppressWarnings("unchecked")
      Cache<String, Connection> cache =
          (Cache<String, Connection>) jdbcMetaConnectionCacheF.get(serverMeta);
      return cache;
    }
  }

  /**
   * Implementation that reaches into current connection state via reflection to extract certain
   * internal information.
   */
  public static class QuasiRemoteProtobufJdbcServiceInternals implements ConnectionInternals {

    @Override public Cache<Integer, Object>
    getRemoteStatementMap(AvaticaConnection connection) throws Exception {
      Field metaF = AvaticaConnection.class.getDeclaredField("meta");
      metaF.setAccessible(true);
      Meta clientMeta = (Meta) metaF.get(connection);
      Field remoteMetaServiceF = clientMeta.getClass().getDeclaredField("service");
      remoteMetaServiceF.setAccessible(true);
      LocalProtobufService remoteMetaService =
          (LocalProtobufService) remoteMetaServiceF.get(clientMeta);
      // Use the explicitly class to avoid issues with LoggingLocalJsonService
      Field remoteMetaServiceServiceF = LocalProtobufService.class.getDeclaredField("service");
      remoteMetaServiceServiceF.setAccessible(true);
      LocalService remoteMetaServiceService =
          (LocalService) remoteMetaServiceServiceF.get(remoteMetaService);
      Field remoteMetaServiceServiceMetaF =
          remoteMetaServiceService.getClass().getDeclaredField("meta");
      remoteMetaServiceServiceMetaF.setAccessible(true);
      JdbcMeta serverMeta = (JdbcMeta) remoteMetaServiceServiceMetaF.get(remoteMetaServiceService);
      Field jdbcMetaStatementMapF = JdbcMeta.class.getDeclaredField("statementCache");
      jdbcMetaStatementMapF.setAccessible(true);
      //noinspection unchecked
      @SuppressWarnings("unchecked")
      Cache<Integer, Object> cache = (Cache<Integer, Object>) jdbcMetaStatementMapF.get(serverMeta);
      return cache;
    }

    @Override public Cache<String, Connection>
    getRemoteConnectionMap(AvaticaConnection connection) throws Exception {
      Field metaF = AvaticaConnection.class.getDeclaredField("meta");
      metaF.setAccessible(true);
      Meta clientMeta = (Meta) metaF.get(connection);
      Field remoteMetaServiceF = clientMeta.getClass().getDeclaredField("service");
      remoteMetaServiceF.setAccessible(true);
      LocalProtobufService remoteMetaService =
          (LocalProtobufService) remoteMetaServiceF.get(clientMeta);
      // Get the field explicitly off the correct class to avoid LocalLoggingJsonService.class
      Field remoteMetaServiceServiceF = LocalProtobufService.class.getDeclaredField("service");
      remoteMetaServiceServiceF.setAccessible(true);
      LocalService remoteMetaServiceService =
          (LocalService) remoteMetaServiceServiceF.get(remoteMetaService);
      Field remoteMetaServiceServiceMetaF =
          remoteMetaServiceService.getClass().getDeclaredField("meta");
      remoteMetaServiceServiceMetaF.setAccessible(true);
      JdbcMeta serverMeta = (JdbcMeta) remoteMetaServiceServiceMetaF.get(remoteMetaServiceService);
      Field jdbcMetaConnectionCacheF = JdbcMeta.class.getDeclaredField("connectionCache");
      jdbcMetaConnectionCacheF.setAccessible(true);
      //noinspection unchecked
      @SuppressWarnings("unchecked")
      Cache<String, Connection> cache =
          (Cache<String, Connection>) jdbcMetaConnectionCacheF.get(serverMeta);
      return cache;
    }
  }

  /**
   * Provides access to a log of requests.
   */
  interface RequestInspection {
    RequestLogger getRequestLogger();
  }

  /** Extension to {@link LocalJsonService} that writes requests and responses
   * into a thread-local. */
  private static class LoggingLocalJsonService extends LocalJsonService
      implements RequestInspection {
    private static final ThreadLocal<RequestLogger> THREAD_LOG =
        new ThreadLocal<RequestLogger>() {
          @Override protected RequestLogger initialValue() {
            return new RequestLogger();
          }
        };

    private LoggingLocalJsonService(LocalService localService) {
      super(localService);
    }

    @Override public String apply(String request) {
      final RequestLogger logger = THREAD_LOG.get();
      logger.requestStart(request);
      final String response = super.apply(request);
      logger.requestEnd(request, response);
      return response;
    }

    @Override public RequestLogger getRequestLogger() {
      return THREAD_LOG.get();
    }
  }

  /** Logs request and response strings if enabled. */
  private static class RequestLogger {
    final List<String[]> requestResponses = new ArrayList<>();
    boolean enabled;

    void enableAndClear() {
      enabled = true;
      requestResponses.clear();
    }

    void requestStart(String request) {
      if (enabled) {
        requestResponses.add(new String[]{request, null});
      }
    }

    void requestEnd(String request, String response) {
      if (enabled) {
        String[] last = requestResponses.get(requestResponses.size() - 1);
        if (!request.equals(last[0])) {
          throw new AssertionError();
        }
        last[1] = response;
      }
    }

    List<String[]> getAndDisable() {
      enabled = false;
      return new ArrayList<>(requestResponses);
    }
  }
}

// End RemoteDriverTest.java
