http://git-wip-us.apache.org/repos/asf/calcite-avatica/blob/fc7b26c8/avatica/server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
----------------------------------------------------------------------
diff --git
a/avatica/server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
b/avatica/server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
deleted file mode 100644
index 0823a12..0000000
---
a/avatica/server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
+++ /dev/null
@@ -1,2077 +0,0 @@
-/*
- * 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 java.util.concurrent.TimeUnit;
-
-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
- 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[] {
- 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[] {
- 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(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 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) {
- 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 String sql1 = "select ? + interval '2' day as c 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();
-
- ps = connection.prepareStatement(sql1);
- parameterMetaData = ps.getParameterMetaData();
- assertThat(parameterMetaData.getParameterCount(), equalTo(1));
-
- ps.setDate(1, date);
- resultSet = ps.executeQuery();
- assertTrue(resultSet.next());
- assertThat(resultSet.getDate(1),
- equalTo(new Date(time + TimeUnit.DAYS.toMillis(2))));
- assertThat(resultSet.getTimestamp(1),
- equalTo(new Timestamp(time + TimeUnit.DAYS.toMillis(2))));
-
- ps.setTimestamp(1, new Timestamp(time));
- resultSet = ps.executeQuery();
- assertTrue(resultSet.next());
- assertThat(resultSet.getTimestamp(1),
- equalTo(new Timestamp(time + TimeUnit.DAYS.toMillis(2))));
- assertThat(resultSet.getTimestamp(1),
- equalTo(new Timestamp(time + TimeUnit.DAYS.toMillis(2))));
-
- ps.setObject(1, new java.util.Date(time));
- resultSet = ps.executeQuery();
- assertTrue(resultSet.next());
- assertThat(resultSet.getDate(1),
- equalTo(new Date(time + TimeUnit.DAYS.toMillis(2))));
- assertThat(resultSet.getTimestamp(1),
- equalTo(new Timestamp(time + TimeUnit.DAYS.toMillis(2))));
-
- resultSet.close();
- 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.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 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();
- }
- };
-
- public 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