content: /*
   * 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.calcite.avatica;
  
  import org.apache.calcite.avatica.util.ByteString;
  
  import java.math.BigDecimal;
  import java.math.BigInteger;
  import java.net.URL;
  import java.sql.Array;
  import java.sql.Blob;
  import java.sql.Clob;
  import java.sql.NClob;
  import java.sql.PreparedStatement;
  import java.sql.Ref;
  import java.sql.RowId;
  import java.sql.Struct;
  import java.sql.Time;
  import java.sql.Timestamp;
  import java.sql.Types;
  import java.util.AbstractMap;
  import java.util.ArrayList;
  import java.util.Calendar;
  import java.util.Collection;
  import java.util.EnumSet;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  /** Extends the information in {@link java.sql.Types}.
   *
   * <p>The information in the following conversions tables
   * (from the JDBC 4.1 specification) is held in members of this class.
   *
   * <p>Table B-1: JDBC Types Mapped to Java Types
   *
   * <pre>
   * JDBC Type     Java Type
   * ============= =========================
   * CHAR          String
   * VARCHAR       String
   * LONGVARCHAR   String
   * NUMERIC       java.math.BigDecimal
   * DECIMAL       java.math.BigDecimal
   * BIT           boolean
   * BOOLEAN       boolean
   * TINYINT       byte
   * SMALLINT      short
   * INTEGER       int
   * BIGINT        long
   * REAL          float
   * FLOAT         double
   * DOUBLE        double
   * BINARY        byte[]
   * VARBINARY     byte[]
   * LONGVARBINARY byte[]
   * DATE          java.sql.Date
   * TIME          java.sql.Time
   * TIMESTAMP     java.sql.Timestamp
   * CLOB          java.sql.Clob
   * BLOB          java.sql.Blob
   * ARRAY         java.sql.Array
   * DISTINCT      mapping of underlying type
   * STRUCT        java.sql.Struct
   * REF           java.sql.Ref
   * DATALINK      java.net.URL
   * JAVA_OBJECT   underlying Java class
   * ROWID         java.sql.RowId
   * NCHAR         String
   * NVARCHAR      String
   * LONGNVARCHAR  String
   * NCLOB         java.sql.NClob
   * SQLXML        java.sql.SQLXML
   * </pre>
   *
   * <p>Table B-2: Standard Mapping from Java Types to JDBC Types
   *
   * <pre>
   * Java Type            JDBC Type
   * ==================== ==============================================
   * String               CHAR, VARCHAR, LONGVARCHAR, NCHAR, NVARCHAR or
   *                      LONGNVARCHAR
   * java.math.BigDecimal NUMERIC
   * boolean              BIT or BOOLEAN
   * byte                 TINYINT
   * short                SMALLINT
   * int                  INTEGER
   * long                 BIGINT
   * float                REAL
   * double               DOUBLE
   * byte[]               BINARY, VARBINARY, or LONGVARBINARY
   * java.sql.Date        DATE
   * java.sql.Time        TIME
   * java.sql.Timestamp   TIMESTAMP
   * java.sql.Clob        CLOB
   * java.sql.Blob        BLOB
   * java.sql.Array       ARRAY
   * java.sql.Struct      STRUCT
   * java.sql.Ref         REF
   * java.net.URL         DATALINK
   * Java class           JAVA_OBJECT
   * java.sql.RowId       ROWID
   * java.sql.NClob       NCLOB
   * java.sql.SQLXML      SQLXML
   * </pre>
   *
   * <p>TABLE B-3: Mapping from JDBC Types to Java Object Types
   *
   * <pre>
   * JDBC Type     Java Object Type
   * ============= ======================
   * CHAR          String
   * VARCHAR       String
   * LONGVARCHAR   String
   * NUMERIC       java.math.BigDecimal
   * DECIMAL       java.math.BigDecimal
   * BIT           Boolean
   * BOOLEAN       Boolean
   * TINYINT       Integer
   * SMALLINT      Integer
   * INTEGER       Integer
   * BIGINT        Long
   * REAL          Float
   * FLOAT         Double
   * DOUBLE        Double
   * BINARY        byte[]
   * VARBINARY     byte[]
   * LONGVARBINARY byte[]
   * DATE          java.sql.Date
   * TIME          java.sql.Time
   * TIMESTAMP     java.sql.Timestamp
   * DISTINCT      Object type of underlying type
   * CLOB          java.sql.Clob
   * BLOB          java.sql.Blob
   * ARRAY         java.sql.Array
   * STRUCT        java.sql.Struct or java.sql.SQLData
   * REF           java.sql.Ref
   * DATALINK      java.net.URL
   * JAVA_OBJECT   underlying Java class
   * ROWID         java.sql.RowId
   * NCHAR         String
   * NVARCHAR      String
   * LONGNVARCHAR  String
   * NCLOB         java.sql.NClob
   * SQLXML        java.sql.SQLXML
   * </pre>
   *
   * <p>TABLE B-4: Mapping from Java Object Types to JDBC Types
   *
   * <pre>
   * Java Object Type     JDBC Type
   * ==================== ===========================================
   * String               CHAR, VARCHAR, LONGVARCHAR, NCHAR, NVARCHAR
   *                      or LONGNVARCHAR
   * java.math.BigDecimal NUMERIC
   * Boolean              BIT or BOOLEAN
   * Byte                 TINYINT
   * Short                SMALLINT
   * Integer              INTEGER
   * Long                 BIGINT
   * Float                REAL
   * Double               DOUBLE
   * byte[]               BINARY, VARBINARY, or LONGVARBINARY
   * java.math.BigInteger BIGINT
   * java.sql.Date        DATE
   * java.sql.Time        TIME
   * java.sql.Timestamp   TIMESTAMP
   * java.sql.Clob        CLOB
   * java.sql.Blob        BLOB
   * java.sql.Array       ARRAY
   * java.sql.Struct      STRUCT
   * java.sql.Ref         REF
   * java.net.URL         DATALINK
   * Java class           JAVA_OBJECT
   * java.sql.RowId       ROWID
   * java.sql.NClob       NCLOB
   * java.sql.SQLXML      SQLXML
   * java.util.Calendar   TIMESTAMP
   * java.util.Date       TIMESTAMP
   * </pre>
   *
   * <p><a id="B5">TABLE B-5</a>: Conversions performed by {@code setObject} and
   * {@code setNull} between Java object types and target JDBC types
   * <!--
   * CHECKSTYLE: OFF
   * -->
   * <pre>
   *                      T S I B R F D D N B B C V L B V L D T T A B C S R D J R N N L N S
   *                      I M N I E L O E U I O H A O I A O A I I R L L T E A A O C V O C Q
   *                      N A T G A O U C M T O A R N N R N T M M R O O R F T V W H A N L L
   *                      Y L E I L A B I E   L R C G A B G E E E A B B U   A A I A R G O X
   *                      I L G N   T L M R   E   H V R I V E   S Y     C   L _ D R C N B M
   *                      N I E T     E A I   A   A A Y N A     T       T   I O     H V   L
   *                      T N R         L C   N   R R   A R     A           N B     A A
   *                        T                       C   R B     M           K J     R R
   *                                                H   Y I     P                     C
   * Java type
   * ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
   * String               x x x x x x x x x x x x x x x x x x x x . . . . . . . . x x x . .
   * java.math.BigDecimal x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * Boolean              x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * Byte                 x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * Short                x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * Integer              x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * Long                 x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * Float                x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * Double               x x x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * byte[]               . . . . . . . . . . . . . . x x x . . . . . . . . . . . . . . . .
   * java.math.BigInteger . . . x . . . . . . . x x x . . . . . . . . . . . . . . . . . . .
   * java.sql.Date        . . . . . . . . . . . x x x . . . x . x . . . . . . . . . . . . .
   * java.sql.Time        . . . . . . . . . . . x x x . . . . x x . . . . . . . . . . . . .
   * java.sql.Timestamp   . . . . . . . . . . . x x x . . . x x x . . . . . . . . . . . . .
   * java.sql.Array       . . . . . . . . . . . . . . . . . . . . x . . . . . . . . . . . .
   * java.sql.Blob        . . . . . . . . . . . . . . . . . . . . . x . . . . . . . . . . .
   * java.sql.Clob        . . . . . . . . . . . . . . . . . . . . . . x . . . . . . . . . .
   * java.sql.Struct      . . . . . . . . . . . . . . . . . . . . . . . x . . . . . . . . .
   * java.sql.Ref         . . . . . . . . . . . . . . . . . . . . . . . . x . . . . . . . .
   * java.net.URL         . . . . . . . . . . . . . . . . . . . . . . . . . x . . . . . . .
   * Java class           . . . . . . . . . . . . . . . . . . . . . . . . . . x . . . . . .
   * java.sql.Rowid       . . . . . . . . . . . . . . . . . . . . . . . . . . . x . . . . .
   * java.sql.NClob       . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x .
   * java.sql.SQLXML      . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x
   * java.util.Calendar   . . . . . . . . . . . x x x . . . x x x . . . . . . . . . . . . .
   * java.util.Date       . . . . . . . . . . . x x x . . . x x x . . . . . . . . . . . . .
   * </pre>
   * <!--
   * CHECKSTYLE: ON
   * -->
   *
   * <p><a id="B6">TABLE B-6</a>: Use of {@code ResultSet} getter methods to
   * retrieve JDBC data types
   * <!--
   * CHECKSTYLE: OFF
   * -->
   * <pre>
   *                      T S I B R F D D N B B C V L B V L D T T C B A R D S J R N N L N S
   *                      I M N I E L O E U I O H A O I A O A I I L L R E A T A O C V O C Q
   *                      N A T G A O U C M T O A R N N R N T M M O O R F T R V W H A N L L
   *                      Y L E I L A B I E   L R C G A B G E E E B B A   A U A I A R G O X
   *                      I L G N   T L M R   E   H V R I V E   S     Y   L C _ D R C N B M
   *                      N I E T     E A I   A   A A Y N A     T         I T O     H V   L
   *                      T N R         L C   N   R R   A R     A         N   B     A A
   *                        T                       C   R B     M         K   J     R R
   *                                                H   Y I     P                     C
   * Java type
   * ==================== = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
   * getByte              X x x x x x x x x x x x x . . . . . . . . . . . . . . x . . . . .
   * getShort             x X x x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * getInt               x x X x x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * getLong              x x x X x x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * getFloat             x x x x X x x x x x x x x . . . . . . . . . . . . . . . . . . . .
   * getDouble            x x x x x X X x x x x x x . . . . . . . . . . . . . . . . . . . .
   * getBigDecimal        x x x x x x x X X x x x x . . . . . . . . . . . . . . . . . . . .
   * getBoolean           x x x x x x x x x X x x x . . . . . . . . . . . . . . . . . . . .
   * getString            x x x x x x x x x x x X X x x x x x x x . . . . x . . . x x x . .
   * getNString           x x x x x x x x x x x x x x x x x x x x . . . . x . . . X X x . .
   * getBytes             . . . . . . . . . . . . . . X X x . . . . . . . . . . . . . . . .
   * getDate              . . . . . . . . . . . x x x . . . X . x . . . . . . . . . . . . .
   * getTime              . . . . . . . . . . . x x x . . . . X x . . . . . . . . . . . . .
   * getTimestamp         . . . . . . . . . . . x x x . . . x x X . . . . . . . . . . . x .
   * getAsciiStream       . . . . . . . . . . . x x X x x x . . . x . . . . . . . . . . . x
   * getBinaryStream      . . . . . . . . . . . . . . x x X . . . . x . . . . . . . . . x x
   * getCharacterStream   . . . . . . . . . . . x x X x x x . . . x . . . . . . . x x x x x
   * getNCharacterStream  . . . . . . . . . . . x x x x x x . . . x . . . . . . . x x X x x
   * getClob              . . . . . . . . . . . . . . . . . . . . X . . . . . . . . . . x .
   * getNClob             . . . . . . . . . . . . . . . . . . . . x . . . . . . . . . . X .
   * getBlob              . . . . . . . . . . . . . . . . . . . . . X . . . . . . . . . . .
   * getArray             . . . . . . . . . . . . . . . . . . . . . . X . . . . . . . . . .
   * getRef               . . . . . . . . . . . . . . . . . . . . . . . X . . . . . . . . .
   * getURL               . . . . . . . . . . . . . . . . . . . . . . . . X . . . . . . . .
   * getObject            x x x x x x x x x x x x x x x x x x x x x x x x x X X x x x x x x
   * getRowId             . . . . . . . . . . . . . . . . . . . . . . . . . . . X . . . . .
   * getSQLXML            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . X
   * </pre>
   * <!--
   * CHECKSTYLE: ON
   * -->
   */
  public enum SqlType {
    BIT(Types.BIT, boolean.class),
    BOOLEAN(Types.BOOLEAN, boolean.class),
    TINYINT(Types.TINYINT, byte.class),
    SMALLINT(Types.SMALLINT, short.class),
    INTEGER(Types.INTEGER, int.class),
    BIGINT(Types.BIGINT, long.class),
    NUMERIC(Types.NUMERIC, BigDecimal.class),
    DECIMAL(Types.DECIMAL, BigDecimal.class),
    FLOAT(Types.FLOAT, double.class),
    REAL(Types.REAL, float.class),
    DOUBLE(Types.DOUBLE, double.class),
    DATE(Types.DATE, java.sql.Date.class, int.class),
    TIME(Types.TIME, Time.class, int.class),
    TIMESTAMP(Types.TIMESTAMP, Timestamp.class, long.class),
    INTERVAL_YEAR_MONTH(Types.OTHER, Boolean.class),
    INTERVAL_DAY_TIME(Types.OTHER, Boolean.class),
    CHAR(Types.CHAR, String.class),
    VARCHAR(Types.VARCHAR, String.class),
    LONGVARCHAR(Types.LONGVARCHAR, String.class),
    BINARY(Types.BINARY, byte[].class, ByteString.class, String.class),
    VARBINARY(Types.VARBINARY, byte[].class, ByteString.class, String.class),
    LONGVARBINARY(Types.LONGVARBINARY, byte[].class, ByteString.class,
        String.class),
    NULL(Types.NULL, Void.class),
    ANY(Types.JAVA_OBJECT, Object.class),
    SYMBOL(Types.OTHER, Object.class),
    MULTISET(Types.ARRAY, List.class),
    ARRAY(Types.ARRAY, Array.class),
    BLOB(Types.BLOB, Blob.class),
    CLOB(Types.CLOB, Clob.class),
    SQLXML(Types.SQLXML, java.sql.SQLXML.class),
    MAP(Types.OTHER, Map.class),
    DISTINCT(Types.DISTINCT, Object.class),
    STRUCT(Types.STRUCT, Struct.class),
    REF(Types.REF, Ref.class),
    DATALINK(Types.DATALINK, URL.class),
    JAVA_OBJECT(Types.JAVA_OBJECT, Object.class),
    ROWID(Types.ROWID, RowId.class),
    NCHAR(Types.NCHAR, String.class),
    NVARCHAR(Types.NVARCHAR, String.class),
    LONGNVARCHAR(Types.LONGNVARCHAR, String.class),
    NCLOB(Types.NCLOB, NClob.class),
    ROW(Types.STRUCT, Object.class),
    OTHER(Types.OTHER, Object.class),
    CURSOR(2012, Object.class),
    TIME_WITH_TIMEZONE(2013, String.class),
    TIMESTAMP_WITH_TIMEZONE(2014, String.class),
    COLUMN_LIST(Types.OTHER + 2, Object.class);
  
    /** Type id as appears in {@link java.sql.Types},
     * e.g. {@link java.sql.Types#INTEGER}. */
    public final int id;
  
    /** Default Java type for this SQL type, as described in table B-1. */
    public final Class clazz;
  
    /** Class used internally in Calcite to represent instances of this type. */
    public final Class internal;
  
    /** Class used to serialize values of this type as JSON. */
    public final Class serial;
  
    private static final Map<Integer, SqlType> BY_ID = new HashMap<>();
    static {
      for (SqlType sqlType : values()) {
        BY_ID.put(sqlType.id, sqlType);
      }
    }
  
    SqlType(int id, Class clazz, Class internal, Class serial) {
      this.id = id;
      this.clazz = clazz;
      this.internal = internal;
      this.serial = serial;
    }
  
    SqlType(int id, Class clazz, Class internal) {
      this(id, clazz, internal, internal);
    }
  
    SqlType(int id, Class clazz) {
      this(id, clazz, clazz, clazz);
    }
  
    public static SqlType valueOf(int type) {
      final SqlType sqlType = BY_ID.get(type);
      if (sqlType == null) {
        throw new IllegalArgumentException("Unknown SQL type " + type);
      }
      return sqlType;
    }
  
    /** Returns the boxed type. */
    public Class boxedClass() {
      return AvaticaUtils.box(clazz);
    }
  
    /** Returns the entries in JDBC table B-5. */
    public static Iterable<Map.Entry<Class, SqlType>> getSetConversions() {
      final ArrayList<Map.Entry<Class, SqlType>> list = new ArrayList<>();
      for (Map.Entry<Class, EnumSet<SqlType>> entry : SET_LIST.entrySet()) {
        for (SqlType sqlType : entry.getValue()) {
          list.add(new AbstractMap.SimpleEntry<>(entry.getKey(), sqlType));
        }
      }
      return list;
    }
  
    public static final Map<Class, EnumSet<SqlType>> SET_LIST;
    public static final Map<Method, EnumSet<SqlType>> GET_LIST;
  
    static {
      SET_LIST = new HashMap<>();
      GET_LIST = new HashMap<>();
  
      EnumSet<SqlType> numericTypes = EnumSet.of(TINYINT, SMALLINT, INTEGER,
          BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, BOOLEAN);
      Class[] numericClasses = {
          BigDecimal.class, Boolean.class, Byte.class, Short.class, Integer.class,
          Long.class, Float.class, Double.class
      };
      EnumSet<SqlType> charTypes = EnumSet.of(CHAR, VARCHAR, LONGVARCHAR);
      EnumSet<SqlType> ncharTypes = EnumSet.of(NCHAR, NVARCHAR, LONGNVARCHAR);
      EnumSet<SqlType> binaryTypes = EnumSet.of(BINARY, VARBINARY, LONGVARBINARY);
      EnumSet<SqlType> dateTimeTypes = EnumSet.of(DATE, TIME, TIMESTAMP);
      final EnumSet<SqlType> numericCharTypes = concat(numericTypes, charTypes);
      SET_LIST.put(String.class,
          concat(numericCharTypes, binaryTypes, dateTimeTypes, ncharTypes));
      for (Class clazz : numericClasses) {
        SET_LIST.put(clazz, numericCharTypes);
      }
      SET_LIST.put(byte[].class, binaryTypes);
      SET_LIST.put(BigInteger.class,
          EnumSet.of(BIGINT, CHAR, VARCHAR, LONGVARCHAR));
      SET_LIST.put(java.sql.Date.class,
          concat(charTypes, EnumSet.of(DATE, TIMESTAMP)));
      SET_LIST.put(Time.class,
          concat(charTypes, EnumSet.of(TIME, TIMESTAMP)));
      SET_LIST.put(Timestamp.class,
          concat(charTypes, EnumSet.of(DATE, TIME, TIMESTAMP)));
      SET_LIST.put(Array.class, EnumSet.of(ARRAY));
      SET_LIST.put(Blob.class, EnumSet.of(BLOB));
      SET_LIST.put(Clob.class, EnumSet.of(CLOB));
      SET_LIST.put(Struct.class, EnumSet.of(STRUCT));
      SET_LIST.put(Ref.class, EnumSet.of(REF));
      SET_LIST.put(URL.class, EnumSet.of(DATALINK));
      SET_LIST.put(Class.class, EnumSet.of(JAVA_OBJECT));
      SET_LIST.put(RowId.class, EnumSet.of(ROWID));
      SET_LIST.put(NClob.class, EnumSet.of(NCLOB));
      SET_LIST.put(java.sql.SQLXML.class, EnumSet.of(SQLXML));
      SET_LIST.put(Calendar.class,
          concat(charTypes, EnumSet.of(DATE, TIME, TIMESTAMP)));
      SET_LIST.put(java.util.Date.class,
          concat(charTypes, EnumSet.of(DATE, TIME, TIMESTAMP)));
  
      EnumSet<Method> numericMethods =
          EnumSet.of(Method.GET_BYTE, Method.GET_SHORT, Method.GET_INT,
              Method.GET_LONG, Method.GET_FLOAT, Method.GET_DOUBLE,
              Method.GET_BIG_DECIMAL, Method.GET_BOOLEAN);
      for (Method method : numericMethods) {
        GET_LIST.put(method, numericCharTypes);
      }
      GET_LIST.put(Method.GET_BYTE, EnumSet.of(ROWID));
      for (Method method : EnumSet.of(Method.GET_STRING, Method.GET_N_STRING)) {
        GET_LIST.put(method,
            concat(numericCharTypes, binaryTypes, dateTimeTypes,
                EnumSet.of(DATALINK), ncharTypes));
      }
      GET_LIST.put(Method.GET_BYTES, binaryTypes);
      GET_LIST.put(Method.GET_DATE,
          concat(charTypes, EnumSet.of(DATE, TIMESTAMP)));
      GET_LIST.put(Method.GET_TIME,
          concat(charTypes, EnumSet.of(TIME, TIMESTAMP)));
      GET_LIST.put(Method.GET_TIMESTAMP,
          concat(charTypes, EnumSet.of(DATE, TIME, TIMESTAMP)));
      GET_LIST.put(Method.GET_ASCII_STREAM,
          concat(charTypes, binaryTypes, EnumSet.of(CLOB, NCLOB)));
      GET_LIST.put(Method.GET_BINARY_STREAM,
          concat(binaryTypes, EnumSet.of(BLOB, SQLXML)));
      GET_LIST.put(Method.GET_CHARACTER_STREAM,
          concat(charTypes, binaryTypes, ncharTypes,
              EnumSet.of(CLOB, NCLOB, SQLXML)));
      GET_LIST.put(Method.GET_N_CHARACTER_STREAM,
          concat(
              charTypes, binaryTypes, ncharTypes, EnumSet.of(CLOB, NCLOB, SQLXML)));
      GET_LIST.put(Method.GET_CLOB, EnumSet.of(CLOB, NCLOB));
      GET_LIST.put(Method.GET_N_CLOB, EnumSet.of(CLOB, NCLOB));
      GET_LIST.put(Method.GET_BLOB, EnumSet.of(BLOB));
      GET_LIST.put(Method.GET_ARRAY, EnumSet.of(ARRAY));
      GET_LIST.put(Method.GET_REF, EnumSet.of(REF));
      GET_LIST.put(Method.GET_BLOB, EnumSet.of(BLOB));
      GET_LIST.put(Method.GET_URL, EnumSet.of(DATALINK));
      GET_LIST.put(Method.GET_OBJECT, EnumSet.allOf(SqlType.class));
      GET_LIST.put(Method.GET_ROW_ID, EnumSet.of(ROWID));
      GET_LIST.put(Method.GET_SQLXML, EnumSet.of(SQLXML));
    }
  
    @SafeVarargs
    private static <E extends Enum<E>> EnumSet<E> concat(Collection<E>... ess) {
      final List<E> list = new ArrayList<>();
      for (Collection<E> es : ess) {
        list.addAll(es);
      }
      return EnumSet.copyOf(list);
    }
  
    /** Returns whether {@link java.sql.PreparedStatement#setObject} and
     * {@link PreparedStatement#setNull} can assign a value of a particular class
     * to a column of a particular SQL type.
     *
     * <p>The JDBC standard describes the mapping in table <a href="#B5">B-5</a>.
     */
    public static boolean canSet(Class aClass, SqlType sqlType) {
      final EnumSet<SqlType> sqlTypes = SET_LIST.get(aClass);
      return sqlTypes != null && sqlTypes.contains(sqlType);
    }
  
    /** Returns whether {@link java.sql.ResultSet#getInt(int)} and similar methods
     * can convert a value to a particular SQL type.
     *
     * <p>The JDBC standard describes the mapping in table <a href="#B6">B-6</a>.
     */
    public static boolean canGet(Method method, SqlType sqlType) {
      final EnumSet<SqlType> sqlTypes = GET_LIST.get(method);
      return sqlTypes != null && sqlTypes.contains(sqlType);
    }
  
    /** Getter methods in {@link java.sql.ResultSet}. */
    public enum Method {
      GET_BYTE("getByte"),
      GET_SHORT("getShort"),
      GET_INT("getInt"),
      GET_LONG("getLong"),
      GET_FLOAT("getFloat"),
      GET_DOUBLE("getDouble"),
      GET_BIG_DECIMAL("getBigDecimal"),
      GET_BOOLEAN("getBoolean"),
      GET_STRING("getString"),
      GET_N_STRING("getNString"),
      GET_BYTES("getBytes"),
      GET_DATE("getDate"),
      GET_TIME("getTime"),
      GET_TIMESTAMP("getTimestamp"),
      GET_ASCII_STREAM("getAsciiStream"),
      GET_BINARY_STREAM("getBinaryStream"),
      GET_CHARACTER_STREAM("getCharacterStream"),
      GET_N_CHARACTER_STREAM("getNCharacterStream"),
      GET_CLOB("getClob"),
      GET_N_CLOB("getNClob"),
      GET_BLOB("getBlob"),
      GET_ARRAY("getArray"),
      GET_REF("getRef"),
      GET_URL("getURL"),
      GET_OBJECT("getObject"),
      GET_ROW_ID("getRowId"),
      GET_SQLXML("getSQLXML");
  
      public final String methodName;
  
      Method(String methodName) {
        this.methodName = methodName;
      }
    }
  }
  
  // End SqlType.java
  