-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Arithmetic function ROUND #615
Changes from 5 commits
57d582d
110cdd0
96c740b
4ea6f4a
27401bd
050b988
602b0e4
96e7e6e
74f758a
48d2fa6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -366,6 +366,22 @@ open class Jpql : JpqlDsl { | |
) | ||
} | ||
|
||
/** | ||
* Creates an expression that represents the rounding of the specified property's value to a specified scale. | ||
*/ | ||
@SinceJdsl("3.4.0") | ||
fun <T : Any, V : Number> round(expr: KProperty1<T, @Exact V>, scale: Expression<Int>): Expression<Double> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think the |
||
return Expressions.round(Paths.path(expr), scale.toExpression()) | ||
} | ||
|
||
/** | ||
* Creates an expression that represents the rounding of the specified property's value to a specified scale. | ||
*/ | ||
@SinceJdsl("3.4.0") | ||
fun <T : Number> round(value: Expressionable<T>, scale: Expressionable<Int>): Expression<Double> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the jakarta specification, the return type of Could you test this to make sure it's really correct? I think it would be okay to test with Int, Double, and BigDecimal only. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
return Expressions.round(value.toExpression(), scale.toExpression()) | ||
} | ||
|
||
/** | ||
* Creates an expression that represents the plus of values. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
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 RoundDslTest : WithAssertions { | ||
private val expression1 = Paths.path(Book::salePrice) | ||
private val intExpression1: Expression<Int> = Expressions.value(3) | ||
private val int1 = 3 | ||
|
||
@Test | ||
fun `round() with a expression`() { | ||
// when | ||
val expression = queryPart { | ||
round(expression1, intExpression1) | ||
}.toExpression() | ||
|
||
val actual: Expression<Double> = expression // for type check | ||
|
||
// then | ||
val expected = Expressions.round( | ||
value = expression1, | ||
scale = intExpression1, | ||
) | ||
|
||
assertThat(actual).isEqualTo(expected) | ||
} | ||
|
||
@Test | ||
fun `round() with a property`() { | ||
// when | ||
val expression = queryPart { | ||
round(Book::price, intExpression1) | ||
}.toExpression() | ||
|
||
val actual: Expression<Double> = expression // for type check | ||
|
||
// then | ||
val expected = Expressions.round( | ||
value = Paths.path(Book::price), | ||
scale = Expressions.value(int1), | ||
) | ||
|
||
assertThat(actual).isEqualTo(expected) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
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 JpqlRound<T: Number> internal constructor( | ||
val value: Expression<T>, | ||
val scale: Expression<Int>, | ||
) : Expression<Double> { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.linecorp.kotlinjdsl.render.jpql.serializer.impl | ||
|
||
import com.linecorp.kotlinjdsl.Internal | ||
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlRound | ||
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 JpqlRoundSerializer : JpqlSerializer<JpqlRound<*>>{ | ||
override fun handledType(): KClass<JpqlRound<*>> { | ||
return JpqlRound::class | ||
} | ||
|
||
override fun serialize(part: JpqlRound<*>, writer: JpqlWriter, context: RenderContext) { | ||
val delegate = context.getValue(JpqlRenderSerializer) | ||
|
||
writer.write("ROUND") | ||
|
||
writer.writeParentheses { | ||
delegate.serialize(part.value, writer, context) | ||
|
||
writer.write(", ") | ||
delegate.serialize(part.scale, writer, context) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package com.linecorp.kotlinjdsl.render.jpql.serializer.impl | ||
|
||
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressions | ||
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlRound | ||
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 JpqlRoundSerializerTest { | ||
private val sut = JpqlRoundSerializer() | ||
|
||
@MockK | ||
private lateinit var writer: JpqlWriter | ||
|
||
@MockK | ||
private lateinit var serializer: JpqlRenderSerializer | ||
|
||
private val expression1 = Paths.path(Book::price) | ||
private val expression2 = Expressions.value(3) | ||
|
||
@Test | ||
fun handledType() { | ||
// when | ||
val actual = sut.handledType() | ||
|
||
// then | ||
assertThat(actual).isEqualTo(JpqlRound::class) | ||
} | ||
@Test | ||
fun serialize() { | ||
// given | ||
val part = Expressions.round( | ||
value = expression1, | ||
scale = expression2 | ||
) | ||
val context = TestRenderContext(serializer) | ||
|
||
// when | ||
sut.serialize(part as JpqlRound<*>, writer, context) | ||
|
||
// then | ||
verifySequence { | ||
writer.write("ROUND") | ||
writer.writeParentheses(any()) | ||
serializer.serialize(expression1, writer, context) | ||
writer.write(", ") | ||
serializer.serialize(expression2, writer, context) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be great to at least
value
instead ofproperty's value
, since not only the value of the property can be passed as a parameter to round, but also the literal.