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

net.snowflake.client.jdbc.SnowflakeResultSetMetaData Maven / Gradle / Ivy

/*
 * Copyright (c) 2012-2018 Snowflake Computing Inc. All rights reserved.
 */

package net.snowflake.client.jdbc;

import net.snowflake.common.core.SqlState;
import net.snowflake.client.core.SFSession;
import net.snowflake.client.core.ResultUtil;

import java.math.BigDecimal;
import java.sql.Date;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import net.snowflake.client.log.SFLogger;
import net.snowflake.client.log.SFLoggerFactory;

/**
 * Snowflake ResultSetMetaData
 *
 * @author jhuang
 */
public class SnowflakeResultSetMetaData implements ResultSetMetaData
{

  static final
  SFLogger logger = SFLoggerFactory.getLogger(SnowflakeResultSetMetaData.class);

  private int columnCount = 0;

  private List columnNames;

  private List columnTypeNames;

  private List columnTypes;

  private List precisions;

  private List scales;

  private String queryId;

  private Map columnNamePositionMap =
  new HashMap<>();

  private Map columnNameUpperCasePositionMap =
      new HashMap<>();

  private SFSession session;

  public SnowflakeResultSetMetaData() {}

  public SnowflakeResultSetMetaData(int columnCount,
                                    List columnNames,
                                    List columnTypeNames,
                                    List columnTypes,
                                    SFSession session)
          throws SnowflakeSQLException
  {
    this.columnCount = columnCount;
    this.columnNames = columnNames;
    this.columnTypeNames = columnTypeNames;
    this.columnTypes = columnTypes;
    this.session = session;
  }

  /**
   * @return query id
   */
  public String getQueryId()
  {
    return queryId;
  }

  /**
   * @return list of column names
   */
  public List getColumnNames()
  {
    return columnNames;
  }

  /**
   * @param columnName column name
   * @return index of the column
   */
  public int getColumnIndex(String columnName)
  {
    boolean caseInsensitive = session != null && session.getRsColumnCaseInsensitive();
    columnName = caseInsensitive ? columnName.toUpperCase() : columnName;
    Map nameToIndexMap = caseInsensitive ?
        columnNameUpperCasePositionMap : columnNamePositionMap;

    if (nameToIndexMap.get(columnName) != null)
    {
      return nameToIndexMap.get(columnName);
    }
    else
    {
      int columnIndex = caseInsensitive ?
          ResultUtil.listSearchCaseInsensitive(columnNames, columnName) :
          columnNames.indexOf(columnName);
      nameToIndexMap.put(columnName, columnIndex);
      return columnIndex;
    }
  }

  /**
   * @return column count
   * @throws SQLException if failed to get column count
   */
  @Override
  public int getColumnCount() throws SQLException
  {
    logger.debug(
	       "public int getColumnCount(), columnCount= {}",
	       columnCount);

    return columnCount;
  }

  @Override
  public boolean isAutoIncrement(int column) throws SQLException
  {
    logger.debug("public boolean isAutoIncrement(int column)");

    return false;
  }

  @Override
  public boolean isCaseSensitive(int column) throws SQLException
  {
    logger.debug("public boolean isCaseSensitive(int column)");

    return false;
  }

  @Override
  public boolean isSearchable(int column) throws SQLException
  {
    logger.debug("public boolean isSearchable(int column)");

    return true;
  }

  @Override
  public boolean isCurrency(int column) throws SQLException
  {
    logger.debug("public boolean isCurrency(int column)");

    return false;
  }

  @Override
  public int isNullable(int column) throws SQLException
  {
    logger.debug("public int isNullable(int column)");

    return columnNullableUnknown;
  }

  @Override
  public boolean isSigned(int column) throws SQLException
  {
    logger.debug("public boolean isSigned(int column)");

    if (columnTypes.get(column-1) == Types.INTEGER ||
        columnTypes.get(column-1) == Types.DECIMAL ||
        columnTypes.get(column-1) == Types.DOUBLE)
      return true;
    else
      return false;
  }

  @Override
  public int getColumnDisplaySize(int column) throws SQLException
  {
    logger.debug("public int getColumnDisplaySize(int column)");

    return 25;
  }

  @Override
  public String getColumnLabel(int column) throws SQLException
  {
    logger.debug("public String getColumnLabel(int column)");

    if(columnNames != null)
      return columnNames.get(column-1);
    else
      return "C" + Integer.toString(column-1);
  }

  @Override
  public String getColumnName(int column) throws SQLException
  {
    logger.debug("public String getColumnName(int column)");

    if(columnNames != null)
      return columnNames.get(column-1);
    else
      return "C" + Integer.toString(column-1);
  }

