blob: d73648d4666c1914541b05c6e1adf7fc628b2591 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.avatica.remote;
import org.apache.calcite.avatica.AvaticaUtils;
import org.apache.calcite.avatica.ColumnMetaData;
import org.apache.calcite.avatica.ColumnMetaData.ArrayType;
import org.apache.calcite.avatica.ColumnMetaData.AvaticaType;
import org.apache.calcite.avatica.ColumnMetaData.Rep;
import org.apache.calcite.avatica.ColumnMetaData.ScalarType;
import org.apache.calcite.avatica.SqlType;
import org.apache.calcite.avatica.remote.Driver.Serialization;
import org.apache.calcite.avatica.server.HttpServer;
import org.apache.calcite.avatica.util.AbstractCursor.ArrayAccessor;
import org.apache.calcite.avatica.util.ArrayImpl;
import org.apache.calcite.avatica.util.Cursor.Accessor;
import org.apache.calcite.avatica.util.ListIteratorCursor;
import org.apache.calcite.avatica.util.Unsafe;
import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.sql.Array;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
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.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Test class for verifying functionality with arrays.
*/
@RunWith(Parameterized.class)
public class ArrayTypeTest {
private static final AvaticaServersForTest SERVERS = new AvaticaServersForTest();
private final HttpServer server;
private final String url;
private final int port;
@SuppressWarnings("unused")
private final Driver.Serialization serialization;
@Parameters(name = "{0}")
public static List<Object[]> parameters() throws Exception {
SERVERS.startServers();
return SERVERS.getJUnitParameters();
}
public ArrayTypeTest(Serialization serialization, HttpServer server) {
this.server = server;
this.port = this.server.getPort();
this.serialization = serialization;
this.url = SERVERS.getJdbcUrl(port, serialization);
}
@AfterClass public static void afterClass() throws Exception {
if (null != SERVERS) {
SERVERS.stopServers();
}
}
@Test public void simpleArrayTest() throws Exception {
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType varcharComponent = ColumnMetaData.scalar(Types.VARCHAR, "VARCHAR", Rep.STRING);
List<Array> varcharArrays = new ArrayList<>();
for (int i = 0; i < 5; i++) {
List<String> value = Collections.singletonList(Integer.toString(i));
varcharArrays.add(createArray("VARCHAR", varcharComponent, value));
}
writeAndReadArrays(conn, "varchar_arrays", "VARCHAR(30)",
varcharComponent, varcharArrays, PRIMITIVE_LIST_VALIDATOR);
}
}
@Test public void booleanArrays() throws Exception {
final Random r = new Random();
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.BOOLEAN, "BOOLEAN", Rep.BOOLEAN);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<Boolean> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
switch (r.nextInt(3)) {
case 0:
elements.add(Boolean.FALSE);
break;
case 1:
elements.add(Boolean.TRUE);
break;
case 2:
elements.add(null);
break;
default:
fail();
}
}
arrays.add(createArray("BOOLEAN", component, elements));
}
// Verify we can read and write the data
writeAndReadArrays(conn, "boolean_arrays", "BOOLEAN", component, arrays,
PRIMITIVE_LIST_VALIDATOR);
}
}
@Test public void shortArrays() throws Exception {
final Random r = new Random();
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.SMALLINT, "SMALLINT", Rep.SHORT);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<Short> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
short value = (short) r.nextInt(Short.MAX_VALUE);
// 50% of the time, negate the value
if (0 == r.nextInt(2)) {
value *= -1;
}
elements.add(Short.valueOf(value));
}
arrays.add(createArray("SMALLINT", component, elements));
}
// Verify read/write
writeAndReadArrays(conn, "short_arrays", "SMALLINT", component, arrays,
PRIMITIVE_LIST_VALIDATOR);
}
}
@Test public void shortArraysWithNull() throws Exception {
final Random r = new Random();
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.SMALLINT, "SMALLINT", Rep.SHORT);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<Short> elements = new ArrayList<>();
for (int j = 0; j < 4; j++) {
short value = (short) r.nextInt(Short.MAX_VALUE);
// 50% of the time, negate the value
if (0 == r.nextInt(2)) {
value *= -1;
}
elements.add(Short.valueOf(value));
}
elements.add(null);
arrays.add(createArray("SMALLINT", component, elements));
}
// Verify read/write
writeAndReadArrays(conn, "short_arrays", "SMALLINT", component, arrays,
PRIMITIVE_LIST_VALIDATOR);
}
}
@Test public void longArrays() throws Exception {
final Random r = new Random();
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.BIGINT, "BIGINT", Rep.LONG);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<Long> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
elements.add(r.nextLong());
}
arrays.add(createArray("BIGINT", component, elements));
}
// Verify read/write
writeAndReadArrays(conn, "long_arrays", "BIGINT", component, arrays,
PRIMITIVE_LIST_VALIDATOR);
}
}
@Test public void stringArrays() throws Exception {
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.VARCHAR, "VARCHAR", Rep.STRING);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<String> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
elements.add(i + "_" + j);
}
arrays.add(createArray("VARCHAR", component, elements));
}
// Verify read/write
writeAndReadArrays(conn, "string_arrays", "VARCHAR", component, arrays,
PRIMITIVE_LIST_VALIDATOR);
}
}
@Test public void bigintArrays() throws Exception {
final Random r = new Random();
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.BIGINT, "BIGINT", Rep.LONG);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 3; i++) {
List<Long> elements = new ArrayList<>();
for (int j = 0; j < 7; j++) {
long element = r.nextLong();
if (r.nextBoolean()) {
element *= -1;
}
elements.add(element);
}
arrays.add(createArray("BIGINT", component, elements));
}
writeAndReadArrays(conn, "long_arrays", "BIGINT", component, arrays,
PRIMITIVE_LIST_VALIDATOR);
}
}
@Test public void doubleArrays() throws Exception {
final Random r = new Random();
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.DOUBLE, "DOUBLE", Rep.DOUBLE);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 3; i++) {
List<Double> elements = new ArrayList<>();
for (int j = 0; j < 7; j++) {
double element = r.nextDouble();
if (r.nextBoolean()) {
element *= -1;
}
elements.add(element);
}
arrays.add(createArray("DOUBLE", component, elements));
}
writeAndReadArrays(conn, "float_arrays", "DOUBLE", component, arrays,
PRIMITIVE_LIST_VALIDATOR);
}
}
@Test public void arraysOfByteArrays() throws Exception {
final Random r = new Random();
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.TINYINT, "TINYINT", Rep.BYTE);
// [ Array([b, b, b]), Array([b, b, b]), ... ]
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<Byte> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
byte value = (byte) r.nextInt(Byte.MAX_VALUE);
// 50% of the time, negate the value
if (0 == r.nextInt(2)) {
value *= -1;
}
elements.add(Byte.valueOf(value));
}
arrays.add(createArray("TINYINT", component, elements));
}
// Verify read/write
writeAndReadArrays(conn, "byte_arrays", "TINYINT", component, arrays, BYTE_ARRAY_VALIDATOR);
}
}
@Test public void varbinaryArrays() throws Exception {
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.VARBINARY, "VARBINARY", Rep.BYTE_STRING);
// [ Array(binary, binary, binary), Array(binary, binary, binary), ...]
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<byte[]> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
elements.add((i + "_" + j).getBytes(UTF_8));
}
arrays.add(createArray("VARBINARY", component, elements));
}
writeAndReadArrays(conn, "binary_arrays", "VARBINARY", component, arrays,
BYTE_ARRAY_ARRAY_VALIDATOR);
}
}
@Test public void timeArrays() throws Exception {
try (Connection conn = DriverManager.getConnection(url)) {
final long now = System.currentTimeMillis();
ScalarType component = ColumnMetaData.scalar(Types.TIME, "TIME", Rep.JAVA_SQL_TIME);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<Time> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
elements.add(new Time(now + i + j));
}
arrays.add(createArray("TIME", component, elements));
}
writeAndReadArrays(conn, "time_arrays", "TIME", component, arrays, new Validator<Array>() {
@Override public void validate(Array expected, Array actual) throws SQLException {
Object[] expectedTimes = (Object[]) expected.getArray();
Object[] actualTimes = (Object[]) actual.getArray();
assertEquals(expectedTimes.length, actualTimes.length);
final Calendar cal = Unsafe.localCalendar();
for (int i = 0; i < expectedTimes.length; i++) {
cal.setTime((Time) expectedTimes[i]);
int expectedHour = cal.get(Calendar.HOUR_OF_DAY);
int expectedMinute = cal.get(Calendar.MINUTE);
int expectedSecond = cal.get(Calendar.SECOND);
cal.setTime((Time) actualTimes[i]);
assertEquals(expectedHour, cal.get(Calendar.HOUR_OF_DAY));
assertEquals(expectedMinute, cal.get(Calendar.MINUTE));
assertEquals(expectedSecond, cal.get(Calendar.SECOND));
}
}
});
// Ensure an array with a null element can be written/read
Array arrayWithNull = createArray("TIME", component, Arrays.asList((Time) null));
writeAndReadArrays(conn, "time_array_with_null", "TIME", component,
Collections.singletonList(arrayWithNull), new Validator<Array>() {
@Override public void validate(Array expected, Array actual) throws Exception {
Object[] expectedArray = (Object[]) expected.getArray();
Object[] actualArray = (Object[]) actual.getArray();
assertEquals(1, expectedArray.length);
assertEquals(expectedArray.length, actualArray.length);
assertEquals(expectedArray[0], actualArray[0]);
}
});
}
}
@Test public void dateArrays() throws Exception {
try (Connection conn = DriverManager.getConnection(url)) {
final long now = System.currentTimeMillis();
ScalarType component = ColumnMetaData.scalar(Types.DATE, "DATE", Rep.JAVA_SQL_DATE);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<Date> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
elements.add(new Date(now + i + j));
}
arrays.add(createArray("DATE", component, elements));
}
writeAndReadArrays(conn, "date_arrays", "DATE", component, arrays, new Validator<Array>() {
@Override public void validate(Array expected, Array actual) throws SQLException {
Object[] expectedDates = (Object[]) expected.getArray();
Object[] actualDates = (Object[]) actual.getArray();
assertEquals(expectedDates.length, actualDates.length);
final Calendar cal = Unsafe.localCalendar();
for (int i = 0; i < expectedDates.length; i++) {
cal.setTime((Date) expectedDates[i]);
int expectedDayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
int expectedMonth = cal.get(Calendar.MONTH);
int expectedYear = cal.get(Calendar.YEAR);
cal.setTime((Date) actualDates[i]);
assertEquals(expectedDayOfMonth, cal.get(Calendar.DAY_OF_MONTH));
assertEquals(expectedMonth, cal.get(Calendar.MONTH));
assertEquals(expectedYear, cal.get(Calendar.YEAR));
}
}
});
// Ensure an array with a null element can be written/read
Array arrayWithNull = createArray("DATE", component, Arrays.asList((Time) null));
writeAndReadArrays(conn, "date_array_with_null", "DATE", component,
Collections.singletonList(arrayWithNull), new Validator<Array>() {
@Override public void validate(Array expected, Array actual) throws Exception {
Object[] expectedArray = (Object[]) expected.getArray();
Object[] actualArray = (Object[]) actual.getArray();
assertEquals(1, expectedArray.length);
assertEquals(expectedArray.length, actualArray.length);
assertEquals(expectedArray[0], actualArray[0]);
}
});
}
}
@Test public void timestampArrays() throws Exception {
try (Connection conn = DriverManager.getConnection(url)) {
final long now = System.currentTimeMillis();
ScalarType component = ColumnMetaData.scalar(Types.TIMESTAMP, "TIMESTAMP",
Rep.JAVA_SQL_TIMESTAMP);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<Timestamp> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
elements.add(new Timestamp(now + i + j));
}
arrays.add(createArray("TIMESTAMP", component, elements));
}
writeAndReadArrays(conn, "timestamp_arrays", "TIMESTAMP", component, arrays,
new Validator<Array>() {
@Override public void validate(Array expected, Array actual) throws SQLException {
Object[] expectedTimestamps = (Object[]) expected.getArray();
Object[] actualTimestamps = (Object[]) actual.getArray();
assertEquals(expectedTimestamps.length, actualTimestamps.length);
final Calendar cal = Unsafe.localCalendar();
for (int i = 0; i < expectedTimestamps.length; i++) {
cal.setTime((Timestamp) expectedTimestamps[i]);
int expectedDayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
int expectedMonth = cal.get(Calendar.MONTH);
int expectedYear = cal.get(Calendar.YEAR);
int expectedHour = cal.get(Calendar.HOUR_OF_DAY);
int expectedMinute = cal.get(Calendar.MINUTE);
int expectedSecond = cal.get(Calendar.SECOND);
int expectedMillisecond = cal.get(Calendar.MILLISECOND);
cal.setTime((Timestamp) actualTimestamps[i]);
assertEquals(expectedDayOfMonth, cal.get(Calendar.DAY_OF_MONTH));
assertEquals(expectedMonth, cal.get(Calendar.MONTH));
assertEquals(expectedYear, cal.get(Calendar.YEAR));
assertEquals(expectedHour, cal.get(Calendar.HOUR_OF_DAY));
assertEquals(expectedMinute, cal.get(Calendar.MINUTE));
assertEquals(expectedSecond, cal.get(Calendar.SECOND));
assertEquals(expectedMillisecond, cal.get(Calendar.MILLISECOND));
}
}
});
// Ensure an array with a null element can be written/read
Array arrayWithNull = createArray("TIMESTAMP", component, Arrays.asList((Timestamp) null));
writeAndReadArrays(conn, "timestamp_array_with_null", "TIMESTAMP", component,
Collections.singletonList(arrayWithNull), new Validator<Array>() {
@Override public void validate(Array expected, Array actual) throws Exception {
Object[] expectedArray = (Object[]) expected.getArray();
Object[] actualArray = (Object[]) actual.getArray();
assertEquals(1, expectedArray.length);
assertEquals(expectedArray.length, actualArray.length);
assertEquals(expectedArray[0], actualArray[0]);
}
});
}
}
@Test public void testCreateArrayOf() throws Exception {
try (Connection conn = DriverManager.getConnection(url)) {
final String componentName = SqlType.INTEGER.name();
Array a1 = conn.createArrayOf(componentName, new Object[] {1, 2, 3, 4, 5});
Array a2 = conn.createArrayOf(componentName, new Object[] {2, 3, 4, 5, 6});
Array a3 = conn.createArrayOf(componentName, new Object[] {3, 4, 5, 6, 7});
AvaticaType arrayType = ColumnMetaData.array(
ColumnMetaData.scalar(Types.INTEGER, componentName, Rep.INTEGER), "NUMBERS", Rep.ARRAY);
writeAndReadArrays(conn, "CREATE_ARRAY_OF_INTEGERS", componentName, arrayType,
Arrays.asList(a1, a2, a3), PRIMITIVE_LIST_VALIDATOR);
}
}
@Test public void testBatchInsert() throws Exception {
try (Connection conn = DriverManager.getConnection(url)) {
ScalarType component = ColumnMetaData.scalar(Types.VARCHAR, "VARCHAR", Rep.STRING);
List<Array> arrays = new ArrayList<>();
// Construct the data
for (int i = 0; i < 5; i++) {
List<String> elements = new ArrayList<>();
for (int j = 0; j < 5; j++) {
elements.add(i + "_" + j);
}
arrays.add(createArray("VARCHAR", component, elements));
}
String tableName = "test_batch_insert";
// Drop and create the table
try (Statement stmt = conn.createStatement()) {
assertFalse(stmt.execute(Unsafe.formatLocalString("DROP TABLE IF EXISTS %s", tableName)));
String createTableSql = Unsafe.formatLocalString(
"CREATE TABLE %s (id integer, vals %s ARRAY)", tableName, "VARCHAR");
assertFalse(stmt.execute(createTableSql));
}
// Insert records, each with an array
final String dml = Unsafe.formatLocalString("INSERT INTO %s VALUES (?, ?)", tableName);
try (PreparedStatement stmt = conn.prepareStatement(dml)) {
int i = 0;
for (Array inputArray : arrays) {
stmt.setInt(1, i);
stmt.setArray(2, inputArray);
stmt.addBatch();
i++;
}
assertEquals(i, stmt.executeBatch().length);
}
// Read the records
try (Statement stmt = conn.createStatement()) {
ResultSet results = stmt.executeQuery(
Unsafe.formatLocalString("SELECT * FROM %s", tableName));
assertNotNull("Expected a ResultSet", results);
int i = 0;
for (Array expectedArray : arrays) {
assertTrue(results.next());
assertEquals(i++, results.getInt(1));
Array actualArray = results.getArray(2);
PRIMITIVE_LIST_VALIDATOR.validate(expectedArray, actualArray);
}
assertFalse("Expected no more records", results.next());
}
}
}
/**
* Creates a JDBC {@link Array} from a list of values.
*
* @param typeName the SQL type name of the elements in the array
* @param componentType The Avatica type for the array elements
* @param arrayValues The array elements
* @return An Array instance for the given component and values
*/
@SuppressWarnings("unchecked")
private <T> Array createArray(String typeName, AvaticaType componentType, List<T> arrayValues) {
// Make a "row" with one "column" (which is really a list)
final List<Object> oneRow = Collections.singletonList((Object) arrayValues);
// Make an iterator over this one "row"
final Iterator<List<Object>> rowIterator = Collections.singletonList(oneRow).iterator();
ArrayType array = ColumnMetaData.array(componentType, typeName, Rep.ARRAY);
try (ListIteratorCursor cursor = new ListIteratorCursor(rowIterator)) {
List<ColumnMetaData> types = Collections.singletonList(ColumnMetaData.dummy(array, true));
Calendar calendar = Unsafe.localCalendar();
List<Accessor> accessors = cursor.createAccessors(types, calendar, null);
assertTrue("Expected at least one accessor, found " + accessors.size(),
!accessors.isEmpty());
ArrayAccessor arrayAccessor = (ArrayAccessor) accessors.get(0);
return new ArrayImpl((List<Object>) arrayValues, arrayAccessor);
}
}
/**
* Creates a table, writes the arrays to the table, and then verifies that the arrays can be
* read from that table and are equivalent to the original arrays.
*
* @param conn The JDBC connection
* @param tableName The name of the table to create and use
* @param componentType The component type of the array
* @param scalarType The Avatica type object for the component type of the array
* @param inputArrays The data to write and read
*/
private void writeAndReadArrays(Connection conn, String tableName, String componentType,
AvaticaType scalarType, List<Array> inputArrays, Validator<Array> validator)
throws Exception {
// Drop and create the table
try (Statement stmt = conn.createStatement()) {
assertFalse(stmt.execute(Unsafe.formatLocalString("DROP TABLE IF EXISTS %s", tableName)));
String createTableSql = Unsafe.formatLocalString(
"CREATE TABLE %s (id integer, vals %s ARRAY)", tableName, componentType);
assertFalse(stmt.execute(createTableSql));
}
// Insert records, each with an array
final String dml = Unsafe.formatLocalString("INSERT INTO %s VALUES (?, ?)", tableName);
try (PreparedStatement stmt = conn.prepareStatement(dml)) {
int i = 0;
for (Array inputArray : inputArrays) {
stmt.setInt(1, i);
stmt.setArray(2, inputArray);
assertEquals(1, stmt.executeUpdate());
i++;
}
}
// Read the records
try (Statement stmt = conn.createStatement()) {
ResultSet results = stmt.executeQuery(
Unsafe.formatLocalString("SELECT * FROM %s", tableName));
assertNotNull("Expected a ResultSet", results);
int i = 0;
for (Array expectedArray : inputArrays) {
assertTrue(results.next());
assertEquals(i++, results.getInt(1));
Array actualArray = results.getArray(2);
validator.validate(expectedArray, actualArray);
// TODO Fix this. See {@link AvaticaResultSet#create(ColumnMetaData.AvaticaType,Iterable)}
//ResultSet inputResults = expectedArray.getResultSet();
//ResultSet actualResult = actualArray.getResultSet();
}
assertFalse("Expected no more records", results.next());
}
}
/**
* A simple interface to validate to objects in support of type test cases
* @param <T> the type of element to be validated
*/
private interface Validator<T> {
void validate(T expected, T actual) throws Exception;
}
private static final PrimitiveArrayValidator PRIMITIVE_LIST_VALIDATOR =
new PrimitiveArrayValidator();
/**
* Validator that coerces primitive arrays into lists and comparse them.
*/
private static class PrimitiveArrayValidator implements Validator<Array> {
@Override public void validate(Array expected, Array actual) throws SQLException {
assertEquals(AvaticaUtils.primitiveList(expected.getArray()),
AvaticaUtils.primitiveList(actual.getArray()));
}
}
private static final ByteArrayValidator BYTE_ARRAY_VALIDATOR = new ByteArrayValidator();
/**
* Validator that compares lists of bytes (the object).
*/
private static class ByteArrayValidator implements Validator<Array> {
@SuppressWarnings("unchecked")
@Override public void validate(Array expected, Array actual) throws SQLException {
// Need to compare the byte arrays.
List<Byte> expectedArray =
(List<Byte>) AvaticaUtils.primitiveList(expected.getArray());
List<Byte> actualArray =
(List<Byte>) AvaticaUtils.primitiveList(actual.getArray());
assertEquals(expectedArray.size(), actualArray.size());
for (int j = 0; j < expectedArray.size(); j++) {
Byte expectedByte = expectedArray.get(j);
Byte actualByte = actualArray.get(j);
assertEquals(expectedByte, actualByte);
}
}
}
// Arrays of byte arrays (e.g. an Array<Varbinary>)
private static final ByteArrayArrayValidator BYTE_ARRAY_ARRAY_VALIDATOR =
new ByteArrayArrayValidator();
/**
* Validator that compares lists of byte arrays.
*/
private static class ByteArrayArrayValidator implements Validator<Array> {
@SuppressWarnings("unchecked")
@Override public void validate(Array expected, Array actual) throws SQLException {
// Need to compare the byte arrays.
List<byte[]> expectedArray =
(List<byte[]>) AvaticaUtils.primitiveList(expected.getArray());
List<byte[]> actualArray =
(List<byte[]>) AvaticaUtils.primitiveList(actual.getArray());
assertEquals(expectedArray.size(), actualArray.size());
for (int j = 0; j < expectedArray.size(); j++) {
byte[] expectedBytes = expectedArray.get(j);
byte[] actualBytes = actualArray.get(j);
assertArrayEquals(expectedBytes, actualBytes);
}
}
}
}
// End ArrayTypeTest.java