From 84228c8db0caf38d600dce1fa9f916c2b2ebe7f3 Mon Sep 17 00:00:00 2001 From: Przemyslaw Motacki Date: Thu, 21 Mar 2024 10:22:32 +0100 Subject: [PATCH 01/11] SNOW-1259709 - add mapping for basic types for arrays and maps --- .../snowflake/client/core/JsonSqlInput.java | 6 + .../client/jdbc/SnowflakeBaseResultSet.java | 299 +++++++++++++++++- .../snowflake/client/jdbc/SnowflakeUtil.java | 2 + .../snowflake/client/AbstractDriverIT.java | 3 + .../ResultSetStructuredTypesLatestIT.java | 55 ++++ 5 files changed, 349 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/snowflake/client/core/JsonSqlInput.java b/src/main/java/net/snowflake/client/core/JsonSqlInput.java index f5c4bd6f0..f6a1d35e9 100644 --- a/src/main/java/net/snowflake/client/core/JsonSqlInput.java +++ b/src/main/java/net/snowflake/client/core/JsonSqlInput.java @@ -21,6 +21,7 @@ import net.snowflake.client.core.structs.SQLDataCreationHelper; import net.snowflake.client.jdbc.FieldMetadata; import net.snowflake.client.jdbc.SnowflakeLoggedFeatureNotSupportedException; +import net.snowflake.client.jdbc.SnowflakeUtil; import net.snowflake.client.util.ThrowingTriFunction; import net.snowflake.common.core.SFTimestamp; import net.snowflake.common.core.SnowflakeDateTimeFormat; @@ -170,6 +171,11 @@ public Time readTime() throws SQLException { }); } + @Override + public Timestamp readTimestamp() throws SQLException { + return readTimestamp(null); + } + @Override public Timestamp readTimestamp(TimeZone tz) throws SQLException { return withNextValue( diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index 5f69a1cc5..c3c2b7cfc 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -4,6 +4,8 @@ package net.snowflake.client.jdbc; +import static net.snowflake.client.jdbc.SnowflakeUtil.mapExceptions; + import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -1372,8 +1374,6 @@ public T getObject(int columnIndex, Class type) throws SQLException { return (T) (Double) getDouble(columnIndex); } else if (Date.class.isAssignableFrom(type)) { return (T) getDate(columnIndex); - } else if (Date.class.isAssignableFrom(type)) { - return (T) getDate(columnIndex); } else if (Time.class.isAssignableFrom(type)) { return (T) getTime(columnIndex); } else if (Timestamp.class.isAssignableFrom(type)) { @@ -1395,26 +1395,147 @@ public List getList(int columnIndex, Class type) throws SQLException { } public T[] getArray(int columnIndex, Class type) throws SQLException { - Map[] jsonMaps = (Map[]) getArray(columnIndex).getArray(); - T[] arr = (T[]) java.lang.reflect.Array.newInstance(type, jsonMaps.length); + int columnType = resultSetMetaData.getInternalColumnType(columnIndex); + int columnSubType = resultSetMetaData.getInternalColumnType(columnIndex); + int scale = resultSetMetaData.getScale(columnIndex); + TimeZone tz = TimeZone.getDefault(); + Object[] objects = (Object[]) getArray(columnIndex).getArray(); + T[] arr = (T[]) java.lang.reflect.Array.newInstance(type, objects.length); int counter = 0; - for (Map map : jsonMaps) { - SQLData instance = (SQLData) SQLDataCreationHelper.create(type); - SQLInput sqlInput = - new JsonSqlInput( - OBJECT_MAPPER.convertValue(map, JsonNode.class), - session, - sfBaseResultSet.getConverters(), - sfBaseResultSet.getMetaData().getColumnMetadata().get(columnIndex - 1).getFields(), - sfBaseResultSet.getSessionTimezone()); - instance.readSQL(sqlInput, null); - arr[counter++] = (T) instance; + for (Object value : objects) { + if (SQLData.class.isAssignableFrom(type)) { + Map[] data = (Map[]) value; + SQLData instance = (SQLData) SQLDataCreationHelper.create(type); + SQLInput sqlInput = + new JsonSqlInput( + OBJECT_MAPPER.convertValue(data, JsonNode.class), + session, + sfBaseResultSet.getConverters(), + sfBaseResultSet.getMetaData().getColumnMetadata().get(columnIndex - 1).getFields(), + sfBaseResultSet.getSessionTimezone()); + instance.readSQL(sqlInput, null); + arr[counter++] = (T) instance; + } else if (String.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getStringConverter() + .getString(value, columnType, columnSubType, scale)); + } else if (Boolean.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getBooleanConverter() + .getBoolean(value, columnType)); + } else if (Byte.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getBytesConverter() + .getBytes(value, columnType, columnSubType, scale)); + } else if (Short.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + Short.valueOf( + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getShort(value, columnType))); + } else if (Integer.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + Integer.valueOf( + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getInt(value, columnType))); + } else if (Long.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + Long.valueOf( + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getLong(value, columnType))); + } else if (Float.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + Float.valueOf( + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getFloat(value, columnType))); + } else if (Double.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + Double.valueOf( + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getDouble(value, columnType))); + } else if (Date.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getDateTimeConverter() + .getDate(value, columnType, columnSubType, tz, scale)); + } else if (Time.class.isAssignableFrom(type)) { + arr[counter++] = + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getDateTimeConverter() + .getTime(value, columnType, columnSubType, tz, scale)); + } else if (Timestamp.class.isAssignableFrom(type)) { + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getDateTimeConverter() + .getTimestamp(value, columnType, columnSubType, tz, scale)); + } else if (BigDecimal.class.isAssignableFrom(type)) { + arr[counter++] = (T) getBigDecimal(columnIndex); + } else { + logger.debug( + "Unsupported type passed to getList(int columnIndex,Class type): " + type.getName()); + throw new SQLException( + "Type passed to 'getObject(int columnIndex,Class type)' is unsupported. Type: " + + type.getName()); + } } - return arr; } public Map getMap(int columnIndex, Class type) throws SQLException { + int columnType = resultSetMetaData.getInternalColumnType(columnIndex); + int columnSubType = resultSetMetaData.getInternalColumnType(columnIndex); + int scale = resultSetMetaData.getScale(columnIndex); + TimeZone tz = TimeZone.getDefault(); Object object = getObject(columnIndex); JsonNode jsonNode = ((JsonSqlInput) object).getInput(); Map map = @@ -1432,6 +1553,152 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep sfBaseResultSet.getSessionTimezone()); instance.readSQL(sqlInput, null); resultMap.put(entry.getKey(), (T) instance); + + if (SQLData.class.isAssignableFrom(type)) { + SQLData instance = (SQLData) SQLDataCreationHelper.create(type); + SQLInput sqlInput = + new JsonSqlInput( + new JsonSqlInput( + jsonNode.get(entry.getKey()), + session, + sfBaseResultSet.getConverters(), + sfBaseResultSet.getMetaData().getColumnMetadata().get(columnIndex - 1).getFields(), + sfBaseResultSet.getSessionTimezone()); + instance.readSQL(sqlInput, null); + resultMap.put(entry.getKey(), (T) instance); + } else if (String.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getStringConverter() + .getString(entry.getValue(), columnType, columnSubType, scale))); + } else if (Boolean.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getBooleanConverter() + .getBoolean(entry.getValue(), columnType))); + } else if (Byte.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getBytesConverter() + .getBytes(entry.getValue(), columnType, columnSubType, scale))); + } else if (Short.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + (Short) + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getShort(entry.getValue(), columnType))); + } else if (Integer.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + (Integer) + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getInt(entry.getValue(), columnType))); + } else if (Long.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + (Long) + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getLong(entry.getValue(), columnType))); + } else if (Float.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + (Float) + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getFloat(entry.getValue(), columnType))); + } else if (Double.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + (Double) + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getDouble(entry.getValue(), columnType))); + } else if (BigDecimal.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getNumberConverter() + .getBigDecimal(entry.getValue(), columnType))); + } else if (Date.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getDateTimeConverter() + .getDate(entry.getValue(), columnType, columnSubType, tz, scale))); + } else if (Time.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getDateTimeConverter() + .getTime(entry.getValue(), columnType, columnSubType, tz, scale))); + } else if (Timestamp.class.isAssignableFrom(type)) { + resultMap.put( + entry.getKey(), + mapExceptions( + () -> + (T) + sfBaseResultSet + .getConverters() + .getDateTimeConverter() + .getTimestamp(entry.getValue(), columnType, columnSubType, tz, scale))); + } else { + logger.debug( + "Unsupported type passed to getObject(int columnIndex,Class type): " + + type.getName()); + throw new SQLException( + "Type passed to 'getObject(int columnIndex,Class type)' is unsupported. Type: " + + type.getName()); + } } return resultMap; diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java index fc0b5dde4..c0b551fa2 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java @@ -43,6 +43,7 @@ import net.snowflake.client.log.SFLogger; import net.snowflake.client.log.SFLoggerFactory; import net.snowflake.client.util.ThrowingCallable; +import net.snowflake.common.core.SnowflakeDateTimeFormat; import net.snowflake.common.core.SqlState; import net.snowflake.common.util.ClassUtil; import net.snowflake.common.util.FixedViewColumn; @@ -791,6 +792,7 @@ public static boolean convertSystemPropertyToBooleanValue( return defaultValue; } + @SnowflakeJdbcInternalApi public static T mapExceptions(ThrowingCallable action) throws SQLException { try { return action.call(); diff --git a/src/test/java/net/snowflake/client/AbstractDriverIT.java b/src/test/java/net/snowflake/client/AbstractDriverIT.java index b44cc31ef..d918b829c 100644 --- a/src/test/java/net/snowflake/client/AbstractDriverIT.java +++ b/src/test/java/net/snowflake/client/AbstractDriverIT.java @@ -317,6 +317,9 @@ public static Connection getConnection( properties.put("role", params.get("role")); properties.put("account", params.get("account")); } + properties.put("useProxy", "true"); + properties.put("proxyHost", "localhost"); + properties.put("proxyPort", "8080"); properties.put("db", params.get("database")); properties.put("schema", params.get("schema")); properties.put("warehouse", params.get("warehouse")); diff --git a/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java b/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java index f54887d2d..12df13135 100644 --- a/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java +++ b/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java @@ -204,6 +204,34 @@ public void testReturnAsArrayOfSqlData() throws SQLException { }); } + @Test + @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) + public void testReturnAsArrayOfString() throws SQLException { + withFirstRow( + "SELECT ARRAY_CONSTRUCT('one', 'two','three')::ARRAY(VARCHAR)", + (resultSet) -> { + String[] resultArray = + resultSet.unwrap(SnowflakeBaseResultSet.class).getArray(1, String.class); + assertEquals("one", resultArray[0]); + assertEquals("two", resultArray[1]); + assertEquals("three", resultArray[2]); + }); + } + + @Test + @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) + public void testReturnAsListOfIntegers() throws SQLException { + withFirstRow( + "SELECT ARRAY_CONSTRUCT(1,2,3)::ARRAY(INTEGER)", + (resultSet) -> { + List resultList = + resultSet.unwrap(SnowflakeBaseResultSet.class).getList(1, Integer.class); + assertEquals(Integer.valueOf(1), resultList.get(0)); + assertEquals(Integer.valueOf(2), resultList.get(1)); + assertEquals(Integer.valueOf(3), resultList.get(2)); + }); + } + @Test @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) public void testReturnAsMap() throws SQLException { @@ -220,6 +248,33 @@ public void testReturnAsMap() throws SQLException { }); } + @Test + @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) + public void testReturnAsMapOfLong() throws SQLException { + withFirstRow( + "SELECT {'x':1, 'y':2, 'z':3}::MAP(VARCHAR, BIGINT)", + (resultSet) -> { + Map map = + resultSet.unwrap(SnowflakeBaseResultSet.class).getMap(1, Long.class); + assertEquals(Long.valueOf(1), map.get("x")); + assertEquals(Long.valueOf(2), map.get("y")); + assertEquals(Long.valueOf(3), map.get("z")); + }); + } + + @Test + @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) + public void testReturnAsMapOfBoolean() throws SQLException { + withFirstRow( + "SELECT {'x':'true', 'y':0}::MAP(VARCHAR, BOOLEAN)", + (resultSet) -> { + Map map = + resultSet.unwrap(SnowflakeBaseResultSet.class).getMap(1, Boolean.class); + assertEquals(Boolean.TRUE, map.get("x")); + assertEquals(Boolean.FALSE, map.get("y")); + }); + } + @Test @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) public void testReturnAsList() throws SQLException { From 978e14a16beb8e09070ab3fc856a97f6a0ab80a7 Mon Sep 17 00:00:00 2001 From: Przemyslaw Motacki Date: Thu, 21 Mar 2024 10:35:51 +0100 Subject: [PATCH 02/11] SNOW-1259709 - add mapping for basic types for arrays and maps --- .../java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java | 3 ++- src/test/java/net/snowflake/client/AbstractDriverIT.java | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index c3c2b7cfc..76c41ac53 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -1522,7 +1522,8 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { arr[counter++] = (T) getBigDecimal(columnIndex); } else { logger.debug( - "Unsupported type passed to getList(int columnIndex,Class type): " + type.getName()); + "Unsupported type passed to getArray(int columnIndex, Class type): " + + type.getName()); throw new SQLException( "Type passed to 'getObject(int columnIndex,Class type)' is unsupported. Type: " + type.getName()); diff --git a/src/test/java/net/snowflake/client/AbstractDriverIT.java b/src/test/java/net/snowflake/client/AbstractDriverIT.java index d918b829c..b44cc31ef 100644 --- a/src/test/java/net/snowflake/client/AbstractDriverIT.java +++ b/src/test/java/net/snowflake/client/AbstractDriverIT.java @@ -317,9 +317,6 @@ public static Connection getConnection( properties.put("role", params.get("role")); properties.put("account", params.get("account")); } - properties.put("useProxy", "true"); - properties.put("proxyHost", "localhost"); - properties.put("proxyPort", "8080"); properties.put("db", params.get("database")); properties.put("schema", params.get("schema")); properties.put("warehouse", params.get("warehouse")); From 9169852d2f272a2709f0134d750c67d8e34bce0e Mon Sep 17 00:00:00 2001 From: Przemyslaw Motacki Date: Thu, 21 Mar 2024 15:29:16 +0100 Subject: [PATCH 03/11] SNOW-1259709 - add mapping for basic types for arrays and maps --- .../snowflake/client/core/JsonSqlInput.java | 24 ++++---- .../client/jdbc/SnowflakeBaseResultSet.java | 56 ++++++++++--------- .../snowflake/client/jdbc/SnowflakeUtil.java | 2 +- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/main/java/net/snowflake/client/core/JsonSqlInput.java b/src/main/java/net/snowflake/client/core/JsonSqlInput.java index f6a1d35e9..d554e8fc9 100644 --- a/src/main/java/net/snowflake/client/core/JsonSqlInput.java +++ b/src/main/java/net/snowflake/client/core/JsonSqlInput.java @@ -3,7 +3,7 @@ */ package net.snowflake.client.core; -import static net.snowflake.client.jdbc.SnowflakeUtil.mapExceptions; +import static net.snowflake.client.jdbc.SnowflakeUtil.mapThrowingCallableExceptions; import com.fasterxml.jackson.databind.JsonNode; import java.math.BigDecimal; @@ -56,7 +56,7 @@ public String readString() throws SQLException { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); int columnSubType = fieldMetadata.getType(); int scale = fieldMetadata.getScale(); - return mapExceptions( + return mapThrowingCallableExceptions( () -> converters .getStringConverter() @@ -69,7 +69,7 @@ public boolean readBoolean() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions( + return mapThrowingCallableExceptions( () -> converters.getBooleanConverter().getBoolean(value, columnType)); }); } @@ -78,7 +78,7 @@ public boolean readBoolean() throws SQLException { public byte readByte() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> - mapExceptions(() -> converters.getNumberConverter().getByte(value))); + mapThrowingCallableExceptions(() -> converters.getNumberConverter().getByte(value))); } @Override @@ -86,7 +86,7 @@ public short readShort() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getShort(value, columnType)); + return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getShort(value, columnType)); }); } @@ -95,7 +95,7 @@ public int readInt() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getInt(value, columnType)); + return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getInt(value, columnType)); }); } @@ -104,7 +104,7 @@ public long readLong() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getLong(value, columnType)); + return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getLong(value, columnType)); }); } @@ -113,7 +113,7 @@ public float readFloat() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getFloat(value, columnType)); + return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getFloat(value, columnType)); }); } @@ -122,7 +122,7 @@ public double readDouble() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getDouble(value, columnType)); + return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getDouble(value, columnType)); }); } @@ -131,7 +131,7 @@ public BigDecimal readBigDecimal() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions( + return mapThrowingCallableExceptions( () -> converters.getNumberConverter().getBigDecimal(value, columnType)); }); } @@ -143,7 +143,7 @@ public byte[] readBytes() throws SQLException { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); int columnSubType = fieldMetadata.getType(); int scale = fieldMetadata.getScale(); - return mapExceptions( + return mapThrowingCallableExceptions( () -> converters.getBytesConverter().getBytes(value, columnType, columnSubType, scale)); }); @@ -192,7 +192,7 @@ public Timestamp readTimestamp(TimeZone tz) throws SQLException { if (result != null) { return result; } - return mapExceptions( + return mapThrowingCallableExceptions( () -> converters .getDateTimeConverter() diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index 76c41ac53..f1eb18d12 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -4,7 +4,7 @@ package net.snowflake.client.jdbc; -import static net.snowflake.client.jdbc.SnowflakeUtil.mapExceptions; +import static net.snowflake.client.jdbc.SnowflakeUtil.mapThrowingCallableExceptions; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; @@ -37,6 +37,8 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; + +import net.snowflake.client.core.ColumnTypeHelper; import net.snowflake.client.core.JsonSqlInput; import net.snowflake.client.core.ObjectMapperFactory; import net.snowflake.client.core.SFBaseResultSet; @@ -1395,8 +1397,8 @@ public List getList(int columnIndex, Class type) throws SQLException { } public T[] getArray(int columnIndex, Class type) throws SQLException { - int columnType = resultSetMetaData.getInternalColumnType(columnIndex); int columnSubType = resultSetMetaData.getInternalColumnType(columnIndex); + int columnType = ColumnTypeHelper.getColumnType(columnSubType, session);; int scale = resultSetMetaData.getScale(columnIndex); TimeZone tz = TimeZone.getDefault(); Object[] objects = (Object[]) getArray(columnIndex).getArray(); @@ -1417,7 +1419,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { arr[counter++] = (T) instance; } else if (String.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1426,7 +1428,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getString(value, columnType, columnSubType, scale)); } else if (Boolean.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1435,7 +1437,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getBoolean(value, columnType)); } else if (Byte.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1444,7 +1446,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getBytes(value, columnType, columnSubType, scale)); } else if (Short.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) Short.valueOf( @@ -1454,7 +1456,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getShort(value, columnType))); } else if (Integer.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) Integer.valueOf( @@ -1464,7 +1466,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getInt(value, columnType))); } else if (Long.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) Long.valueOf( @@ -1474,7 +1476,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getLong(value, columnType))); } else if (Float.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) Float.valueOf( @@ -1484,7 +1486,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getFloat(value, columnType))); } else if (Double.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) Double.valueOf( @@ -1494,7 +1496,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getDouble(value, columnType))); } else if (Date.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1503,7 +1505,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getDate(value, columnType, columnSubType, tz, scale)); } else if (Time.class.isAssignableFrom(type)) { arr[counter++] = - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1511,7 +1513,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getDateTimeConverter() .getTime(value, columnType, columnSubType, tz, scale)); } else if (Timestamp.class.isAssignableFrom(type)) { - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1521,7 +1523,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { } else if (BigDecimal.class.isAssignableFrom(type)) { arr[counter++] = (T) getBigDecimal(columnIndex); } else { - logger.debug( + logger.warn( "Unsupported type passed to getArray(int columnIndex, Class type): " + type.getName()); throw new SQLException( @@ -1536,7 +1538,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep int columnType = resultSetMetaData.getInternalColumnType(columnIndex); int columnSubType = resultSetMetaData.getInternalColumnType(columnIndex); int scale = resultSetMetaData.getScale(columnIndex); - TimeZone tz = TimeZone.getDefault(); + TimeZone tz = session.getTim Object object = getObject(columnIndex); JsonNode jsonNode = ((JsonSqlInput) object).getInput(); Map map = @@ -1570,7 +1572,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (String.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1580,7 +1582,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Boolean.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1590,7 +1592,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Byte.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1600,7 +1602,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Short.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) (Short) @@ -1611,7 +1613,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Integer.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) (Integer) @@ -1622,7 +1624,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Long.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) (Long) @@ -1633,7 +1635,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Float.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) (Float) @@ -1644,7 +1646,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Double.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) (Double) @@ -1655,7 +1657,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (BigDecimal.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1665,7 +1667,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Date.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1675,7 +1677,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Time.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet @@ -1685,7 +1687,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Timestamp.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapExceptions( + mapThrowingCallableExceptions( () -> (T) sfBaseResultSet diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java index c0b551fa2..40989d27d 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java @@ -793,7 +793,7 @@ public static boolean convertSystemPropertyToBooleanValue( } @SnowflakeJdbcInternalApi - public static T mapExceptions(ThrowingCallable action) throws SQLException { + public static T mapThrowingCallableExceptions(ThrowingCallable action) throws SQLException { try { return action.call(); } catch (SFException e) { From 1369a8845a1ef9b1017acf06cdb742ecf57d1532 Mon Sep 17 00:00:00 2001 From: Przemyslaw Motacki Date: Fri, 22 Mar 2024 10:48:20 +0100 Subject: [PATCH 04/11] SNOW-1259709 - add mapping for basic types for arrays and maps --- .../net/snowflake/client/core/JsonSqlInput.java | 15 ++++++++++----- .../snowflake/client/core/SFBaseResultSet.java | 4 ++++ .../client/jdbc/SnowflakeBaseResultSet.java | 4 ++-- .../net/snowflake/client/jdbc/SnowflakeUtil.java | 3 ++- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/snowflake/client/core/JsonSqlInput.java b/src/main/java/net/snowflake/client/core/JsonSqlInput.java index d554e8fc9..d1d3deec4 100644 --- a/src/main/java/net/snowflake/client/core/JsonSqlInput.java +++ b/src/main/java/net/snowflake/client/core/JsonSqlInput.java @@ -86,7 +86,8 @@ public short readShort() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getShort(value, columnType)); + return mapThrowingCallableExceptions( + () -> converters.getNumberConverter().getShort(value, columnType)); }); } @@ -95,7 +96,8 @@ public int readInt() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getInt(value, columnType)); + return mapThrowingCallableExceptions( + () -> converters.getNumberConverter().getInt(value, columnType)); }); } @@ -104,7 +106,8 @@ public long readLong() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getLong(value, columnType)); + return mapThrowingCallableExceptions( + () -> converters.getNumberConverter().getLong(value, columnType)); }); } @@ -113,7 +116,8 @@ public float readFloat() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getFloat(value, columnType)); + return mapThrowingCallableExceptions( + () -> converters.getNumberConverter().getFloat(value, columnType)); }); } @@ -122,7 +126,8 @@ public double readDouble() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions(() -> converters.getNumberConverter().getDouble(value, columnType)); + return mapThrowingCallableExceptions( + () -> converters.getNumberConverter().getDouble(value, columnType)); }); } diff --git a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java index f81c5338b..049950e24 100644 --- a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java @@ -208,4 +208,8 @@ public Converters getConverters() { logger.debug("Json converters weren't created"); return null; } + @SnowflakeJdbcInternalApi + public TimeZone getSessionTimeZone() { + return resultSetSerializable.getTimeZone(); + } } diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index f1eb18d12..bc9b2b202 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -1400,7 +1400,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { int columnSubType = resultSetMetaData.getInternalColumnType(columnIndex); int columnType = ColumnTypeHelper.getColumnType(columnSubType, session);; int scale = resultSetMetaData.getScale(columnIndex); - TimeZone tz = TimeZone.getDefault(); + TimeZone tz = sfBaseResultSet.getSessionTimeZone(); Object[] objects = (Object[]) getArray(columnIndex).getArray(); T[] arr = (T[]) java.lang.reflect.Array.newInstance(type, objects.length); int counter = 0; @@ -1538,7 +1538,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep int columnType = resultSetMetaData.getInternalColumnType(columnIndex); int columnSubType = resultSetMetaData.getInternalColumnType(columnIndex); int scale = resultSetMetaData.getScale(columnIndex); - TimeZone tz = session.getTim + TimeZone tz = sfBaseResultSet.getSessionTimeZone(); Object object = getObject(columnIndex); JsonNode jsonNode = ((JsonSqlInput) object).getInput(); Map map = diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java index 40989d27d..5365feaba 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java @@ -793,7 +793,8 @@ public static boolean convertSystemPropertyToBooleanValue( } @SnowflakeJdbcInternalApi - public static T mapThrowingCallableExceptions(ThrowingCallable action) throws SQLException { + public static T mapThrowingCallableExceptions(ThrowingCallable action) + throws SQLException { try { return action.call(); } catch (SFException e) { From f531d93dcc451f91f18ae81c1a17cb147799d153 Mon Sep 17 00:00:00 2001 From: Przemyslaw Motacki Date: Fri, 22 Mar 2024 10:49:26 +0100 Subject: [PATCH 05/11] SNOW-1259709 - add mapping for basic types for arrays and maps --- src/main/java/net/snowflake/client/core/SFBaseResultSet.java | 1 + .../net/snowflake/client/jdbc/SnowflakeBaseResultSet.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java index 049950e24..97509d2a7 100644 --- a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java @@ -208,6 +208,7 @@ public Converters getConverters() { logger.debug("Json converters weren't created"); return null; } + @SnowflakeJdbcInternalApi public TimeZone getSessionTimeZone() { return resultSetSerializable.getTimeZone(); diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index bc9b2b202..59ab72558 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -37,7 +37,6 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; - import net.snowflake.client.core.ColumnTypeHelper; import net.snowflake.client.core.JsonSqlInput; import net.snowflake.client.core.ObjectMapperFactory; @@ -1398,7 +1397,8 @@ public List getList(int columnIndex, Class type) throws SQLException { public T[] getArray(int columnIndex, Class type) throws SQLException { int columnSubType = resultSetMetaData.getInternalColumnType(columnIndex); - int columnType = ColumnTypeHelper.getColumnType(columnSubType, session);; + int columnType = ColumnTypeHelper.getColumnType(columnSubType, session); + ; int scale = resultSetMetaData.getScale(columnIndex); TimeZone tz = sfBaseResultSet.getSessionTimeZone(); Object[] objects = (Object[]) getArray(columnIndex).getArray(); From c91f0b131d7db78b1d5d21e75a9860a3a3d89b78 Mon Sep 17 00:00:00 2001 From: Przemyslaw Motacki Date: Fri, 22 Mar 2024 12:33:36 +0100 Subject: [PATCH 06/11] SNOW-1259709 - add mapping for basic types for arrays and maps --- .../snowflake/client/core/JsonSqlInput.java | 24 +++++----- .../client/jdbc/SnowflakeBaseResultSet.java | 48 +++++++++---------- .../snowflake/client/jdbc/SnowflakeUtil.java | 2 +- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/main/java/net/snowflake/client/core/JsonSqlInput.java b/src/main/java/net/snowflake/client/core/JsonSqlInput.java index d1d3deec4..bf210db02 100644 --- a/src/main/java/net/snowflake/client/core/JsonSqlInput.java +++ b/src/main/java/net/snowflake/client/core/JsonSqlInput.java @@ -3,7 +3,7 @@ */ package net.snowflake.client.core; -import static net.snowflake.client.jdbc.SnowflakeUtil.mapThrowingCallableExceptions; +import static net.snowflake.client.jdbc.SnowflakeUtil.mapSFExceptionToSQLException; import com.fasterxml.jackson.databind.JsonNode; import java.math.BigDecimal; @@ -56,7 +56,7 @@ public String readString() throws SQLException { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); int columnSubType = fieldMetadata.getType(); int scale = fieldMetadata.getScale(); - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters .getStringConverter() @@ -69,7 +69,7 @@ public boolean readBoolean() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters.getBooleanConverter().getBoolean(value, columnType)); }); } @@ -78,7 +78,7 @@ public boolean readBoolean() throws SQLException { public byte readByte() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> - mapThrowingCallableExceptions(() -> converters.getNumberConverter().getByte(value))); + mapSFExceptionToSQLException(() -> converters.getNumberConverter().getByte(value))); } @Override @@ -86,7 +86,7 @@ public short readShort() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters.getNumberConverter().getShort(value, columnType)); }); } @@ -96,7 +96,7 @@ public int readInt() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters.getNumberConverter().getInt(value, columnType)); }); } @@ -106,7 +106,7 @@ public long readLong() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters.getNumberConverter().getLong(value, columnType)); }); } @@ -116,7 +116,7 @@ public float readFloat() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters.getNumberConverter().getFloat(value, columnType)); }); } @@ -126,7 +126,7 @@ public double readDouble() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters.getNumberConverter().getDouble(value, columnType)); }); } @@ -136,7 +136,7 @@ public BigDecimal readBigDecimal() throws SQLException { return withNextValue( (value, jsonNode, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters.getNumberConverter().getBigDecimal(value, columnType)); }); } @@ -148,7 +148,7 @@ public byte[] readBytes() throws SQLException { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); int columnSubType = fieldMetadata.getType(); int scale = fieldMetadata.getScale(); - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters.getBytesConverter().getBytes(value, columnType, columnSubType, scale)); }); @@ -197,7 +197,7 @@ public Timestamp readTimestamp(TimeZone tz) throws SQLException { if (result != null) { return result; } - return mapThrowingCallableExceptions( + return mapSFExceptionToSQLException( () -> converters .getDateTimeConverter() diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index 59ab72558..d3e67d49f 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -4,7 +4,7 @@ package net.snowflake.client.jdbc; -import static net.snowflake.client.jdbc.SnowflakeUtil.mapThrowingCallableExceptions; +import static net.snowflake.client.jdbc.SnowflakeUtil.mapSFExceptionToSQLException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; @@ -1419,7 +1419,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { arr[counter++] = (T) instance; } else if (String.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1428,7 +1428,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getString(value, columnType, columnSubType, scale)); } else if (Boolean.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1437,7 +1437,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getBoolean(value, columnType)); } else if (Byte.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1446,7 +1446,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getBytes(value, columnType, columnSubType, scale)); } else if (Short.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) Short.valueOf( @@ -1456,7 +1456,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getShort(value, columnType))); } else if (Integer.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) Integer.valueOf( @@ -1466,7 +1466,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getInt(value, columnType))); } else if (Long.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) Long.valueOf( @@ -1476,7 +1476,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getLong(value, columnType))); } else if (Float.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) Float.valueOf( @@ -1486,7 +1486,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getFloat(value, columnType))); } else if (Double.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) Double.valueOf( @@ -1496,7 +1496,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getDouble(value, columnType))); } else if (Date.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1505,7 +1505,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getDate(value, columnType, columnSubType, tz, scale)); } else if (Time.class.isAssignableFrom(type)) { arr[counter++] = - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1513,7 +1513,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { .getDateTimeConverter() .getTime(value, columnType, columnSubType, tz, scale)); } else if (Timestamp.class.isAssignableFrom(type)) { - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1572,7 +1572,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (String.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1582,7 +1582,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Boolean.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1592,7 +1592,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Byte.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1602,7 +1602,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Short.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) (Short) @@ -1613,7 +1613,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Integer.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) (Integer) @@ -1624,7 +1624,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Long.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) (Long) @@ -1635,7 +1635,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Float.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) (Float) @@ -1646,7 +1646,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Double.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) (Double) @@ -1657,7 +1657,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (BigDecimal.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1667,7 +1667,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Date.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1677,7 +1677,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Time.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet @@ -1687,7 +1687,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Timestamp.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapThrowingCallableExceptions( + mapSFExceptionToSQLException( () -> (T) sfBaseResultSet diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java index 5365feaba..e3e58fa30 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java @@ -793,7 +793,7 @@ public static boolean convertSystemPropertyToBooleanValue( } @SnowflakeJdbcInternalApi - public static T mapThrowingCallableExceptions(ThrowingCallable action) + public static T mapSFExceptionToSQLException(ThrowingCallable action) throws SQLException { try { return action.call(); From baf98e992aaba9dfc72e960395bb2dedcc7661b4 Mon Sep 17 00:00:00 2001 From: Przemyslaw Motacki Date: Mon, 25 Mar 2024 10:51:24 +0100 Subject: [PATCH 07/11] SNOW-1259709 - add mapping for basic types for arrays and maps --- .../snowflake/client/core/ArrowSqlInput.java | 30 +++++++++---------- .../client/jdbc/SnowflakeBaseResultSet.java | 15 +--------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/main/java/net/snowflake/client/core/ArrowSqlInput.java b/src/main/java/net/snowflake/client/core/ArrowSqlInput.java index c63291f34..e25dbe360 100644 --- a/src/main/java/net/snowflake/client/core/ArrowSqlInput.java +++ b/src/main/java/net/snowflake/client/core/ArrowSqlInput.java @@ -4,8 +4,6 @@ package net.snowflake.client.core; -import static net.snowflake.client.jdbc.SnowflakeUtil.mapExceptions; - import java.math.BigDecimal; import java.sql.Date; import java.sql.SQLData; @@ -21,6 +19,8 @@ import net.snowflake.client.util.ThrowingBiFunction; import org.apache.arrow.vector.util.JsonStringHashMap; +import static net.snowflake.client.jdbc.SnowflakeUtil.mapSFExceptionToSQLException; + @SnowflakeJdbcInternalApi public class ArrowSqlInput extends BaseSqlInput { @@ -43,7 +43,7 @@ public String readString() throws SQLException { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); int columnSubType = fieldMetadata.getType(); int scale = fieldMetadata.getScale(); - return mapExceptions( + return mapSFExceptionToSQLException( () -> converters .getStringConverter() @@ -56,7 +56,7 @@ public boolean readBoolean() throws SQLException { return withNextValue( (value, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions( + return mapSFExceptionToSQLException( () -> converters.getBooleanConverter().getBoolean(value, columnType)); }); } @@ -65,7 +65,7 @@ public boolean readBoolean() throws SQLException { public byte readByte() throws SQLException { return withNextValue( (value, fieldMetadata) -> - mapExceptions(() -> converters.getNumberConverter().getByte(value))); + mapSFExceptionToSQLException(() -> converters.getNumberConverter().getByte(value))); } @Override @@ -73,7 +73,7 @@ public short readShort() throws SQLException { return withNextValue( (value, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getShort(value, columnType)); + return mapSFExceptionToSQLException(() -> converters.getNumberConverter().getShort(value, columnType)); }); } @@ -82,7 +82,7 @@ public int readInt() throws SQLException { return withNextValue( (value, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getInt(value, columnType)); + return mapSFExceptionToSQLException(() -> converters.getNumberConverter().getInt(value, columnType)); }); } @@ -91,7 +91,7 @@ public long readLong() throws SQLException { return withNextValue( (value, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getLong(value, columnType)); + return mapSFExceptionToSQLException(() -> converters.getNumberConverter().getLong(value, columnType)); }); } @@ -100,7 +100,7 @@ public float readFloat() throws SQLException { return withNextValue( (value, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getFloat(value, columnType)); + return mapSFExceptionToSQLException(() -> converters.getNumberConverter().getFloat(value, columnType)); }); } @@ -109,7 +109,7 @@ public double readDouble() throws SQLException { return withNextValue( (value, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions(() -> converters.getNumberConverter().getDouble(value, columnType)); + return mapSFExceptionToSQLException(() -> converters.getNumberConverter().getDouble(value, columnType)); }); } @@ -118,7 +118,7 @@ public BigDecimal readBigDecimal() throws SQLException { return withNextValue( (value, fieldMetadata) -> { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); - return mapExceptions( + return mapSFExceptionToSQLException( () -> converters.getNumberConverter().getBigDecimal(value, columnType)); }); } @@ -130,7 +130,7 @@ public byte[] readBytes() throws SQLException { int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); int columnSubType = fieldMetadata.getType(); int scale = fieldMetadata.getScale(); - return mapExceptions( + return mapSFExceptionToSQLException( () -> converters.getBytesConverter().getBytes(value, columnType, columnSubType, scale)); }); @@ -140,7 +140,7 @@ public byte[] readBytes() throws SQLException { public Date readDate() throws SQLException { return withNextValue( (value, fieldMetadata) -> - mapExceptions( + mapSFExceptionToSQLException( () -> converters .getStructuredTypeDateTimeConverter() @@ -151,7 +151,7 @@ public Date readDate() throws SQLException { public Time readTime() throws SQLException { return withNextValue( (value, fieldMetadata) -> - mapExceptions( + mapSFExceptionToSQLException( () -> { int scale = fieldMetadata.getScale(); return converters @@ -168,7 +168,7 @@ public Timestamp readTimestamp(TimeZone tz) throws SQLException { return null; } int scale = fieldMetadata.getScale(); - return mapExceptions( + return mapSFExceptionToSQLException( () -> converters .getStructuredTypeDateTimeConverter() diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index d3e67d49f..1a4a1c82e 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -1406,7 +1406,7 @@ public T[] getArray(int columnIndex, Class type) throws SQLException { int counter = 0; for (Object value : objects) { if (SQLData.class.isAssignableFrom(type)) { - Map[] data = (Map[]) value; + Map data = (Map) value; SQLData instance = (SQLData) SQLDataCreationHelper.create(type); SQLInput sqlInput = new JsonSqlInput( @@ -1544,23 +1544,10 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep Map map = OBJECT_MAPPER.convertValue(jsonNode, new TypeReference>() {}); Map resultMap = new HashMap<>(); - for (Map.Entry entry : map.entrySet()) { - SQLData instance = (SQLData) SQLDataCreationHelper.create(type); - SQLInput sqlInput = - new JsonSqlInput( - jsonNode.get(entry.getKey()), - session, - sfBaseResultSet.getConverters(), - sfBaseResultSet.getMetaData().getColumnMetadata().get(columnIndex - 1).getFields(), - sfBaseResultSet.getSessionTimezone()); - instance.readSQL(sqlInput, null); - resultMap.put(entry.getKey(), (T) instance); - if (SQLData.class.isAssignableFrom(type)) { SQLData instance = (SQLData) SQLDataCreationHelper.create(type); SQLInput sqlInput = - new JsonSqlInput( new JsonSqlInput( jsonNode.get(entry.getKey()), session, From 73c0f0578031f9d83ea27bfd09b732082aa5844a Mon Sep 17 00:00:00 2001 From: Dawid Heyman Date: Wed, 27 Mar 2024 16:16:50 +0100 Subject: [PATCH 08/11] SNOW-1234214 Add support for maps in native arrow structured types --- .../snowflake/client/core/ArrowSqlInput.java | 12 +- .../client/core/SFArrowResultSet.java | 14 ++- .../client/core/arrow/MapConverter.java | 31 +++++ .../StructuredTypeDateTimeConverter.java | 17 +-- .../core/structs/StructureTypeHelper.java | 3 +- .../client/jdbc/ArrowResultChunk.java | 31 +---- .../client/jdbc/SnowflakeBaseResultSet.java | 113 ++++++++++++------ .../snowflake/client/AbstractDriverIT.java | 5 +- .../ResultSetStructuredTypesLatestIT.java | 25 +++- 9 files changed, 170 insertions(+), 81 deletions(-) create mode 100644 src/main/java/net/snowflake/client/core/arrow/MapConverter.java diff --git a/src/main/java/net/snowflake/client/core/ArrowSqlInput.java b/src/main/java/net/snowflake/client/core/ArrowSqlInput.java index e25dbe360..b84be490c 100644 --- a/src/main/java/net/snowflake/client/core/ArrowSqlInput.java +++ b/src/main/java/net/snowflake/client/core/ArrowSqlInput.java @@ -12,6 +12,7 @@ import java.sql.Timestamp; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.TimeZone; import net.snowflake.client.core.json.Converters; import net.snowflake.client.core.structs.SQLDataCreationHelper; @@ -24,6 +25,7 @@ @SnowflakeJdbcInternalApi public class ArrowSqlInput extends BaseSqlInput { + private final JsonStringHashMap input; private final Iterator structuredTypeFields; private int currentIndex = 0; @@ -34,6 +36,11 @@ public ArrowSqlInput( List fields) { super(session, converters, fields); this.structuredTypeFields = input.values().iterator(); + this.input = input; + } + + public Map getInput() { + return input; } @Override @@ -167,6 +174,8 @@ public Timestamp readTimestamp(TimeZone tz) throws SQLException { if (value == null) { return null; } + int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session); + int columnSubType = fieldMetadata.getType(); int scale = fieldMetadata.getScale(); return mapSFExceptionToSQLException( () -> @@ -174,7 +183,8 @@ public Timestamp readTimestamp(TimeZone tz) throws SQLException { .getStructuredTypeDateTimeConverter() .getTimestamp( (JsonStringHashMap) value, - fieldMetadata.getBase(), + columnType, + columnSubType, tz, scale)); }); diff --git a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java index daf60b804..22f0609ca 100644 --- a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java @@ -104,7 +104,7 @@ public class SFArrowResultSet extends SFBaseResultSet implements DataConversionC */ private boolean formatDateWithTimezone; - @SnowflakeJdbcInternalApi protected Converters jsonConverters; + @SnowflakeJdbcInternalApi protected Converters converters; /** * Constructor takes a result from the API response that we get from executing a SQL statement. @@ -124,7 +124,7 @@ public SFArrowResultSet( boolean sortResult) throws SQLException { this(resultSetSerializable, session.getTelemetryClient(), sortResult); - this.jsonConverters = + this.converters = new Converters( resultSetSerializable.getTimeZone(), session, @@ -356,6 +356,12 @@ private boolean fetchNextRowSorted() throws SnowflakeSQLException { } } + @Override + @SnowflakeJdbcInternalApi + public Converters getConverters() { + return converters; + } + /** * Advance to next row * @@ -522,7 +528,7 @@ private Object createJsonSqlInput(int columnIndex, Object obj) throws SFExceptio return new JsonSqlInput( jsonNode, session, - jsonConverters, + converters, resultSetMetaData.getColumnMetadata().get(columnIndex - 1).getFields(), sessionTimezone); } catch (JsonProcessingException e) { @@ -534,7 +540,7 @@ private Object createArrowSqlInput(int columnIndex, JsonStringHashMap> entriesList = (List>) vector.getObject(index); + return entriesList.stream().collect(Collectors.toMap(entry-> entry.get("key").toString(), entry -> entry.get("value"))); + } + + @Override + public String toString(int index) throws SFException { + return vector.getObject(index).toString(); + } +} diff --git a/src/main/java/net/snowflake/client/core/arrow/StructuredTypeDateTimeConverter.java b/src/main/java/net/snowflake/client/core/arrow/StructuredTypeDateTimeConverter.java index cd30c4bf5..5f32e76a0 100644 --- a/src/main/java/net/snowflake/client/core/arrow/StructuredTypeDateTimeConverter.java +++ b/src/main/java/net/snowflake/client/core/arrow/StructuredTypeDateTimeConverter.java @@ -11,11 +11,13 @@ import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; +import java.sql.Types; import java.util.TimeZone; import net.snowflake.client.core.SFException; import net.snowflake.client.core.SnowflakeJdbcInternalApi; import net.snowflake.client.jdbc.ErrorCode; import net.snowflake.client.jdbc.SnowflakeType; +import net.snowflake.client.jdbc.SnowflakeUtil; import org.apache.arrow.vector.util.JsonStringHashMap; @SnowflakeJdbcInternalApi @@ -45,22 +47,23 @@ public StructuredTypeDateTimeConverter( } public Timestamp getTimestamp( - JsonStringHashMap obj, SnowflakeType type, TimeZone tz, int scale) + JsonStringHashMap obj, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { if (tz == null) { tz = TimeZone.getDefault(); } - switch (type) { - case TIMESTAMP_LTZ: + if ( Types.TIMESTAMP == columnType) { + if (SnowflakeUtil.EXTRA_TYPES_TIMESTAMP_LTZ == columnSubType) { return convertTimestampLtz(obj, scale); - case TIMESTAMP_NTZ: + } else { return convertTimestampNtz(obj, tz, scale); - case TIMESTAMP_TZ: - return convertTimestampTz(obj, scale); + } + } else if (Types.TIMESTAMP_WITH_TIMEZONE == columnType && SnowflakeUtil.EXTRA_TYPES_TIMESTAMP_TZ == columnSubType) { + return convertTimestampTz(obj, scale); } throw new SFException( ErrorCode.INVALID_VALUE_CONVERT, - "Unexpected Arrow Field for " + type.name() + " and object type " + obj.getClass()); + "Unexpected Arrow Field for columnType " + columnType + " , column subtype " + columnSubType + " , and object type " + obj.getClass()); } public Date getDate(int value, TimeZone tz) throws SFException { diff --git a/src/main/java/net/snowflake/client/core/structs/StructureTypeHelper.java b/src/main/java/net/snowflake/client/core/structs/StructureTypeHelper.java index 46e8bb2e8..1f44779dd 100644 --- a/src/main/java/net/snowflake/client/core/structs/StructureTypeHelper.java +++ b/src/main/java/net/snowflake/client/core/structs/StructureTypeHelper.java @@ -5,8 +5,7 @@ @SnowflakeJdbcInternalApi public class StructureTypeHelper { private static final String STRUCTURED_TYPE_ENABLED_PROPERTY_NAME = "STRUCTURED_TYPE_ENABLED"; - private static boolean structuredTypeEnabled = - Boolean.valueOf(System.getProperty(STRUCTURED_TYPE_ENABLED_PROPERTY_NAME)); + private static boolean structuredTypeEnabled = true; public static boolean isStructureTypeEnabled() { return structuredTypeEnabled; diff --git a/src/main/java/net/snowflake/client/jdbc/ArrowResultChunk.java b/src/main/java/net/snowflake/client/jdbc/ArrowResultChunk.java index c273a8817..2bed387f1 100644 --- a/src/main/java/net/snowflake/client/jdbc/ArrowResultChunk.java +++ b/src/main/java/net/snowflake/client/jdbc/ArrowResultChunk.java @@ -13,31 +13,7 @@ import net.snowflake.client.core.DataConversionContext; import net.snowflake.client.core.SFBaseSession; import net.snowflake.client.core.SFException; -import net.snowflake.client.core.arrow.ArrowResultChunkIndexSorter; -import net.snowflake.client.core.arrow.ArrowVectorConverter; -import net.snowflake.client.core.arrow.BigIntToFixedConverter; -import net.snowflake.client.core.arrow.BigIntToScaledFixedConverter; -import net.snowflake.client.core.arrow.BigIntToTimeConverter; -import net.snowflake.client.core.arrow.BigIntToTimestampLTZConverter; -import net.snowflake.client.core.arrow.BigIntToTimestampNTZConverter; -import net.snowflake.client.core.arrow.BitToBooleanConverter; -import net.snowflake.client.core.arrow.DateConverter; -import net.snowflake.client.core.arrow.DecimalToScaledFixedConverter; -import net.snowflake.client.core.arrow.DoubleToRealConverter; -import net.snowflake.client.core.arrow.IntToFixedConverter; -import net.snowflake.client.core.arrow.IntToScaledFixedConverter; -import net.snowflake.client.core.arrow.IntToTimeConverter; -import net.snowflake.client.core.arrow.SmallIntToFixedConverter; -import net.snowflake.client.core.arrow.SmallIntToScaledFixedConverter; -import net.snowflake.client.core.arrow.StructConverter; -import net.snowflake.client.core.arrow.ThreeFieldStructToTimestampTZConverter; -import net.snowflake.client.core.arrow.TinyIntToFixedConverter; -import net.snowflake.client.core.arrow.TinyIntToScaledFixedConverter; -import net.snowflake.client.core.arrow.TwoFieldStructToTimestampLTZConverter; -import net.snowflake.client.core.arrow.TwoFieldStructToTimestampNTZConverter; -import net.snowflake.client.core.arrow.TwoFieldStructToTimestampTZConverter; -import net.snowflake.client.core.arrow.VarBinaryToBinaryConverter; -import net.snowflake.client.core.arrow.VarCharConverter; +import net.snowflake.client.core.arrow.*; import net.snowflake.client.log.SFLogger; import net.snowflake.client.log.SFLoggerFactory; import net.snowflake.common.core.SqlState; @@ -55,6 +31,7 @@ import org.apache.arrow.vector.VarBinaryVector; import org.apache.arrow.vector.VarCharVector; import org.apache.arrow.vector.VectorSchemaRoot; +import org.apache.arrow.vector.complex.MapVector; import org.apache.arrow.vector.complex.StructVector; import org.apache.arrow.vector.ipc.ArrowStreamReader; import org.apache.arrow.vector.types.Types; @@ -206,6 +183,10 @@ private static List initConverters( converters.add(new VarCharConverter(vector, i, context)); break; + case MAP: + converters.add(new MapConverter((MapVector) vector, i, context)); + break; + case OBJECT: if (vector instanceof StructVector) { converters.add(new StructConverter((StructVector) vector, i, context)); diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index 1a4a1c82e..67aa870a9 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -37,15 +37,13 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; -import net.snowflake.client.core.ColumnTypeHelper; -import net.snowflake.client.core.JsonSqlInput; -import net.snowflake.client.core.ObjectMapperFactory; -import net.snowflake.client.core.SFBaseResultSet; -import net.snowflake.client.core.SFBaseSession; + +import net.snowflake.client.core.*; import net.snowflake.client.core.structs.SQLDataCreationHelper; import net.snowflake.client.log.SFLogger; import net.snowflake.client.log.SFLoggerFactory; import net.snowflake.common.core.SqlState; +import org.apache.arrow.vector.util.JsonStringHashMap; /** Base class for query result set and metadata result set */ public abstract class SnowflakeBaseResultSet implements ResultSet { @@ -1355,8 +1353,13 @@ public T getObject(int columnIndex, Class type) throws SQLException { instance.readSQL(sqlInput, null); return (T) instance; } else if (Map.class.isAssignableFrom(type)) { - JsonNode jsonNode = ((JsonSqlInput) getObject(columnIndex)).getInput(); - return (T) OBJECT_MAPPER.convertValue(jsonNode, new TypeReference>() {}); + Object object = getObject(columnIndex); + if (object instanceof JsonSqlInput) { + JsonNode jsonNode = ((JsonSqlInput) object).getInput(); + return (T) OBJECT_MAPPER.convertValue(jsonNode, new TypeReference>() {}); + } else { + return (T) ((ArrowSqlInput) object).getInput(); + } } else if (String.class.isAssignableFrom(type)) { return (T) getString(columnIndex); } else if (Boolean.class.isAssignableFrom(type)) { @@ -1540,20 +1543,31 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep int scale = resultSetMetaData.getScale(columnIndex); TimeZone tz = sfBaseResultSet.getSessionTimeZone(); Object object = getObject(columnIndex); - JsonNode jsonNode = ((JsonSqlInput) object).getInput(); - Map map = - OBJECT_MAPPER.convertValue(jsonNode, new TypeReference>() {}); + Map map; + if (object instanceof JsonSqlInput) { + JsonNode jsonNode = ((JsonSqlInput) object).getInput(); + map = OBJECT_MAPPER.convertValue(jsonNode, new TypeReference>() {}); + } else { + map = (Map) object; + } Map resultMap = new HashMap<>(); for (Map.Entry entry : map.entrySet()) { if (SQLData.class.isAssignableFrom(type)) { SQLData instance = (SQLData) SQLDataCreationHelper.create(type); - SQLInput sqlInput = - new JsonSqlInput( - jsonNode.get(entry.getKey()), - session, - sfBaseResultSet.getConverters(), - sfBaseResultSet.getMetaData().getColumnMetadata().get(columnIndex - 1).getFields(), - sfBaseResultSet.getSessionTimezone()); + SQLInput sqlInput; + if (object instanceof JsonSqlInput) { + sqlInput = new JsonSqlInput( + (((JsonSqlInput) object).getInput()).get(entry.getKey()), + session, + sfBaseResultSet.getConverters(), + sfBaseResultSet.getMetaData().getColumnMetadata().get(columnIndex - 1).getFields(), + sfBaseResultSet.getSessionTimezone()); + } else { + sqlInput = new ArrowSqlInput((JsonStringHashMap) entry.getValue(), + session, + sfBaseResultSet.getConverters(), + sfBaseResultSet.getMetaData().getColumnMetadata().get(columnIndex - 1).getFields()); + } instance.readSQL(sqlInput, null); resultMap.put(entry.getKey(), (T) instance); } else if (String.class.isAssignableFrom(type)) { @@ -1655,32 +1669,19 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep resultMap.put( entry.getKey(), mapSFExceptionToSQLException( - () -> - (T) - sfBaseResultSet - .getConverters() - .getDateTimeConverter() - .getDate(entry.getValue(), columnType, columnSubType, tz, scale))); + () -> (T) convertToDate(entry.getValue(), columnType, columnSubType, tz, scale))); } else if (Time.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), mapSFExceptionToSQLException( - () -> - (T) - sfBaseResultSet - .getConverters() - .getDateTimeConverter() - .getTime(entry.getValue(), columnType, columnSubType, tz, scale))); + () -> (T) convertToTime(entry.getValue(), columnType, columnSubType, tz, scale))); + } else if (Timestamp.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), mapSFExceptionToSQLException( - () -> - (T) - sfBaseResultSet - .getConverters() - .getDateTimeConverter() - .getTimestamp(entry.getValue(), columnType, columnSubType, tz, scale))); + () -> (T) convertToTimestamp(entry.getValue(), columnType, columnSubType, tz, scale))); + } else { logger.debug( "Unsupported type passed to getObject(int columnIndex,Class type): " @@ -1718,4 +1719,46 @@ public boolean isWrapperFor(Class iface) throws SQLException { return iface.isInstance(this); } + + private Date convertToDate(Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { + if (sfBaseResultSet instanceof SFArrowResultSet) { + return sfBaseResultSet + .getConverters() + .getStructuredTypeDateTimeConverter() + .getDate((int) object, tz); + } else { + return sfBaseResultSet + .getConverters() + .getDateTimeConverter() + .getDate(object, columnType, columnSubType, tz, scale); + } + } + + private Time convertToTime(Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { + if (sfBaseResultSet instanceof SFArrowResultSet) { + return sfBaseResultSet + .getConverters() + .getStructuredTypeDateTimeConverter() + .getTime((int) object, scale); + } else { + return sfBaseResultSet + .getConverters() + .getDateTimeConverter() + .getTime(object, columnType, columnSubType, tz, scale); + } + } + + private Timestamp convertToTimestamp(Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { + if (sfBaseResultSet instanceof SFArrowResultSet) { + return sfBaseResultSet + .getConverters() + .getStructuredTypeDateTimeConverter() + .getTimestamp((JsonStringHashMap) object, columnType, columnSubType, tz, scale); + } else { + return sfBaseResultSet + .getConverters() + .getDateTimeConverter() + .getTimestamp(object, columnType, columnSubType, tz, scale); + } + } } diff --git a/src/test/java/net/snowflake/client/AbstractDriverIT.java b/src/test/java/net/snowflake/client/AbstractDriverIT.java index b44cc31ef..e8354604b 100644 --- a/src/test/java/net/snowflake/client/AbstractDriverIT.java +++ b/src/test/java/net/snowflake/client/AbstractDriverIT.java @@ -321,9 +321,12 @@ public static Connection getConnection( properties.put("schema", params.get("schema")); properties.put("warehouse", params.get("warehouse")); properties.put("ssl", params.get("ssl")); + properties.put("proxyHost", "localhost"); + properties.put("proxyPort", "8080"); + properties.put("useProxy", "true"); properties.put("internal", Boolean.TRUE.toString()); // TODO: do we need this? - properties.put("insecureMode", false); // use OCSP for all tests. + properties.put("insecureMode", true); // use OCSP for all tests. if (injectSocketTimeout > 0) { properties.put("injectSocketTimeout", String.valueOf(injectSocketTimeout)); diff --git a/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java b/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java index 12df13135..40a967140 100644 --- a/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java +++ b/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java @@ -38,7 +38,7 @@ public class ResultSetStructuredTypesLatestIT extends BaseJDBCTest { private final ResultSetFormatType queryResultFormat; public ResultSetStructuredTypesLatestIT() { - this(ResultSetFormatType.JSON); + this(ResultSetFormatType.NATIVE_ARROW); } protected ResultSetStructuredTypesLatestIT(ResultSetFormatType queryResultFormat) { @@ -178,7 +178,6 @@ private void testMapAllTypes(boolean registerFactory) throws SQLException { @Test @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) public void testMapJsonToMap() throws SQLException { - Assume.assumeTrue(queryResultFormat != ResultSetFormatType.NATIVE_ARROW); withFirstRow( "SELECT OBJECT_CONSTRUCT('string','a','string2',1)", (resultSet) -> { @@ -207,7 +206,8 @@ public void testReturnAsArrayOfSqlData() throws SQLException { @Test @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) public void testReturnAsArrayOfString() throws SQLException { - withFirstRow( + Assume.assumeTrue(queryResultFormat != ResultSetFormatType.NATIVE_ARROW); + withFirstRow( "SELECT ARRAY_CONSTRUCT('one', 'two','three')::ARRAY(VARCHAR)", (resultSet) -> { String[] resultArray = @@ -221,7 +221,8 @@ public void testReturnAsArrayOfString() throws SQLException { @Test @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) public void testReturnAsListOfIntegers() throws SQLException { - withFirstRow( + Assume.assumeTrue(queryResultFormat != ResultSetFormatType.NATIVE_ARROW); + withFirstRow( "SELECT ARRAY_CONSTRUCT(1,2,3)::ARRAY(INTEGER)", (resultSet) -> { List resultList = @@ -235,7 +236,6 @@ public void testReturnAsListOfIntegers() throws SQLException { @Test @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) public void testReturnAsMap() throws SQLException { - Assume.assumeTrue(queryResultFormat != ResultSetFormatType.NATIVE_ARROW); SnowflakeObjectTypeFactories.register(SimpleClass.class, SimpleClass::new); withFirstRow( "select {'x':{'string':'one'},'y':{'string':'two'},'z':{'string':'three'}}::MAP(VARCHAR, OBJECT(string VARCHAR));", @@ -262,6 +262,20 @@ public void testReturnAsMapOfLong() throws SQLException { }); } + @Test + @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) + public void testReturnAsMapOfTimestampsNTz() throws SQLException { + withFirstRow( + "SELECT {'x': TO_TIMESTAMP_NTZ('2021-12-23 09:44:44'), 'y': TO_TIMESTAMP_NTZ('2021-12-24 09:55:55')}::MAP(VARCHAR, TIMESTAMP)", + (resultSet) -> { + Map map = resultSet.unwrap(SnowflakeBaseResultSet.class).getMap(1, Timestamp.class); + assertEquals( + Timestamp.valueOf(LocalDateTime.of(2021, 12, 23, 10, 44, 44)), map.get("x")); + assertEquals( + Timestamp.valueOf(LocalDateTime.of(2021, 12, 24, 10, 55, 55)), map.get("y")); + }); + } + @Test @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) public void testReturnAsMapOfBoolean() throws SQLException { @@ -294,7 +308,6 @@ public void testReturnAsList() throws SQLException { @Test @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class) public void testMapStructsFromChunks() throws SQLException { - Assume.assumeTrue(queryResultFormat != ResultSetFormatType.NATIVE_ARROW); withFirstRow( "select {'string':'a'}::OBJECT(string VARCHAR) FROM TABLE(GENERATOR(ROWCOUNT=>30000))", (resultSet) -> { From 2659cdef77b940d7d8ee6ed35e7e4551b2813881 Mon Sep 17 00:00:00 2001 From: Dawid Heyman Date: Thu, 28 Mar 2024 14:39:36 +0100 Subject: [PATCH 09/11] CR suggestions --- .../snowflake/client/core/ArrowSqlInput.java | 6 +-- .../client/core/SFArrowResultSet.java | 26 ++++++++- .../client/core/SFBaseResultSet.java | 21 ++++++-- .../client/core/SFJsonResultSet.java | 17 ++++++ .../client/jdbc/SnowflakeBaseResultSet.java | 53 +++---------------- 5 files changed, 67 insertions(+), 56 deletions(-) diff --git a/src/main/java/net/snowflake/client/core/ArrowSqlInput.java b/src/main/java/net/snowflake/client/core/ArrowSqlInput.java index 017823718..f73a6a0ec 100644 --- a/src/main/java/net/snowflake/client/core/ArrowSqlInput.java +++ b/src/main/java/net/snowflake/client/core/ArrowSqlInput.java @@ -25,12 +25,12 @@ @SnowflakeJdbcInternalApi public class ArrowSqlInput extends BaseSqlInput { - private final JsonStringHashMap input; + private final Map input; private final Iterator structuredTypeFields; private int currentIndex = 0; public ArrowSqlInput( - JsonStringHashMap input, + Map input, SFBaseSession session, Converters converters, List fields) { @@ -214,7 +214,7 @@ public T readObject(Class type) throws SQLException { SQLData instance = (SQLData) SQLDataCreationHelper.create(type); instance.readSQL( new ArrowSqlInput( - (JsonStringHashMap) value, + (Map) value, session, converters, fieldMetadata.getFields()), diff --git a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java index f98fdd8c2..355881144 100644 --- a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java @@ -19,6 +19,7 @@ import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; +import java.util.Map; import java.util.TimeZone; import net.snowflake.client.core.arrow.ArrowVectorConverter; import net.snowflake.client.core.arrow.StructConverter; @@ -362,6 +363,27 @@ public Converters getConverters() { return converters; } + @Override + public Date convertToDate(Object object, TimeZone tz) throws SFException { + return converters + .getStructuredTypeDateTimeConverter() + .getDate((int) object, tz); + } + + @Override + public Time convertToTime(Object object, int scale) throws SFException { + return converters.getStructuredTypeDateTimeConverter() + .getTime((long) object, scale); + } + + @Override + public Timestamp convertToTimestamp(Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { + return converters + .getStructuredTypeDateTimeConverter() + .getTimestamp( + (JsonStringHashMap) object, columnType, columnSubType, tz, scale); + } + /** * Advance to next row * @@ -516,7 +538,7 @@ public Object getObject(int columnIndex) throws SFException { if (converter instanceof VarCharConverter) { return createJsonSqlInput(columnIndex, obj); } else if (converter instanceof StructConverter) { - return createArrowSqlInput(columnIndex, (JsonStringHashMap) obj); + return createArrowSqlInput(columnIndex, (Map) obj); } } return obj; @@ -536,7 +558,7 @@ private Object createJsonSqlInput(int columnIndex, Object obj) throws SFExceptio } } - private Object createArrowSqlInput(int columnIndex, JsonStringHashMap input) { + private Object createArrowSqlInput(int columnIndex, Map input) { return new ArrowSqlInput( input, session, diff --git a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java index 97509d2a7..a5026442c 100644 --- a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java @@ -191,15 +191,15 @@ public boolean isArrayBindSupported() { * data size. * * @param maxSizeInBytes The expected max data size wrapped in the ResultSetSerializables object. - * NOTE: this parameter is intended to make the data size in each serializable object to be - * less than it. But if user specifies a small value which may be smaller than the data size - * of one result chunk. So the definition can't be guaranteed completely. For this special - * case, one serializable object is used to wrap the data chunk. + * NOTE: this parameter is intended to make the data size in each serializable object to be + * less than it. But if user specifies a small value which may be smaller than the data size + * of one result chunk. So the definition can't be guaranteed completely. For this special + * case, one serializable object is used to wrap the data chunk. * @return a list of SnowflakeResultSetSerializable * @throws SQLException if fails to split objects. */ public List getResultSetSerializables(long maxSizeInBytes) - throws SQLException { + throws SQLException { return this.resultSetSerializable.splitBySize(maxSizeInBytes); } @@ -213,4 +213,15 @@ public Converters getConverters() { public TimeZone getSessionTimeZone() { return resultSetSerializable.getTimeZone(); } + + @SnowflakeJdbcInternalApi + public abstract Date convertToDate(Object object, TimeZone tz) throws SFException; + + @SnowflakeJdbcInternalApi + public abstract Time convertToTime(Object object, int scale) throws SFException; + + @SnowflakeJdbcInternalApi + public abstract Timestamp convertToTimestamp( + Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException; } + diff --git a/src/main/java/net/snowflake/client/core/SFJsonResultSet.java b/src/main/java/net/snowflake/client/core/SFJsonResultSet.java index d8955bdeb..600cfe0b8 100644 --- a/src/main/java/net/snowflake/client/core/SFJsonResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFJsonResultSet.java @@ -426,4 +426,21 @@ private static Object convert(JsonStringToTypeConverter converter, JsonNode node return converter.convert(node.toString()); } } + + @Override + public Date convertToDate(Object object, TimeZone tz) throws SFException { + return (Date) converters.dateConverter(session).convert((String) object); + } + + @Override + public Time convertToTime(Object object, int scale) throws SFException { + return (Time) converters.timeConverter(session).convert((String) object); + } + + @Override + public Timestamp convertToTimestamp(Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { + return (Timestamp) converters + .timestampConverter(columnSubType, columnType, scale, session, null, tz) + .convert((String) object); + } } diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index 426ebae06..11952877d 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -1577,10 +1577,10 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep .get(columnIndex - 1) .getFields(), sfBaseResultSet.getSessionTimezone()); - } else { + } else if (object instanceof ArrowSqlInput || object instanceof Map) { sqlInput = new ArrowSqlInput( - (JsonStringHashMap) entry.getValue(), + (Map) entry.getValue(), session, sfBaseResultSet.getConverters(), sfBaseResultSet @@ -1588,6 +1588,8 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep .getColumnMetadata() .get(columnIndex - 1) .getFields()); + } else { + throw new SQLException("SqlInput type " + object.getClass() + " is not supported when mapping to SQLData class"); } instance.readSQL(sqlInput, null); resultMap.put(entry.getKey(), (T) instance); @@ -1689,19 +1691,17 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Date.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapSFExceptionToSQLException(() -> (T) convertToDate(entry.getValue(), tz))); + mapSFExceptionToSQLException(() -> (T) sfBaseResultSet.convertToDate(entry.getValue(), tz))); } else if (Time.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapSFExceptionToSQLException(() -> (T) convertToTime(entry.getValue(), tz, scale))); + mapSFExceptionToSQLException(() -> (T) sfBaseResultSet.convertToTime(entry.getValue(), scale))); } else if (Timestamp.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), mapSFExceptionToSQLException( - () -> - (T) - convertToTimestamp( + () -> (T) sfBaseResultSet.convertToTimestamp( entry.getValue(), columnType, columnSubType, tz, scale))); } else { @@ -1741,43 +1741,4 @@ public boolean isWrapperFor(Class iface) throws SQLException { return iface.isInstance(this); } - - private Date convertToDate(Object object, TimeZone tz) throws SFException { - if (sfBaseResultSet instanceof SFArrowResultSet) { - return sfBaseResultSet - .getConverters() - .getStructuredTypeDateTimeConverter() - .getDate((int) object, tz); - } else { - return (Date) sfBaseResultSet.getConverters().dateConverter(session).convert((String) object); - } - } - - private Time convertToTime(Object object, TimeZone tz, int scale) throws SFException { - if (sfBaseResultSet instanceof SFArrowResultSet) { - return sfBaseResultSet - .getConverters() - .getStructuredTypeDateTimeConverter() - .getTime((long) object, scale); - } else { - return (Time) sfBaseResultSet.getConverters().timeConverter(session).convert((String) object); - } - } - - private Timestamp convertToTimestamp( - Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { - if (sfBaseResultSet instanceof SFArrowResultSet) { - return sfBaseResultSet - .getConverters() - .getStructuredTypeDateTimeConverter() - .getTimestamp( - (JsonStringHashMap) object, columnType, columnSubType, tz, scale); - } else { - return (Timestamp) - sfBaseResultSet - .getConverters() - .timestampConverter(columnSubType, columnType, scale, session, null, tz) - .convert((String) object); - } - } } From 882c8104c803e9d2d13e3ed20307c4253c3f5850 Mon Sep 17 00:00:00 2001 From: Dawid Heyman Date: Thu, 28 Mar 2024 14:42:52 +0100 Subject: [PATCH 10/11] reformat --- .../snowflake/client/core/ArrowSqlInput.java | 5 +---- .../client/core/SFArrowResultSet.java | 18 ++++++++---------- .../snowflake/client/core/SFBaseResultSet.java | 13 ++++++------- .../snowflake/client/core/SFJsonResultSet.java | 6 ++++-- .../client/jdbc/SnowflakeBaseResultSet.java | 18 +++++++++++------- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/java/net/snowflake/client/core/ArrowSqlInput.java b/src/main/java/net/snowflake/client/core/ArrowSqlInput.java index f73a6a0ec..2ea95de0b 100644 --- a/src/main/java/net/snowflake/client/core/ArrowSqlInput.java +++ b/src/main/java/net/snowflake/client/core/ArrowSqlInput.java @@ -214,10 +214,7 @@ public T readObject(Class type) throws SQLException { SQLData instance = (SQLData) SQLDataCreationHelper.create(type); instance.readSQL( new ArrowSqlInput( - (Map) value, - session, - converters, - fieldMetadata.getFields()), + (Map) value, session, converters, fieldMetadata.getFields()), null); return (T) instance; }); diff --git a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java index 355881144..58aa3a709 100644 --- a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java @@ -365,23 +365,21 @@ public Converters getConverters() { @Override public Date convertToDate(Object object, TimeZone tz) throws SFException { - return converters - .getStructuredTypeDateTimeConverter() - .getDate((int) object, tz); + return converters.getStructuredTypeDateTimeConverter().getDate((int) object, tz); } @Override public Time convertToTime(Object object, int scale) throws SFException { - return converters.getStructuredTypeDateTimeConverter() - .getTime((long) object, scale); + return converters.getStructuredTypeDateTimeConverter().getTime((long) object, scale); } @Override - public Timestamp convertToTimestamp(Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { - return converters - .getStructuredTypeDateTimeConverter() - .getTimestamp( - (JsonStringHashMap) object, columnType, columnSubType, tz, scale); + public Timestamp convertToTimestamp( + Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { + return converters + .getStructuredTypeDateTimeConverter() + .getTimestamp( + (JsonStringHashMap) object, columnType, columnSubType, tz, scale); } /** diff --git a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java index a5026442c..a68bf82b6 100644 --- a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java @@ -191,15 +191,15 @@ public boolean isArrayBindSupported() { * data size. * * @param maxSizeInBytes The expected max data size wrapped in the ResultSetSerializables object. - * NOTE: this parameter is intended to make the data size in each serializable object to be - * less than it. But if user specifies a small value which may be smaller than the data size - * of one result chunk. So the definition can't be guaranteed completely. For this special - * case, one serializable object is used to wrap the data chunk. + * NOTE: this parameter is intended to make the data size in each serializable object to be + * less than it. But if user specifies a small value which may be smaller than the data size + * of one result chunk. So the definition can't be guaranteed completely. For this special + * case, one serializable object is used to wrap the data chunk. * @return a list of SnowflakeResultSetSerializable * @throws SQLException if fails to split objects. */ public List getResultSetSerializables(long maxSizeInBytes) - throws SQLException { + throws SQLException { return this.resultSetSerializable.splitBySize(maxSizeInBytes); } @@ -222,6 +222,5 @@ public TimeZone getSessionTimeZone() { @SnowflakeJdbcInternalApi public abstract Timestamp convertToTimestamp( - Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException; + Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException; } - diff --git a/src/main/java/net/snowflake/client/core/SFJsonResultSet.java b/src/main/java/net/snowflake/client/core/SFJsonResultSet.java index 600cfe0b8..5a91b7591 100644 --- a/src/main/java/net/snowflake/client/core/SFJsonResultSet.java +++ b/src/main/java/net/snowflake/client/core/SFJsonResultSet.java @@ -438,8 +438,10 @@ public Time convertToTime(Object object, int scale) throws SFException { } @Override - public Timestamp convertToTimestamp(Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { - return (Timestamp) converters + public Timestamp convertToTimestamp( + Object object, int columnType, int columnSubType, TimeZone tz, int scale) throws SFException { + return (Timestamp) + converters .timestampConverter(columnSubType, columnType, scale, session, null, tz) .convert((String) object); } diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index 11952877d..c1c3e5154 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -41,15 +41,12 @@ import net.snowflake.client.core.ColumnTypeHelper; import net.snowflake.client.core.JsonSqlInput; import net.snowflake.client.core.ObjectMapperFactory; -import net.snowflake.client.core.SFArrowResultSet; import net.snowflake.client.core.SFBaseResultSet; import net.snowflake.client.core.SFBaseSession; -import net.snowflake.client.core.SFException; import net.snowflake.client.core.structs.SQLDataCreationHelper; import net.snowflake.client.log.SFLogger; import net.snowflake.client.log.SFLoggerFactory; import net.snowflake.common.core.SqlState; -import org.apache.arrow.vector.util.JsonStringHashMap; /** Base class for query result set and metadata result set */ public abstract class SnowflakeBaseResultSet implements ResultSet { @@ -1589,7 +1586,10 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep .get(columnIndex - 1) .getFields()); } else { - throw new SQLException("SqlInput type " + object.getClass() + " is not supported when mapping to SQLData class"); + throw new SQLException( + "SqlInput type " + + object.getClass() + + " is not supported when mapping to SQLData class"); } instance.readSQL(sqlInput, null); resultMap.put(entry.getKey(), (T) instance); @@ -1691,17 +1691,21 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep } else if (Date.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapSFExceptionToSQLException(() -> (T) sfBaseResultSet.convertToDate(entry.getValue(), tz))); + mapSFExceptionToSQLException( + () -> (T) sfBaseResultSet.convertToDate(entry.getValue(), tz))); } else if (Time.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), - mapSFExceptionToSQLException(() -> (T) sfBaseResultSet.convertToTime(entry.getValue(), scale))); + mapSFExceptionToSQLException( + () -> (T) sfBaseResultSet.convertToTime(entry.getValue(), scale))); } else if (Timestamp.class.isAssignableFrom(type)) { resultMap.put( entry.getKey(), mapSFExceptionToSQLException( - () -> (T) sfBaseResultSet.convertToTimestamp( + () -> + (T) + sfBaseResultSet.convertToTimestamp( entry.getValue(), columnType, columnSubType, tz, scale))); } else { From 10d80623cf774cfb0e075e3081a078528adee2f0 Mon Sep 17 00:00:00 2001 From: Przemyslaw Motacki Date: Thu, 28 Mar 2024 17:07:45 +0100 Subject: [PATCH 11/11] Mapping to json node --- .../net/snowflake/client/jdbc/SnowflakeBaseResultSet.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java index c1c3e5154..2bad0a4e5 100644 --- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java +++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java @@ -1552,8 +1552,11 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep Object object = getObject(columnIndex); Map map; if (object instanceof JsonSqlInput) { + map = new HashMap<>(); JsonNode jsonNode = ((JsonSqlInput) object).getInput(); - map = OBJECT_MAPPER.convertValue(jsonNode, new TypeReference>() {}); + jsonNode + .fieldNames() + .forEachRemaining(node -> map.put(node.toString(), jsonNode.get(node.toString()))); } else { map = (Map) object; } @@ -1565,7 +1568,7 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep if (object instanceof JsonSqlInput) { sqlInput = new JsonSqlInput( - (((JsonSqlInput) object).getInput()).get(entry.getKey()), + (JsonNode) entry.getValue(), session, sfBaseResultSet.getConverters(), sfBaseResultSet