Search in sources :

Example 1 with ArrayType

use of org.apache.calcite.avatica.ColumnMetaData.ArrayType in project calcite-avatica by apache.

the class ArrayFactoryImpl method createArray.

@Override
public Array createArray(AvaticaType elementType, Iterable<Object> elements) {
    final ArrayType array = ColumnMetaData.array(elementType, elementType.name, Rep.ARRAY);
    final List<ColumnMetaData> types = Collections.singletonList(ColumnMetaData.dummy(array, true));
    // Avoid creating a new List if we already have a List
    List<Object> elementList;
    if (elements instanceof List) {
        elementList = (List<Object>) elements;
    } else {
        elementList = new ArrayList<>();
        for (Object element : elements) {
            elementList.add(element);
        }
    }
    try (ListIteratorCursor cursor = new ListIteratorCursor(createRowForArrayData(elementList))) {
        List<Accessor> accessor = cursor.createAccessors(types, Unsafe.localCalendar(), this);
        assert 1 == accessor.size();
        return new ArrayImpl(elementList, (ArrayAccessor) accessor.get(0));
    }
}
Also used : ArrayType(org.apache.calcite.avatica.ColumnMetaData.ArrayType) ArrayList(java.util.ArrayList) List(java.util.List) ColumnMetaData(org.apache.calcite.avatica.ColumnMetaData) ArrayAccessor(org.apache.calcite.avatica.util.AbstractCursor.ArrayAccessor) Accessor(org.apache.calcite.avatica.util.Cursor.Accessor)

Example 2 with ArrayType

use of org.apache.calcite.avatica.ColumnMetaData.ArrayType in project calcite-avatica by apache.

the class ArrayTypeTest method createArray.

/**
 * 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);
        assertFalse("Expected at least one accessor, found " + accessors.size(), accessors.isEmpty());
        ArrayAccessor arrayAccessor = (ArrayAccessor) accessors.get(0);
        return new ArrayImpl((List<Object>) arrayValues, arrayAccessor);
    }
}
Also used : Calendar(java.util.Calendar) ArrayImpl(org.apache.calcite.avatica.util.ArrayImpl) ArrayAccessor(org.apache.calcite.avatica.util.AbstractCursor.ArrayAccessor) Accessor(org.apache.calcite.avatica.util.Cursor.Accessor) ArrayAccessor(org.apache.calcite.avatica.util.AbstractCursor.ArrayAccessor) ArrayType(org.apache.calcite.avatica.ColumnMetaData.ArrayType) ListIteratorCursor(org.apache.calcite.avatica.util.ListIteratorCursor) ArrayList(java.util.ArrayList) List(java.util.List) ColumnMetaData(org.apache.calcite.avatica.ColumnMetaData)

Example 3 with ArrayType

use of org.apache.calcite.avatica.ColumnMetaData.ArrayType in project calcite-avatica by apache.

the class JdbcResultSet method frame.

/**
 * Creates a frame containing a given number or unlimited number of rows
 * from a result set.
 */
static Meta.Frame frame(StatementInfo info, ResultSet resultSet, long offset, int fetchMaxRowCount, Calendar calendar, Optional<Meta.Signature> sig) throws SQLException {
    final ResultSetMetaData metaData = resultSet.getMetaData();
    final int columnCount = metaData.getColumnCount();
    final int[] types = new int[columnCount];
    Set<Integer> arrayOffsets = new HashSet<>();
    for (int i = 0; i < types.length; i++) {
        types[i] = metaData.getColumnType(i + 1);
        if (Types.ARRAY == types[i]) {
            arrayOffsets.add(i);
        }
    }
    final List<Object> rows = new ArrayList<>();
    // Meta prepare/prepareAndExecute 0 return 0 row and done
    boolean done = fetchMaxRowCount == 0;
    for (int i = 0; fetchMaxRowCount < 0 || i < fetchMaxRowCount; i++) {
        final boolean hasRow;
        if (null != info) {
            hasRow = info.next();
        } else {
            hasRow = resultSet.next();
        }
        if (!hasRow) {
            done = true;
            resultSet.close();
            break;
        }
        Object[] columns = new Object[columnCount];
        for (int j = 0; j < columnCount; j++) {
            columns[j] = getValue(resultSet, types[j], j, calendar);
            if (arrayOffsets.contains(j)) {
                // If we have an Array type, our Signature is lacking precision. We can't extract the
                // component type of an Array from metadata, we have to update it as we're serializing
                // the ResultSet.
                final Array array = resultSet.getArray(j + 1);
                // Only attempt to determine the component type for the array when non-null
                if (null != array && sig.isPresent()) {
                    ColumnMetaData columnMetaData = sig.get().columns.get(j);
                    ArrayType arrayType = (ArrayType) columnMetaData.type;
                    SqlType componentSqlType = SqlType.valueOf(array.getBaseType());
                    // Avatica Server will always return non-primitives to ensure nullable is guaranteed.
                    ColumnMetaData.Rep rep = ColumnMetaData.Rep.serialRepOf(componentSqlType);
                    AvaticaType componentType = ColumnMetaData.scalar(array.getBaseType(), array.getBaseTypeName(), rep);
                    // Update the ArrayType from the Signature
                    arrayType.updateComponentType(componentType);
                    // We only need to update the array's type once.
                    arrayOffsets.remove(j);
                }
            }
        }
        rows.add(columns);
    }
    return new Meta.Frame(offset, done, rows);
}
Also used : AvaticaType(org.apache.calcite.avatica.ColumnMetaData.AvaticaType) ArrayList(java.util.ArrayList) ResultSetMetaData(java.sql.ResultSetMetaData) Array(java.sql.Array) ArrayType(org.apache.calcite.avatica.ColumnMetaData.ArrayType) SqlType(org.apache.calcite.avatica.SqlType) ColumnMetaData(org.apache.calcite.avatica.ColumnMetaData) HashSet(java.util.HashSet)

