This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git
The following commit(s) were added to refs/heads/main by this push:
new ca17097 Add test suite for Java ADBC drivers (#31)
ca17097 is described below
commit ca17097b1e4a704fd8ba97e7c44ac2d99392374b
Author: David Li <[email protected]>
AuthorDate: Fri Jul 8 13:51:45 2022 -0400
Add test suite for Java ADBC drivers (#31)
---
.../org/apache/arrow/adbc/core/AdbcConnection.java | 25 ++++
.../org/apache/arrow/adbc/core/AdbcStatement.java | 7 -
java/driver/jdbc-util/pom.xml | 5 +
.../driver/jdbc/util/MockPreparedStatement.java | 1 +
java/driver/jdbc/pom.xml | 7 +-
.../arrow/adbc/driver/jdbc/JdbcConnection.java | 36 +++++
.../arrow/adbc/driver/jdbc/JdbcStatement.java | 25 ++--
.../arrow/adbc/driver/jdbc/JdbcConnectionTest.java | 36 +++++
.../arrow/adbc/driver/jdbc/JdbcDatabaseTest.java | 107 --------------
.../arrow/adbc/driver/jdbc/JdbcStatementTest.java | 37 +++++
.../adbc/driver/jdbc/JdbcTransactionTest.java | 36 +++++
java/driver/{jdbc-util => testsuite}/pom.xml | 16 +-
.../driver/testsuite/AbstractConnectionTest.java | 49 ++++++
.../driver/testsuite/AbstractStatementTest.java | 99 +++++++++++++
.../driver/testsuite/AbstractTransactionTest.java | 164 +++++++++++++++++++++
.../adbc/driver/testsuite/ArrowAssertions.java | 55 +++++++
java/pom.xml | 11 ++
17 files changed, 580 insertions(+), 136 deletions(-)
diff --git
a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcConnection.java
b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcConnection.java
index f6cb228..0917f65 100644
--- a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcConnection.java
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcConnection.java
@@ -16,6 +16,8 @@
*/
package org.apache.arrow.adbc.core;
+import org.apache.arrow.vector.VectorSchemaRoot;
+
/** A connection to a {@link AdbcDatabase}. */
public interface AdbcConnection extends AutoCloseable {
/**
@@ -32,6 +34,11 @@ public interface AdbcConnection extends AutoCloseable {
/** Create a new statement that can be executed. */
AdbcStatement createStatement() throws AdbcException;
+ /** Create a new statement to bulk insert a {@link VectorSchemaRoot} into a
table. */
+ default AdbcStatement bulkIngest(String targetTableName) throws
AdbcException {
+ throw new UnsupportedOperationException("Connection does not support bulk
ingestion");
+ }
+
/**
* Rollback the pending transaction.
*
@@ -42,4 +49,22 @@ public interface AdbcConnection extends AutoCloseable {
default void rollback() throws AdbcException {
throw new UnsupportedOperationException("Connection does not support
transactions");
}
+
+ /**
+ * Get the autocommit state.
+ *
+ * <p>Connections start in autocommit mode by default.
+ */
+ default boolean getAutoCommit() throws AdbcException {
+ return true;
+ }
+
+ /**
+ * Toggle whether autocommit is enabled.
+ *
+ * @throws UnsupportedOperationException if the database does not support
toggling autocommit
+ */
+ default void setAutoCommit(boolean enableAutoCommit) throws AdbcException {
+ throw new UnsupportedOperationException("Connection does not support
transactions");
+ }
}
diff --git
a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcStatement.java
b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcStatement.java
index dbba624..6b464e9 100644
--- a/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcStatement.java
+++ b/java/core/src/main/java/org/apache/arrow/adbc/core/AdbcStatement.java
@@ -24,13 +24,6 @@ import org.apache.arrow.vector.VectorSchemaRoot;
import org.apache.arrow.vector.ipc.ArrowReader;
public interface AdbcStatement extends AutoCloseable {
- /**
- * The name of the target table for a bulk insert.
- *
- * @see #setOption(String, String)
- */
- String INGEST_OPTION_TARGET_TABLE = "adbc.ingest.target_table";
-
/** Set a generic query option. */
default void setOption(String key, String value) {
throw new UnsupportedOperationException("Unsupported option " + key);
diff --git a/java/driver/jdbc-util/pom.xml b/java/driver/jdbc-util/pom.xml
index 8aa20f2..44b5405 100644
--- a/java/driver/jdbc-util/pom.xml
+++ b/java/driver/jdbc-util/pom.xml
@@ -49,5 +49,10 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.arrow.adbc</groupId>
+ <artifactId>adbc-driver-testsuite</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git
a/java/driver/jdbc-util/src/test/java/org/apache/arrow/adbc/driver/jdbc/util/MockPreparedStatement.java
b/java/driver/jdbc-util/src/test/java/org/apache/arrow/adbc/driver/jdbc/util/MockPreparedStatement.java
index bbaea4b..51ae7db 100644
---
a/java/driver/jdbc-util/src/test/java/org/apache/arrow/adbc/driver/jdbc/util/MockPreparedStatement.java
+++
b/java/driver/jdbc-util/src/test/java/org/apache/arrow/adbc/driver/jdbc/util/MockPreparedStatement.java
@@ -158,6 +158,7 @@ class MockPreparedStatement implements PreparedStatement {
}
@Override
+ @Deprecated
public void setUnicodeStream(int parameterIndex, InputStream x, int length)
throws SQLException {
parameters.put(parameterIndex, new ParameterHolder(x, null));
}
diff --git a/java/driver/jdbc/pom.xml b/java/driver/jdbc/pom.xml
index 1437f59..105ad4f 100644
--- a/java/driver/jdbc/pom.xml
+++ b/java/driver/jdbc/pom.xml
@@ -18,7 +18,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
- <artifactId>adbc-driver-derby</artifactId>
+ <artifactId>adbc-driver-jdbc</artifactId>
<packaging>jar</packaging>
<name>Arrow ADBC Driver JDBC</name>
<description>An ADBC driver wrapping the JDBC API.</description>
@@ -77,5 +77,10 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.arrow.adbc</groupId>
+ <artifactId>adbc-driver-testsuite</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git
a/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/JdbcConnection.java
b/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/JdbcConnection.java
index c2e4091..71554f9 100644
---
a/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/JdbcConnection.java
+++
b/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/JdbcConnection.java
@@ -35,6 +35,7 @@ public class JdbcConnection implements AdbcConnection {
@Override
public void commit() throws AdbcException {
try {
+ checkAutoCommit();
connection.commit();
} catch (SQLException e) {
throw JdbcDriverUtil.fromSqlException(e);
@@ -46,17 +47,52 @@ public class JdbcConnection implements AdbcConnection {
return new JdbcStatement(allocator, connection);
}
+ @Override
+ public AdbcStatement bulkIngest(String targetTableName) throws AdbcException
{
+ return JdbcStatement.ingestRoot(allocator, connection, targetTableName);
+ }
+
@Override
public void rollback() throws AdbcException {
try {
+ checkAutoCommit();
connection.rollback();
} catch (SQLException e) {
throw JdbcDriverUtil.fromSqlException(e);
}
}
+ @Override
+ public boolean getAutoCommit() throws AdbcException {
+ try {
+ return connection.getAutoCommit();
+ } catch (SQLException e) {
+ throw JdbcDriverUtil.fromSqlException(e);
+ }
+ }
+
+ @Override
+ public void setAutoCommit(boolean enableAutoCommit) throws AdbcException {
+ try {
+ connection.setAutoCommit(enableAutoCommit);
+ } catch (SQLException e) {
+ throw JdbcDriverUtil.fromSqlException(e);
+ }
+ }
+
@Override
public void close() throws Exception {
connection.close();
}
+
+ private void checkAutoCommit() throws SQLException {
+ if (connection.getAutoCommit()) {
+ throw new IllegalStateException("Cannot perform operation in autocommit
mode");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "JdbcConnection{" + "connection=" + connection + '}';
+ }
}
diff --git
a/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/JdbcStatement.java
b/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/JdbcStatement.java
index d21fc80..56bb626 100644
---
a/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/JdbcStatement.java
+++
b/java/driver/jdbc/src/main/java/org/apache/arrow/adbc/driver/jdbc/JdbcStatement.java
@@ -27,6 +27,7 @@ import org.apache.arrow.adbc.core.AdbcException;
import org.apache.arrow.adbc.core.AdbcStatement;
import org.apache.arrow.adbc.driver.jdbc.util.JdbcParameterBinder;
import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.util.AutoCloseables;
import org.apache.arrow.vector.VectorSchemaRoot;
import org.apache.arrow.vector.ipc.ArrowReader;
import org.apache.arrow.vector.types.pojo.Field;
@@ -36,6 +37,7 @@ public class JdbcStatement implements AdbcStatement {
private final Connection connection;
// State for SQL queries
+ private Statement statement;
private String sqlQuery;
private ResultSet resultSet;
// State for bulk ingest
@@ -48,14 +50,12 @@ public class JdbcStatement implements AdbcStatement {
this.sqlQuery = null;
}
- @Override
- public void setOption(String key, String value) {
- if (AdbcStatement.INGEST_OPTION_TARGET_TABLE.equals(key)) {
- bulkTargetTable = Objects.requireNonNull(value);
- sqlQuery = null;
- return;
- }
- AdbcStatement.super.setOption(key, value);
+ static AdbcStatement ingestRoot(
+ BufferAllocator allocator, Connection connection, String
targetTableName) {
+ Objects.requireNonNull(targetTableName);
+ final JdbcStatement statement = new JdbcStatement(allocator, connection);
+ statement.bulkTargetTable = targetTableName;
+ return statement;
}
@Override
@@ -109,7 +109,10 @@ public class JdbcStatement implements AdbcStatement {
create.append(" INT");
break;
case FloatingPoint:
+ throw new UnsupportedOperationException("Type " + field);
case Utf8:
+ create.append(" CLOB");
+ break;
case LargeUtf8:
case Binary:
case LargeBinary:
@@ -164,7 +167,7 @@ public class JdbcStatement implements AdbcStatement {
if (resultSet != null) {
resultSet.close();
}
- final Statement statement =
+ statement =
connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
resultSet = statement.executeQuery(sqlQuery);
} catch (SQLException e) {
@@ -189,8 +192,6 @@ public class JdbcStatement implements AdbcStatement {
@Override
public void close() throws Exception {
- if (resultSet != null) {
- resultSet.close();
- }
+ AutoCloseables.close(resultSet, statement);
}
}
diff --git
a/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcConnectionTest.java
b/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcConnectionTest.java
new file mode 100644
index 0000000..bbfe424
--- /dev/null
+++
b/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcConnectionTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.arrow.adbc.driver.jdbc;
+
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.arrow.adbc.core.AdbcDatabase;
+import org.apache.arrow.adbc.core.AdbcException;
+import org.apache.arrow.adbc.driver.testsuite.AbstractConnectionTest;
+import org.junit.jupiter.api.io.TempDir;
+
+public class JdbcConnectionTest extends AbstractConnectionTest {
+ @TempDir Path tempDir;
+
+ @Override
+ protected AdbcDatabase init() throws AdbcException {
+ final Map<String, String> parameters = new HashMap<>();
+ parameters.put("path", tempDir.toString() + "/db;create=true");
+ return JdbcDriver.INSTANCE.connect(parameters);
+ }
+}
diff --git
a/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcDatabaseTest.java
b/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcDatabaseTest.java
deleted file mode 100644
index f80649f..0000000
---
a/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcDatabaseTest.java
+++ /dev/null
@@ -1,107 +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.arrow.adbc.driver.jdbc;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.arrow.adbc.core.AdbcConnection;
-import org.apache.arrow.adbc.core.AdbcDatabase;
-import org.apache.arrow.adbc.core.AdbcStatement;
-import org.apache.arrow.memory.BufferAllocator;
-import org.apache.arrow.memory.RootAllocator;
-import org.apache.arrow.vector.FieldVector;
-import org.apache.arrow.vector.IntVector;
-import org.apache.arrow.vector.VectorSchemaRoot;
-import org.apache.arrow.vector.ipc.ArrowReader;
-import org.apache.arrow.vector.types.pojo.ArrowType;
-import org.apache.arrow.vector.types.pojo.Field;
-import org.apache.arrow.vector.types.pojo.Schema;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-class JdbcDatabaseTest {
- @BeforeAll
- static void beforeAll() {
- new org.apache.derby.jdbc.EmbeddedDriver();
- }
-
- @Test
- void simpleQuery(@TempDir Path tempDir) throws Exception {
- final Map<String, String> parameters = new HashMap<>();
- parameters.put("path", tempDir.toString() + "/db;create=true");
- try (final AdbcDatabase database = JdbcDriver.INSTANCE.connect(parameters);
- final AdbcConnection connection = database.connect();
- final AdbcStatement statement = connection.createStatement()) {
- statement.setSqlQuery("SELECT * FROM SYS.SYSTABLES");
- statement.execute();
- try (final ArrowReader reader = statement.getArrowReader()) {
- assertThat(reader.loadNextBatch()).isTrue();
- }
- }
- }
-
- @Test
- void bulkInsert(@TempDir Path tempDir) throws Exception {
- final Map<String, String> parameters = new HashMap<>();
- parameters.put("path", tempDir.toString() + "/db;create=true");
- final Schema schema =
- new Schema(
- Collections.singletonList(
- Field.nullable("ints", new ArrowType.Int(32, /*signed=*/
true))));
- try (final BufferAllocator allocator = new RootAllocator();
- final AdbcDatabase database = JdbcDriver.INSTANCE.connect(parameters);
- final AdbcConnection connection = database.connect()) {
- try (final AdbcStatement statement = connection.createStatement();
- final VectorSchemaRoot ingest = VectorSchemaRoot.create(schema,
allocator)) {
- statement.setOption(AdbcStatement.INGEST_OPTION_TARGET_TABLE, "foo");
- statement.bind(ingest);
- final IntVector ints = (IntVector) ingest.getVector(0);
- ints.allocateNew(4);
- ints.setSafe(0, 0);
- ints.setSafe(1, 1);
- ints.setSafe(2, 2);
- ints.setSafe(3, 3);
- ingest.setRowCount(4);
- statement.execute();
- }
-
- try (final AdbcStatement statement = connection.createStatement()) {
- statement.setSqlQuery("SELECT * FROM foo");
- statement.execute();
-
- try (final ArrowReader reader = statement.getArrowReader()) {
- assertThat(reader.loadNextBatch()).isTrue();
- final FieldVector vector = reader.getVectorSchemaRoot().getVector(0);
- assertThat(vector).isInstanceOf(IntVector.class);
- assertThat(vector.getValueCount()).isEqualTo(4);
- final IntVector ints = (IntVector) vector;
- for (int i = 0; i < 4; i++) {
- assertThat(ints.isNull(i)).isFalse();
- assertThat(ints.get(i)).isEqualTo(i);
- }
- assertThat(reader.loadNextBatch()).isFalse();
- }
- }
- }
- }
-}
diff --git
a/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcStatementTest.java
b/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcStatementTest.java
new file mode 100644
index 0000000..d81347d
--- /dev/null
+++
b/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcStatementTest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.arrow.adbc.driver.jdbc;
+
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.arrow.adbc.core.AdbcDatabase;
+import org.apache.arrow.adbc.core.AdbcException;
+import org.apache.arrow.adbc.driver.testsuite.AbstractStatementTest;
+import org.junit.jupiter.api.io.TempDir;
+
+class JdbcStatementTest extends AbstractStatementTest {
+ @TempDir Path tempDir;
+
+ @Override
+ protected AdbcDatabase init() throws AdbcException {
+ final Map<String, String> parameters = new HashMap<>();
+ parameters.put("path", tempDir.toString() + "/db;create=true");
+ return JdbcDriver.INSTANCE.connect(parameters);
+ }
+}
diff --git
a/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcTransactionTest.java
b/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcTransactionTest.java
new file mode 100644
index 0000000..622f5e8
--- /dev/null
+++
b/java/driver/jdbc/src/test/java/org/apache/arrow/adbc/driver/jdbc/JdbcTransactionTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.arrow.adbc.driver.jdbc;
+
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.arrow.adbc.core.AdbcDatabase;
+import org.apache.arrow.adbc.core.AdbcException;
+import org.apache.arrow.adbc.driver.testsuite.AbstractTransactionTest;
+import org.junit.jupiter.api.io.TempDir;
+
+public class JdbcTransactionTest extends AbstractTransactionTest {
+ @TempDir Path tempDir;
+
+ @Override
+ protected AdbcDatabase init() throws AdbcException {
+ final Map<String, String> parameters = new HashMap<>();
+ parameters.put("path", tempDir.toString() + "/db;create=true");
+ return JdbcDriver.INSTANCE.connect(parameters);
+ }
+}
diff --git a/java/driver/jdbc-util/pom.xml b/java/driver/testsuite/pom.xml
similarity index 84%
copy from java/driver/jdbc-util/pom.xml
copy to java/driver/testsuite/pom.xml
index 8aa20f2..cf489bc 100644
--- a/java/driver/jdbc-util/pom.xml
+++ b/java/driver/testsuite/pom.xml
@@ -15,20 +15,20 @@
<artifactId>arrow-adbc-java-root</artifactId>
<groupId>org.apache.arrow.adbc</groupId>
<version>9.0.0-SNAPSHOT</version>
- <relativePath>../../pom.xml</relativePath>
</parent>
- <artifactId>adbc-driver-jdbc-util</artifactId>
+ <artifactId>adbc-driver-testsuite</artifactId>
<packaging>jar</packaging>
- <name>Arrow ADBC Driver JDBC Util</name>
- <description>Utilities for working with Arrow and JDBC.</description>
+ <name>Arrow ADBC Driver Test Suite</name>
+ <description>A reusable ADBC driver compliance/test suite.</description>
<dependencies>
- <!-- Arrow -->
<dependency>
- <groupId>org.apache.arrow</groupId>
- <artifactId>arrow-jdbc</artifactId>
+ <groupId>org.apache.arrow.adbc</groupId>
+ <artifactId>adbc-core</artifactId>
</dependency>
+
+ <!-- Arrow -->
<dependency>
<groupId>org.apache.arrow</groupId>
<artifactId>arrow-memory-core</artifactId>
@@ -42,12 +42,10 @@
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
- <scope>test</scope>
</dependency>
</dependencies>
</project>
diff --git
a/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractConnectionTest.java
b/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractConnectionTest.java
new file mode 100644
index 0000000..fb22e8a
--- /dev/null
+++
b/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractConnectionTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.arrow.adbc.driver.testsuite;
+
+import org.apache.arrow.adbc.core.AdbcConnection;
+import org.apache.arrow.adbc.core.AdbcDatabase;
+import org.apache.arrow.adbc.core.AdbcException;
+import org.apache.arrow.util.AutoCloseables;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public abstract class AbstractConnectionTest {
+ protected AdbcDatabase database;
+ protected AdbcConnection connection;
+
+ protected abstract AdbcDatabase init() throws AdbcException;
+
+ @BeforeEach
+ public void beforeEach() throws Exception {
+ database = init();
+ connection = database.connect();
+ }
+
+ @AfterEach
+ public void afterEach() throws Exception {
+ AutoCloseables.close(connection, database);
+ }
+
+ @Test
+ void multipleConnections() throws Exception {
+ try (final AdbcConnection ignored = database.connect()) {}
+ }
+}
diff --git
a/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractStatementTest.java
b/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractStatementTest.java
new file mode 100644
index 0000000..fc10c56
--- /dev/null
+++
b/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractStatementTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.arrow.adbc.driver.testsuite;
+
+import static
org.apache.arrow.adbc.driver.testsuite.ArrowAssertions.assertRoot;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import org.apache.arrow.adbc.core.AdbcConnection;
+import org.apache.arrow.adbc.core.AdbcDatabase;
+import org.apache.arrow.adbc.core.AdbcException;
+import org.apache.arrow.adbc.core.AdbcStatement;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.RootAllocator;
+import org.apache.arrow.util.AutoCloseables;
+import org.apache.arrow.vector.IntVector;
+import org.apache.arrow.vector.VarCharVector;
+import org.apache.arrow.vector.VectorSchemaRoot;
+import org.apache.arrow.vector.ipc.ArrowReader;
+import org.apache.arrow.vector.types.pojo.ArrowType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.Schema;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public abstract class AbstractStatementTest {
+ protected AdbcDatabase database;
+ protected AdbcConnection connection;
+ protected BufferAllocator allocator;
+
+ protected abstract AdbcDatabase init() throws AdbcException;
+
+ @BeforeEach
+ public void beforeEach() throws Exception {
+ database = init();
+ connection = database.connect();
+ allocator = new RootAllocator();
+ }
+
+ @AfterEach
+ public void afterEach() throws Exception {
+ AutoCloseables.close(connection, database, allocator);
+ }
+
+ @Test
+ public void bulkInsert() throws Exception {
+ final Schema schema =
+ new Schema(
+ Arrays.asList(
+ Field.nullable("INTS", new ArrowType.Int(32, /*signed=*/
true)),
+ Field.nullable("STRS", new ArrowType.Utf8())));
+ try (final VectorSchemaRoot root = VectorSchemaRoot.create(schema,
allocator)) {
+ final IntVector ints = (IntVector) root.getVector(0);
+ final VarCharVector strs = (VarCharVector) root.getVector(1);
+
+ ints.allocateNew(4);
+ ints.setSafe(0, 0);
+ ints.setSafe(1, 1);
+ ints.setSafe(2, 2);
+ ints.setNull(3);
+ strs.allocateNew(4);
+ strs.setNull(0);
+ strs.setSafe(1, "foo".getBytes(StandardCharsets.UTF_8));
+ strs.setSafe(2, "".getBytes(StandardCharsets.UTF_8));
+ strs.setSafe(3, "asdf".getBytes(StandardCharsets.UTF_8));
+ root.setRowCount(4);
+
+ try (final AdbcStatement stmt = connection.bulkIngest("foo")) {
+ stmt.bind(root);
+ stmt.execute();
+ }
+ try (final AdbcStatement stmt = connection.createStatement()) {
+ stmt.setSqlQuery("SELECT * FROM foo");
+ stmt.execute();
+ try (ArrowReader arrowReader = stmt.getArrowReader()) {
+ assertThat(arrowReader.loadNextBatch()).isTrue();
+ assertRoot(arrowReader.getVectorSchemaRoot()).isEqualTo(root);
+ }
+ }
+ }
+ }
+}
diff --git
a/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractTransactionTest.java
b/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractTransactionTest.java
new file mode 100644
index 0000000..96f0247
--- /dev/null
+++
b/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/AbstractTransactionTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.arrow.adbc.driver.testsuite;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Collections;
+import org.apache.arrow.adbc.core.AdbcConnection;
+import org.apache.arrow.adbc.core.AdbcDatabase;
+import org.apache.arrow.adbc.core.AdbcException;
+import org.apache.arrow.adbc.core.AdbcStatement;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.RootAllocator;
+import org.apache.arrow.util.AutoCloseables;
+import org.apache.arrow.vector.IntVector;
+import org.apache.arrow.vector.VectorSchemaRoot;
+import org.apache.arrow.vector.types.pojo.ArrowType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.Schema;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public abstract class AbstractTransactionTest {
+ protected BufferAllocator allocator;
+ protected AdbcDatabase database;
+ protected AdbcConnection connection;
+
+ protected abstract AdbcDatabase init() throws AdbcException;
+
+ @BeforeEach
+ public void beforeEach() throws Exception {
+ database = init();
+ connection = database.connect();
+ allocator = new RootAllocator();
+ }
+
+ @AfterEach
+ public void afterEach() throws Exception {
+ AutoCloseables.close(connection, database, allocator);
+ }
+
+ @Test
+ void autoCommitByDefault() throws Exception {
+ assertThrows(IllegalStateException.class, () -> connection.commit());
+ assertThrows(IllegalStateException.class, () -> connection.rollback());
+ assertThat(connection.getAutoCommit()).isTrue();
+ }
+
+ @Test
+ void toggleAutoCommit() throws Exception {
+ assertThat(connection.getAutoCommit()).isTrue();
+ connection.setAutoCommit(true);
+ assertThat(connection.getAutoCommit()).isTrue();
+ connection.setAutoCommit(false);
+ assertThat(connection.getAutoCommit()).isFalse();
+ connection.setAutoCommit(true);
+ assertThat(connection.getAutoCommit()).isTrue();
+ }
+
+ @Test
+ void rollback() throws Exception {
+ final Schema schema =
+ new Schema(
+ Collections.singletonList(
+ Field.nullable("ints", new ArrowType.Int(32, /*signed=*/
true))));
+
+ connection.setAutoCommit(false);
+ try (VectorSchemaRoot root = VectorSchemaRoot.create(schema, allocator)) {
+ final IntVector ints = (IntVector) root.getVector(0);
+ ints.setSafe(0, 1);
+ ints.setSafe(1, 2);
+ root.setRowCount(2);
+ try (final AdbcStatement stmt = connection.bulkIngest("foo")) {
+ stmt.bind(root);
+ stmt.execute();
+ }
+ try (final AdbcStatement stmt = connection.createStatement()) {
+ stmt.setSqlQuery("SELECT * FROM foo");
+ stmt.execute();
+ }
+ connection.rollback();
+ try (final AdbcStatement stmt = connection.createStatement()) {
+ stmt.setSqlQuery("SELECT * FROM foo");
+ assertThrows(AdbcException.class, stmt::execute);
+ }
+ }
+ }
+
+ @Test
+ void commit() throws Exception {
+ final Schema schema =
+ new Schema(
+ Collections.singletonList(
+ Field.nullable("ints", new ArrowType.Int(32, /*signed=*/
true))));
+
+ connection.setAutoCommit(false);
+ try (VectorSchemaRoot root = VectorSchemaRoot.create(schema, allocator)) {
+ final IntVector ints = (IntVector) root.getVector(0);
+ ints.setSafe(0, 1);
+ ints.setSafe(1, 2);
+ root.setRowCount(2);
+ try (final AdbcStatement stmt = connection.bulkIngest("foo")) {
+ stmt.bind(root);
+ stmt.execute();
+ }
+ try (final AdbcStatement stmt = connection.createStatement()) {
+ stmt.setSqlQuery("SELECT * FROM foo");
+ stmt.execute();
+ }
+ connection.commit();
+ try (final AdbcStatement stmt = connection.createStatement()) {
+ stmt.setSqlQuery("SELECT * FROM foo");
+ stmt.execute();
+ }
+ connection.commit();
+ }
+ }
+
+ @Test
+ void enableAutoCommitAlsoCommits() throws Exception {
+ final Schema schema =
+ new Schema(
+ Collections.singletonList(
+ Field.nullable("ints", new ArrowType.Int(32, /*signed=*/
true))));
+
+ connection.setAutoCommit(false);
+ try (VectorSchemaRoot root = VectorSchemaRoot.create(schema, allocator)) {
+ final IntVector ints = (IntVector) root.getVector(0);
+ ints.setSafe(0, 1);
+ ints.setSafe(1, 2);
+ root.setRowCount(2);
+ try (final AdbcStatement stmt = connection.bulkIngest("foo")) {
+ stmt.bind(root);
+ stmt.execute();
+ }
+ try (final AdbcStatement stmt = connection.createStatement()) {
+ stmt.setSqlQuery("SELECT * FROM foo");
+ stmt.execute();
+ }
+ connection.setAutoCommit(true);
+ try (final AdbcStatement stmt = connection.createStatement()) {
+ stmt.setSqlQuery("SELECT * FROM foo");
+ stmt.execute();
+ }
+ }
+ }
+}
diff --git
a/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/ArrowAssertions.java
b/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/ArrowAssertions.java
new file mode 100644
index 0000000..194fa00
--- /dev/null
+++
b/java/driver/testsuite/src/main/java/org/apache/arrow/adbc/driver/testsuite/ArrowAssertions.java
@@ -0,0 +1,55 @@
+/*
+ * 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.arrow.adbc.driver.testsuite;
+
+import org.apache.arrow.vector.VectorSchemaRoot;
+import org.assertj.core.api.AbstractAssert;
+
+/** AssertJ assertions for Arrow. */
+public final class ArrowAssertions {
+ /** Assert on a {@link VectorSchemaRoot}. */
+ public static VectorSchemaRootAssert assertRoot(VectorSchemaRoot actual) {
+ return new VectorSchemaRootAssert(actual);
+ }
+
+ public static final class VectorSchemaRootAssert
+ extends AbstractAssert<VectorSchemaRootAssert, VectorSchemaRoot> {
+ VectorSchemaRootAssert(VectorSchemaRoot vectorSchemaRoot) {
+ super(vectorSchemaRoot, VectorSchemaRootAssert.class);
+ }
+
+ @Override
+ public VectorSchemaRootAssert isEqualTo(Object expected) {
+ if (!(expected instanceof VectorSchemaRoot)) {
+ throw failure(
+ "Expected object is not a VectorSchemaRoot, but rather a %s",
+ expected.getClass().getName());
+ }
+ final VectorSchemaRoot expectedRoot = (VectorSchemaRoot) expected;
+ if (!actual.equals(expectedRoot)) {
+ throw failureWithActualExpected(
+ actual,
+ expected,
+ "Expected Root:\n%sActual Root:\n%s",
+ expectedRoot.contentToTSVString(),
+ actual.contentToTSVString());
+ }
+ return this;
+ }
+ }
+}
diff --git a/java/pom.xml b/java/pom.xml
index 8645c11..8dc6657 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -70,6 +70,7 @@
<module>core</module>
<module>driver/jdbc</module>
<module>driver/jdbc-util</module>
+ <module>driver/testsuite</module>
<module>driver-manager</module>
</modules>
@@ -97,11 +98,21 @@
<artifactId>adbc-core</artifactId>
<version>${adbc.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.arrow.adbc</groupId>
+ <artifactId>adbc-driver-jdbc</artifactId>
+ <version>${adbc.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.arrow.adbc</groupId>
<artifactId>adbc-driver-jdbc-util</artifactId>
<version>${adbc.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.arrow.adbc</groupId>
+ <artifactId>adbc-driver-testsuite</artifactId>
+ <version>${adbc.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.arrow.adbc</groupId>
<artifactId>adbc-driver-manager</artifactId>