Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
41 changes: 41 additions & 0 deletions yawn-api/src/main/kotlin/com/faire/yawn/project/YawnProjections.kt
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,47 @@ object YawnProjections {
): YawnQueryProjection<SOURCE, Triple<A, B, C>> {
return TripleProjection(firstProjection, secondProjection, thirdProjection)
}

/**
* Provides an in-memory transformation over a column value to a different type.
* Use this when using more complex data classes as projections to apply minor
* type or value compliance transformations to database column values
* while keeping your projection classes type-safe, without needing to use
* intermediary representations.
* NOTE: this _does not_ change the query and is post-processed in memory.
*/
fun <SOURCE : Any, FROM, TO> mapping(
column: YawnQueryProjection<SOURCE, FROM>,
transform: (FROM) -> TO,
): YawnQueryProjection<SOURCE, TO> {
return object : YawnQueryProjection<SOURCE, TO> {
override fun compile(context: YawnCompilationContext): Projection = column.compile(context)

@Suppress("UNCHECKED_CAST")
override fun project(value: Any?): TO = transform(column.project(value))
}
}

/**
* A 2-arity version of the [mapping] method.
*/
fun <SOURCE : Any, C1, C2, TO> mapping(
column1: YawnQueryProjection<SOURCE, C1>,
column2: YawnQueryProjection<SOURCE, C2>,
transform: (C1, C2) -> TO,
): YawnQueryProjection<SOURCE, TO> {
return object : YawnQueryProjection<SOURCE, TO> {
override fun compile(context: YawnCompilationContext): Projection {
return Projections.projectionList()
.add(column1.compile(context))
.add(column2.compile(context))
}

override fun project(value: Any?): TO {
return transform(column1.project(value), column2.project(value))
}
}
}
}

private const val CONSTANT_ALIAS = "_yawn_ct"
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.faire.yawn.database

import com.faire.yawn.project.YawnProjection
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 YawnProjectionMappingTest : BaseYawnDatabaseTest() {
@Test
fun `yawn query with projection`() {
transactor.open { session ->
val hobbit = session.project(BookTable) { books ->
addEq(books.name, "The Hobbit")
val authors = join(books.author)
project(
YawnProjectionMappingTest_BookNameAndNotesProjection.create(
uppercaseTitle = YawnProjections.mapping(books.name) { it.uppercase() },
authorNotes = YawnProjections.mapping(authors.name, books.notes) { author, notes ->
"$author says: $notes"
},
),
)
}.uniqueResult()

with(hobbit!!) {
assertThat(uppercaseTitle).isEqualTo("THE HOBBIT")
assertThat(authorNotes).isEqualTo("J.R.R. Tolkien says: J.R.R. Tolkien")
}
}
}

@YawnProjection
internal data class BookNameAndNotes(
val uppercaseTitle: String,
val authorNotes: String,
)
}
Loading