Example 4 with ArrayType

use of org.apache.calcite.avatica.ColumnMetaData.ArrayType in project calcite-avatica by apache.

the class ArrayImplTest method resultSetFromArray.

@Test
public void resultSetFromArray() throws Exception {
    // Define the struct type we're creating
    ScalarType intType = ColumnMetaData.scalar(Types.INTEGER, "INTEGER", Rep.INTEGER);
    ArrayType arrayType = ColumnMetaData.array(intType, "INTEGER", Rep.INTEGER);
    ColumnMetaData arrayMetaData = MetaImpl.columnMetaData("MY_ARRAY", 1, arrayType, false);
    ArrayImpl.Factory factory = new ArrayFactoryImpl(Unsafe.localCalendar().getTimeZone());
    // Create some arrays from the structs
    Array array1 = factory.createArray(intType, Arrays.<Object>asList(1, 2));
    Array array2 = factory.createArray(intType, Arrays.<Object>asList(3));
    Array array3 = factory.createArray(intType, Arrays.<Object>asList(4, 5, 6));
    List<List<Object>> rows = Arrays.asList(Collections.<Object>singletonList(array1), Collections.<Object>singletonList(array2), Collections.<Object>singletonList(array3));
    // Create two rows, each with one (array) column
    try (Cursor cursor = new ListIteratorCursor(rows.iterator())) {
        List<Accessor> accessors = cursor.createAccessors(Collections.singletonList(arrayMetaData), Unsafe.localCalendar(), factory);
        assertEquals(1, accessors.size());
        Accessor accessor = accessors.get(0);
        assertTrue(cursor.next());
        Array actualArray = accessor.getArray();
        // An Array's result set has one row per array element.
        // Each row has two columns. Column 1 is the array offset (1-based), Column 2 is the value.
        ResultSet actualArrayResultSet = actualArray.getResultSet();
        assertEquals(2, actualArrayResultSet.getMetaData().getColumnCount());
        assertTrue(actualArrayResultSet.next());
        // Order is Avatica implementation specific
        assertEquals(1, actualArrayResultSet.getInt(1));
        assertEquals(1, actualArrayResultSet.getInt(2));
        assertTrue(actualArrayResultSet.next());
        assertEquals(2, actualArrayResultSet.getInt(1));
        assertEquals(2, actualArrayResultSet.getInt(2));
        assertFalse(actualArrayResultSet.next());
        assertTrue(cursor.next());
        actualArray = accessor.getArray();
        actualArrayResultSet = actualArray.getResultSet();
        assertEquals(2, actualArrayResultSet.getMetaData().getColumnCount());
        assertTrue(actualArrayResultSet.next());
        assertEquals(1, actualArrayResultSet.getInt(1));
        assertEquals(3, actualArrayResultSet.getInt(2));
        assertFalse(actualArrayResultSet.next());
        assertTrue(cursor.next());
        actualArray = accessor.getArray();
        actualArrayResultSet = actualArray.getResultSet();
        assertEquals(2, actualArrayResultSet.getMetaData().getColumnCount());
        assertTrue(actualArrayResultSet.next());
        assertEquals(1, actualArrayResultSet.getInt(1));
        assertEquals(4, actualArrayResultSet.getInt(2));
        assertTrue(actualArrayResultSet.next());
        assertEquals(2, actualArrayResultSet.getInt(1));
        assertEquals(5, actualArrayResultSet.getInt(2));
        assertTrue(actualArrayResultSet.next());
        assertEquals(3, actualArrayResultSet.getInt(1));
        assertEquals(6, actualArrayResultSet.getInt(2));
        assertFalse(actualArrayResultSet.next());
        assertFalse(cursor.next());
    }
}
Also used : ScalarType(org.apache.calcite.avatica.ColumnMetaData.ScalarType) Accessor(org.apache.calcite.avatica.util.Cursor.Accessor) ArrayType(org.apache.calcite.avatica.ColumnMetaData.ArrayType) Array(java.sql.Array) ResultSet(java.sql.ResultSet) List(java.util.List) ColumnMetaData(org.apache.calcite.avatica.ColumnMetaData) Test(org.junit.Test)

