JdbcFieldSchema.java
// 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.doris.datasource.jdbc.util;
import lombok.Data;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Map;
import java.util.Optional;
@Data
public class JdbcFieldSchema {
protected String columnName;
// The SQL type of the corresponding java.sql.types (Type ID)
protected int dataType;
// The SQL type of the corresponding java.sql.types (Type Name)
protected Optional<String> dataTypeName;
// For CHAR/DATA, columnSize means the maximum number of chars.
// For NUMERIC/DECIMAL, columnSize means precision.
protected Optional<Integer> columnSize;
protected Optional<Integer> decimalDigits;
protected Optional<Integer> arrayDimensions;
// Base number (usually 10 or 2)
protected int numPrecRadix;
// column description
protected String remarks;
// This length is the maximum number of bytes for CHAR type
// for utf8 encoding, if columnSize=10, then charOctetLength=30
// because for utf8 encoding, a Chinese character takes up 3 bytes
protected int charOctetLength;
protected boolean isAllowNull;
public JdbcFieldSchema(JdbcFieldSchema other) {
this.columnName = other.columnName;
this.dataType = other.dataType;
this.dataTypeName = other.dataTypeName;
this.columnSize = other.columnSize;
this.decimalDigits = other.decimalDigits;
this.arrayDimensions = other.arrayDimensions;
this.numPrecRadix = other.numPrecRadix;
this.remarks = other.remarks;
this.charOctetLength = other.charOctetLength;
this.isAllowNull = other.isAllowNull;
}
public JdbcFieldSchema(ResultSet rs) throws SQLException {
this.columnName = rs.getString("COLUMN_NAME");
this.dataType = getInteger(rs, "DATA_TYPE").orElseThrow(() -> new IllegalStateException("DATA_TYPE is null"));
this.dataTypeName = Optional.ofNullable(rs.getString("TYPE_NAME"));
this.columnSize = getInteger(rs, "COLUMN_SIZE");
this.decimalDigits = getInteger(rs, "DECIMAL_DIGITS");
this.numPrecRadix = rs.getInt("NUM_PREC_RADIX");
this.isAllowNull = rs.getInt("NULLABLE") != DatabaseMetaData.columnNoNulls;
this.remarks = rs.getString("REMARKS");
this.charOctetLength = rs.getInt("CHAR_OCTET_LENGTH");
}
public JdbcFieldSchema(ResultSet rs, int arrayDimensions) throws SQLException {
this.columnName = rs.getString("COLUMN_NAME");
this.dataType = getInteger(rs, "DATA_TYPE").orElseThrow(() -> new IllegalStateException("DATA_TYPE is null"));
this.dataTypeName = Optional.ofNullable(rs.getString("TYPE_NAME"));
this.columnSize = getInteger(rs, "COLUMN_SIZE");
this.decimalDigits = getInteger(rs, "DECIMAL_DIGITS");
this.numPrecRadix = rs.getInt("NUM_PREC_RADIX");
this.isAllowNull = rs.getInt("NULLABLE") != DatabaseMetaData.columnNoNulls;
this.remarks = rs.getString("REMARKS");
this.charOctetLength = rs.getInt("CHAR_OCTET_LENGTH");
this.arrayDimensions = Optional.of(arrayDimensions);
}
public JdbcFieldSchema(ResultSet rs, Map<String, String> dataTypeOverrides) throws SQLException {
this.columnName = rs.getString("COLUMN_NAME");
this.dataType = getInteger(rs, "DATA_TYPE").orElseThrow(() -> new IllegalStateException("DATA_TYPE is null"));
this.dataTypeName = Optional.ofNullable(dataTypeOverrides.getOrDefault(columnName, rs.getString("TYPE_NAME")));
this.columnSize = getInteger(rs, "COLUMN_SIZE");
this.decimalDigits = getInteger(rs, "DECIMAL_DIGITS");
this.numPrecRadix = rs.getInt("NUM_PREC_RADIX");
this.isAllowNull = rs.getInt("NULLABLE") != 0;
this.remarks = rs.getString("REMARKS");
this.charOctetLength = rs.getInt("CHAR_OCTET_LENGTH");
}
public JdbcFieldSchema(ResultSetMetaData metaData, int columnIndex) throws SQLException {
this.columnName = metaData.getColumnName(columnIndex);
this.dataType = metaData.getColumnType(columnIndex);
this.dataTypeName = Optional.ofNullable(metaData.getColumnTypeName(columnIndex));
this.columnSize = Optional.of(metaData.getPrecision(columnIndex));
this.decimalDigits = Optional.of(metaData.getScale(columnIndex));
this.arrayDimensions = Optional.of(0);
}
public int requiredColumnSize() {
return columnSize.orElseThrow(() -> new IllegalStateException("column size not present"));
}
public int requiredDecimalDigits() {
return decimalDigits.orElseThrow(() -> new IllegalStateException("decimal digits not present"));
}
protected static Optional<Integer> getInteger(ResultSet resultSet, String columnLabel)
throws SQLException {
int value = resultSet.getInt(columnLabel);
if (resultSet.wasNull()) {
return Optional.empty();
}
return Optional.of(value);
}
}