Skip to content

Commit

Permalink
SNOW-1856886 Narrow toString calculation to structured types only (#2007
Browse files Browse the repository at this point in the history
)

Co-authored-by: Przemyslaw Motacki <przemyslaw.motacki@snowflake.com>
  • Loading branch information
sfc-gh-mkubik and sfc-gh-pmotacki authored Jan 14, 2025
1 parent 1d58f57 commit e8e3bac
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 40 deletions.
45 changes: 32 additions & 13 deletions src/main/java/net/snowflake/client/core/SFArrowResultSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.stream.Stream;
import net.snowflake.client.core.arrow.ArrayConverter;
import net.snowflake.client.core.arrow.ArrowVectorConverter;
import net.snowflake.client.core.arrow.MapConverter;
import net.snowflake.client.core.arrow.StructConverter;
import net.snowflake.client.core.arrow.StructObjectWrapper;
import net.snowflake.client.core.arrow.VarCharConverter;
Expand Down Expand Up @@ -574,10 +575,11 @@ public Object getObjectWithoutString(int columnIndex) throws SFException {
return getObjectRepresentation(columnIndex, false);
}

private Object getObjectRepresentation(int columnIndex, boolean withString) throws SFException {
private StructObjectWrapper getObjectRepresentation(int columnIndex, boolean withString)
throws SFException {
int type = resultSetMetaData.getColumnType(columnIndex);
if (type == SnowflakeUtil.EXTRA_TYPES_VECTOR) {
return getString(columnIndex);
return new StructObjectWrapper(getString(columnIndex), null);
}
ArrowVectorConverter converter = currentChunkIterator.getCurrentConverter(columnIndex - 1);
int index = currentChunkIterator.getCurrentRowInRecordBatch();
Expand All @@ -589,15 +591,33 @@ private Object getObjectRepresentation(int columnIndex, boolean withString) thro
if (obj == null) {
return null;
}
String jsonString = withString ? converter.toString(index) : null;
boolean isStructuredType = resultSetMetaData.isStructuredTypeColumn(columnIndex);
if (isVarcharConvertedStruct(type, isStructuredType, converter)) {
return new StructObjectWrapper(jsonString, createJsonSqlInput(columnIndex, obj));
} else if (converter instanceof StructConverter) {
return new StructObjectWrapper(
jsonString, createArrowSqlInput(columnIndex, (Map<String, Object>) obj));
if (isStructuredType) {
if (converter instanceof VarCharConverter) {
if (type == Types.STRUCT) {
JsonSqlInput jsonSqlInput = createJsonSqlInput(columnIndex, obj);
return new StructObjectWrapper(jsonSqlInput.getText(), jsonSqlInput);
} else if (type == Types.ARRAY) {
SfSqlArray sfArray = getJsonArray((String) obj, columnIndex);
return new StructObjectWrapper(sfArray.getText(), sfArray);
} else {
throw new SFException(queryId, ErrorCode.INVALID_STRUCT_DATA);
}
} else if (converter instanceof StructConverter) {
String jsonString = withString ? converter.toString(index) : null;
return new StructObjectWrapper(
jsonString, createArrowSqlInput(columnIndex, (Map<String, Object>) obj));
} else if (converter instanceof MapConverter) {
String jsonString = withString ? converter.toString(index) : null;
return new StructObjectWrapper(jsonString, obj);
} else if (converter instanceof ArrayConverter || converter instanceof VectorTypeConverter) {
String jsonString = converter.toString(index);
return new StructObjectWrapper(jsonString, obj);
} else {
throw new SFException(queryId, ErrorCode.INVALID_STRUCT_DATA);
}
} else {
return new StructObjectWrapper(jsonString, obj);
return new StructObjectWrapper(null, obj);
}
}

Expand All @@ -610,12 +630,11 @@ private SQLInput createArrowSqlInput(int columnIndex, Map<String, Object> input)
input, session, converters, resultSetMetaData.getColumnFields(columnIndex));
}

