Skip to content

Commit a36390a

Browse files
authored
SNOW-1234378 Return correct column type for structs depending on the run flag (#1673)
1 parent 066e25a commit a36390a

File tree

8 files changed

+103
-14
lines changed

8 files changed

+103
-14
lines changed

src/main/java/net/snowflake/client/core/SFArrowResultSet.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.TimeZone;
2323
import net.snowflake.client.core.arrow.ArrowVectorConverter;
2424
import net.snowflake.client.core.json.Converters;
25+
import net.snowflake.client.core.structs.StructureTypeHelper;
2526
import net.snowflake.client.jdbc.ArrowResultChunk;
2627
import net.snowflake.client.jdbc.ArrowResultChunk.ArrowChunkIterator;
2728
import net.snowflake.client.jdbc.ErrorCode;
@@ -517,8 +518,7 @@ public Array getArray(int columnIndex) throws SFException {
517518

518519
private Object handleObjectType(int columnIndex, Object obj) throws SFException {
519520
int columnType = resultSetMetaData.getColumnType(columnIndex);
520-
if (columnType == Types.STRUCT
521-
&& Boolean.valueOf(System.getProperty(STRUCTURED_TYPE_ENABLED_PROPERTY_NAME))) {
521+
if (columnType == Types.STRUCT && StructureTypeHelper.isStructureTypeEnabled()) {
522522
try {
523523
JsonNode jsonNode = OBJECT_MAPPER.readTree((String) obj);
524524
return new JsonSqlInput(

src/main/java/net/snowflake/client/core/SFBaseResultSet.java

-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
/** Base class for query result set and metadata result set */
2929
public abstract class SFBaseResultSet {
3030
private static final SFLogger logger = SFLoggerFactory.getLogger(SFBaseResultSet.class);
31-
static final String STRUCTURED_TYPE_ENABLED_PROPERTY_NAME = "STRUCTURED_TYPE_ENABLED";
3231

3332
boolean wasNull = false;
3433

src/main/java/net/snowflake/client/core/SFJsonResultSet.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.stream.Stream;
2424
import java.util.stream.StreamSupport;
2525
import net.snowflake.client.core.json.Converters;
26+
import net.snowflake.client.core.structs.StructureTypeHelper;
2627
import net.snowflake.client.jdbc.ErrorCode;
2728
import net.snowflake.client.jdbc.FieldMetadata;
2829
import net.snowflake.client.jdbc.SnowflakeColumnMetadata;
@@ -95,13 +96,13 @@ public Object getObject(int columnIndex) throws SFException {
9596
return getBoolean(columnIndex);
9697

9798
case Types.STRUCT:
98-
if (Boolean.parseBoolean(System.getProperty(STRUCTURED_TYPE_ENABLED_PROPERTY_NAME))) {
99+
if (StructureTypeHelper.isStructureTypeEnabled()) {
99100
return getSqlInput((String) obj, columnIndex);
100101
} else {
101102
throw new SFException(ErrorCode.FEATURE_UNSUPPORTED, "data type: " + type);
102103
}
103104
case Types.ARRAY:
104-
if (Boolean.parseBoolean(System.getProperty(STRUCTURED_TYPE_ENABLED_PROPERTY_NAME))) {
105+
if (StructureTypeHelper.isStructureTypeEnabled()) {
105106
return getArray(columnIndex);
106107
} else {
107108
throw new SFException(ErrorCode.FEATURE_UNSUPPORTED, "data type: " + type);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package net.snowflake.client.core.structs;
2+
3+
import net.snowflake.client.core.SnowflakeJdbcInternalApi;
4+
5+
@SnowflakeJdbcInternalApi
6+
public class StructureTypeHelper {
7+
private static final String STRUCTURED_TYPE_ENABLED_PROPERTY_NAME = "STRUCTURED_TYPE_ENABLED";
8+
private static boolean structuredTypeEnabled =
9+
Boolean.valueOf(System.getProperty(STRUCTURED_TYPE_ENABLED_PROPERTY_NAME));
10+
11+
public static boolean isStructureTypeEnabled() {
12+
return structuredTypeEnabled;
13+
}
14+
15+
public static void enableStructuredType() {
16+
structuredTypeEnabled = true;
17+
}
18+
19+
public static void disableStructuredType() {
20+
structuredTypeEnabled = false;
21+
}
22+
}

src/main/java/net/snowflake/client/jdbc/SnowflakeType.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.HashSet;
1616
import java.util.Set;
1717
import net.snowflake.client.core.SFBaseSession;
18+
import net.snowflake.client.core.structs.StructureTypeHelper;
1819
import net.snowflake.common.core.SFBinary;
1920
import net.snowflake.common.core.SqlState;
2021

@@ -79,8 +80,13 @@ public static JavaDataType getJavaType(SnowflakeType type) {
7980
case BINARY:
8081
return JavaDataType.JAVA_BYTES;
8182
case ANY:
82-
case OBJECT:
8383
return JavaDataType.JAVA_OBJECT;
84+
case OBJECT:
85+
if (StructureTypeHelper.isStructureTypeEnabled()) {
86+
return JavaDataType.JAVA_OBJECT;
87+
} else {
88+
return JavaDataType.JAVA_STRING;
89+
}
8490
default:
8591
// Those are not supported, but no reason to panic
8692
return JavaDataType.JAVA_STRING;

src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java

+15-6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import net.snowflake.client.core.SFBaseSession;
3939
import net.snowflake.client.core.SFSessionProperty;
4040
import net.snowflake.client.core.SnowflakeJdbcInternalApi;
41+
import net.snowflake.client.core.structs.StructureTypeHelper;
4142
import net.snowflake.client.log.SFLogger;
4243
import net.snowflake.client.log.SFLoggerFactory;
4344
import net.snowflake.common.core.SnowflakeDateTimeFormat;
@@ -278,14 +279,22 @@ static ColumnTypeInfo getSnowflakeType(
278279
new ColumnTypeInfo(Types.ARRAY, defaultIfNull(extColTypeName, "ARRAY"), baseType);
279280
break;
280281

281-
case OBJECT:
282282
case MAP:
283-
int targetType =
284-
"GEOGRAPHY".equals(extColTypeName) || "GEOMETRY".equals(extColTypeName)
285-
? Types.VARCHAR
286-
: Types.STRUCT;
287283
columnTypeInfo =
288-
new ColumnTypeInfo(targetType, defaultIfNull(extColTypeName, "OBJECT"), baseType);
284+
new ColumnTypeInfo(Types.STRUCT, defaultIfNull(extColTypeName, "OBJECT"), baseType);
285+
break;
286+
287+
case OBJECT:
288+
if (StructureTypeHelper.isStructureTypeEnabled()) {
289+
boolean isGeoType =
290+
"GEOMETRY".equals(extColTypeName) || "GEOGRAPHY".equals(extColTypeName);
291+
int type = isGeoType ? Types.VARCHAR : Types.STRUCT;
292+
columnTypeInfo =
293+
new ColumnTypeInfo(type, defaultIfNull(extColTypeName, "OBJECT"), baseType);
294+
} else {
295+
columnTypeInfo =
296+
new ColumnTypeInfo(Types.VARCHAR, defaultIfNull(extColTypeName, "OBJECT"), baseType);
297+
}
289298
break;
290299

291300
case VARIANT:

src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java

+53-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.sql.Statement;
1616
import java.sql.Time;
1717
import java.sql.Timestamp;
18+
import java.sql.Types;
1819
import java.time.LocalDate;
1920
import java.time.LocalDateTime;
2021
import java.time.LocalTime;
@@ -23,8 +24,10 @@
2324
import net.snowflake.client.ConditionalIgnoreRule;
2425
import net.snowflake.client.RunningOnGithubAction;
2526
import net.snowflake.client.ThrowingConsumer;
27+
import net.snowflake.client.ThrowingRunnable;
2628
import net.snowflake.client.category.TestCategoryStructuredType;
2729
import net.snowflake.client.core.structs.SnowflakeObjectTypeFactories;
30+
import net.snowflake.client.core.structs.StructureTypeHelper;
2831
import org.junit.Before;
2932
import org.junit.Test;
3033
import org.junit.experimental.categories.Category;
@@ -404,6 +407,32 @@ public void testMapArrayOfArrays() throws SQLException {
404407
});
405408
}
406409

410+
@Test
411+
@ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class)
412+
public void testColumnTypeWhenStructureTypeIsDisabled() throws Exception {
413+
withStructureTypeTemporaryDisabled(
414+
() -> {
415+
withFirstRow(
416+
"SELECT {'string':'a'}::OBJECT(string VARCHAR)",
417+
resultSet -> {
418+
assertEquals(Types.VARCHAR, resultSet.getMetaData().getColumnType(1));
419+
});
420+
});
421+
}
422+
423+
@Test
424+
@ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class)
425+
public void testColumnTypeWhenStructureTypeIsEnabled() throws Exception {
426+
withStructureTypeTemporaryEnabled(
427+
() -> {
428+
withFirstRow(
429+
"SELECT {'string':'a'}::OBJECT(string VARCHAR)",
430+
resultSet -> {
431+
assertEquals(Types.STRUCT, resultSet.getMetaData().getColumnType(1));
432+
});
433+
});
434+
}
435+
407436
private void withFirstRow(String sqlText, ThrowingConsumer<ResultSet, SQLException> consumer)
408437
throws SQLException {
409438
try (Connection connection = init();
@@ -413,5 +442,28 @@ private void withFirstRow(String sqlText, ThrowingConsumer<ResultSet, SQLExcepti
413442
consumer.accept(rs);
414443
}
415444
}
416-
;
445+
446+
private void withStructureTypeTemporaryEnabled(ThrowingRunnable action) throws Exception {
447+
boolean isStructureTypeEnabled = StructureTypeHelper.isStructureTypeEnabled();
448+
try {
449+
StructureTypeHelper.enableStructuredType();
450+
action.run();
451+
} finally {
452+
if (!isStructureTypeEnabled) {
453+
StructureTypeHelper.disableStructuredType();
454+
}
455+
}
456+
}
457+
458+
private void withStructureTypeTemporaryDisabled(ThrowingRunnable action) throws Exception {
459+
boolean isStructureTypeEnabled = StructureTypeHelper.isStructureTypeEnabled();
460+
try {
461+
StructureTypeHelper.disableStructuredType();
462+
action.run();
463+
} finally {
464+
if (isStructureTypeEnabled) {
465+
StructureTypeHelper.enableStructuredType();
466+
}
467+
}
468+
}
417469
}

src/test/java/net/snowflake/client/jdbc/SnowflakeDriverLatestIT.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ public void testGeoOutputTypes() throws Throwable {
838838
regularStatement.execute("insert into t_geo values ('POINT(0 0)'), ('LINESTRING(1 1, 2 2)')");
839839

840840
testGeoOutputTypeSingle(
841-
regularStatement, false, "geoJson", "OBJECT", "java.lang.String", Types.STRUCT);
841+
regularStatement, false, "geoJson", "OBJECT", "java.lang.String", Types.VARCHAR);
842842

843843
testGeoOutputTypeSingle(
844844
regularStatement, true, "geoJson", "GEOGRAPHY", "java.lang.String", Types.VARCHAR);

0 commit comments

Comments
 (0)