/* * Copyright © 2014 Cask Data, Inc. * * 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. */ package co.cask.cdap.explore.jdbc; import co.cask.cdap.proto.ColumnDesc; import com.google.common.base.Preconditions; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.List; /** * Result Set returned when executing a query using Explore JDBC {@link ExploreStatement}. */ public class ExploreResultSetMetaData implements ResultSetMetaData { private final List<ColumnDesc> columnDescs; ExploreResultSetMetaData(List<ColumnDesc> columnDescs) { Preconditions.checkNotNull(columnDescs, "Column metadata list cannot be null."); this.columnDescs = columnDescs; } int getColumnPosition(String name) throws SQLException { // If several columns have the same name, we have to return the one with the smaller position // hence we have to iterate through all the columns Integer min = null; for (ColumnDesc desc : columnDescs) { if (desc.getName().toLowerCase().equals(name)) { if (min == null || min > desc.getPosition()) { min = desc.getPosition(); } } } if (min != null) { return min.intValue(); } throw new SQLException("Could not find column with name: " + name); } private ColumnDesc getColumnDesc(int position) throws SQLException { if (columnDescs == null) { throw new SQLException("Could not determine column meta data for ResultSet"); } for (ColumnDesc desc : columnDescs) { if (desc.getPosition() == position) { return desc; } } throw new SQLException("Could not find column at position: " + position); } @Override public int getColumnCount() throws SQLException { return columnDescs.size(); } @Override public int getColumnType(int column) throws SQLException { ColumnDesc desc = getColumnDesc(column); return JdbcColumn.hiveTypeToSqlType(desc.getType()); } @Override public String getColumnTypeName(int column) throws SQLException { ColumnDesc desc = getColumnDesc(column); return JdbcColumn.getColumnTypeName(desc.getType()); } @Override public String getColumnClassName(int column) throws SQLException { int columnType = getColumnType(column); return JdbcColumn.columnClassName(columnType); } @Override public String getColumnName(int column) throws SQLException { ColumnDesc desc = getColumnDesc(column); return desc.getName(); } @Override public String getColumnLabel(int column) throws SQLException { return getColumnName(column); } @Override public boolean isAutoIncrement(int i) throws SQLException { // From Hive JDBC code: Hive doesn't have an auto-increment concept return false; } @Override public boolean isCaseSensitive(int column) throws SQLException { // Content of a column is case sensitive only if it is a string // This includes maps, arrays and structs, since they are passed as json ColumnDesc desc = getColumnDesc(column); if ("string".equalsIgnoreCase(desc.getType())) { return true; } return false; } @Override public int isNullable(int i) throws SQLException { // From Hive JDBC code: Hive doesn't have the concept of not-null return ResultSetMetaData.columnNullable; } @Override public int getColumnDisplaySize(int column) throws SQLException { int columnType = getColumnType(column); return JdbcColumn.columnDisplaySize(columnType); } @Override public int getPrecision(int column) throws SQLException { int columnType = getColumnType(column); return JdbcColumn.columnPrecision(columnType); } @Override public int getScale(int column) throws SQLException { int columnType = getColumnType(column); return JdbcColumn.columnScale(columnType); } @Override public boolean isCurrency(int i) throws SQLException { // Hive doesn't support a currency type return false; } @Override public boolean isSearchable(int i) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public boolean isSigned(int column) throws SQLException { int columnType = getColumnType(column); return JdbcColumn.isNumber(columnType); } @Override public String getSchemaName(int i) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public String getTableName(int i) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public String getCatalogName(int i) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public boolean isReadOnly(int i) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public boolean isWritable(int i) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public boolean isDefinitelyWritable(int i) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public <T> T unwrap(Class<T> tClass) throws SQLException { throw new SQLFeatureNotSupportedException(); } @Override public boolean isWrapperFor(Class<?> aClass) throws SQLException { throw new SQLFeatureNotSupportedException(); } }