private boolean isVarcharConvertedStruct(
int type, boolean isStructuredType, ArrowVectorConverter converter) {
return type == Types.STRUCT && isStructuredType && converter instanceof VarCharConverter;
private boolean isVarcharConvertedStruct(int type, ArrowVectorConverter converter) {
return (type == Types.STRUCT || type == Types.ARRAY) && converter instanceof VarCharConverter;
}

private Object createJsonSqlInput(int columnIndex, Object obj) throws SFException {
private JsonSqlInput createJsonSqlInput(int columnIndex, Object obj) throws SFException {
try {
if (obj == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public Object getObject(int columnIndex) throws SFException {
}
case Types.ARRAY:
if (resultSetMetaData.isStructuredTypeColumn(columnIndex)) {
return getArray(columnIndex);
return new StructObjectWrapper((String) obj, getArray(columnIndex));
} else {
throw new SFException(ErrorCode.FEATURE_UNSUPPORTED, "data type: " + type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1643,7 +1643,7 @@ public <T> Map<String, T> getMap(int columnIndex, Class<T> type) throws SQLExcep
(StructObjectWrapper)
SnowflakeUtil.mapSFExceptionToSQLException(
() -> sfBaseResultSet.getObjectWithoutString(columnIndex));
if (structObjectWrapper == null) {
if (structObjectWrapper == null || structObjectWrapper.getObject() == null) {
return null;
}
Map<String, Object> map =
Expand Down Expand Up @@ -1835,22 +1835,4 @@ private <T> Map<String, Object> prepareMapWithValues(Object object, Class<T> typ
throw new SFException(ErrorCode.INVALID_STRUCT_DATA, "Object couldn't be converted to map");
}
}

private Object createJsonSqlInput(int columnIndex, StructObjectWrapper obj) throws SFException {
try {
if (obj == null) {
return null;
}
JsonNode jsonNode = OBJECT_MAPPER.readTree(obj.getJsonString());
return new JsonSqlInput(
obj.getJsonString(),
jsonNode,
session,
sfBaseResultSet.getConverters(),
sfBaseResultSet.getMetaData().getColumnFields(columnIndex),
sfBaseResultSet.getSessionTimeZone());
} catch (JsonProcessingException e) {
throw new SFException(sfBaseResultSet.getQueryId(), e, ErrorCode.INVALID_STRUCT_DATA);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import net.snowflake.client.core.QueryStatus;
import net.snowflake.client.core.SFBaseResultSet;
import net.snowflake.client.core.SFException;
import net.snowflake.client.core.SfSqlArray;
import net.snowflake.client.core.arrow.StructObjectWrapper;
import net.snowflake.client.log.SFLogger;
import net.snowflake.client.log.SFLoggerFactory;
Expand Down Expand Up @@ -270,22 +269,21 @@ public Object getObject(int columnIndex) throws SQLException {
raiseSQLExceptionIfResultSetIsClosed();
Object object =
SnowflakeUtil.mapSFExceptionToSQLException(() -> sfBaseResultSet.getObject(columnIndex));

if (object == null) {
return null;
}
if (object instanceof SfSqlArray) {
return ((SfSqlArray) object).getText();
}

if (object instanceof StructObjectWrapper) {
StructObjectWrapper structObjectWrapper = (StructObjectWrapper) object;
if (resultSetMetaData.isStructuredTypeColumn(columnIndex)
&& structObjectWrapper.getJsonString() != null) {
return structObjectWrapper.getJsonString();
}
if (structObjectWrapper.getObject() != null) {
return structObjectWrapper.getObject();
}

return structObjectWrapper.getObject();
}

return object;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,19 @@ public void testMapIntegerArray(ResultSetFormatType format) throws SQLException
format);
}

@ParameterizedTest
@ArgumentsSource(ResultFormatProvider.class)
@DontRunOnGithubActions
public void testMapIntegerArrayGetObject(ResultSetFormatType format) throws SQLException {
withFirstRow(
"SELECT ARRAY_CONSTRUCT(10, 20, 30)::ARRAY(INTEGER)",
(resultSet) -> {
Object resultArray = resultSet.getObject(1);
TestUtil.assertEqualsIgnoringWhitespace("[10,20,30]", (String) resultArray);
},
format);
}

@ParameterizedTest
@ArgumentsSource(ResultFormatProvider.class)
@DontRunOnGithubActions
Expand Down

0 comments on commit e8e3bac

Please sign in to comment.