-
Notifications
You must be signed in to change notification settings - Fork 10
GH-180 Introduced YdbType complement type-safe variant #185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 68 additions & 18 deletions
86
spring-data-jdbc-ydb/src/main/java/tech/ydb/data/core/convert/YQLType.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,75 @@ | ||
package tech.ydb.data.core.convert; | ||
|
||
import java.sql.SQLType; | ||
import tech.ydb.jdbc.YdbConst; | ||
import tech.ydb.table.values.PrimitiveType; | ||
|
||
/** | ||
* @author Madiyar Nurgazin | ||
*/ | ||
public record YQLType(PrimitiveType type) implements SQLType { | ||
@Override | ||
public String getName() { | ||
return type.name(); | ||
} | ||
|
||
@Override | ||
public String getVendor() { | ||
return "YDB"; | ||
public enum YQLType { | ||
/** Boolean value. */ | ||
Bool(YdbConst.SQL_KIND_PRIMITIVE + 0), | ||
/** A signed integer. Acceptable values: from -2^7 to 2^7–1. Not supported for table columns */ | ||
Int8(YdbConst.SQL_KIND_PRIMITIVE + 1), | ||
/** An unsigned integer. Acceptable values: from 0 to 2^8–1. */ | ||
Uint8(YdbConst.SQL_KIND_PRIMITIVE + 2), | ||
/** A signed integer. Acceptable values: from –2^15 to 2^15–1. Not supported for table columns */ | ||
Int16(YdbConst.SQL_KIND_PRIMITIVE + 3), | ||
/** An unsigned integer. Acceptable values: from 0 to 2^16–1. Not supported for table columns */ | ||
Uint16(YdbConst.SQL_KIND_PRIMITIVE + 4), | ||
/** A signed integer. Acceptable values: from –2^31 to 2^31–1. */ | ||
Int32(YdbConst.SQL_KIND_PRIMITIVE + 5), | ||
/** An unsigned integer. Acceptable values: from 0 to 2^32–1. */ | ||
Uint32(YdbConst.SQL_KIND_PRIMITIVE + 6), | ||
/** A signed integer. Acceptable values: from –2^63 to 2^63–1. */ | ||
Int64(YdbConst.SQL_KIND_PRIMITIVE + 7), | ||
/** An unsigned integer. Acceptable values: from 0 to 2^64–1. */ | ||
Uint64(YdbConst.SQL_KIND_PRIMITIVE + 8), | ||
/** A real number with variable precision, 4 bytes in size. Can't be used in the primary key */ | ||
Float(YdbConst.SQL_KIND_PRIMITIVE + 9), | ||
/** A real number with variable precision, 8 bytes in size. Can't be used in the primary key */ | ||
Double(YdbConst.SQL_KIND_PRIMITIVE + 10), | ||
/** A binary data, synonym for YDB type String */ | ||
Bytes(YdbConst.SQL_KIND_PRIMITIVE + 11), | ||
/** Text encoded in UTF-8, synonym for YDB type Utf8 */ | ||
Text(YdbConst.SQL_KIND_PRIMITIVE + 12), | ||
/** YSON in a textual or binary representation. Doesn't support matching, can't be used in the primary key */ | ||
Yson(YdbConst.SQL_KIND_PRIMITIVE + 13), | ||
/** JSON represented as text. Doesn't support matching, can't be used in the primary key */ | ||
Json(YdbConst.SQL_KIND_PRIMITIVE + 14), | ||
/** Universally unique identifier UUID. Not supported for table columns */ | ||
Uuid(YdbConst.SQL_KIND_PRIMITIVE + 15), | ||
/** Date, precision to the day */ | ||
Date(YdbConst.SQL_KIND_PRIMITIVE + 16), | ||
/** Date/time, precision to the second */ | ||
Datetime(YdbConst.SQL_KIND_PRIMITIVE + 17), | ||
/** Date/time, precision to the microsecond */ | ||
Timestamp(YdbConst.SQL_KIND_PRIMITIVE + 18), | ||
/** Time interval (signed), precision to microseconds */ | ||
Interval(YdbConst.SQL_KIND_PRIMITIVE + 19), | ||
/** Date with time zone label, precision to the day */ | ||
TzDate(YdbConst.SQL_KIND_PRIMITIVE + 20), | ||
/** Date/time with time zone label, precision to the second */ | ||
TzDatetime(YdbConst.SQL_KIND_PRIMITIVE + 21), | ||
/** Date/time with time zone label, precision to the microsecond */ | ||
TzTimestamp(YdbConst.SQL_KIND_PRIMITIVE + 22), | ||
/** JSON in an indexed binary representation. Doesn't support matching, can't be used in the primary key */ | ||
JsonDocument(YdbConst.SQL_KIND_PRIMITIVE + 23), | ||
|
||
// DyNumber(YdbConst.SQL_KIND_PRIMITIVE + 24), -- not supported by JDBC Driver | ||
|
||
Date32(YdbConst.SQL_KIND_PRIMITIVE + 25), | ||
|
||
Datetime64(YdbConst.SQL_KIND_PRIMITIVE + 26), | ||
|
||
Timestamp64(YdbConst.SQL_KIND_PRIMITIVE + 27), | ||
|
||
Interval64(YdbConst.SQL_KIND_PRIMITIVE + 28), | ||
|
||
Decimal(YdbConst.SQL_DEFAULT_DECIMAL); // special case | ||
|
||
private final int sqlType; | ||
|
||
private YQLType(int sqlType) { | ||
this.sqlType = sqlType; | ||
} | ||
|
||
@Override | ||
public Integer getVendorTypeNumber() { | ||
return YdbConst.SQL_KIND_PRIMITIVE + type.ordinal(); | ||
public int getSqlType() { | ||
return this.sqlType; | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
spring-data-jdbc-ydb/src/main/java/tech/ydb/data/core/convert/YdbConst.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package tech.ydb.data.core.convert; | ||
|
||
/** | ||
* That class contain custom YDB type codes | ||
* @see <a href="https://github.com/ydb-platform/ydb-jdbc-driver/blob/3d74021/jdbc/src/main/java/tech/ydb/jdbc/YdbConst.java#L8-L9">JDBC Driver constants</a> | ||
* @see <a href="https://github.com/ydb-platform/ydb-jdbc-driver/blob/3d74021/jdbc/src/main/java/tech/ydb/jdbc/impl/YdbTypes.java#L37-L66">Primitive types</a> | ||
* @see <a href="https://github.com/ydb-platform/ydb-jdbc-driver/blob/3d74021/jdbc/src/main/java/tech/ydb/jdbc/impl/YdbTypes.java#L138-L144">Decimal type</a> | ||
* | ||
* @author Aleksandr Gorshenin | ||
*/ | ||
final class YdbConst { | ||
public static final int SQL_KIND_PRIMITIVE = 10000; | ||
public static final int SQL_DEFAULT_DECIMAL = ydbDecimal(22, 9); | ||
private static final int SQL_KIND_DECIMAL = 1 << 14; // 16384 | ||
|
||
public static int ydbDecimal(int precision, int scale) { | ||
return SQL_KIND_DECIMAL + (precision << 6) + (scale & 0x111111); | ||
} | ||
|
||
private YdbConst() { }; | ||
} |
38 changes: 34 additions & 4 deletions
38
spring-data-jdbc-ydb/src/main/java/tech/ydb/data/core/convert/YdbMappingJdbcConverter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,57 @@ | ||
package tech.ydb.data.core.convert; | ||
|
||
import java.sql.SQLType; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.ConcurrentMap; | ||
|
||
import org.springframework.data.convert.CustomConversions; | ||
import org.springframework.data.jdbc.core.convert.JdbcTypeFactory; | ||
import org.springframework.data.jdbc.core.convert.MappingJdbcConverter; | ||
import org.springframework.data.jdbc.core.convert.RelationResolver; | ||
import org.springframework.data.relational.core.mapping.RelationalMappingContext; | ||
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; | ||
import tech.ydb.table.values.PrimitiveType; | ||
|
||
import tech.ydb.data.core.convert.annotation.YdbType; | ||
|
||
|
||
/** | ||
* @author Madiyar Nurgazin | ||
* @author Mikhail Polivakha | ||
*/ | ||
@SuppressWarnings("removal") | ||
public class YdbMappingJdbcConverter extends MappingJdbcConverter { | ||
private final static Class<YdbType> ANNOTATION = YdbType.class; | ||
private final static Class<tech.ydb.data.core.convert.YdbType> OLD_TYPE = tech.ydb.data.core.convert.YdbType.class; | ||
|
||
private final ConcurrentMap<RelationalPersistentProperty, SQLType> typesCache = new ConcurrentHashMap<>(); | ||
|
||
public YdbMappingJdbcConverter(RelationalMappingContext context, RelationResolver relationResolver, | ||
CustomConversions conversions, JdbcTypeFactory typeFactory) { | ||
super(context, relationResolver, conversions, typeFactory); | ||
} | ||
|
||
@Override | ||
public SQLType getTargetSqlType(RelationalPersistentProperty property) { | ||
return property.isAnnotationPresent(YdbType.class) ? | ||
new YQLType(PrimitiveType.valueOf(property.getRequiredAnnotation(YdbType.class).value())) : | ||
super.getTargetSqlType(property); | ||
return typesCache.computeIfAbsent(property, this::resolveSqlType); | ||
} | ||
|
||
private SQLType resolveSqlType(RelationalPersistentProperty property) { | ||
if (property.isAnnotationPresent(ANNOTATION)) { | ||
tech.ydb.data.core.convert.annotation.YdbType type = property.getRequiredAnnotation(ANNOTATION); | ||
YQLType yql = type.value(); | ||
if (yql == YQLType.Decimal) { | ||
int precision = type.decimalPrecision(); | ||
int scale = type.decimalScale(); | ||
return new YdbSqlType(precision, scale); | ||
} | ||
return new YdbSqlType(yql); | ||
} | ||
|
||
if (property.isAnnotationPresent(OLD_TYPE)) { | ||
String typeName = property.getRequiredAnnotation(OLD_TYPE).value(); | ||
return new YdbSqlType(YQLType.valueOf(typeName)); | ||
} | ||
|
||
return super.getTargetSqlType(property); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
spring-data-jdbc-ydb/src/main/java/tech/ydb/data/core/convert/YdbSqlType.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package tech.ydb.data.core.convert; | ||
|
||
import java.io.Serializable; | ||
import java.sql.SQLType; | ||
|
||
/** | ||
* | ||
* @author Aleksandr Gorshenin | ||
*/ | ||
class YdbSqlType implements SQLType, Serializable { | ||
private static final long serialVersionUID = -5722445668088782880L; | ||
|
||
private final String name; | ||
private final int vendorCode; | ||
|
||
public YdbSqlType(YQLType type) { | ||
this.name = type.name(); | ||
this.vendorCode = type.getSqlType(); | ||
} | ||
|
||
public YdbSqlType(int decimalPrecision, int decimalScale) { | ||
this.name = "Decimal(" + decimalPrecision + "," + decimalScale + ")"; | ||
this.vendorCode = YdbConst.ydbDecimal(decimalPrecision, decimalScale); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return name; | ||
} | ||
|
||
@Override | ||
public String getVendor() { | ||
return "YDB"; | ||
} | ||
|
||
@Override | ||
public Integer getVendorTypeNumber() { | ||
return vendorCode; | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
spring-data-jdbc-ydb/src/main/java/tech/ydb/data/core/convert/YdbType.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,26 @@ | ||
package tech.ydb.data.core.convert; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* The annotation for qualification of the target YDB data type. | ||
* | ||
* @author Madiyar Nurgazin | ||
* @author Mikhail Polivakha | ||
* @deprecated Please, use {@link tech.ydb.data.core.convert.annotation.YdbType} instead because of type safety considerations. | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.FIELD) | ||
@Deprecated(forRemoval = true) | ||
@Documented | ||
public @interface YdbType { | ||
/** | ||
* The target YDB data type. | ||
* @return name of YDB data type | ||
*/ | ||
String value(); | ||
} |
39 changes: 39 additions & 0 deletions
39
spring-data-jdbc-ydb/src/main/java/tech/ydb/data/core/convert/annotation/YdbType.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package tech.ydb.data.core.convert.annotation; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
import tech.ydb.data.core.convert.YQLType; | ||
|
||
|
||
/** | ||
* The annotation for qualification of the target YDB data type. | ||
* | ||
* @author Mikhail Polivakha | ||
* @author Aleksandr Gorshenin | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.FIELD) | ||
@Documented | ||
public @interface YdbType { | ||
/** | ||
* The target YDB data type. | ||
* @return The target YDB data type. | ||
*/ | ||
YQLType value(); | ||
|
||
/** | ||
* Decimal precision. Applies only to {@link YQLType#Decimal } | ||
* @return Custom decimal type precision. | ||
*/ | ||
int decimalPrecision() default 22; | ||
|
||
/** | ||
* Decimal scale. Applies only to {@link YQLType#Decimal } | ||
* @return Custom decimal type scale. | ||
*/ | ||
int decimalScale() default 9; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.