Skip to content

Commit 8dcd217

Browse files
SNOW-1157904 write and bindings structured types (#1727)
* Structures type write by bindings
1 parent 804ef67 commit 8dcd217

30 files changed

+1492
-80
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package net.snowflake.client.core;
2+
3+
import java.sql.SQLException;
4+
import java.sql.Types;
5+
import java.util.Optional;
6+
import net.snowflake.client.jdbc.BindingParameterMetadata;
7+
import net.snowflake.client.jdbc.SnowflakeColumn;
8+
import net.snowflake.client.jdbc.SnowflakeType;
9+
import net.snowflake.client.log.SFLogger;
10+
import net.snowflake.client.log.SFLoggerFactory;
11+
12+
@SnowflakeJdbcInternalApi
13+
public class FieldSchemaCreator {
14+
static final SFLogger logger = SFLoggerFactory.getLogger(FieldSchemaCreator.class);
15+
public static final int MAX_TEXT_COLUMN_SIZE = 134217728;
16+
public static final int MAX_BINARY_COLUMN_SIZE = 67108864;
17+
18+
public static BindingParameterMetadata buildSchemaForText(
19+
String fieldName, Optional<SnowflakeColumn> maybeColumn) {
20+
return BindingParameterMetadata.BindingParameterMetadataBuilder.bindingParameterMetadata()
21+
.withType(maybeColumn.map(cl -> cl.type()).filter(str -> !str.isEmpty()).orElse("text"))
22+
.withLength(maybeColumn.map(cl -> cl.length()).orElse(MAX_TEXT_COLUMN_SIZE))
23+
.withName(maybeColumn.map(cl -> cl.name()).filter(str -> !str.isEmpty()).orElse(fieldName))
24+
.build();
25+
}
26+
27+
public static BindingParameterMetadata buildSchemaForBytesType(
28+
String fieldName, Optional<SnowflakeColumn> maybeColumn) {
29+
return BindingParameterMetadata.BindingParameterMetadataBuilder.bindingParameterMetadata()
30+
.withType(maybeColumn.map(cl -> cl.type()).filter(str -> !str.isEmpty()).orElse("binary"))
31+
.withName(maybeColumn.map(cl -> cl.name()).filter(str -> !str.isEmpty()).orElse(fieldName))
32+
.withLength(maybeColumn.map(cl -> cl.precision()).orElse(MAX_TEXT_COLUMN_SIZE))
33+
.withByteLength(maybeColumn.map(cl -> cl.byteLength()).orElse(MAX_BINARY_COLUMN_SIZE))
34+
.build();
35+
}
36+
37+
public static BindingParameterMetadata buildSchemaTypeAndNameOnly(
38+
String fieldName, String type, Optional<SnowflakeColumn> maybeColumn) {
39+
return BindingParameterMetadata.BindingParameterMetadataBuilder.bindingParameterMetadata()
40+
.withType(maybeColumn.map(cl -> cl.type()).filter(str -> !str.isEmpty()).orElse(type))
41+
.withName(maybeColumn.map(cl -> cl.name()).filter(str -> !str.isEmpty()).orElse(fieldName))
42+
.build();
43+
}
44+
45+
public static BindingParameterMetadata buildSchemaWithScaleAndPrecision(
46+
String fieldName,
47+
String type,
48+
int scale,
49+
int precision,
50+
Optional<SnowflakeColumn> maybeColumn) {
51+
return BindingParameterMetadata.BindingParameterMetadataBuilder.bindingParameterMetadata()
52+
.withType(maybeColumn.map(cl -> cl.type()).filter(str -> !str.isEmpty()).orElse(type))
53+
.withScale(maybeColumn.map(cl -> cl.scale()).filter(i -> i > 0).orElse(scale))
54+
.withName(maybeColumn.map(cl -> cl.name()).filter(str -> !str.isEmpty()).orElse(fieldName))
55+
.withPrecision(maybeColumn.map(cl -> cl.precision()).filter(i -> i > 0).orElse(precision))
56+
.build();
57+
}
58+
59+
public static BindingParameterMetadata buildBindingSchemaForType(int baseType)
60+
throws SQLException {
61+
return buildBindingSchemaForType(baseType, true);
62+
}
63+
64+
public static BindingParameterMetadata buildBindingSchemaForType(int baseType, boolean addName)
65+
throws SQLException {
66+
String name = addName ? SnowflakeType.javaTypeToSFType(baseType, null).name() : null;
67+
switch (baseType) {
68+
case Types.VARCHAR:
69+
case Types.CHAR:
70+
return FieldSchemaCreator.buildSchemaForText(name, Optional.empty());
71+
case Types.FLOAT:
72+
case Types.DOUBLE:
73+
case Types.DECIMAL:
74+
return FieldSchemaCreator.buildSchemaWithScaleAndPrecision(
75+
name, "real", 9, 38, Optional.empty());
76+
case Types.NUMERIC:
77+
case Types.INTEGER:
78+
case Types.SMALLINT:
79+
case Types.TINYINT:
80+
case Types.BIGINT:
81+
return FieldSchemaCreator.buildSchemaWithScaleAndPrecision(
82+
null, "fixed", 0, 38, Optional.empty());
83+
case Types.BOOLEAN:
84+
return FieldSchemaCreator.buildSchemaTypeAndNameOnly(name, "boolean", Optional.empty());
85+
case Types.DATE:
86+
return FieldSchemaCreator.buildSchemaTypeAndNameOnly(name, "date", Optional.empty());
87+
case Types.TIMESTAMP:
88+
case Types.TIME:
89+
return FieldSchemaCreator.buildSchemaWithScaleAndPrecision(
90+
name, "timestamp", 9, 0, Optional.empty());
91+
default:
92+
logger.error("Could not create schema for type : " + baseType);
93+
throw new SQLException("Could not create schema for type : " + baseType);
94+
}
95+
}
96+
}

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

+12-4
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,12 @@ public <T> List<T> readList(Class<T> type) throws SQLException {
234234
List<T> result = new ArrayList();
235235
if (ArrayNode.class.isAssignableFrom(value.getClass())) {
236236
for (JsonNode node : (ArrayNode) value) {
237-
238-
result.add(convertObject(type, TimeZone.getDefault(), getValue(node), fieldMetadata));
237+
result.add(
238+
convertObject(
239+
type,
240+
TimeZone.getDefault(),
241+
getValue(node),
242+
fieldMetadata.getFields().get(0)));
239243
}
240244
return result;
241245
} else {
@@ -259,7 +263,11 @@ public <T> T[] readArray(Class<T> type) throws SQLException {
259263
int counter = 0;
260264
for (JsonNode node : valueNodes) {
261265
array[counter++] =
262-
convertObject(type, TimeZone.getDefault(), getValue(node), fieldMetadata);
266+
convertObject(
267+
type,
268+
TimeZone.getDefault(),
269+
getValue(node),
270+
fieldMetadata.getFields().get(0));
263271
}
264272
return array;
265273
} else {
@@ -306,7 +314,7 @@ private Timestamp convertTimestamp(TimeZone tz, Object value, FieldMetadata fiel
306314
int columnSubType = fieldMetadata.getType();
307315
int scale = fieldMetadata.getScale();
308316
Timestamp result =
309-
SqlInputTimestampUtil.getTimestampFromType(
317+
SfTimestampUtil.getTimestampFromType(
310318
columnSubType, (String) value, session, sessionTimeZone, tz);
311319
if (result != null) {
312320
return result;

0 commit comments

Comments
 (0)