/**
* 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.drill.jdbc.impl;
import java.sql.SQLException;
import org.apache.calcite.avatica.AvaticaResultSetMetaData;
import org.apache.calcite.avatica.AvaticaStatement;
import org.apache.calcite.avatica.Meta;
import org.apache.drill.jdbc.AlreadyClosedSqlException;
import org.apache.drill.jdbc.InvalidParameterSqlException;
public class DrillResultSetMetaDataImpl extends AvaticaResultSetMetaData {
private final AvaticaStatement statement;
public DrillResultSetMetaDataImpl(AvaticaStatement statement,
Object query,
Meta.Signature signature) {
super(statement, query, signature);
this.statement = statement;
}
/**
* Throws AlreadyClosedSqlException if the associated ResultSet is closed.
*
* @throws AlreadyClosedSqlException if ResultSet is closed
* @throws SQLException if error in checking ResultSet's status
*/
private void throwIfClosed() throws AlreadyClosedSqlException,
SQLException {
// Statement.isClosed() call is to avoid exception from getResultSet().
if (statement.isClosed()
|| (statement.getResultSet() != null // result set doesn't exist for prepared statement cases
&& statement.getResultSet().isClosed())) {
throw new AlreadyClosedSqlException(
"ResultSetMetaData's ResultSet is already closed." );
}
}
private void throwIfClosedOrOutOfBounds(int columnNumber)
throws InvalidParameterSqlException,
SQLException {
throwIfClosed();
if (1 > columnNumber || columnNumber > getColumnCount()) {
throw new InvalidParameterSqlException(
"Column number " + columnNumber + " out of range of from 1 through "
+ getColumnCount() + " (column count)");
}
}
// Note: Using dynamic proxies would reduce the quantity (450?) of method
// overrides by eliminating those that exist solely to check whether the
// object is closed. It would also eliminate the need to throw non-compliant
// RuntimeExceptions when Avatica's method declarations won't let us throw
// proper SQLExceptions. (Check performance before applying to frequently
// called ResultSet.)
// Note: Methods are in same order as in java.sql.ResultSetMetaData.
// No isWrapperFor(Class<?>) (it doesn't throw SQLException if already closed).
// No unwrap(Class<T>) (it doesn't throw SQLException if already closed).
@Override
public int getColumnCount() throws SQLException {
throwIfClosed();
return super.getColumnCount();
}
@Override
public boolean isAutoIncrement(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.isAutoIncrement(columnNumber);
}
@Override
public boolean isCaseSensitive(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.isCaseSensitive(columnNumber);
}
@Override
public boolean isSearchable(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.isSearchable(columnNumber);
}
@Override
public boolean isCurrency(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.isCurrency(columnNumber);
}
@Override
public int isNullable(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.isNullable(columnNumber);
}
@Override
public boolean isSigned(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.isSigned(columnNumber);
}
@Override
public int getColumnDisplaySize(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getColumnDisplaySize(columnNumber);
}
@Override
public String getColumnLabel(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getColumnLabel(columnNumber);
}
@Override
public String getColumnName(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getColumnName(columnNumber);
}
@Override
public String getSchemaName(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getSchemaName(columnNumber);
}
@Override
public int getPrecision(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getPrecision(columnNumber);
}
@Override
public int getScale(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getScale(columnNumber);
}
@Override
public String getTableName(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getTableName(columnNumber);
}
@Override
public String getCatalogName(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getCatalogName(columnNumber);
}
@Override
public int getColumnType(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getColumnType(columnNumber);
}
@Override
public String getColumnTypeName(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getColumnTypeName(columnNumber);
}
@Override
public boolean isReadOnly(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.isReadOnly(columnNumber);
}
@Override
public boolean isWritable(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.isWritable(columnNumber);
}
@Override
public boolean isDefinitelyWritable(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.isDefinitelyWritable(columnNumber);
}
@Override
public String getColumnClassName(int columnNumber) throws SQLException {
throwIfClosedOrOutOfBounds(columnNumber);
return super.getColumnClassName(columnNumber);
}
}