All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.apache.calcite.avatica.util.ArrayFactoryImpl Maven / Gradle / Ivy

There is a newer version: 5.4.0
Show newest version
/*
 * 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 com.hazelcast.com.liance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.com.hazelcast.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 com.hazelcast.org.apache.calcite.avatica.util;

import com.hazelcast.org.apache.calcite.avatica.AvaticaParameter;
import com.hazelcast.org.apache.calcite.avatica.AvaticaResultSet;
import com.hazelcast.org.apache.calcite.avatica.AvaticaResultSetMetaData;
import com.hazelcast.org.apache.calcite.avatica.ColumnMetaData;
import com.hazelcast.org.apache.calcite.avatica.ColumnMetaData.ArrayType;
import com.hazelcast.org.apache.calcite.avatica.ColumnMetaData.AvaticaType;
import com.hazelcast.org.apache.calcite.avatica.ColumnMetaData.Rep;
import com.hazelcast.org.apache.calcite.avatica.ColumnMetaData.ScalarType;
import com.hazelcast.org.apache.calcite.avatica.Meta;
import com.hazelcast.org.apache.calcite.avatica.QueryState;
import com.hazelcast.org.apache.calcite.avatica.util.AbstractCursor.ArrayAccessor;
import com.hazelcast.org.apache.calcite.avatica.util.Cursor.Accessor;

import java.sql.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.TimeZone;

/**
 * Implementation of {@link ArrayImpl.Factory}.
 */
public class ArrayFactoryImpl implements ArrayImpl.Factory {
  private TimeZone timeZone;

  public ArrayFactoryImpl(TimeZone timeZone) {
    this.timeZone = Objects.requireNonNull(timeZone);
  }

  @Override public ResultSet create(AvaticaType elementType, Iterable elements)
      throws SQLException {
    // The ColumnMetaData for offset "1" in the ResultSet for an Array.
    ScalarType arrayOffsetType = ColumnMetaData.scalar(Types.INTEGER, "INTEGER", Rep.PRIMITIVE_INT);
    // Two columns (types) in the ResultSet we will create
    List types = Arrays.asList(ColumnMetaData.dummy(arrayOffsetType, false),
        ColumnMetaData.dummy(elementType, true));
    List> rows = createResultSetRowsForArrayData(elements);
    // `(List) rows` is a com.hazelcast.com.ile error.
    @SuppressWarnings({ "unchecked", "rawtypes" })
    List untypedRows = (List) ((List) rows);
    try (ListIteratorCursor cursor = new ListIteratorCursor(rows.iterator())) {
      final String sql = "MOCKED";
      QueryState state = new QueryState(sql);
      Meta.Signature signature = new Meta.Signature(types, sql,
          Collections.emptyList(), Collections.emptyMap(),
          Meta.CursorFactory.LIST, Meta.StatementType.SELECT);
      AvaticaResultSetMetaData resultSetMetaData = new AvaticaResultSetMetaData(null, sql,
          signature);
      Meta.Frame frame = new Meta.Frame(0, true, untypedRows);
      AvaticaResultSet resultSet = new AvaticaResultSet(null, state, signature, resultSetMetaData,
          timeZone, frame);
      resultSet.execute2(cursor, types);
      return resultSet;
    }
  }

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

  /**
   * Creates the row-level view over the values that will make up an Array. The Iterator has a row
   * per Array element, each row containing two columns. The second column is the array element and
   * the first column is the offset into the array of that array element (one-based, not
   * zero-based).
   *
   * 

The ordering of the rows is not guaranteed to be in the same order as the array elements. * *

A list of {@code elements}: *

[1, 2, 3]
*

might be converted into *

Iterator{ [1, 1], [2, 2], [3, 3] }
* * @param elements The elements of an array. */ private List> createResultSetRowsForArrayData(Iterable elements) { List> rows = new ArrayList<>(); int i = 0; for (Object element : elements) { rows.add(Arrays.asList(i + 1, element)); i++; } return rows; } /** * Creates an row-level view over the values that will make up an Array. The Iterator has one * entry which has a list that also has one entry. * *

A provided list of {@code elements} *

[1, 2, 3]
*

would be converted into *

Iterator{ [ [1,2,3] ] }
* * @param elements The elements of an array */ private Iterator> createRowForArrayData(List elements) { // Make a "row" with one "column" (which is really a list) final List row = Collections.singletonList((Object) elements); // Make an iterator over this one "row" return Collections.singletonList(row).iterator(); } } // End ArrayFactoryImpl.java