/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed 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.
* </p>
*/
package com.dangdang.ddframe.rdb.sharding.merger.resultset.memory;
import com.dangdang.ddframe.rdb.sharding.merger.resultset.memory.row.ResultSetRow;
import com.dangdang.ddframe.rdb.sharding.merger.util.ResultSetUtil;
import com.dangdang.ddframe.rdb.sharding.util.SQLUtil;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.List;
/**
* 内存结果集抽象类.
*
* @author gaohongtao
* @author zhangliang
*/
@Slf4j
public abstract class AbstractMemoryResultSet extends AbstractUnsupportedOperationMemoryResultSet {
private boolean beforeFirst = true;
@Getter(AccessLevel.PROTECTED)
private ResultSetRow currentRow;
private boolean wasNull;
public AbstractMemoryResultSet(final List<ResultSet> resultSets) throws SQLException {
super(resultSets);
LoggerFactory.getLogger(this.getClass().getName()).debug("{} join pipeline", this.hashCode());
}
@Override
public boolean next() throws SQLException {
if (beforeFirst) {
initRows(getResultSets());
beforeFirst = false;
}
Optional<? extends ResultSetRow> row = nextRow();
if (row.isPresent()) {
currentRow = row.get();
log.trace("Current row is {}", currentRow);
return true;
}
return false;
}
protected abstract void initRows(List<ResultSet> resultSets) throws SQLException;
protected abstract Optional<? extends ResultSetRow> nextRow() throws SQLException;
@Override
public boolean wasNull() throws SQLException {
return wasNull;
}
@Override
public int findColumn(final String columnLabel) throws SQLException {
String formattedColumnLabel = getColumnLabelIndexMap().containsKey(columnLabel) ? columnLabel : SQLUtil.getExactlyValue(columnLabel);
if (!getColumnLabelIndexMap().containsKey(formattedColumnLabel)) {
throw new SQLException(String.format("Column label %s does not exist", formattedColumnLabel));
}
return getColumnLabelIndexMap().get(formattedColumnLabel);
}
@Override
public Object getObject(final int columnIndex) throws SQLException {
Preconditions.checkState(!isClosed(), "Result set is closed");
Preconditions.checkState(!beforeFirst, "Before start of result set");
Preconditions.checkState(null != currentRow, "After end of result set");
Preconditions.checkArgument(currentRow.inRange(columnIndex), String.format("Column Index %d out of range", columnIndex));
Object result = currentRow.getCell(columnIndex);
wasNull = null == result;
return result;
}
@Override
public Object getObject(final String columnLabel) throws SQLException {
return getObject(findColumn(columnLabel));
}
@Override
public String getString(final int columnIndex) throws SQLException {
return (String) ResultSetUtil.convertValue(getObject(columnIndex), String.class);
}
@Override
public String getString(final String columnLabel) throws SQLException {
return getString(findColumn(columnLabel));
}
@Override
public boolean getBoolean(final int columnIndex) throws SQLException {
Object cell = getObject(columnIndex);
if (null == cell) {
return false;
}
return (cell instanceof Boolean) ? (Boolean) cell : Boolean.valueOf(cell.toString());
}
@Override
public boolean getBoolean(final String columnLabel) throws SQLException {
return getBoolean(findColumn(columnLabel));
}
@Override
public byte getByte(final int columnIndex) throws SQLException {
return (byte) ResultSetUtil.convertValue(getObject(columnIndex), byte.class);
}
@Override
public byte getByte(final String columnLabel) throws SQLException {
return getByte(findColumn(columnLabel));
}
@Override
public short getShort(final int columnIndex) throws SQLException {
return (short) ResultSetUtil.convertValue(getObject(columnIndex), short.class);
}
@Override
public short getShort(final String columnLabel) throws SQLException {
return getShort(findColumn(columnLabel));
}
@Override
public int getInt(final int columnIndex) throws SQLException {
return (int) ResultSetUtil.convertValue(getObject(columnIndex), int.class);
}
@Override
public int getInt(final String columnLabel) throws SQLException {
return getInt(findColumn(columnLabel));
}
@Override
public long getLong(final int columnIndex) throws SQLException {
return (long) ResultSetUtil.convertValue(getObject(columnIndex), long.class);
}
@Override
public long getLong(final String columnLabel) throws SQLException {
return getLong(findColumn(columnLabel));
}
@Override
public float getFloat(final int columnIndex) throws SQLException {
return (float) ResultSetUtil.convertValue(getObject(columnIndex), float.class);
}
@Override
public float getFloat(final String columnLabel) throws SQLException {
return getFloat(findColumn(columnLabel));
}
@Override
public double getDouble(final int columnIndex) throws SQLException {
return (double) ResultSetUtil.convertValue(getObject(columnIndex), double.class);
}
@Override
public double getDouble(final String columnLabel) throws SQLException {
return getDouble(findColumn(columnLabel));
}
@Override
public BigDecimal getBigDecimal(final int columnIndex, final int scale) throws SQLException {
BigDecimal result = (BigDecimal) ResultSetUtil.convertValue(getObject(columnIndex), BigDecimal.class);
return result.setScale(scale, BigDecimal.ROUND_HALF_UP);
}
@Override
public BigDecimal getBigDecimal(final String columnLabel, final int scale) throws SQLException {
return getBigDecimal(findColumn(columnLabel), scale);
}
@Override
public BigDecimal getBigDecimal(final int columnIndex) throws SQLException {
return (BigDecimal) ResultSetUtil.convertValue(getObject(columnIndex), BigDecimal.class);
}
@Override
public BigDecimal getBigDecimal(final String columnLabel) throws SQLException {
return getBigDecimal(findColumn(columnLabel));
}
@Override
public byte[] getBytes(final int columnIndex) throws SQLException {
String value = getString(columnIndex);
if (null == value) {
return null;
}
return value.getBytes();
}
@Override
public byte[] getBytes(final String columnLabel) throws SQLException {
return getBytes(findColumn(columnLabel));
}
@Override
public Date getDate(final int columnIndex) throws SQLException {
return getDate(columnIndex, null);
}
@Override
public Date getDate(final String columnLabel) throws SQLException {
return getDate(findColumn(columnLabel));
}
@Override
public Date getDate(final int columnIndex, final Calendar cal) throws SQLException {
// TODO 时间相关取值未实现calendar模式
return (Date) ResultSetUtil.convertValue(getObject(columnIndex), Date.class);
}
@Override
public Date getDate(final String columnLabel, final Calendar cal) throws SQLException {
return getDate(findColumn(columnLabel), cal);
}
@Override
public Time getTime(final int columnIndex) throws SQLException {
return getTime(columnIndex, null);
}
@Override
public Time getTime(final String columnLabel) throws SQLException {
return getTime(findColumn(columnLabel));
}
@Override
public Time getTime(final int columnIndex, final Calendar cal) throws SQLException {
return (Time) ResultSetUtil.convertValue(getObject(columnIndex), Time.class);
}
@Override
public Time getTime(final String columnLabel, final Calendar cal) throws SQLException {
return getTime(findColumn(columnLabel), cal);
}
@Override
public Timestamp getTimestamp(final int columnIndex) throws SQLException {
return getTimestamp(columnIndex, null);
}
@Override
public Timestamp getTimestamp(final String columnLabel) throws SQLException {
return getTimestamp(findColumn(columnLabel));
}
@Override
public Timestamp getTimestamp(final int columnIndex, final Calendar cal) throws SQLException {
return (Timestamp) ResultSetUtil.convertValue(getObject(columnIndex), Timestamp.class);
}
@Override
public Timestamp getTimestamp(final String columnLabel, final Calendar cal) throws SQLException {
return getTimestamp(findColumn(columnLabel), cal);
}
@Override
public URL getURL(final int columnIndex) throws SQLException {
String value = getString(columnIndex);
if (null == value) {
return null;
}
try {
return new URL(value);
} catch (final MalformedURLException ex) {
throw new SQLException("URL Malformed URL exception");
}
}
@Override
public URL getURL(final String columnLabel) throws SQLException {
return getURL(findColumn(columnLabel));
}
@Override
public Statement getStatement() throws SQLException {
return getResultSets().get(0).getStatement();
}
@Override
public ResultSetMetaData getMetaData() throws SQLException {
return getResultSets().get(0).getMetaData();
}
@Override
public int getFetchDirection() throws SQLException {
return ResultSet.FETCH_FORWARD;
}
@Override
public int getFetchSize() throws SQLException {
int result = 0;
for (ResultSet each : getResultSets()) {
result += each.getFetchSize();
}
return result;
}
@Override
public int getType() throws SQLException {
return ResultSet.TYPE_FORWARD_ONLY;
}
@Override
public int getConcurrency() throws SQLException {
return ResultSet.CONCUR_READ_ONLY;
}
@Override
public SQLWarning getWarnings() throws SQLException {
return null;
}
@Override
public void clearWarnings() throws SQLException {
}
}