Skip to content

Commit

Permalink
feat: implement floor function expression
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkyoungdeok committed Jan 30, 2024
1 parent 347096d commit 4e58c3f
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 0 deletions.
16 changes: 16 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 @@ -568,6 +568,22 @@ open class Jpql : JpqlDsl {
return Expressions.ceiling(value.toExpression())
}

/**
* Creates an expression that is enclosed in floor
*/
@SinceJdsl("3.4.0")
fun <T : Any, V : Number> floor(expr: KProperty1<T, @Exact V>): Expression<V> {
return Expressions.floor(Paths.path(expr))
}

/**
* Creates an expression that is enclosed in floor
*/
@SinceJdsl("3.4.0")
fun <T : Number> floor(value: Expressionable<T>): Expression<T> {
return Expressions.floor(value.toExpression())
}

/**
* Creates an expression that represents the count of non-null values.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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
import java.math.BigDecimal

class FloorDslTest : WithAssertions {
private val expression1 = Paths.path(Book::salePrice)

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

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

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

assertThat(actual).isEqualTo(expected)
}

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

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

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

assertThat(actual).isEqualTo(expected)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlDivide
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlEntityType
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlExpression
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlExpressionParentheses
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlFloor
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlFunctionExpression
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlLength
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlLiteral
Expand Down Expand Up @@ -204,6 +205,14 @@ object Expressions {
return JpqlCeiling(value)
}

/**
* Creates an expression that is enclosed in floor
*/
@SinceJdsl("3.4.0")
fun <T : Number> floor(value: Expression<T>): Expression<T> {
return JpqlFloor(value)
}

/**
* Creates an expression that represents the times of values.
*
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 applies the floor function to [value].
*/
@Internal
data class JpqlFloor<T : Number> internal constructor(
val value: Expression<T>,
) : Expression<T>
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlDivide
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlEntityType
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlExpression
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlExpressionParentheses
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlFloor
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlFunctionExpression
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlLength
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl.JpqlLiteral
Expand Down Expand Up @@ -915,4 +916,17 @@ class ExpressionsTest : WithAssertions {

assertThat(actual).isEqualTo(expected)
}

@Test
fun floor() {
// when
val actual = Expressions.floor(doubleExpression1)

// then
val expected = JpqlFloor(
doubleExpression1,
)

assertThat(actual).isEqualTo(expected)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlEqualSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlExistsSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlExpressionParenthesesSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlExpressionSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlFloorSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlFunctionExpressionSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlFunctionPredicateSerializer
import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlGreaterThanAllSerializer
Expand Down Expand Up @@ -286,6 +287,7 @@ private class DefaultModule : JpqlRenderModule {
JpqlExistsSerializer(),
JpqlExpressionParenthesesSerializer(),
JpqlExpressionSerializer(),
JpqlFloorSerializer(),
JpqlFunctionExpressionSerializer(),
JpqlFunctionPredicateSerializer(),
JpqlGreaterThanAllSerializer(),
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.JpqlFloor
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 JpqlFloorSerializer : JpqlSerializer<JpqlFloor<*>> {
override fun handledType(): KClass<JpqlFloor<*>> {
return JpqlFloor::class
}

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

writer.write("FLOOR")

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.JpqlFloor
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 JpqlFloorSerializerTest : WithAssertions {
private val sut = JpqlFloorSerializer()

@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(JpqlFloor::class)
}

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

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

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

0 comments on commit 4e58c3f

Please sign in to comment.