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

studio.raptor.ddal.jdbc.adapter.AbstractResultSetAdapter Maven / Gradle / Ivy

/*
 * 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 studio.raptor.ddal.jdbc.adapter;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import studio.raptor.ddal.common.exception.GenericException;
import studio.raptor.ddal.common.exception.code.JdbcErrCodes;
import studio.raptor.ddal.core.executor.resultset.ColumnDefinition;
import studio.raptor.ddal.core.executor.resultset.ResultData;
import studio.raptor.ddal.core.executor.resultset.RowData;
import studio.raptor.ddal.jdbc.unsupported.AbstractUnsupportedOperationResultSet;

/**
 * Proxy result set adapter.
 *
 * @author jackcao
 * @since 3.0
 */
public abstract class AbstractResultSetAdapter extends AbstractUnsupportedOperationResultSet {

  /**
   * 结果集列名索引,key是columnLabel, value是columnIndex
   */
  protected final Map columnLabelIndex;
  private static Map colLabelUCaseCache;
  /**
   * 内部结果集对象
   */
  private final ResultData resultData;
  /**
   * 结果集头信息
   */
  private final List resultDataHead;
  /**
   * 最近一次从ResultSet中获取的值是否为null
   */
  protected boolean wasNull;
  /**
   * 游标在第一条数据之前的标志。
   */
  private boolean beforeFirst = true;
  /**
   * 数据访问游标
   */
  private int cursor = 0;
  private boolean closed;
  /**
   * RaptorResultSet对象创建好之后,后端物理连接的ResultSet其实
   * 已经关闭了,此参数已无太大价值。
   */
  private int fetchSize;
  /**
   * 当前行数据
   */
  private RowData currentRowData;

  private ResultSetMetaData resultSetMetaData;

  /**
   * RaptorResultSet构造器。设置当前ResultSet需要处理的数据对象,创建列名索引避免
   * 在获取结果集数据时重复遍历列集合。
   *
   * 处理ResultData的ColumnLabel时使用缓存技术,避免频繁做upperCase,减小耗时。
   *
   * @param resultData 内部数据对象
   * @throws SQLException exception when build {@link studio.raptor.ddal.jdbc.RaptorResultSet}
   */
  public AbstractResultSetAdapter(final ResultData resultData) throws SQLException {
    this.resultData = resultData;
    this.resultDataHead = this.resultData.getHead();
    resultSetMetaData = resultData.getMetaData();

    if (null == colLabelUCaseCache) {
      synchronized (this) {
        if (null == colLabelUCaseCache) {
          colLabelUCaseCache = new ConcurrentHashMap<>();
        }
      }
    }
    if (null != this.resultDataHead && !this.resultDataHead.isEmpty()) {
      columnLabelIndex = new HashMap<>(this.resultDataHead.size());
      int columnIndex = 1;
      for (ColumnDefinition columnDefinition : this.resultDataHead) {
        String colDef = colLabelUCaseCache.get(columnDefinition.getName());
        if (null == colDef) {
          colDef = columnDefinition.getName().toUpperCase();
          colLabelUCaseCache.put(columnDefinition.getName(), colDef);
        }
        columnLabelIndex.put(colDef, columnIndex++);
      }
    } else {
      columnLabelIndex = new HashMap<>();
    }
  }

  @Override
  public boolean next() throws SQLException {
    if (beforeFirst) {
      cursor = 0;
      beforeFirst = false;
    }
    Optional row = nextRow();
    if (null != row && row.isPresent()) {
      currentRowData = row.get();
      return true;
    }
    return false;
  }

  /**
   * Set next row data to currentRowData, and plus cursor by 1.
   *
   * @return next row data
   */
  private Optional nextRow() {
    if (null == resultData || resultData.getRowCount() < 1) {
      return Optional.absent();
    }
    if (cursor <= resultData.getRowCount() - 1) {
      return Optional.of(resultData.getRows().get(cursor++));
    }
    return Optional.absent();
  }

  /**
   * 获取当前字段的SQL类型
   *
   * @param columnIndex 列索引,从1开始
   * @return SQL类型
   */
  protected int getRowFieldSQLType(int columnIndex) {
    return resultDataHead.get(columnIndex - 1).getType();
  }

  /**
   * Check column index is in range or not, if not throw RuntimeException of
   * {@link JdbcErrCodes#JDBC_604}
   *
   * @param columnIndex column index
   */
  protected void checkColumnIndexInRange(int columnIndex) {
    if (!inRange(columnIndex)) {
      throw new GenericException(JdbcErrCodes.JDBC_604, columnIndex);
    }
  }

  private boolean inRange(int columnIndex) {
    return columnIndex > 0 && columnIndex <= currentRowData.getCellCount();
  }

  protected Object getObjectInternal(int columnIndex) throws SQLException {
    Preconditions.checkState(!isClosed(), "ResultSet is closed");
    Preconditions.checkState(!beforeFirst, "Before start of ResultSet");
    Preconditions.checkState(inRange(columnIndex),
        String.format("Column Index %d out of range", columnIndex));
    Object obj = currentRowData.getCell(columnIndex);
    this.wasNull = null == obj;
    return obj;
  }

  @Override
  public final void close() throws SQLException {
    closed = true;
  }

  @Override
  public final boolean isClosed() throws SQLException {
    return closed;
  }

  @Override
  public final void setFetchDirection(final int direction) throws SQLException {

  }

  @Override
  public int getFetchSize() throws SQLException {
    return fetchSize;
  }

  @Override
  public final void setFetchSize(final int rows) throws SQLException {
    fetchSize = rows;
  }

  @Override
  public ResultSetMetaData getMetaData() throws SQLException {
    return this.resultSetMetaData;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy