Skip to content

Commit

Permalink
Cassandra module additional date time types support (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
GoodforGod committed Jul 31, 2023
1 parent 3ac2dc1 commit e761d94
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.*;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -71,6 +69,16 @@ public class CassandraNativeTypes {
(rsName, i) -> CodeBlock.of("$L.getInstant($L)", rsName, i),
(stmt, var, i) -> CodeBlock.of("$L.setInstant($L, $L)", stmt, i, var)
);
var localTime = CassandraNativeType.of(
TypeName.get(LocalTime.class),
(rsName, i) -> CodeBlock.of("$L.getLocalTime($L)", rsName, i),
(stmt, var, i) -> CodeBlock.of("$L.setLocalTime($L, $L)", stmt, i, var)
);
var zonedDateTime = CassandraNativeType.of(
TypeName.get(ZonedDateTime.class),
(rsName, i) -> CodeBlock.of("$L.get($L, $T.class)", rsName, i, ZonedDateTime.class),
(stmt, var, i) -> CodeBlock.of("$L.set($L, $L, $T.class)", stmt, i, var, ZonedDateTime.class)
);

nativeTypes = List.of(
booleanPrimitive,
Expand All @@ -86,7 +94,9 @@ public class CassandraNativeTypes {
byteBuffer,
localDateTime,
localDate,
instant
instant,
localTime,
zonedDateTime
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import com.squareup.javapoet.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import ru.tinkoff.kora.annotation.processor.common.*;
import ru.tinkoff.kora.annotation.processor.common.CommonClassNames;
import ru.tinkoff.kora.annotation.processor.common.CommonUtils;
import ru.tinkoff.kora.annotation.processor.common.FieldFactory;
import ru.tinkoff.kora.annotation.processor.common.Visitors;
import ru.tinkoff.kora.common.Tag;
import ru.tinkoff.kora.database.annotation.processor.DbUtils;
import ru.tinkoff.kora.database.annotation.processor.QueryWithParameters;
Expand All @@ -23,10 +26,7 @@
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.*;

public class CassandraRepositoryGenerator implements RepositoryGenerator {
private final TypeMirror repositoryInterface;
Expand Down Expand Up @@ -123,6 +123,7 @@ private MethodSpec generate(ExecutableElement method, ExecutableType methodType,
if (CommonUtils.isVoid(((DeclaredType) returnType).getTypeArguments().get(0))) {
b.addStatement("return $T.from(_rrs).then()", CommonClassNames.flux);
} else {
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
b.addStatement("return $N.apply(_rrs)", resultMapperName);
}
b.endControlFlow().addCode(")\n");// flatMap Statement
Expand All @@ -140,6 +141,7 @@ private MethodSpec generate(ExecutableElement method, ExecutableType methodType,
b.beginControlFlow("try");
b.addStatement("var _rs = _session.execute(_s)");
if (returnType.getKind() != TypeKind.VOID) {
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
b.addStatement("var _result = $N.apply(_rs)", resultMapperName);
}
b.addStatement("_telemetry.close(null)");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ public CassandraTypesExtension(ProcessingEnvironment env) {
}
},
fd -> CodeBlock.builder()
.beginControlFlow("if (_row.isNull($S))", fd.fieldName())
.beginControlFlow("if (_row.isNull(_idx_$L))", fd.fieldName())
.add(fd.nullable()
? CodeBlock.of("$N = null;\n", fd.fieldName())
: CodeBlock.of("throw new $T($S);\n", NullPointerException.class, "Result field %s is not nullable but row has null".formatted(fd.fieldName()))
: 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()))
)
.endControlFlow()
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ public MethodSpec generate(ExecutableElement method, ExecutableType methodType,
var result = CommonUtils.isNullable(method) || method.getReturnType().getKind().isPrimitive() || isMono
? CodeBlock.of("_result")
: CodeBlock.of("$T.requireNonNull(_result)", Objects.class);

Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());

b.addCode("try (var _rs = _stmt.executeQuery()) {$>\n")
.addCode("var _result = $L.apply(_rs);\n", resultMapperName)
.addCode("_telemetry.close(null);\n")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import com.squareup.javapoet.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import ru.tinkoff.kora.annotation.processor.common.*;
import ru.tinkoff.kora.annotation.processor.common.CommonUtils;
import ru.tinkoff.kora.annotation.processor.common.FieldFactory;
import ru.tinkoff.kora.annotation.processor.common.TagUtils;
import ru.tinkoff.kora.annotation.processor.common.Visitors;
import ru.tinkoff.kora.common.Context;
import ru.tinkoff.kora.common.Tag;
import ru.tinkoff.kora.database.annotation.processor.DbUtils;
Expand All @@ -26,6 +29,7 @@
import javax.lang.model.util.Types;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

public final class R2dbcRepositoryGenerator implements RepositoryGenerator {
Expand Down Expand Up @@ -121,8 +125,10 @@ private MethodSpec generate(ExecutableElement method, ExecutableType methodType,
if (returnType.toString().equals(DbUtils.UPDATE_COUNT.canonicalName())) {
b.addCode("return _flux.flatMap($T::getRowsUpdated).reduce(0L, Long::sum).map($T::new)", R2dbcTypes.RESULT, DbUtils.UPDATE_COUNT);
} else if (resultFluxMapper != null) {
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
b.addCode("return $L.apply(_flux)\n", resultMapperName);
} else if (rowMapper != null || !CommonUtils.isVoid(returnType)) {
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
b.addCode("return $L.apply(_flux)\n", resultMapperName);
} else {
b.addCode("return _flux.flatMap($T::getRowsUpdated).then()", R2dbcTypes.RESULT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ private MethodSpec generate(ExecutableElement method, ExecutableType methodType,
} else if (returnType.toString().equals(DbUtils.UPDATE_COUNT.canonicalName())) {
resultMapper = CodeBlock.of("$T::extractUpdateCount", VertxTypes.ROW_SET_MAPPER);
} else {
Objects.requireNonNull(resultMapperName, () -> "Illegal State occurred when expected to get result mapper, but got null in " + method.getEnclosingElement().getSimpleName() + "#" + method.getSimpleName());
resultMapper = CodeBlock.of("$N", resultMapperName);
}
if (returnType.getKind() != TypeKind.VOID) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@

import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.*;
import java.util.List;
import java.util.Optional;

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

default CassandraRowMapper<LocalTime> localTimeCassandraRowMapper() {
return row -> row.isNull(0)
? null
: row.getLocalTime(0);
}

default CassandraRowMapper<LocalDate> localDateCassandraRowMapper() {
return row -> row.isNull(0)
? null
Expand All @@ -86,6 +91,18 @@ default CassandraRowMapper<LocalDateTime> localDateTimeCassandraRowMapper() {
: row.get(0, LocalDateTime.class);
}

default CassandraRowMapper<ZonedDateTime> zonedDateTimeCassandraRowMapper() {
return row -> row.isNull(0)
? null
: row.get(0, ZonedDateTime.class);
}

default CassandraRowMapper<Instant> instantCassandraRowMapper() {
return row -> row.isNull(0)
? null
: row.getInstant(0);
}

default CassandraReactiveResultSetMapper<Void, Mono<Void>> voidMonoCassandraReactiveResultSetMapper() {
return rs -> Flux.from(rs).then();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.asTypeName
import java.math.BigDecimal
import java.nio.ByteBuffer
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.*

object CassandraNativeTypes {
private val nativeTypes = listOf(
Expand Down Expand Up @@ -111,6 +109,26 @@ object CassandraNativeTypes {
{ rsName, i -> CodeBlock.of("%N.getInstant(%L)", rsName, i) },
{ stmt, variableName, idx -> CodeBlock.of("%N.setInstant(%L, %L)", stmt, idx, variableName) },
),
CassandraNativeType.of(
LocalTime::class.asTypeName(),
{ rsName, i -> CodeBlock.of("%N.getLocalTime(%L)", rsName, i) },
{ stmt, variableName, idx -> CodeBlock.of("%N.setLocalTime(%L, %L)", stmt, idx, variableName) },
),
CassandraNativeType.of(
LocalTime::class.asTypeName().copy(true),
{ rsName, i -> CodeBlock.of("%N.getLocalTime(%L)", rsName, i) },
{ stmt, variableName, idx -> CodeBlock.of("%N.setLocalTime(%L, %L)", stmt, idx, variableName) },
),
CassandraNativeType.of(
ZonedDateTime::class.asTypeName(),
{ rsName, i -> CodeBlock.of("%N.get(%L, %T::class.java)", rsName, i) },
{ stmt, variableName, idx -> CodeBlock.of("%N.setLocalTime(%L, %L, %T::class.java)", stmt, idx, variableName, ZonedDateTime::class) },
),
CassandraNativeType.of(
ZonedDateTime::class.asTypeName().copy(true),
{ rsName, i -> CodeBlock.of("%N.get(%L, %T::class.java)", rsName, i) },
{ stmt, variableName, idx -> CodeBlock.of("%N.setLocalTime(%L, %L, %T::class.java)", stmt, idx, variableName, ZonedDateTime::class) },
),
)

fun findNativeType(typeName: TypeName): CassandraNativeType? {
Expand Down
8 changes: 4 additions & 4 deletions mkdocs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ nav:
- HTTP Server: features/http-server.md
- HTTP Client: features/http-client.md
- Кодогенерация из OpenAPI: features/openapi-codegen.md
- SOAP: features/soap.md
- Kafka: features/kafka.md
- Database: features/database.md
- Cassandra: features/cassandra.md
- Database SQL: features/database.md
- Database Cassandra: features/cassandra.md
- Json: features/json.md
- Soap: features/soap.md
- gRPC server: features/grpc-server.md
- gRPC Server: features/grpc-server.md
- Tracing: features/tracing.md
- Scheduling: features/scheduling.md
- Resilient: features/resilient.md
Expand Down

0 comments on commit e761d94

Please sign in to comment.