From b97e5267d703b565875405e860c553dac1744c53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Fern=C3=A1ndez=20Giraldo?= Date: Mon, 14 Aug 2023 12:24:11 -0400 Subject: [PATCH] GH-35916 [Java][arrow-jdbc] Add extra fields to JdbcFieldInfo (#37123) ### Rationale for this change Existing info is not enough to make completely accurate conversion decisions. ### What changes are included in this PR? Include the type name reported by the database and the max number of characters as part of the `JdbcFieldInfo`. * Closes: #35916 Authored-by: Diego Fernandez Signed-off-by: David Li --- .../arrow/adapter/jdbc/JdbcFieldInfo.java | 43 ++++++++++++++++++- .../arrow/adapter/jdbc/ResultSetUtility.java | 32 ++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcFieldInfo.java b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcFieldInfo.java index 3237c9bf97be8..97ca8f27ceb49 100644 --- a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcFieldInfo.java +++ b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcFieldInfo.java @@ -17,6 +17,7 @@ package org.apache.arrow.adapter.jdbc; +import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; @@ -40,6 +41,8 @@ public class JdbcFieldInfo { private final int nullability; private final int precision; private final int scale; + private final String typeName; + private final int displaySize; /** * Builds a JdbcFieldInfo using only the {@link java.sql.Types} type. Do not use this constructor @@ -53,12 +56,13 @@ public JdbcFieldInfo(int jdbcType) { Preconditions.checkArgument( (jdbcType != Types.DECIMAL && jdbcType != Types.NUMERIC), "DECIMAL and NUMERIC types require a precision and scale; please use another constructor."); - this.column = 0; this.jdbcType = jdbcType; this.nullability = ResultSetMetaData.columnNullableUnknown; this.precision = 0; this.scale = 0; + this.typeName = ""; + this.displaySize = 0; } /** @@ -75,6 +79,8 @@ public JdbcFieldInfo(int jdbcType, int precision, int scale) { this.nullability = ResultSetMetaData.columnNullableUnknown; this.precision = precision; this.scale = scale; + this.typeName = ""; + this.displaySize = 0; } /** @@ -92,6 +98,8 @@ public JdbcFieldInfo(int jdbcType, int nullability, int precision, int scale) { this.nullability = nullability; this.precision = precision; this.scale = scale; + this.typeName = ""; + this.displaySize = 0; } /** @@ -115,6 +123,25 @@ public JdbcFieldInfo(ResultSetMetaData rsmd, int column) throws SQLException { this.nullability = rsmd.isNullable(column); this.precision = rsmd.getPrecision(column); this.scale = rsmd.getScale(column); + this.typeName = rsmd.getColumnTypeName(column); + this.displaySize = rsmd.getColumnDisplaySize(column); + } + + /** + * Builds a JdbcFieldInfo from the corresponding row from a {@link java.sql.DatabaseMetaData#getColumns} + * ResulSet. + * + * @param rs The {@link java.sql.ResultSet} to get the field information from. + * @throws SQLException If the column information cannot be retrieved. + */ + public JdbcFieldInfo(ResultSet rs) throws SQLException { + this.column = rs.getInt("ORDINAL_POSITION"); + this.jdbcType = rs.getInt("DATA_TYPE"); + this.nullability = rs.getInt("NULLABLE"); + this.precision = rs.getInt("COLUMN_SIZE"); + this.scale = rs.getInt("DECIMAL_DIGITS"); + this.typeName = rs.getString("TYPE_NAME"); + this.displaySize = rs.getInt("CHAR_OCTET_LENGTH"); } /** @@ -151,4 +178,18 @@ public int getScale() { public int getColumn() { return column; } + + /** + * The type name as reported by the database. + */ + public String getTypeName() { + return typeName; + } + + /** + * The max number of characters for the column. + */ + public int getDisplaySize() { + return displaySize; + } } diff --git a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/ResultSetUtility.java b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/ResultSetUtility.java index 339e120beea76..c712741b51f5b 100644 --- a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/ResultSetUtility.java +++ b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/ResultSetUtility.java @@ -308,6 +308,16 @@ public int isNullable(int column) throws SQLException { return columns.get(column - 1).isNullable(); } + @Override + public int getColumnDisplaySize(int column) throws SQLException { + return columns.get(column - 1).getDisplaySize(); + } + + @Override + public String getColumnTypeName(int column) throws SQLException { + return columns.get(column - 1).getTypeName(); + } + public static MockResultSetMetaData fromRows(ArrayList rows) throws SQLException { // Note: This attempts to dynamically construct ResultSetMetaData from the first row in a given result set. // If there are now rows, or the result set contains no columns, this cannot be dynamically generated and @@ -334,6 +344,8 @@ public static class MockColumnMetaData { private int scale; private int nullable; private String label; + private String typeName; + private int displaySize; private MockColumnMetaData() {} @@ -362,6 +374,14 @@ private int isNullable() { return nullable; } + private String getTypeName() { + return typeName; + } + + private int getDisplaySize() { + return displaySize; + } + public static MockColumnMetaData fromDataElement(MockDataElement element, int i) throws SQLException { return MockColumnMetaData.builder() .index(i) @@ -369,6 +389,8 @@ public static MockColumnMetaData fromDataElement(MockDataElement element, int i) .precision(element.getPrecision()) .scale(element.getScale()) .nullable(element.isNullable()) + .setTypeName("TYPE") + .setDisplaySize(420) .label("col_" + i) .build(); } @@ -410,6 +432,16 @@ public Builder nullable(int nullable) { return this; } + public Builder setTypeName(String typeName) { + this.columnMetaData.typeName = typeName; + return this; + } + + public Builder setDisplaySize(int displaySize) { + this.columnMetaData.displaySize = displaySize; + return this; + } + public MockColumnMetaData build() { return this.columnMetaData; }