diff --git a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java index f237caf13..78019e51a 100644 --- a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java @@ -34,7 +34,6 @@ import net.snowflake.client.jdbc.ArrowResultChunk.ArrowChunkIterator; import net.snowflake.client.jdbc.ErrorCode; import net.snowflake.client.jdbc.FieldMetadata; -import net.snowflake.client.jdbc.SnowflakeColumnMetadata; import net.snowflake.client.jdbc.SnowflakeResultSetSerializableV1; import net.snowflake.client.jdbc.SnowflakeSQLException; import net.snowflake.client.jdbc.SnowflakeSQLLoggedException; @@ -586,19 +585,17 @@ private Object createJsonSqlInput(int columnIndex, Object obj) throws SFExceptio jsonNode, session, converters, - resultSetMetaData.getColumnMetadata().get(columnIndex - 1).getFields(), + resultSetMetaData.getColumnFields(columnIndex), sessionTimeZone); } catch (JsonProcessingException e) { throw new SFException(e, ErrorCode.INVALID_STRUCT_DATA); } } - private Object createArrowSqlInput(int columnIndex, Map input) { + private Object createArrowSqlInput(int columnIndex, Map input) + throws SFException { return new ArrowSqlInput( - input, - session, - converters, - resultSetMetaData.getColumnMetadata().get(columnIndex - 1).getFields()); + input, session, converters, resultSetMetaData.getColumnFields(columnIndex)); } @Override @@ -621,10 +618,13 @@ public Array getArray(int columnIndex) throws SFException { private SfSqlArray getArrowArray(List elements, int columnIndex) throws SFException { try { - SnowflakeColumnMetadata arrayMetadata = - resultSetMetaData.getColumnMetadata().get(columnIndex - 1); - FieldMetadata fieldMetadata = arrayMetadata.getFields().get(0); - + List fieldMetadataList = resultSetMetaData.getColumnFields(columnIndex); + if (fieldMetadataList.size() != 1) { + throw new SFException( + ErrorCode.INVALID_STRUCT_DATA, + "Wrong size of fields for array type " + fieldMetadataList.size()); + } + FieldMetadata fieldMetadata = fieldMetadataList.get(0); int columnSubType = fieldMetadata.getType(); int columnType = ColumnTypeHelper.getColumnType(columnSubType, session); int scale = fieldMetadata.getScale(); diff --git a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java index 0943afb42..1932b7a24 100644 --- a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java @@ -32,7 +32,6 @@ import net.snowflake.client.core.json.Converters; import net.snowflake.client.jdbc.ErrorCode; import net.snowflake.client.jdbc.FieldMetadata; -import net.snowflake.client.jdbc.SnowflakeColumnMetadata; import net.snowflake.client.jdbc.SnowflakeResultSetSerializable; import net.snowflake.client.jdbc.SnowflakeResultSetSerializableV1; import net.snowflake.client.jdbc.SnowflakeSQLException; @@ -275,9 +274,14 @@ protected SQLInput createJsonSqlInputForColumn( @SnowflakeJdbcInternalApi protected SfSqlArray getJsonArray(String obj, int columnIndex) throws SFException { try { - SnowflakeColumnMetadata arrayMetadata = - resultSetMetaData.getColumnMetadata().get(columnIndex - 1); - FieldMetadata fieldMetadata = arrayMetadata.getFields().get(0); + List fieldMetadataList = resultSetMetaData.getColumnFields(columnIndex); + if (fieldMetadataList.size() != 1) { + throw new SFException( + ErrorCode.FEATURE_UNSUPPORTED, + "Wrong size of fields for array type " + fieldMetadataList.size()); + } + + FieldMetadata fieldMetadata = fieldMetadataList.get(0); int columnSubType = fieldMetadata.getType(); int columnType = ColumnTypeHelper.getColumnType(columnSubType, session); diff --git a/src/main/java/net/snowflake/client/core/SFJsonResultSet.java b/src/main/java/net/snowflake/client/core/SFJsonResultSet.java index a9ccc00b9..f4a2fe04b 100644 --- a/src/main/java/net/snowflake/client/core/SFJsonResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFJsonResultSet.java @@ -298,7 +298,7 @@ private Object getSqlInput(String input, int columnIndex) throws SFException { jsonNode, session, converters, - resultSetMetaData.getColumnMetadata().get(columnIndex - 1).getFields(), + resultSetMetaData.getColumnFields(columnIndex), sessionTimeZone); } catch (JsonProcessingException e) { throw new SFException(e, ErrorCode.INVALID_STRUCT_DATA); diff --git a/src/main/java/net/snowflake/client/core/SFResultSetMetaData.java b/src/main/java/net/snowflake/client/core/SFResultSetMetaData.java index ce129788b..586768c6a 100644 --- a/src/main/java/net/snowflake/client/core/SFResultSetMetaData.java +++ b/src/main/java/net/snowflake/client/core/SFResultSetMetaData.java @@ -14,6 +14,7 @@ import java.util.Map; import java.util.TimeZone; import net.snowflake.client.jdbc.ErrorCode; +import net.snowflake.client.jdbc.FieldMetadata; import net.snowflake.client.jdbc.SnowflakeColumnMetadata; import net.snowflake.client.jdbc.SnowflakeUtil; import net.snowflake.client.log.SFLogger; @@ -474,7 +475,15 @@ public List getIsAutoIncrementList() { } @SnowflakeJdbcInternalApi - public List getColumnMetadata() { - return columnMetadata; + public List getColumnFields(int column) throws SFException { + if (column < 1 || column > columnMetadata.size()) { + throw new SFException(ErrorCode.COLUMN_DOES_NOT_EXIST, column); + } + + if (columnMetadata.get(column - 1) == null) { + throw new SFException(ErrorCode.INTERNAL_ERROR, "Missing column fields for column " + column); + } + + return columnMetadata.get(column - 1).getFields(); } } diff --git a/src/main/java/net/snowflake/client/jdbc/FieldMetadata.java b/src/main/java/net/snowflake/client/jdbc/FieldMetadata.java index 55979cd83..cf019d62e 100644 --- a/src/main/java/net/snowflake/client/jdbc/FieldMetadata.java +++ b/src/main/java/net/snowflake/client/jdbc/FieldMetadata.java @@ -4,9 +4,7 @@ package net.snowflake.client.jdbc; import java.util.List; -import net.snowflake.client.core.SnowflakeJdbcInternalApi; -@SnowflakeJdbcInternalApi public class FieldMetadata { private String name; diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index ff15ff631..102e27eeb 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -1419,8 +1419,11 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { if (!StructureTypeHelper.isStructureTypeEnabled()) { throw new SnowflakeLoggedFeatureNotSupportedException(session); } - FieldMetadata fieldMetadata = - sfBaseResultSet.getMetaData().getColumnMetadata().get(columnIndex - 1).getFields().get(0); + List fieldMetadataList = resultSetMetaData.getColumnFields(columnIndex); + if (fieldMetadataList.size() != 1) { + throw new SQLException("Wrong size of fields for array type " + fieldMetadataList.size()); + } + FieldMetadata fieldMetadata = fieldMetadataList.get(0); int columnSubType = fieldMetadata.getType(); int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); int scale = fieldMetadata.getScale(); @@ -1569,8 +1572,12 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep if (!StructureTypeHelper.isStructureTypeEnabled()) { throw new SnowflakeLoggedFeatureNotSupportedException(session); } - FieldMetadata valueFieldMetadata = - sfBaseResultSet.getMetaData().getColumnMetadata().get(columnIndex - 1).getFields().get(1); + List fieldMetadataList = resultSetMetaData.getColumnFields(columnIndex); + if (fieldMetadataList.size() != 2) { + throw new SQLException( + "Wrong size of fields metadata for map type " + fieldMetadataList.size()); + } + FieldMetadata valueFieldMetadata = fieldMetadataList.get(1); int columnSubType = valueFieldMetadata.getType(); int columnType = ColumnTypeHelper.getColumnType(valueFieldMetadata.getType(), session); int scale = valueFieldMetadata.getScale(); diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaData.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaData.java index 5b2fc402c..dcc5250b5 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaData.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaData.java @@ -11,4 +11,6 @@ public interface SnowflakeResultSetMetaData { int getColumnIndex(String columnName) throws SQLException; int getInternalColumnType(int column) throws SQLException; + + List getColumnFields(int column) throws SQLException; } diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaDataV1.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaDataV1.java index 4bc90bd54..170188d39 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaDataV1.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaDataV1.java @@ -78,6 +78,12 @@ public int getInternalColumnType(int column) throws SQLException { } } + @Override + public List getColumnFields(int column) throws SQLException { + return SnowflakeUtil.mapSFExceptionToSQLException( + () -> resultSetMetaData.getColumnFields(column)); + } + @Override public T unwrap(Class iface) throws SQLException { logger.debug("public T unwrap(Class iface)", false); diff --git a/src/test/java/net/snowflake/client/jdbc/structuredtypes/ResultSetStructuredTypesLatestIT.java b/src/test/java/net/snowflake/client/jdbc/structuredtypes/ResultSetStructuredTypesLatestIT.java index b35d8c840..d7300732b 100644 --- a/src/test/java/net/snowflake/client/jdbc/structuredtypes/ResultSetStructuredTypesLatestIT.java +++ b/src/test/java/net/snowflake/client/jdbc/structuredtypes/ResultSetStructuredTypesLatestIT.java @@ -31,6 +31,7 @@ import net.snowflake.client.core.structs.StructureTypeHelper; import net.snowflake.client.jdbc.BaseJDBCTest; import net.snowflake.client.jdbc.SnowflakeBaseResultSet; +import net.snowflake.client.jdbc.SnowflakeResultSetMetaData; import net.snowflake.client.jdbc.structuredtypes.sqldata.AllTypesClass; import net.snowflake.client.jdbc.structuredtypes.sqldata.FewTypesSqlData; import net.snowflake.client.jdbc.structuredtypes.sqldata.SimpleClass; @@ -43,6 +44,7 @@ @RunWith(Parameterized.class) @Category(TestCategoryStructuredType.class) +@Ignore public class ResultSetStructuredTypesLatestIT extends BaseJDBCTest { @Parameterized.Parameters(name = "format={0}") @@ -650,11 +652,11 @@ public void testMapArrayOfArrays() throws SQLException { } @Test - public void testColumnTypeWhenStructureTypeIsDisabled() throws Exception { + public void testColumnTypeWhenStructureTypeIsNotReturned() throws Exception { withStructureTypeTemporaryDisabled( () -> { withFirstRow( - "SELECT {'string':'a'}::OBJECT(string VARCHAR)", + "SELECT {'string':'a'}", resultSet -> { assertEquals(Types.VARCHAR, resultSet.getMetaData().getColumnType(1)); }); @@ -663,13 +665,36 @@ public void testColumnTypeWhenStructureTypeIsDisabled() throws Exception { @Test @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) - public void testColumnTypeWhenStructureTypeIsEnabled() throws Exception { + public void testColumnTypeAndFieldsWhenStructureTypeIsReturned() throws Exception { withStructureTypeTemporaryEnabled( () -> { withFirstRow( "SELECT {'string':'a'}::OBJECT(string VARCHAR)", resultSet -> { assertEquals(Types.STRUCT, resultSet.getMetaData().getColumnType(1)); + assertEquals( + 1, + resultSet + .getMetaData() + .unwrap(SnowflakeResultSetMetaData.class) + .getColumnFields(1) + .size()); + assertEquals( + "VARCHAR", + resultSet + .getMetaData() + .unwrap(SnowflakeResultSetMetaData.class) + .getColumnFields(1) + .get(0) + .getTypeName()); + assertEquals( + "string", + resultSet + .getMetaData() + .unwrap(SnowflakeResultSetMetaData.class) + .getColumnFields(1) + .get(0) + .getName()); }); }); }