Skip to content
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
38 changes: 19 additions & 19 deletions yawn-api/src/main/kotlin/com/faire/yawn/project/YawnProjections.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.faire.yawn.project

import com.faire.yawn.YawnTableDef
import com.faire.yawn.YawnDef
import com.faire.yawn.query.YawnCompilationContext
import org.hibernate.criterion.Projection
import org.hibernate.criterion.Projections
Expand Down Expand Up @@ -28,7 +28,7 @@ object YawnProjections {
}

internal class Count<SOURCE : Any, FROM : Any?>(
private val columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
private val columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
) : YawnQueryProjection<SOURCE, Long> {
override fun compile(
context: YawnCompilationContext,
Expand All @@ -38,13 +38,13 @@ object YawnProjections {
}

fun <SOURCE : Any, FROM : Any?> count(
columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
): YawnQueryProjection<SOURCE, Long> {
return Count(columnDef)
}

internal class CountDistinct<SOURCE : Any, FROM : Any?>(
private val columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
private val columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
) : YawnQueryProjection<SOURCE, Long> {
override fun compile(
context: YawnCompilationContext,
Expand All @@ -54,13 +54,13 @@ object YawnProjections {
}

fun <SOURCE : Any, FROM : Any?> countDistinct(
columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
): YawnQueryProjection<SOURCE, Long> {
return CountDistinct(columnDef)
}

internal class SumNullable<SOURCE : Any, FROM : Number?>(
private val columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
private val columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
) : YawnQueryProjection<SOURCE, Long?> {
override fun compile(
context: YawnCompilationContext,
Expand All @@ -71,13 +71,13 @@ object YawnProjections {

@JvmName("sumNullable")
fun <SOURCE : Any, FROM : Number?> sum(
columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
): YawnQueryProjection<SOURCE, Long?> {
return SumNullable(columnDef)
}

internal class Sum<SOURCE : Any, FROM : Number>(
private val columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
private val columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
) : YawnQueryProjection<SOURCE, Long> {
override fun compile(
context: YawnCompilationContext,
Expand All @@ -87,13 +87,13 @@ object YawnProjections {
}

fun <SOURCE : Any, FROM : Number> sum(
columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
): YawnQueryProjection<SOURCE, Long> {
return Sum(columnDef)
}

internal class AvgNullable<SOURCE : Any, FROM : Any?>(
private val columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
private val columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
) : YawnQueryProjection<SOURCE, Double?> {
override fun compile(
context: YawnCompilationContext,
Expand All @@ -104,13 +104,13 @@ object YawnProjections {

@JvmName("avgNullable")
fun <SOURCE : Any, FROM : Number?> avg(
columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
): YawnQueryProjection<SOURCE, Double?> {
return AvgNullable(columnDef)
}

internal class Avg<SOURCE : Any, FROM : Number>(
private val columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
private val columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
) : YawnQueryProjection<SOURCE, Double> {
override fun compile(
context: YawnCompilationContext,
Expand All @@ -120,13 +120,13 @@ object YawnProjections {
}

fun <SOURCE : Any, FROM : Number> avg(
columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
): YawnQueryProjection<SOURCE, Double> {
return Avg(columnDef)
}

internal class Max<SOURCE : Any, FROM : Comparable<FROM>?>(
private val columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
private val columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
) : YawnQueryProjection<SOURCE, FROM> {
override fun compile(
context: YawnCompilationContext,
Expand All @@ -137,13 +137,13 @@ object YawnProjections {
}

fun <SOURCE : Any, FROM : Comparable<FROM>?> max(
columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
): YawnQueryProjection<SOURCE, FROM> {
return Max(columnDef)
}

internal class Min<SOURCE : Any, FROM : Comparable<FROM>?>(
private val columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
private val columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
) : YawnQueryProjection<SOURCE, FROM> {
override fun compile(
context: YawnCompilationContext,
Expand All @@ -154,13 +154,13 @@ object YawnProjections {
}

fun <SOURCE : Any, FROM : Comparable<FROM>?> min(
columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
): YawnQueryProjection<SOURCE, FROM> {
return Min(columnDef)
}

internal class GroupBy<SOURCE : Any, FROM : Any?>(
private val columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
private val columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
) : YawnQueryProjection<SOURCE, FROM> {
override fun compile(
context: YawnCompilationContext,
Expand All @@ -171,7 +171,7 @@ object YawnProjections {
}

fun <SOURCE : Any, FROM : Any?> groupBy(
columnDef: YawnTableDef<SOURCE, *>.ColumnDef<FROM>,
columnDef: YawnDef<SOURCE, *>.YawnColumnDef<FROM>,
): YawnQueryProjection<SOURCE, FROM> {
return GroupBy(columnDef)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.faire.yawn.database

import com.faire.yawn.project.YawnProjections
import com.faire.yawn.setup.entities.BookTable
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

internal class YawnAggregationNullabilityTest : BaseYawnDatabaseTest() {
@Test
fun `count with addIsNotNull`() {
transactor.open { session ->
val count = session.project(BookTable) { books ->
val notes = addIsNotNull(books.notes)
project(YawnProjections.count(notes))
}.uniqueResult()!!

// 3 books have notes: harry potter, lord of the rings, the hobbit
assertThat(count).isEqualTo(3)
}
}

@Test
fun `countDistinct with addIsNotNull`() {
transactor.open { session ->
val distinctCount = session.project(BookTable) { books ->
val notes = addIsNotNull(books.notes)
project(YawnProjections.countDistinct(notes))
}.uniqueResult()!!

// harry potter and the hobbit share the same note
assertThat(distinctCount).isEqualTo(2)
}
}

@Test
fun `sum with addIsNotNull`() {
transactor.open { session ->
val total = session.project(BookTable) { books ->
val rating = addIsNotNull(books.rating)
project(YawnProjections.sum(rating))
}.uniqueResult()!!

// lord of the rings (10) + the hobbit (9)
assertThat(total).isEqualTo(19)
}
}

@Test
fun `avg with addIsNotNull`() {
transactor.open { session ->
val average = session.project(BookTable) { books ->
val rating = addIsNotNull(books.rating)
project(YawnProjections.avg(rating))
}.uniqueResult()!!

// (10 + 9) / 2
assertThat(average).isEqualTo(9.5)
}
}

@Test
fun `max with addIsNotNull`() {
transactor.open { session ->
val maxRating = session.project(BookTable) { books ->
val rating = addIsNotNull(books.rating)
project(YawnProjections.max(rating))
}.uniqueResult()!!

assertThat(maxRating).isEqualTo(10)
}
}

@Test
fun `min with addIsNotNull`() {
transactor.open { session ->
val minRating = session.project(BookTable) { books ->
val rating = addIsNotNull(books.rating)
project(YawnProjections.min(rating))
}.uniqueResult()!!

assertThat(minRating).isEqualTo(9)
}
}

@Test
fun `groupBy with addIsNotNull`() {
transactor.open { session ->
val results = session.project(BookTable) { books ->
val notes = addIsNotNull(books.notes)
val rating = addIsNotNull(books.rating)
project(
YawnProjections.pair(
YawnProjections.groupBy(notes),
YawnProjections.sum(rating),
),
)
}.list()

// lord of the rings has rating 10, the hobbit has rating 9
assertThat(results).containsExactlyInAnyOrder(
"Note for The Hobbit and Harry Potter" to 9L,
"Note for Lord of the Rings" to 10L,
)
}
}
}
Loading