Example 5 with ArrayType

use of org.apache.calcite.avatica.ColumnMetaData.ArrayType in project calcite-avatica by apache.

the class ArrayImplTest method listOfJavaObjects.

/**
 * Test case for when a column is a list of plain Java objects.
 */
@Test
public void listOfJavaObjects() throws Exception {
    final ColumnMetaData.Rep rep = ColumnMetaData.Rep.of(PlainJavaObject.class);
    final ColumnMetaData.Rep rep2 = ColumnMetaData.Rep.of(PlainJavaObject.class);
    ColumnMetaData.AvaticaType objectAvaticaType = ColumnMetaData.scalar(Types.OTHER, "OTHER", rep);
    String arrayTypeName = "JavaType(" + PlainJavaObject.class.toString() + ") ARRAY";
    ArrayType arrayType = ColumnMetaData.array(objectAvaticaType, arrayTypeName, rep2);
    ColumnMetaData javaObjectArrayMetaData = MetaImpl.columnMetaData("PLAIN_JAVA_OBJECT_ARRAY", 1, arrayType, true);
    PlainJavaObject pjo1 = new PlainJavaObject(1, "one");
    PlainJavaObject pjo2 = new PlainJavaObject(2, "two");
    PlainJavaObject pjo3 = new PlainJavaObject(3, "three");
    PlainJavaObject pjo4 = new PlainJavaObject(4, "four");
    ArrayImpl.Factory factory = new ArrayFactoryImpl(Unsafe.localCalendar().getTimeZone());
    List<Object> list1 = Arrays.asList(pjo1, pjo2);
    List<Object> list2 = Arrays.asList(pjo3, pjo4);
    List<List<Object>> rows = Arrays.asList(Arrays.asList(list1), Arrays.asList(list2));
    try (Cursor cursor = new ListIteratorCursor(rows.iterator())) {
        List<Accessor> accessors = cursor.createAccessors(Arrays.asList(javaObjectArrayMetaData), Unsafe.localCalendar(), factory);
        assertEquals(1, accessors.size());
        Accessor accessor = accessors.get(0);
        assertTrue(cursor.next());
        Array actualArray = accessor.getArray();
        Object[] arrayData = (Object[]) actualArray.getArray();
        assertEquals(2, arrayData.length);
        assertEquals(pjo1, arrayData[0]);
        assertEquals(pjo2, arrayData[1]);
        assertTrue(cursor.next());
        actualArray = accessor.getArray();
        arrayData = (Object[]) actualArray.getArray();
        assertEquals(2, arrayData.length);
        assertEquals(pjo3, arrayData[0]);
        assertEquals(pjo4, arrayData[1]);
    }
}
Also used : Accessor(org.apache.calcite.avatica.util.Cursor.Accessor) ArrayType(org.apache.calcite.avatica.ColumnMetaData.ArrayType) Array(java.sql.Array) Rep(org.apache.calcite.avatica.ColumnMetaData.Rep) List(java.util.List) ColumnMetaData(org.apache.calcite.avatica.ColumnMetaData) Test(org.junit.Test)

Aggregations

ColumnMetaData (org.apache.calcite.avatica.ColumnMetaData)8 ArrayType (org.apache.calcite.avatica.ColumnMetaData.ArrayType)8 List (java.util.List)7 Accessor (org.apache.calcite.avatica.util.Cursor.Accessor)7 Array (java.sql.Array)6 Test (org.junit.Test)5 ArrayList (java.util.ArrayList)3 Struct (java.sql.Struct)2 Rep (org.apache.calcite.avatica.ColumnMetaData.Rep)2 StructType (org.apache.calcite.avatica.ColumnMetaData.StructType)2 ArrayAccessor (org.apache.calcite.avatica.util.AbstractCursor.ArrayAccessor)2 ResultSet (java.sql.ResultSet)1 ResultSetMetaData (java.sql.ResultSetMetaData)1 Calendar (java.util.Calendar)1 HashSet (java.util.HashSet)1 AvaticaType (org.apache.calcite.avatica.ColumnMetaData.AvaticaType)1 ScalarType (org.apache.calcite.avatica.ColumnMetaData.ScalarType)1 SqlType (org.apache.calcite.avatica.SqlType)1 ArrayImpl (org.apache.calcite.avatica.util.ArrayImpl)1 ListIteratorCursor (org.apache.calcite.avatica.util.ListIteratorCursor)1