From 67a4be276ca339b73a7d1931fb8b44fe99516620 Mon Sep 17 00:00:00 2001 From: progress0407 Date: Wed, 21 Feb 2024 14:58:52 +0900 Subject: [PATCH 1/8] feat: implement power arithmetic operation --- docs/en/jpql-with-kotlin-jdsl/expressions.md | 3 + docs/ko/jpql-with-kotlin-jdsl/expressions.md | 4 +- .../com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt | 29 ++++++++ .../dsl/jpql/expression/PowerDslTest.kt | 73 +++++++++++++++++++ .../kotlinjdsl/dsl/jpql/entity/book/Book.kt | 1 + .../querymodel/jpql/expression/Expressions.kt | 9 +++ .../jpql/expression/impl/JpqlPower.kt | 13 ++++ .../jpql/expression/ExpressionsTest.kt | 15 ++++ .../render/jpql/JpqlRenderContext.kt | 2 + .../serializer/impl/JpqlPowerSerializer.kt | 26 +++++++ .../impl/JpqlPowerSerializerTest.kt | 60 +++++++++++++++ .../render/jpql/entity/book/Book.kt | 1 + 12 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt create mode 100644 query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt create mode 100644 render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt create mode 100644 render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt diff --git a/docs/en/jpql-with-kotlin-jdsl/expressions.md b/docs/en/jpql-with-kotlin-jdsl/expressions.md index e4006cf8b..56679be63 100644 --- a/docs/en/jpql-with-kotlin-jdsl/expressions.md +++ b/docs/en/jpql-with-kotlin-jdsl/expressions.md @@ -227,6 +227,7 @@ locate("Book", path(Book::title)) * FLOOR (floor) * INDEX (index) * LN (ln) +* POWER (power) * SIGN (sign) * SQRT (sqrt) * ROUND (round) @@ -245,6 +246,8 @@ index(path(Book::authors)) ln(path(Book::price)) +power(path(Book::verticalLength), 2) + sign(path(Book::price)) sqrt(path(Book::price)) diff --git a/docs/ko/jpql-with-kotlin-jdsl/expressions.md b/docs/ko/jpql-with-kotlin-jdsl/expressions.md index 158ae7478..388bd175f 100644 --- a/docs/ko/jpql-with-kotlin-jdsl/expressions.md +++ b/docs/ko/jpql-with-kotlin-jdsl/expressions.md @@ -223,6 +223,7 @@ locate("Book", path(Book::title)) * FLOOR (floor) * INDEX (index) * LN (ln) +* POWER (power) * SIGN (sign) * SQRT (sqrt) * ROUND (round) @@ -241,6 +242,8 @@ index(path(Book::authors)) ln(path(Book::price)) +power(path(Book::verticalLength), 2) + sign(path(Book::price)) sqrt(path(Book::price)) @@ -253,7 +256,6 @@ size(path(Book::authors)) | Function | DSL function | |----------|--------------| | MOD | not yet | -| POWER | not yet | ### Datetime functions diff --git a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt index d76395c42..a4bdf6e37 100644 --- a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt +++ b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt @@ -638,6 +638,35 @@ open class Jpql : JpqlDsl { return Expressions.ln(value.toExpression()) } + /** + * Creates an expression that represents the rounding of the value to a specified scale. + */ + @SinceJdsl("3.4.0") + fun power(expr: KProperty1, scale: Int): Expression { + return Expressions.round(Paths.path(expr), Expressions.value(scale)) + } + + /** + * Creates an expression that represents the rounding of the value to a specified scale. + */ + @SinceJdsl("3.4.0") + fun power(value: Expressionable, scale: Int): Expression { + return Expressions.round(value.toExpression(), Expressions.value(scale)) + } + + @SinceJdsl("3.4.0") + fun power(expr: KProperty1, scale: Expression): Expression { + return Expressions.round(Paths.path(expr), scale.toExpression()) + } + + /** + * Creates an expression that represents the rounding of the value to a specified scale. + */ + @SinceJdsl("3.4.0") + fun power(value: Expressionable, scale: Expressionable): Expression { + return Expressions.round(value.toExpression(), scale.toExpression()) + } + /** * Creates an expression that represents the sign of value. * diff --git a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt new file mode 100644 index 000000000..0e29ee05b --- /dev/null +++ b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt @@ -0,0 +1,73 @@ +package com.linecorp.kotlinjdsl.dsl.jpql.expression + +import com.linecorp.kotlinjdsl.dsl.jpql.entity.book.Book +import com.linecorp.kotlinjdsl.dsl.jpql.queryPart +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expression +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressions +import com.linecorp.kotlinjdsl.querymodel.jpql.path.Paths +import org.assertj.core.api.WithAssertions +import org.junit.jupiter.api.Test + +class PowerDslTest : WithAssertions { + private val intPath1 = Paths.path(Book::verticalLength) + private val intExpression1 = Expressions.value(2) + private val int1 = 2 + + @Test + fun `power() with a property`() { + // when + val expression1 = queryPart { + power(Book::verticalLength, int1) + }.toExpression() + + val expression2 = queryPart { + round(Book::verticalLength, intExpression1) + }.toExpression() + + val actual1: Expression = expression1 // for type check + val actual2: Expression = expression2 // for type check + + // then + val expected1 = Expressions.round( + value = Paths.path(Book::verticalLength), + scale = Expressions.value(int1), + ) + + val expected2 = Expressions.round( + value = Paths.path(Book::verticalLength), + scale = intExpression1, + ) + + assertThat(actual1).isEqualTo(expected1) + assertThat(actual2).isEqualTo(expected2) + } + + @Test + fun `power() with a expression`() { + // when + val expression1 = queryPart { + round(intPath1, int1) + }.toExpression() + + val expression2 = queryPart { + round(intPath1, intExpression1) + }.toExpression() + + val actual1: Expression = expression1 // for type check + val actual2: Expression = expression2 // for type check + + // then + val expected1 = Expressions.round( + value = intPath1, + scale = Expressions.value(int1), + ) + + val expected2 = Expressions.round( + value = intPath1, + scale = intExpression1, + ) + + assertThat(actual1).isEqualTo(expected1) + assertThat(actual2).isEqualTo(expected2) + } +} diff --git a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/book/Book.kt b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/book/Book.kt index bf99afdbe..1cb5c420d 100644 --- a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/book/Book.kt +++ b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/book/Book.kt @@ -9,6 +9,7 @@ class Book( val imageUrl: String, val price: BigDecimal, val salePrice: BigDecimal, + val verticalLength: Int, val publishDate: OffsetDateTime, val authors: MutableSet, val publisher: BookPublisher, diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt index 75f837d67..fa272c7e5 100644 --- a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt @@ -39,6 +39,7 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlNullIf import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlParam import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlPathType import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlPlus +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlPower import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlRound import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSign import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSize @@ -276,6 +277,14 @@ object Expressions { return JpqlLn(value) } + /** + * Creates an expression that represents the rounding of the specified value to a specified scale. + */ + @SinceJdsl("3.4.0") + fun power(value: Expression, scale: Expression): Expression { + return JpqlPower(value, scale) + } + /** * Creates an expression that represents the sign of a numeric value. */ diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt new file mode 100644 index 000000000..e9d12688c --- /dev/null +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt @@ -0,0 +1,13 @@ +package com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl + +import com.linecorp.kotlinjdsl.Internal +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expression + +/** + * Expression that calculates the rounding of a numeric [value] to a specified [scale]. + */ +@Internal +data class JpqlPower internal constructor( + val value: Expression, + val scale: Expression, +) : Expression diff --git a/query-model/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/ExpressionsTest.kt b/query-model/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/ExpressionsTest.kt index 1926ff3fb..38a02b2d6 100644 --- a/query-model/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/ExpressionsTest.kt +++ b/query-model/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/ExpressionsTest.kt @@ -41,6 +41,7 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlNullIf import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlParam import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlPathType import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlPlus +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlPower import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlRound import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSign import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSize @@ -427,6 +428,20 @@ class ExpressionsTest : WithAssertions { assertThat(actual).isEqualTo(expected) } + @Test + fun power() { + // when + val actual = Expressions.power(doubleExpression1, intExpression1) + + // then + val expected = JpqlPower( + doubleExpression1, + intExpression1, + ) + + assertThat(actual).isEqualTo(expected) + } + @Test fun sign() { // when diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt index b805b01cc..0c73760a1 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt @@ -104,6 +104,7 @@ import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlPathPropertySeria import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlPathTreatSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlPathTypeSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlPlusSerializer +import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlPowerSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlPredicateParenthesesSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlRoundSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlSelectQuerySerializer @@ -368,6 +369,7 @@ private class DefaultModule : JpqlRenderModule { JpqlPredicateParenthesesSerializer(), JpqlRoundSerializer(), JpqlSelectQuerySerializer(), + JpqlPowerSerializer(), JpqlSignSerializer(), JpqlSizeSerializer(), JpqlSortSerializer(), diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt new file mode 100644 index 000000000..e5ab7d681 --- /dev/null +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt @@ -0,0 +1,26 @@ +package com.linecorp.kotlinjdsl.render.jpql.serializer.impl + +import com.linecorp.kotlinjdsl.Internal +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlPower +import com.linecorp.kotlinjdsl.render.RenderContext +import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlRenderSerializer +import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializer +import com.linecorp.kotlinjdsl.render.jpql.writer.JpqlWriter +import kotlin.reflect.KClass + +@Internal +class JpqlPowerSerializer : JpqlSerializer> { + override fun handledType(): KClass> { + return JpqlPower::class + } + + override fun serialize(part: JpqlPower<*>, writer: JpqlWriter, context: RenderContext) { + val delegate = context.getValue(JpqlRenderSerializer) + + writer.write("POWER") + + writer.writeParentheses { + delegate.serialize(part.value, writer, context) + } + } +} diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt new file mode 100644 index 000000000..dfbed610c --- /dev/null +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt @@ -0,0 +1,60 @@ +package com.linecorp.kotlinjdsl.render.jpql.serializer.impl + +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressions +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlPower +import com.linecorp.kotlinjdsl.querymodel.jpql.path.Paths +import com.linecorp.kotlinjdsl.render.TestRenderContext +import com.linecorp.kotlinjdsl.render.jpql.entity.book.Book +import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlRenderSerializer +import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializerTest +import com.linecorp.kotlinjdsl.render.jpql.writer.JpqlWriter +import io.mockk.impl.annotations.MockK +import io.mockk.verifySequence +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +@JpqlSerializerTest +class JpqlPowerSerializerTest { + private val sut = JpqlPowerSerializer() + + @MockK + private lateinit var writer: JpqlWriter + + @MockK + private lateinit var serializer: JpqlRenderSerializer + + private val expression1 = Paths.path(Book::verticalLength) + private val expression2 = Expressions.value(2) + + @Test + fun handledType() { + // when + val actual = sut.handledType() + + // then + assertThat(actual).isEqualTo(JpqlPower::class) + } + + @Test + fun serialize() { + // given + val part = Expressions.round( + value = expression1, + scale = expression2, + ) + val context = TestRenderContext(serializer) + + // when + sut.serialize(part as JpqlPower<*>, writer, context) + + // then + verifySequence { + writer.write("POWER") + writer.writeParentheses(any()) + serializer.serialize(expression1, writer, context) + writer.write(",") + writer.write(" ") + serializer.serialize(expression2, writer, context) + } + } +} diff --git a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/book/Book.kt b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/book/Book.kt index 4fa2c1e30..007301180 100644 --- a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/book/Book.kt +++ b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/book/Book.kt @@ -9,6 +9,7 @@ class Book( val imageUrl: String, val price: BigDecimal, val salePrice: BigDecimal, + val verticalLength: Int, val publishDate: OffsetDateTime, val authors: MutableSet, val publisher: BookPublisher, From 2384029f46cf91eed5f86758880837dcf16593bf Mon Sep 17 00:00:00 2001 From: progress0407 Date: Wed, 21 Feb 2024 19:06:07 +0900 Subject: [PATCH 2/8] style: merged from develop and reorder expressions --- .../com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt | 32 ++++++++ .../dsl/jpql/expression/ModDslTest.kt | 74 +++++++++++++++++++ .../dsl/jpql/entity/employee/Employee.kt | 1 + .../jpql/entity/employee/FullTimeEmployee.kt | 2 + .../jpql/entity/employee/PartTimeEmployee.kt | 2 + .../querymodel/jpql/expression/Expressions.kt | 9 +++ .../jpql/expression/impl/JpqlMod.kt | 13 ++++ .../jpql/expression/ExpressionsTest.kt | 15 ++++ .../render/jpql/JpqlRenderContext.kt | 2 + .../jpql/serializer/impl/JpqlModSerializer.kt | 31 ++++++++ .../serializer/impl/JpqlModSerializerTest.kt | 60 +++++++++++++++ .../render/jpql/entity/employee/Employee.kt | 1 + .../jpql/entity/employee/FullTimeEmployee.kt | 2 + .../jpql/entity/employee/PartTimeEmployee.kt | 2 + 14 files changed, 246 insertions(+) create mode 100644 dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/ModDslTest.kt create mode 100644 query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlMod.kt create mode 100644 render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlModSerializer.kt create mode 100644 render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlModSerializerTest.kt diff --git a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt index a4bdf6e37..874120cde 100644 --- a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt +++ b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt @@ -638,6 +638,38 @@ open class Jpql : JpqlDsl { return Expressions.ln(value.toExpression()) } + /** + * Creates an expression that represents the mod of values. + */ + @SinceJdsl("3.4.0") + fun mod(expr: KProperty1, value: Int): Expression { + return Expressions.mod(Paths.path(expr), Expressions.value(value)) + } + + /** + * Creates an expression that represents the mod of values. + */ + @SinceJdsl("3.4.0") + fun mod(value1: Expressionable, value2: Int): Expression { + return Expressions.mod(value1.toExpression(), Expressions.value(value2)) + } + + /** + * Creates an expression that represents the mod of values. + */ + @SinceJdsl("3.4.0") + fun mod(expr: KProperty1, value: Expression): Expression { + return Expressions.mod(Paths.path(expr), value.toExpression()) + } + + /** + * Creates an expression that represents the mod of values. + */ + @SinceJdsl("3.4.0") + fun mod(value1: Expressionable, value2: Expressionable): Expression { + return Expressions.mod(value1.toExpression(), value2.toExpression()) + } + /** * Creates an expression that represents the rounding of the value to a specified scale. */ diff --git a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/ModDslTest.kt b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/ModDslTest.kt new file mode 100644 index 000000000..b87901cb1 --- /dev/null +++ b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/ModDslTest.kt @@ -0,0 +1,74 @@ +package com.linecorp.kotlinjdsl.dsl.jpql.expression + +import com.linecorp.kotlinjdsl.dsl.jpql.entity.employee.Employee +import com.linecorp.kotlinjdsl.dsl.jpql.queryPart +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expression +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressions +import com.linecorp.kotlinjdsl.querymodel.jpql.path.Paths +import org.assertj.core.api.WithAssertions +import org.junit.jupiter.api.Test + +class ModDslTest : WithAssertions { + private val intExpression1 = Paths.path(Employee::age) + private val intExpression2 = Expressions.value(2) + + private val int1 = 2 + + @Test + fun `mod() with a property`() { + // when + val expression1 = queryPart { + mod(Employee::age, int1) + }.toExpression() + + val expression2 = queryPart { + mod(Employee::age, intExpression1) + }.toExpression() + + val actual1: Expression = expression1 // for type check + val actual2: Expression = expression2 // for type check + + // then + val expected1 = Expressions.mod( + value1 = Paths.path(Employee::age), + value2 = Expressions.value(int1), + ) + + val expected2 = Expressions.mod( + value1 = Paths.path(Employee::age), + value2 = intExpression1, + ) + + assertThat(actual1).isEqualTo(expected1) + assertThat(actual2).isEqualTo(expected2) + } + + @Test + fun `mod() with a expression`() { + // when + val expression1 = queryPart { + mod(intExpression1, int1) + }.toExpression() + + val expression2 = queryPart { + mod(intExpression1, intExpression2) + }.toExpression() + + val actual1: Expression = expression1 // for type check + val actual2: Expression = expression2 // for type check + + // then + val expected1 = Expressions.mod( + value1 = intExpression1, + value2 = Expressions.value(int1), + ) + + val expected2 = Expressions.mod( + value1 = intExpression1, + value2 = intExpression2, + ) + + assertThat(actual1).isEqualTo(expected1) + assertThat(actual2).isEqualTo(expected2) + } +} diff --git a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/Employee.kt b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/Employee.kt index 293ce31bb..6fbe50d0e 100644 --- a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/Employee.kt +++ b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/Employee.kt @@ -4,6 +4,7 @@ abstract class Employee( val employeeId: Long, val name: String, val nickname: String?, + val age: Int, val phone: String, val address: EmployeeAddress, val departments: MutableSet, diff --git a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/FullTimeEmployee.kt b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/FullTimeEmployee.kt index 6eb177bb8..f023be25b 100644 --- a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/FullTimeEmployee.kt +++ b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/FullTimeEmployee.kt @@ -6,6 +6,7 @@ class FullTimeEmployee( employeeId: Long, name: String, nickname: String?, + age: Int, phone: String, address: EmployeeAddress, departments: MutableSet, @@ -14,6 +15,7 @@ class FullTimeEmployee( employeeId = employeeId, name = name, nickname = nickname, + age = age, phone = phone, address = address, departments = departments, diff --git a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/PartTimeEmployee.kt b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/PartTimeEmployee.kt index ffc4e87f7..cfb1bb117 100644 --- a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/PartTimeEmployee.kt +++ b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/employee/PartTimeEmployee.kt @@ -6,6 +6,7 @@ class PartTimeEmployee( employeeId: Long, name: String, nickname: String?, + age: Int, phone: String, address: EmployeeAddress, departments: MutableSet, @@ -14,6 +15,7 @@ class PartTimeEmployee( employeeId = employeeId, name = name, nickname = nickname, + age = age, phone = phone, address = address, departments = departments, diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt index fa272c7e5..465d6d568 100644 --- a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt @@ -33,6 +33,7 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlLower import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMax import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMin import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMinus +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMod import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlNew import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlNull import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlNullIf @@ -309,6 +310,14 @@ object Expressions { return JpqlRound(value, scale) } + /** + * Creates an expression that represents the mod of values. + */ + @SinceJdsl("3.4.0") + fun mod(value1: Expression, value2: Expression): Expression { + return JpqlMod(value1, value2) + } + /** * Creates an expression that represents the number of elements of the collection. */ diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlMod.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlMod.kt new file mode 100644 index 000000000..fa1da8e34 --- /dev/null +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlMod.kt @@ -0,0 +1,13 @@ +package com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl + +import com.linecorp.kotlinjdsl.Internal +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expression + +/** + * Expression that calculates the mod of a integer [value1] to a specified integer [value2]. + */ +@Internal +data class JpqlMod internal constructor( + val value1: Expression, + val value2: Expression, +) : Expression diff --git a/query-model/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/ExpressionsTest.kt b/query-model/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/ExpressionsTest.kt index 38a02b2d6..e2d937e39 100644 --- a/query-model/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/ExpressionsTest.kt +++ b/query-model/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/ExpressionsTest.kt @@ -35,6 +35,7 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlLower import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMax import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMin import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMinus +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMod import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlNew import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlNull import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlNullIf @@ -482,6 +483,20 @@ class ExpressionsTest : WithAssertions { assertThat(actual).isEqualTo(expected) } + @Test + fun mod() { + // when + val actual = Expressions.mod(intExpression1, intExpression2) + + // then + val expected = JpqlMod( + intExpression1, + intExpression2, + ) + + assertThat(actual).isEqualTo(expected) + } + @Test fun size() { // when diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt index 0c73760a1..b2c3b22be 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt @@ -86,6 +86,7 @@ import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlLowerSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlMaxSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlMinSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlMinusSerializer +import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlModSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlNewSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlNotBetweenSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlNotEqualAllSerializer @@ -348,6 +349,7 @@ private class DefaultModule : JpqlRenderModule { JpqlMaxSerializer(), JpqlMinSerializer(), JpqlMinusSerializer(), + JpqlModSerializer(), JpqlNewSerializer(), JpqlNotBetweenSerializer(), JpqlNotEqualAllSerializer(), diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlModSerializer.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlModSerializer.kt new file mode 100644 index 000000000..395599bd9 --- /dev/null +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlModSerializer.kt @@ -0,0 +1,31 @@ +package com.linecorp.kotlinjdsl.render.jpql.serializer.impl + +import com.linecorp.kotlinjdsl.Internal +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMod +import com.linecorp.kotlinjdsl.render.RenderContext +import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlRenderSerializer +import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializer +import com.linecorp.kotlinjdsl.render.jpql.writer.JpqlWriter +import kotlin.reflect.KClass + +@Internal +class JpqlModSerializer : JpqlSerializer { + override fun handledType(): KClass { + return JpqlMod::class + } + + override fun serialize(part: JpqlMod, writer: JpqlWriter, context: RenderContext) { + val delegate = context.getValue(JpqlRenderSerializer) + + writer.write("MOD") + + writer.writeParentheses { + delegate.serialize(part.value1, writer, context) + + writer.write(",") + writer.write(" ") + + delegate.serialize(part.value2, writer, context) + } + } +} diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlModSerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlModSerializerTest.kt new file mode 100644 index 000000000..4990eec99 --- /dev/null +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlModSerializerTest.kt @@ -0,0 +1,60 @@ +package com.linecorp.kotlinjdsl.render.jpql.serializer.impl + +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressions +import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlMod +import com.linecorp.kotlinjdsl.querymodel.jpql.path.Paths +import com.linecorp.kotlinjdsl.render.TestRenderContext +import com.linecorp.kotlinjdsl.render.jpql.entity.employee.Employee +import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlRenderSerializer +import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializerTest +import com.linecorp.kotlinjdsl.render.jpql.writer.JpqlWriter +import io.mockk.impl.annotations.MockK +import io.mockk.verifySequence +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +@JpqlSerializerTest +class JpqlModSerializerTest { + private val sut = JpqlModSerializer() + + @MockK + private lateinit var writer: JpqlWriter + + @MockK + private lateinit var serializer: JpqlRenderSerializer + + private val expression1 = Paths.path(Employee::age) + private val expression2 = Expressions.value(3) + + @Test + fun handledType() { + // when + val actual = sut.handledType() + + // then + assertThat(actual).isEqualTo(JpqlMod::class) + } + + @Test + fun serialize() { + // given + val part = Expressions.mod( + value1 = expression1, + value2 = expression2, + ) + val context = TestRenderContext(serializer) + + // when + sut.serialize(part as JpqlMod, writer, context) + + // then + verifySequence { + writer.write("MOD") + writer.writeParentheses(any()) + serializer.serialize(expression1, writer, context) + writer.write(",") + writer.write(" ") + serializer.serialize(expression2, writer, context) + } + } +} diff --git a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/Employee.kt b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/Employee.kt index b7c8adf41..b26bae7b1 100644 --- a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/Employee.kt +++ b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/Employee.kt @@ -4,6 +4,7 @@ abstract class Employee( val employeeId: Long, val name: String, val nickname: String?, + val age: Int, val phone: String, val address: EmployeeAddress, val departments: MutableSet, diff --git a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/FullTimeEmployee.kt b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/FullTimeEmployee.kt index 7da53527d..668d35937 100644 --- a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/FullTimeEmployee.kt +++ b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/FullTimeEmployee.kt @@ -6,6 +6,7 @@ class FullTimeEmployee( employeeId: Long, name: String, nickname: String?, + age: Int, phone: String, address: EmployeeAddress, departments: MutableSet, @@ -14,6 +15,7 @@ class FullTimeEmployee( employeeId = employeeId, name = name, nickname = nickname, + age = age, phone = phone, address = address, departments = departments, diff --git a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/PartTimeEmployee.kt b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/PartTimeEmployee.kt index 539c089b3..8321b8aeb 100644 --- a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/PartTimeEmployee.kt +++ b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/employee/PartTimeEmployee.kt @@ -6,6 +6,7 @@ class PartTimeEmployee( employeeId: Long, name: String, nickname: String?, + age: Int, phone: String, address: EmployeeAddress, departments: MutableSet, @@ -14,6 +15,7 @@ class PartTimeEmployee( employeeId = employeeId, name = name, nickname = nickname, + age = age, phone = phone, address = address, departments = departments, From 9822e0b7b694553a0c4b0e880c719b89d28f586e Mon Sep 17 00:00:00 2001 From: progress0407 Date: Wed, 21 Feb 2024 19:14:51 +0900 Subject: [PATCH 3/8] test: remove book property and choose employ fixture --- .../kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt | 12 ++++++------ .../linecorp/kotlinjdsl/dsl/jpql/entity/book/Book.kt | 1 - .../jpql/serializer/impl/JpqlPowerSerializerTest.kt | 4 ++-- .../kotlinjdsl/render/jpql/entity/book/Book.kt | 1 - 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt index 0e29ee05b..3c0a33a9e 100644 --- a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt +++ b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt @@ -1,6 +1,6 @@ package com.linecorp.kotlinjdsl.dsl.jpql.expression -import com.linecorp.kotlinjdsl.dsl.jpql.entity.book.Book +import com.linecorp.kotlinjdsl.dsl.jpql.entity.employee.Employee import com.linecorp.kotlinjdsl.dsl.jpql.queryPart import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expression import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressions @@ -9,7 +9,7 @@ import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.Test class PowerDslTest : WithAssertions { - private val intPath1 = Paths.path(Book::verticalLength) + private val intPath1 = Paths.path(Employee::age) private val intExpression1 = Expressions.value(2) private val int1 = 2 @@ -17,11 +17,11 @@ class PowerDslTest : WithAssertions { fun `power() with a property`() { // when val expression1 = queryPart { - power(Book::verticalLength, int1) + power(Employee::age, int1) }.toExpression() val expression2 = queryPart { - round(Book::verticalLength, intExpression1) + round(Employee::age, intExpression1) }.toExpression() val actual1: Expression = expression1 // for type check @@ -29,12 +29,12 @@ class PowerDslTest : WithAssertions { // then val expected1 = Expressions.round( - value = Paths.path(Book::verticalLength), + value = Paths.path(Employee::age), scale = Expressions.value(int1), ) val expected2 = Expressions.round( - value = Paths.path(Book::verticalLength), + value = Paths.path(Employee::age), scale = intExpression1, ) diff --git a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/book/Book.kt b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/book/Book.kt index 1cb5c420d..bf99afdbe 100644 --- a/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/book/Book.kt +++ b/dsl/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/entity/book/Book.kt @@ -9,7 +9,6 @@ class Book( val imageUrl: String, val price: BigDecimal, val salePrice: BigDecimal, - val verticalLength: Int, val publishDate: OffsetDateTime, val authors: MutableSet, val publisher: BookPublisher, diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt index dfbed610c..29b13294e 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt @@ -4,7 +4,7 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressions import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlPower import com.linecorp.kotlinjdsl.querymodel.jpql.path.Paths import com.linecorp.kotlinjdsl.render.TestRenderContext -import com.linecorp.kotlinjdsl.render.jpql.entity.book.Book +import com.linecorp.kotlinjdsl.render.jpql.entity.employee.Employee import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlRenderSerializer import com.linecorp.kotlinjdsl.render.jpql.serializer.JpqlSerializerTest import com.linecorp.kotlinjdsl.render.jpql.writer.JpqlWriter @@ -23,7 +23,7 @@ class JpqlPowerSerializerTest { @MockK private lateinit var serializer: JpqlRenderSerializer - private val expression1 = Paths.path(Book::verticalLength) + private val expression1 = Paths.path(Employee::age) private val expression2 = Expressions.value(2) @Test diff --git a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/book/Book.kt b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/book/Book.kt index 007301180..4fa2c1e30 100644 --- a/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/book/Book.kt +++ b/render/jpql/src/testFixtures/kotlin/com/linecorp/kotlinjdsl/render/jpql/entity/book/Book.kt @@ -9,7 +9,6 @@ class Book( val imageUrl: String, val price: BigDecimal, val salePrice: BigDecimal, - val verticalLength: Int, val publishDate: OffsetDateTime, val authors: MutableSet, val publisher: BookPublisher, From bfb8d484de101bbd3a2ca848c44d15df12c594f6 Mon Sep 17 00:00:00 2001 From: progress0407 Date: Wed, 21 Feb 2024 20:24:35 +0900 Subject: [PATCH 4/8] style: rewrite comments to conform to conventions --- .../com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt | 25 +++++++++++-------- .../querymodel/jpql/expression/Expressions.kt | 6 ++--- .../jpql/expression/impl/JpqlPower.kt | 6 ++--- .../serializer/impl/JpqlPowerSerializer.kt | 2 +- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt index 874120cde..0c57762d0 100644 --- a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt +++ b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt @@ -671,32 +671,35 @@ open class Jpql : JpqlDsl { } /** - * Creates an expression that represents the rounding of the value to a specified scale. + * Create expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @SinceJdsl("3.4.0") - fun power(expr: KProperty1, scale: Int): Expression { - return Expressions.round(Paths.path(expr), Expressions.value(scale)) + fun power(base: KProperty1, exponent: Int): Expression { + return Expressions.round(Paths.path(base), Expressions.value(exponent)) } /** - * Creates an expression that represents the rounding of the value to a specified scale. + * Create expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @SinceJdsl("3.4.0") - fun power(value: Expressionable, scale: Int): Expression { - return Expressions.round(value.toExpression(), Expressions.value(scale)) + fun power(base: Expressionable, exponent: Int): Expression { + return Expressions.round(base.toExpression(), Expressions.value(exponent)) } + /** + * Create expression that calculates the powering of a numeric [base] to a specified [exponent]. + */ @SinceJdsl("3.4.0") - fun power(expr: KProperty1, scale: Expression): Expression { - return Expressions.round(Paths.path(expr), scale.toExpression()) + fun power(base: KProperty1, exponent: Expression): Expression { + return Expressions.round(Paths.path(base), exponent.toExpression()) } /** - * Creates an expression that represents the rounding of the value to a specified scale. + * Create expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @SinceJdsl("3.4.0") - fun power(value: Expressionable, scale: Expressionable): Expression { - return Expressions.round(value.toExpression(), scale.toExpression()) + fun power(base: Expressionable, exponent: Expressionable): Expression { + return Expressions.round(base.toExpression(), exponent.toExpression()) } /** diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt index 465d6d568..642f2ebe0 100644 --- a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt @@ -279,11 +279,11 @@ object Expressions { } /** - * Creates an expression that represents the rounding of the specified value to a specified scale. + * Creates expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @SinceJdsl("3.4.0") - fun power(value: Expression, scale: Expression): Expression { - return JpqlPower(value, scale) + fun power(base: Expression, exponent: Expression): Expression { + return JpqlPower(base, exponent) } /** diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt index e9d12688c..eecc9b2d2 100644 --- a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt @@ -4,10 +4,10 @@ import com.linecorp.kotlinjdsl.Internal import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expression /** - * Expression that calculates the rounding of a numeric [value] to a specified [scale]. + * Expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @Internal data class JpqlPower internal constructor( - val value: Expression, - val scale: Expression, + val base: Expression, + val exponent: Expression, ) : Expression diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt index e5ab7d681..41edd4c6c 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt @@ -20,7 +20,7 @@ class JpqlPowerSerializer : JpqlSerializer> { writer.write("POWER") writer.writeParentheses { - delegate.serialize(part.value, writer, context) + delegate.serialize(part.base, writer, context) } } } From 8b8046707b6d84ada6e1a33716f571c400cbc87a Mon Sep 17 00:00:00 2001 From: progress0407 Date: Wed, 21 Feb 2024 20:57:11 +0900 Subject: [PATCH 5/8] fix: fix poorly implemented serializer code --- .../render/jpql/serializer/impl/JpqlPowerSerializer.kt | 5 +++++ .../render/jpql/serializer/impl/JpqlPowerSerializerTest.kt | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt index 41edd4c6c..49c273cf1 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializer.kt @@ -21,6 +21,11 @@ class JpqlPowerSerializer : JpqlSerializer> { writer.writeParentheses { delegate.serialize(part.base, writer, context) + + writer.write(",") + writer.write(" ") + + delegate.serialize(part.exponent, writer, context) } } } diff --git a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt index 29b13294e..1bddd5e89 100644 --- a/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt +++ b/render/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/render/jpql/serializer/impl/JpqlPowerSerializerTest.kt @@ -38,9 +38,9 @@ class JpqlPowerSerializerTest { @Test fun serialize() { // given - val part = Expressions.round( - value = expression1, - scale = expression2, + val part = Expressions.power( + base = expression1, + exponent = expression2, ) val context = TestRenderContext(serializer) From 69109b2f20a3dda99fef1d9e35d68719a645bf97 Mon Sep 17 00:00:00 2001 From: progress0407 Date: Thu, 22 Feb 2024 10:11:05 +0900 Subject: [PATCH 6/8] fix: fix poorly implemented jpql code and test --- .../com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt | 8 ++-- .../dsl/jpql/expression/PowerDslTest.kt | 38 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt index 0c57762d0..2c477a4a2 100644 --- a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt +++ b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt @@ -675,7 +675,7 @@ open class Jpql : JpqlDsl { */ @SinceJdsl("3.4.0") fun power(base: KProperty1, exponent: Int): Expression { - return Expressions.round(Paths.path(base), Expressions.value(exponent)) + return Expressions.power(Paths.path(base), Expressions.value(exponent)) } /** @@ -683,7 +683,7 @@ open class Jpql : JpqlDsl { */ @SinceJdsl("3.4.0") fun power(base: Expressionable, exponent: Int): Expression { - return Expressions.round(base.toExpression(), Expressions.value(exponent)) + return Expressions.power(base.toExpression(), Expressions.value(exponent)) } /** @@ -691,7 +691,7 @@ open class Jpql : JpqlDsl { */ @SinceJdsl("3.4.0") fun power(base: KProperty1, exponent: Expression): Expression { - return Expressions.round(Paths.path(base), exponent.toExpression()) + return Expressions.power(Paths.path(base), exponent.toExpression()) } /** @@ -699,7 +699,7 @@ open class Jpql : JpqlDsl { */ @SinceJdsl("3.4.0") fun power(base: Expressionable, exponent: Expressionable): Expression { - return Expressions.round(base.toExpression(), exponent.toExpression()) + return Expressions.power(base.toExpression(), exponent.toExpression()) } /** diff --git a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt index 3c0a33a9e..bd346f15b 100644 --- a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt +++ b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt @@ -9,33 +9,33 @@ import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.Test class PowerDslTest : WithAssertions { - private val intPath1 = Paths.path(Employee::age) - private val intExpression1 = Expressions.value(2) - private val int1 = 2 + private val baseExpression = Paths.path(Employee::age) + private val exponentExpression = Expressions.value(2) + private val exponentPrimitive = 2 @Test fun `power() with a property`() { // when val expression1 = queryPart { - power(Employee::age, int1) + power(Employee::age, exponentPrimitive) }.toExpression() val expression2 = queryPart { - round(Employee::age, intExpression1) + power(Employee::age, exponentExpression) }.toExpression() val actual1: Expression = expression1 // for type check val actual2: Expression = expression2 // for type check // then - val expected1 = Expressions.round( - value = Paths.path(Employee::age), - scale = Expressions.value(int1), + val expected1 = Expressions.power( + base = Paths.path(Employee::age), + exponent = Expressions.value(exponentPrimitive), ) - val expected2 = Expressions.round( - value = Paths.path(Employee::age), - scale = intExpression1, + val expected2 = Expressions.power( + base = Paths.path(Employee::age), + exponent = exponentExpression, ) assertThat(actual1).isEqualTo(expected1) @@ -46,25 +46,25 @@ class PowerDslTest : WithAssertions { fun `power() with a expression`() { // when val expression1 = queryPart { - round(intPath1, int1) + power(baseExpression, exponentPrimitive) }.toExpression() val expression2 = queryPart { - round(intPath1, intExpression1) + power(baseExpression, exponentExpression) }.toExpression() val actual1: Expression = expression1 // for type check val actual2: Expression = expression2 // for type check // then - val expected1 = Expressions.round( - value = intPath1, - scale = Expressions.value(int1), + val expected1 = Expressions.power( + base = baseExpression, + exponent = Expressions.value(exponentPrimitive), ) - val expected2 = Expressions.round( - value = intPath1, - scale = intExpression1, + val expected2 = Expressions.power( + base = baseExpression, + exponent = exponentExpression, ) assertThat(actual1).isEqualTo(expected1) From 1bfb2cf5c5cf02fee763d7cf58bbf9e1835a8e51 Mon Sep 17 00:00:00 2001 From: progress0407 Date: Fri, 23 Feb 2024 02:31:21 +0900 Subject: [PATCH 7/8] docs: reflect reviews of updating example --- docs/en/jpql-with-kotlin-jdsl/expressions.md | 2 +- docs/ko/jpql-with-kotlin-jdsl/expressions.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/jpql-with-kotlin-jdsl/expressions.md b/docs/en/jpql-with-kotlin-jdsl/expressions.md index 55c66cc5b..85b23792d 100644 --- a/docs/en/jpql-with-kotlin-jdsl/expressions.md +++ b/docs/en/jpql-with-kotlin-jdsl/expressions.md @@ -249,7 +249,7 @@ ln(path(Book::price)) mod(path(Employee::age), 3) -power(path(Book::verticalLength), 2) +power(path(Employee::age), 2) sign(path(Book::price)) diff --git a/docs/ko/jpql-with-kotlin-jdsl/expressions.md b/docs/ko/jpql-with-kotlin-jdsl/expressions.md index 22ff39076..5bae48f6d 100644 --- a/docs/ko/jpql-with-kotlin-jdsl/expressions.md +++ b/docs/ko/jpql-with-kotlin-jdsl/expressions.md @@ -245,7 +245,7 @@ ln(path(Book::price)) mod(path(Employee::age), 3) -power(path(Book::verticalLength), 2) +power(path(Employee::age), 2) sign(path(Book::price)) From 5d231b10e7c5f2282c80951075e771baef159f0d Mon Sep 17 00:00:00 2001 From: progress0407 Date: Wed, 13 Mar 2024 01:34:43 +0900 Subject: [PATCH 8/8] refactor: reflect reviews of updating example --- .../com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt | 76 +++++++++---------- .../dsl/jpql/expression/PowerDslTest.kt | 35 ++++----- .../querymodel/jpql/expression/Expressions.kt | 2 +- .../jpql/expression/impl/JpqlPower.kt | 4 +- .../render/jpql/JpqlRenderContext.kt | 2 +- 5 files changed, 60 insertions(+), 59 deletions(-) diff --git a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt index 4d6b95262..67a437fc6 100644 --- a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt +++ b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt @@ -646,43 +646,11 @@ open class Jpql : JpqlDsl { return Expressions.ln(value.toExpression()) } - /** - * Creates an expression that represents the mod of values. - */ - @SinceJdsl("3.4.0") - fun mod(expr: KProperty1, value: Int): Expression { - return Expressions.mod(Paths.path(expr), Expressions.value(value)) - } - - /** - * Creates an expression that represents the mod of values. - */ - @SinceJdsl("3.4.0") - fun mod(value1: Expressionable, value2: Int): Expression { - return Expressions.mod(value1.toExpression(), Expressions.value(value2)) - } - - /** - * Creates an expression that represents the mod of values. - */ - @SinceJdsl("3.4.0") - fun mod(expr: KProperty1, value: Expression): Expression { - return Expressions.mod(Paths.path(expr), value.toExpression()) - } - - /** - * Creates an expression that represents the mod of values. - */ - @SinceJdsl("3.4.0") - fun mod(value1: Expressionable, value2: Expressionable): Expression { - return Expressions.mod(value1.toExpression(), value2.toExpression()) - } - /** * Create expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @SinceJdsl("3.4.0") - fun power(base: KProperty1, exponent: Int): Expression { + fun power(base: KProperty1, exponent: Number): Expression { return Expressions.power(Paths.path(base), Expressions.value(exponent)) } @@ -690,23 +658,23 @@ open class Jpql : JpqlDsl { * Create expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @SinceJdsl("3.4.0") - fun power(base: Expressionable, exponent: Int): Expression { - return Expressions.power(base.toExpression(), Expressions.value(exponent)) + fun power(base: KProperty1, exponent: Expressionable): Expression { + return Expressions.power(Paths.path(base), exponent.toExpression()) } /** * Create expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @SinceJdsl("3.4.0") - fun power(base: KProperty1, exponent: Expression): Expression { - return Expressions.power(Paths.path(base), exponent.toExpression()) + fun power(base: Expressionable, exponent: T): Expression { + return Expressions.power(base.toExpression(), Expressions.value(exponent)) } /** * Create expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @SinceJdsl("3.4.0") - fun power(base: Expressionable, exponent: Expressionable): Expression { + fun power(base: Expressionable, exponent: Expressionable): Expression { return Expressions.power(base.toExpression(), exponent.toExpression()) } @@ -782,6 +750,38 @@ open class Jpql : JpqlDsl { return Expressions.round(value.toExpression(), scale.toExpression()) } + /** + * Creates an expression that represents the mod of values. + */ + @SinceJdsl("3.4.0") + fun mod(expr: KProperty1, value: Int): Expression { + return Expressions.mod(Paths.path(expr), Expressions.value(value)) + } + + /** + * Creates an expression that represents the mod of values. + */ + @SinceJdsl("3.4.0") + fun mod(value1: Expressionable, value2: Int): Expression { + return Expressions.mod(value1.toExpression(), Expressions.value(value2)) + } + + /** + * Creates an expression that represents the mod of values. + */ + @SinceJdsl("3.4.0") + fun mod(expr: KProperty1, value: Expression): Expression { + return Expressions.mod(Paths.path(expr), value.toExpression()) + } + + /** + * Creates an expression that represents the mod of values. + */ + @SinceJdsl("3.4.0") + fun mod(value1: Expressionable, value2: Expressionable): Expression { + return Expressions.mod(value1.toExpression(), value2.toExpression()) + } + /** * Creates an expression that the number of elements of the collection. */ diff --git a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt index bd346f15b..d6f778673 100644 --- a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt +++ b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/expression/PowerDslTest.kt @@ -9,33 +9,34 @@ import org.assertj.core.api.WithAssertions import org.junit.jupiter.api.Test class PowerDslTest : WithAssertions { - private val baseExpression = Paths.path(Employee::age) - private val exponentExpression = Expressions.value(2) - private val exponentPrimitive = 2 + private val intExpression1 = Paths.path(Employee::age) + private val intExpression2 = Expressions.value(2) + + private val int1 = 2 @Test fun `power() with a property`() { // when val expression1 = queryPart { - power(Employee::age, exponentPrimitive) + power(Employee::age, int1) }.toExpression() val expression2 = queryPart { - power(Employee::age, exponentExpression) + power(Employee::age, intExpression2) }.toExpression() - val actual1: Expression = expression1 // for type check - val actual2: Expression = expression2 // for type check + val actual1: Expression = expression1 // for type check + val actual2: Expression = expression2 // for type check // then val expected1 = Expressions.power( base = Paths.path(Employee::age), - exponent = Expressions.value(exponentPrimitive), + exponent = Expressions.value(int1), ) val expected2 = Expressions.power( base = Paths.path(Employee::age), - exponent = exponentExpression, + exponent = intExpression2, ) assertThat(actual1).isEqualTo(expected1) @@ -46,25 +47,25 @@ class PowerDslTest : WithAssertions { fun `power() with a expression`() { // when val expression1 = queryPart { - power(baseExpression, exponentPrimitive) + power(intExpression1, int1) }.toExpression() val expression2 = queryPart { - power(baseExpression, exponentExpression) + power(intExpression1, intExpression2) }.toExpression() - val actual1: Expression = expression1 // for type check - val actual2: Expression = expression2 // for type check + val actual1: Expression = expression1 // for type check + val actual2: Expression = expression2 // for type check // then val expected1 = Expressions.power( - base = baseExpression, - exponent = Expressions.value(exponentPrimitive), + base = intExpression1, + exponent = Expressions.value(int1), ) val expected2 = Expressions.power( - base = baseExpression, - exponent = exponentExpression, + base = intExpression1, + exponent = intExpression2, ) assertThat(actual1).isEqualTo(expected1) diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt index 642f2ebe0..d851af550 100644 --- a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/Expressions.kt @@ -282,7 +282,7 @@ object Expressions { * Creates expression that calculates the powering of a numeric [base] to a specified [exponent]. */ @SinceJdsl("3.4.0") - fun power(base: Expression, exponent: Expression): Expression { + fun power(base: Expression, exponent: Expression): Expression { return JpqlPower(base, exponent) } diff --git a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt index eecc9b2d2..bea6c6610 100644 --- a/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt +++ b/query-model/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/querymodel/jpql/expression/impl/JpqlPower.kt @@ -9,5 +9,5 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expression @Internal data class JpqlPower internal constructor( val base: Expression, - val exponent: Expression, -) : Expression + val exponent: Expression, +) : Expression diff --git a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt index b2c3b22be..2a3a0e9a9 100644 --- a/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt +++ b/render/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/render/jpql/JpqlRenderContext.kt @@ -368,10 +368,10 @@ private class DefaultModule : JpqlRenderModule { JpqlPathTreatSerializer(), JpqlPathTypeSerializer(), JpqlPlusSerializer(), + JpqlPowerSerializer(), JpqlPredicateParenthesesSerializer(), JpqlRoundSerializer(), JpqlSelectQuerySerializer(), - JpqlPowerSerializer(), JpqlSignSerializer(), JpqlSizeSerializer(), JpqlSortSerializer(),