Skip to content
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 SIZE #626

Merged
merged 5 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ locate("Book", path(Book::title))
* LN (ln)
* ROUND (round)
* SIGN (sign)
* SIZE (size)
cj848 marked this conversation as resolved.
Show resolved Hide resolved
* SQRT (sqrt)

```kotlin
Expand All @@ -245,14 +246,15 @@ round(path(Book::price), 2)

sign(path(Book::price))

size(path(Book::authors))

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

| Function | DSL function |
|----------|--------------|
| MOD | not yet |
| POWER | not yet |
| SIZE | not yet |
| INDEX | not yet |

### Datetime functions
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))
* LN (ln)
* ROUND (round)
* SIGN (sign)
* SIZE (size)
* SQRT (sqrt)

```kotlin
Expand All @@ -241,14 +242,15 @@ round(path(Book::price), 2)

sign(path(Book::price))

size(path(Book::authors))

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

| Function | DSL function |
|----------|--------------|
| MOD | not yet |
| POWER | not yet |
| SIZE | not yet |
| INDEX | not yet |

### Datetime functions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,22 @@ open class Jpql : JpqlDsl {
return Expressions.sqrt(value.toExpression())
}

/**
* Creates an expression that the number of elements of the collection.
*/
@SinceJdsl("3.4.0")
fun <T : Any, V, S : Collection<V>> size(expr: KProperty1<T, @Exact S>): Expression<Int> {
return Expressions.size(Paths.path(expr))
}

/**
* Creates an expression that the number of elements of the collection.
*/
@SinceJdsl("3.4.0")
fun <T, S : Collection<T>> size(path: Pathable<S>): Expression<Int> {
return Expressions.size(path.toPath())
}

/**
* 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,47 @@
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 SizeDslTest : WithAssertions {
private val path1 = Paths.path(Employee::departments)

@Test
fun `size() with property`() {
// when
val expression = queryPart {
size(Employee::departments)
}.toExpression()

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

// then
val expected = Expressions.size(
path = Paths.path(Employee::departments),
)

assertThat(actual).isEqualTo(expected)
}

@Test
fun `size() with path`() {
// when
val expression = queryPart {
size(path1)
}.toExpression()

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

// then
val expected = Expressions.size(
path = path1,
)

assertThat(actual).isEqualTo(expected)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ 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.JpqlSize
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 @@ -282,6 +283,14 @@ object Expressions {
return JpqlSqrt(value)
}

/**
* Creates an expression that represents the number of elements of the collection.
*/
@SinceJdsl("3.4.0")
fun <T, S : Collection<T>> size(path: Path<S>): Expression<Int> {
return JpqlSize(path)
}

/**
* 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,10 @@
package com.linecorp.kotlinjdsl.querymodel.jpql.expression.impl

import com.linecorp.kotlinjdsl.Internal
import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expression
import com.linecorp.kotlinjdsl.querymodel.jpql.path.Path

@Internal
data class JpqlSize<T, S : Collection<T>>internal constructor(
val path: Path<S>,
) : Expression<Int>
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ 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.JpqlSize
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 @@ -91,6 +92,7 @@ class ExpressionsTest : WithAssertions {
private val entity1 = Entities.entity(Employee::class)

private val path1 = Paths.path(Employee::employeeId)
private val path2 = Paths.path(Employee::departments)

private val predicate1 = Predicates.equal(Paths.path(Book::price), Expressions.value(BigDecimal.valueOf(100)))
private val predicate2 = Predicates.equal(Paths.path(Book::price), Expressions.value(BigDecimal.valueOf(200)))
Expand Down Expand Up @@ -469,6 +471,19 @@ class ExpressionsTest : WithAssertions {
assertThat(actual).isEqualTo(expected)
}

@Test
fun size() {
// when
val actual = Expressions.size(path2)

// then
val expected = JpqlSize(
path2,
)

assertThat(actual).isEqualTo(expected)
}

@ParameterizedTest
@ValueSource(booleans = [true, false])
fun count(distinct: Boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import com.linecorp.kotlinjdsl.render.jpql.serializer.impl.JpqlPredicateParenthe
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.JpqlSizeSerializer
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 @@ -358,6 +359,7 @@ private class DefaultModule : JpqlRenderModule {
JpqlRoundSerializer(),
JpqlSelectQuerySerializer(),
JpqlSignSerializer(),
JpqlSizeSerializer(),
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.JpqlSize
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 JpqlSizeSerializer : JpqlSerializer<JpqlSize<*, *>> {
override fun handledType(): KClass<JpqlSize<*, *>> {
return JpqlSize::class
}

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

writer.write("SIZE")

writer.writeParentheses {
delegate.serialize(part.path, 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.JpqlSize
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 JpqlSizeSerializerTest : WithAssertions {
private val sut = JpqlSizeSerializer()

@MockK
private lateinit var writer: JpqlWriter

@MockK
private lateinit var serializer: JpqlRenderSerializer

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

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

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

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

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

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