|
| 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 | +} |
0 commit comments