Skip to content

Commit

Permalink
Merge pull request #622 from jbl428/feat/sign
Browse files Browse the repository at this point in the history
Support Arithmetic function SIGN
  • Loading branch information
shouwn authored Feb 5, 2024
2 parents b480368 + 1a4187c commit d3fa944
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 2 deletions.
4 changes: 3 additions & 1 deletion docs/en/jpql-with-kotlin-jdsl/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ Use the following functions to build arithmetic functions:
* EXP (exp)
* FLOOR (floor)
* ROUND (round)
* SIGN (sign)
* SQRT (sqrt)

```kotlin
Expand All @@ -241,6 +242,8 @@ floor(path(Book::price))

round(path(Book::price), 2)

sign(path(Book::price))

sqrt(path(Book::price))
```

Expand All @@ -250,7 +253,6 @@ sqrt(path(Book::price))
| LN | not yet |
| MOD | not yet |
| POWER | not yet |
| SIGN | not yet |
| SIZE | not yet |
| INDEX | not yet |

Expand Down
4 changes: 3 additions & 1 deletion docs/ko/jpql-with-kotlin-jdsl/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ locate("Book", path(Book::title))
* EXP (exp)
* FLOOR (floor)
* ROUND (round)
* SIGN (sign)
* SQRT (sqrt)

```kotlin
Expand All @@ -237,6 +238,8 @@ floor(path(Book::price))

round(path(Book::price), 2)

sign(path(Book::price))

sqrt(path(Book::price))
```

Expand All @@ -246,7 +249,6 @@ sqrt(path(Book::price))
| LN | not yet |
| MOD | not yet |
| POWER | not yet |
| SIGN | not yet |
| SIZE | not yet |
| INDEX | not yet |

Expand Down
24 changes: 24 additions & 0 deletions dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,30 @@ open class Jpql : JpqlDsl {
return Expressions.round(value.toExpression(), scale.toExpression())
}

/**
* Creates an expression that represents the sign of value.
*
* - If value is positive, it returns 1.
* - If value is negative, it returns -1.
* - If value is zero, it returns 0.
*/
@SinceJdsl("3.4.0")
fun <T : Any, V : Number> sign(expr: KProperty1<T, @Exact V>): Expression<Int> {
return Expressions.sign(Paths.path(expr))
}

/**
* Creates an expression that represents the sign of value.
*
* - If value is positive, it returns 1.
* - If value is negative, it returns -1.
* - If value is zero, it returns 0.
*/
@SinceJdsl("3.4.0")
fun <T : Number> sign(value: Expressionable<T>): Expression<Int> {
return Expressions.sign(value.toExpression())
}

/**
* Creates an expression that represents the square root of value.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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 SignDslTest : WithAssertions {
private val expression1 = Paths.path(Book::salePrice)

@Test
fun `sign() with a property`() {
// when
val expression = queryPart {
sign(Book::price)
}.toExpression()

val actual: Expression<Int> = expression // for type check

// then
val expected = Expressions.sign(
value = Paths.path(Book::price),
)

assertThat(actual).isEqualTo(expected)
}

@Test
fun `sign() with a expression`() {
// when
val expression = queryPart {
sign(expression1)
}.toExpression()

val actual: Expression<Int> = expression // for type check

// then
val expected = Expressions.sign(
value = expression1,
)

assertThat(actual).isEqualTo(expected)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ 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.JpqlRound
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSign
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSqrt
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSubquery
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSubstring
Expand Down Expand Up @@ -252,6 +253,14 @@ object Expressions {
return JpqlRound(value, scale)
}

/**
* Creates an expression that represents the sign of a numeric value.
*/
@SinceJdsl("3.4.0")
fun <T : Number> sign(value: Expression<T>): Expression<Int> {
return JpqlSign(value)
}

/**
* Creates an expression that represents the square root of the value.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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 sign of a numeric [value].
*/
@Internal
data class JpqlSign<T : Number> internal constructor(
val value: Expression<T>,
) : Expression<Int>
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ 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.JpqlRound
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSign
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSqrt
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSubquery
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSubstring
Expand Down Expand Up @@ -404,6 +405,19 @@ class ExpressionsTest : WithAssertions {
assertThat(actual).isEqualTo(expected)
}

@Test
fun sign() {
// when
val actual = Expressions.sign(intExpression1)

// then
val expected = JpqlSign(
intExpression1,
)

assertThat(actual).isEqualTo(expected)
}

@Test
fun sqrt() {
// when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlPlusSerializer
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
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlSignSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlSortSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlSqrtSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlSubquerySerializer
Expand Down Expand Up @@ -350,6 +351,7 @@ private class DefaultModule : JpqlRenderModule {
JpqlPredicateParenthesesSerializer(),
JpqlRoundSerializer(),
JpqlSelectQuerySerializer(),
JpqlSignSerializer(),
JpqlSortSerializer(),
JpqlSqrtSerializer(),
JpqlSubquerySerializer(),
Expand Down
Original file line number Diff line number Diff line change
@@ -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.JpqlSign
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 JpqlSignSerializer : JpqlSerializer<JpqlSign<*>> {
override fun handledType(): KClass<JpqlSign<*>> {
return JpqlSign::class
}

override fun serialize(part: JpqlSign<*>, writer: JpqlWriter, context: RenderContext) {
val delegate = context.getValue(JpqlRenderSerializer)

writer.write("SIGN")

writer.writeParentheses {
delegate.serialize(part.value, writer, context)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.linecorp.kotlinjdsl.render.jpql.serializer.impl

import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressions
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlSign
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.WithAssertions
import org.junit.jupiter.api.Test

@JpqlSerializerTest
class JpqlSignSerializerTest : WithAssertions {
private val sut = JpqlSignSerializer()

@MockK
private lateinit var writer: JpqlWriter

@MockK
private lateinit var serializer: JpqlRenderSerializer

private val expression1 = Paths.path(Book::price)

@Test
fun handledType() {
// when
val actual = sut.handledType()

// then
assertThat(actual).isEqualTo(JpqlSign::class)
}

@Test
fun serialize() {
// given
val part = Expressions.sign(
value = expression1,
)
val context = TestRenderContext(serializer)

// when
sut.serialize(part as JpqlSign<*>, writer, context)

// then
verifySequence {
writer.write("SIGN")
writer.writeParentheses(any())
serializer.serialize(expression1, writer, context)
}
}
}

0 comments on commit d3fa944

Please sign in to comment.