  @Override
  public String getSchemaName(int column) throws SQLException
  {
    logger.debug("public String getSchemaName(int column)");

    return "";
  }

  @Override
  public int getPrecision(int column) throws SQLException
  {
    logger.debug("public int getPrecision(int column)");

    if (precisions != null && precisions.size() >= column)
    {
      return precisions.get(column-1);
    }
    else
    {
      // TODO: fix this later to use different defaults for number or timestamp
      return 9;
    }
  }

  @Override
  public int getScale(int column) throws SQLException
  {
    logger.debug("public int getScale(int column)");

    if (scales != null && scales.size() >= column)
    {
      return scales.get(column-1);
    }
    else
    {
      // TODO: fix this later to use different defaults for number or timestamp
      return 9;
    }
  }

  @Override
  public String getTableName(int column) throws SQLException
  {
    logger.debug("public String getTableName(int column)");

    return "T";
  }

  @Override
  public String getCatalogName(int column) throws SQLException
  {
    logger.debug("public String getCatalogName(int column)");

    return "";
  }

  @Override
  public int getColumnType(int column) throws SQLException
  {
    logger.debug("public int getColumnType(int column)");

    int internalColumnType = getInternalColumnType(column);

    int externalColumnType = internalColumnType;

    if (internalColumnType == SnowflakeUtil.EXTRA_TYPES_TIMESTAMP_LTZ ||
        internalColumnType == SnowflakeUtil.EXTRA_TYPES_TIMESTAMP_TZ)
      externalColumnType = Types.TIMESTAMP;

    logger.debug(
	       "column type = {}", 
	       externalColumnType);

    return externalColumnType;
  }

  public int getInternalColumnType(int column) throws SQLException
  {
    logger.debug("public int getInternalColumnType(int column)");

    int columnIdx = column-1;
    if (column > columnTypes.size())
    {
      throw new SQLException("Invalid column index: " + column);
    }

    if(columnTypes.get(columnIdx) == null)
    {
      throw new SnowflakeSQLException(SqlState.INTERNAL_ERROR,
              ErrorCode.INTERNAL_ERROR.getMessageCode(),
              "Missing column type for column " + column);
    }

    logger.debug(
	       "column type = {}",
	       columnTypes.get(column-1));

    return columnTypes.get(columnIdx);
  }

  @Override
  public String getColumnTypeName(int column) throws SQLException
  {
    logger.debug("public String getColumnTypeName(int column)");

    if (column > columnTypeNames.size())
    {
      throw new SQLException("Invalid column index: " + column);
    }

    if(columnTypeNames == null || columnTypeNames.get(column-1) == null)
    {
      throw new SnowflakeSQLException(SqlState.INTERNAL_ERROR,
              ErrorCode.INTERNAL_ERROR.getMessageCode(),
              "Missing column type for column " + column);
    }

    return columnTypeNames.get(column-1);
  }

  @Override
  public boolean isReadOnly(int column) throws SQLException
  {
    logger.debug("public boolean isReadOnly(int column)");

    return true;
  }

  @Override
  public boolean isWritable(int column) throws SQLException
  {
    logger.debug("public boolean isWritable(int column)");

    return false;
  }

  @Override
  public boolean isDefinitelyWritable(int column) throws SQLException
  {
    logger.debug("public boolean isDefinitelyWritable(int column)");

    return false;
  }

  @Override
  public String getColumnClassName(int column) throws SQLException
  {
    logger.debug("public String getColumnClassName(int column)");

    int type = this.getColumnType(column);

    switch(type)
    {
      case Types.VARCHAR:
      case Types.CHAR:
      case Types.BINARY:
        return String.class.getName();

      case Types.INTEGER:
        return Integer.class.getName();

      case Types.DECIMAL:
        return BigDecimal.class.getName();

      case Types.DOUBLE:
        return Double.class.getName();

      case Types.TIMESTAMP:
        return Timestamp.class.getName();

      case Types.DATE:
        return Date.class.getName();

      case Types.TIME:
        return Time.class.getName();

      case Types.BOOLEAN:
        return Boolean.class.getName();

      case Types.BIGINT:
        return Long.class.getName();

      default:
        throw new SQLFeatureNotSupportedException();
    }
  }

  @Override
  public  T unwrap(Class iface) throws SQLException
  {
    logger.debug("public  T unwrap(Class iface)");

    throw new SQLFeatureNotSupportedException();
  }

  @Override
  public boolean isWrapperFor(Class iface) throws SQLException
  {
    logger.debug("public boolean isWrapperFor(Class iface)");

    throw new SQLFeatureNotSupportedException();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy