Skip to content

Commit e761d94

Browse files
authored
Cassandra module additional date time types support (#230)
1 parent 3ac2dc1 commit e761d94

File tree

9 files changed

+78
-21
lines changed

9 files changed

+78
-21
lines changed

database/database-annotation-processor/src/main/java/ru/tinkoff/kora/database/annotation/processor/cassandra/CassandraNativeTypes.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
import javax.annotation.Nullable;
88
import java.math.BigDecimal;
99
import java.nio.ByteBuffer;
10-
import java.time.Instant;
11-
import java.time.LocalDate;
12-
import java.time.LocalDateTime;
10+
import java.time.*;
1311
import java.util.List;
1412
import java.util.Objects;
1513

@@ -71,6 +69,16 @@ public class CassandraNativeTypes {
7169
(rsName, i) -> CodeBlock.of("$L.getInstant($L)", rsName, i),
7270
(stmt, var, i) -> CodeBlock.of("$L.setInstant($L, $L)", stmt, i, var)
7371
);
72+
var localTime = CassandraNativeType.of(
73+
TypeName.get(LocalTime.class),
74+
(rsName, i) -> CodeBlock.of("$L.getLocalTime($L)", rsName, i),
75+
(stmt, var, i) -> CodeBlock.of("$L.setLocalTime($L, $L)", stmt, i, var)
76+
);
77+
var zonedDateTime = CassandraNativeType.of(
78+
TypeName.get(ZonedDateTime.class),
79+
(rsName, i) -> CodeBlock.of("$L.get($L, $T.class)", rsName, i, ZonedDateTime.class),
80+
(stmt, var, i) -> CodeBlock.of("$L.set($L, $L, $T.class)", stmt, i, var, ZonedDateTime.class)
81+
);
7482

7583
nativeTypes = List.of(
7684
booleanPrimitive,
@@ -86,7 +94,9 @@ public class CassandraNativeTypes {
8694
byteBuffer,
8795
localDateTime,
8896
localDate,
89-
instant
97+
instant,
98+
localTime,
99+
zonedDateTime
90100
);
91101
}
92102

database/database-annotation-processor/src/main/java/ru/tinkoff/kora/database/annotation/processor/cassandra/CassandraRepositoryGenerator.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import com.squareup.javapoet.*;
44
import reactor.core.publisher.Flux;
55
import reactor.core.publisher.Mono;
6-
import ru.tinkoff.kora.annotation.processor.common.*;
6+
import ru.tinkoff.kora.annotation.processor.common.CommonClassNames;
7+
import ru.tinkoff.kora.annotation.processor.common.CommonUtils;
8+
import ru.tinkoff.kora.annotation.processor.common.FieldFactory;
9+
import ru.tinkoff.kora.annotation.processor.common.Visitors;
710
import ru.tinkoff.kora.common.Tag;
811
import ru.tinkoff.kora.database.annotation.processor.DbUtils;
912
import ru.tinkoff.kora.database.annotation.processor.QueryWithParameters;
@@ -23,10 +26,7 @@
2326
import javax.lang.model.type.TypeMirror;
2427
import javax.lang.model.util.Elements;
2528
import javax.lang.model.util.Types;
26-
import java.util.Comparator;
27-
import java.util.List;
28-
import java.util.Optional;
29-
import java.util.Set;
29+
import java.util.*;
3030

3131
public class CassandraRepositoryGenerator implements RepositoryGenerator {
3232
private final TypeMirror repositoryInterface;
@@ -123,6 +123,7 @@ private MethodSpec generate(ExecutableElement method, ExecutableType methodType,
123123
if (CommonUtils.isVoid(((DeclaredType) returnType).getTypeArguments().get(0))) {
124124
b.addStatement("return $T.from(_rrs).then()", CommonClassNames.flux);
125125
} else {
126+
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
126127
b.addStatement("return $N.apply(_rrs)", resultMapperName);
127128
}
128129
b.endControlFlow().addCode(")\n");// flatMap Statement
@@ -140,6 +141,7 @@ private MethodSpec generate(ExecutableElement method, ExecutableType methodType,
140141
b.beginControlFlow("try");
141142
b.addStatement("var _rs = _session.execute(_s)");
142143
if (returnType.getKind() != TypeKind.VOID) {
144+
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
143145
b.addStatement("var _result = $N.apply(_rs)", resultMapperName);
144146
}
145147
b.addStatement("_telemetry.close(null)");

database/database-annotation-processor/src/main/java/ru/tinkoff/kora/database/annotation/processor/cassandra/extension/CassandraTypesExtension.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ public CassandraTypesExtension(ProcessingEnvironment env) {
5858
}
5959
},
6060
fd -> CodeBlock.builder()
61-
.beginControlFlow("if (_row.isNull($S))", fd.fieldName())
61+
.beginControlFlow("if (_row.isNull(_idx_$L))", fd.fieldName())
6262
.add(fd.nullable()
6363
? CodeBlock.of("$N = null;\n", fd.fieldName())
64-
: CodeBlock.of("throw new $T($S);\n", NullPointerException.class, "Result field %s is not nullable but row has null".formatted(fd.fieldName()))
64+
: CodeBlock.of("throw new $T($S);\n", NullPointerException.class, "Result field %s is not nullable but row %s has null".formatted(fd.fieldName(), fd.columnName()))
6565
)
6666
.endControlFlow()
6767
.build()

database/database-annotation-processor/src/main/java/ru/tinkoff/kora/database/annotation/processor/jdbc/JdbcRepositoryGenerator.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ public MethodSpec generate(ExecutableElement method, ExecutableType methodType,
196196
var result = CommonUtils.isNullable(method) || method.getReturnType().getKind().isPrimitive() || isMono
197197
? CodeBlock.of("_result")
198198
: CodeBlock.of("$T.requireNonNull(_result)", Objects.class);
199+
200+
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
201+
199202
b.addCode("try (var _rs = _stmt.executeQuery()) {$>\n")
200203
.addCode("var _result = $L.apply(_rs);\n", resultMapperName)
201204
.addCode("_telemetry.close(null);\n")

database/database-annotation-processor/src/main/java/ru/tinkoff/kora/database/annotation/processor/r2dbc/R2dbcRepositoryGenerator.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import com.squareup.javapoet.*;
44
import reactor.core.publisher.Flux;
55
import reactor.core.publisher.Mono;
6-
import ru.tinkoff.kora.annotation.processor.common.*;
6+
import ru.tinkoff.kora.annotation.processor.common.CommonUtils;
7+
import ru.tinkoff.kora.annotation.processor.common.FieldFactory;
8+
import ru.tinkoff.kora.annotation.processor.common.TagUtils;
9+
import ru.tinkoff.kora.annotation.processor.common.Visitors;
710
import ru.tinkoff.kora.common.Context;
811
import ru.tinkoff.kora.common.Tag;
912
import ru.tinkoff.kora.database.annotation.processor.DbUtils;
@@ -26,6 +29,7 @@
2629
import javax.lang.model.util.Types;
2730
import java.util.Comparator;
2831
import java.util.List;
32+
import java.util.Objects;
2933
import java.util.Optional;
3034

3135
public final class R2dbcRepositoryGenerator implements RepositoryGenerator {
@@ -121,8 +125,10 @@ private MethodSpec generate(ExecutableElement method, ExecutableType methodType,
121125
if (returnType.toString().equals(DbUtils.UPDATE_COUNT.canonicalName())) {
122126
b.addCode("return _flux.flatMap($T::getRowsUpdated).reduce(0L, Long::sum).map($T::new)", R2dbcTypes.RESULT, DbUtils.UPDATE_COUNT);
123127
} else if (resultFluxMapper != null) {
128+
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
124129
b.addCode("return $L.apply(_flux)\n", resultMapperName);
125130
} else if (rowMapper != null || !CommonUtils.isVoid(returnType)) {
131+
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
126132
b.addCode("return $L.apply(_flux)\n", resultMapperName);
127133
} else {
128134
b.addCode("return _flux.flatMap($T::getRowsUpdated).then()", R2dbcTypes.RESULT);

database/database-annotation-processor/src/main/java/ru/tinkoff/kora/database/annotation/processor/vertx/VertxRepositoryGenerator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ private MethodSpec generate(ExecutableElement method, ExecutableType methodType,
114114
} else if (returnType.toString().equals(DbUtils.UPDATE_COUNT.canonicalName())) {
115115
resultMapper = CodeBlock.of("$T::extractUpdateCount", VertxTypes.ROW_SET_MAPPER);
116116
} else {
117+
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
117118
resultMapper = CodeBlock.of("$N", resultMapperName);
118119
}
119120
if (returnType.getKind() != TypeKind.VOID) {

database/database-cassandra/src/main/java/ru/tinkoff/kora/database/cassandra/CassandraModule.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99

1010
import java.math.BigDecimal;
1111
import java.nio.ByteBuffer;
12-
import java.time.LocalDate;
13-
import java.time.LocalDateTime;
12+
import java.time.*;
1413
import java.util.List;
1514
import java.util.Optional;
1615

@@ -74,6 +73,12 @@ default CassandraRowMapper<ByteBuffer> byteBufferCassandraRowMapper() {
7473
: row.getByteBuffer(0);
7574
}
7675

76+
default CassandraRowMapper<LocalTime> localTimeCassandraRowMapper() {
77+
return row -> row.isNull(0)
78+
? null
79+
: row.getLocalTime(0);
80+
}
81+
7782
default CassandraRowMapper<LocalDate> localDateCassandraRowMapper() {
7883
return row -> row.isNull(0)
7984
? null
@@ -86,6 +91,18 @@ default CassandraRowMapper<LocalDateTime> localDateTimeCassandraRowMapper() {
8691
: row.get(0, LocalDateTime.class);
8792
}
8893

94+
default CassandraRowMapper<ZonedDateTime> zonedDateTimeCassandraRowMapper() {
95+
return row -> row.isNull(0)
96+
? null
97+
: row.get(0, ZonedDateTime.class);
98+
}
99+
100+
default CassandraRowMapper<Instant> instantCassandraRowMapper() {
101+
return row -> row.isNull(0)
102+
? null
103+
: row.getInstant(0);
104+
}
105+
89106
default CassandraReactiveResultSetMapper<Void, Mono<Void>> voidMonoCassandraReactiveResultSetMapper() {
90107
return rs -> Flux.from(rs).then();
91108
}

database/database-symbol-processor/src/main/kotlin/ru/tinkoff/kora/database/symbol/processor/cassandra/CassandraNativeTypes.kt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import com.squareup.kotlinpoet.TypeName
55
import com.squareup.kotlinpoet.asTypeName
66
import java.math.BigDecimal
77
import java.nio.ByteBuffer
8-
import java.time.Instant
9-
import java.time.LocalDate
10-
import java.time.LocalDateTime
8+
import java.time.*
119

1210
object CassandraNativeTypes {
1311
private val nativeTypes = listOf(
@@ -111,6 +109,26 @@ object CassandraNativeTypes {
111109
{ rsName, i -> CodeBlock.of("%N.getInstant(%L)", rsName, i) },
112110
{ stmt, variableName, idx -> CodeBlock.of("%N.setInstant(%L, %L)", stmt, idx, variableName) },
113111
),
112+
CassandraNativeType.of(
113+
LocalTime::class.asTypeName(),
114+
{ rsName, i -> CodeBlock.of("%N.getLocalTime(%L)", rsName, i) },
115+
{ stmt, variableName, idx -> CodeBlock.of("%N.setLocalTime(%L, %L)", stmt, idx, variableName) },
116+
),
117+
CassandraNativeType.of(
118+
LocalTime::class.asTypeName().copy(true),
119+
{ rsName, i -> CodeBlock.of("%N.getLocalTime(%L)", rsName, i) },
120+
{ stmt, variableName, idx -> CodeBlock.of("%N.setLocalTime(%L, %L)", stmt, idx, variableName) },
121+
),
122+
CassandraNativeType.of(
123+
ZonedDateTime::class.asTypeName(),
124+
{ rsName, i -> CodeBlock.of("%N.get(%L, %T::class.java)", rsName, i) },
125+
{ stmt, variableName, idx -> CodeBlock.of("%N.setLocalTime(%L, %L, %T::class.java)", stmt, idx, variableName, ZonedDateTime::class) },
126+
),
127+
CassandraNativeType.of(
128+
ZonedDateTime::class.asTypeName().copy(true),
129+
{ rsName, i -> CodeBlock.of("%N.get(%L, %T::class.java)", rsName, i) },
130+
{ stmt, variableName, idx -> CodeBlock.of("%N.setLocalTime(%L, %L, %T::class.java)", stmt, idx, variableName, ZonedDateTime::class) },
131+
),
114132
)
115133

116134
fun findNativeType(typeName: TypeName): CassandraNativeType? {

mkdocs/mkdocs.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ nav:
1414
- HTTP Server: features/http-server.md
1515
- HTTP Client: features/http-client.md
1616
- Кодогенерация из OpenAPI: features/openapi-codegen.md
17+
- SOAP: features/soap.md
1718
- Kafka: features/kafka.md
18-
- Database: features/database.md
19-
- Cassandra: features/cassandra.md
19+
- Database SQL: features/database.md
20+
- Database Cassandra: features/cassandra.md
2021
- Json: features/json.md
21-
- Soap: features/soap.md
22-
- gRPC server: features/grpc-server.md
22+
- gRPC Server: features/grpc-server.md
2323
- Tracing: features/tracing.md
2424
- Scheduling: features/scheduling.md
2525
- Resilient: features/resilient.md

0 commit comments

Comments
 (0)