Skip to content

Commit

Permalink
Working on inheritance where clause tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kurbaniec committed Jan 16, 2024
1 parent 37935bf commit f3e5894
Show file tree
Hide file tree
Showing 2 changed files with 274 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
package com.beeproduced.bee.persistent.test.select

import com.beeproduced.bee.persistent.blaze.selection.BeeSelection
import com.beeproduced.bee.persistent.test.config.BTestConfig
import com.beeproduced.datasource.b.*
import com.beeproduced.datasource.b.dsl.ComposerDSL
import jakarta.persistence.EntityManager
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.TestPropertySource
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.transaction.PlatformTransactionManager
import org.springframework.transaction.support.TransactionTemplate
import java.util.*
import kotlin.test.*

/**
*
*
* @author Kacper Urbaniec
* @version 2024-01-16
*/
@ExtendWith(SpringExtension::class)
@SpringBootTest(classes = [BTestConfig::class])
@TestPropertySource("classpath:application.properties")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class SelectWhereInheritanceBTest(
@Qualifier("bEM")
val em: EntityManager,
@Qualifier("bTM")
transactionManager: PlatformTransactionManager,
@Autowired
val composerRepo: ComposerRepository,
@Autowired
val containerRepo: ComposerContainerRepository,
@Autowired
val aiDataRepo: AiDataRepository,
@Autowired
val humanDataRepo: HumanDataRepository
) {
private val transaction = TransactionTemplate(transactionManager)

@BeforeAll
fun beforeAll() = clear()

@AfterEach
fun afterEach() = clear()

fun clear() = transaction.executeWithoutResult {
containerRepo.cbf.delete(em, ComposerContainer::class.java).executeUpdate()
composerRepo.cbf.delete(em, Composer::class.java).executeUpdate()
aiDataRepo.cbf.delete(em, AiData::class.java).executeUpdate()
humanDataRepo.cbf.delete(em, HumanData::class.java).executeUpdate()
}

@Test
fun `where with treat`() {
transaction.executeWithoutResult {
val aiData1 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data"))
val aiComposer1 = composerRepo.persist(
AiComposer(UUID.randomUUID(), "AI", "GPT", AiParams("1", "2"), aiData1.id)
)
val aiData2 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data2"))
val aiComposer2 = composerRepo.persist(
AiComposer(UUID.randomUUID(),"AI2", "GPT2", AiParams("3", "4"), aiData2.id)
)
val humanData1 = humanDataRepo.persist(HumanData(UUID.randomUUID(), "Bar"))
val humanComposer1 = composerRepo.persist(
HumanComposer(UUID.randomUUID(), "Mario", "Mario", humanData1.id)
)

val selection = ComposerDSL.select {
aiData { }
humanData { }
}
val composers = composerRepo.select(selection) {
where(ComposerDSL.aiDataId.eq(aiData2.id))
}

assertEquals(1, composers.count())
val composer = composers.first()
assertEquals(aiComposer2.id, composer.id)
assertTrue { composer is AiComposer }
}
}

@Test
fun `where with treat on relation`() {
transaction.executeWithoutResult {
val aiData1 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data"))
val aiComposer1 = composerRepo.persist(
AiComposer(UUID.randomUUID(), "AI", "GPT", AiParams("1", "2"), aiData1.id)
)
val aiData2 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data2"))
val aiComposer2 = composerRepo.persist(
AiComposer(UUID.randomUUID(),"AI2", "GPT2", AiParams("3", "4"), aiData2.id)
)
val humanData1 = humanDataRepo.persist(HumanData(UUID.randomUUID(), "Bar"))
val humanComposer1 = composerRepo.persist(
HumanComposer(UUID.randomUUID(), "Mario", "Mario", humanData1.id)
)

val selection = ComposerDSL.select {
aiData { }
humanData { }
}
val composers = composerRepo.select(selection) {
where(ComposerDSL.aiData.data.eq(aiData2.data))
}

assertEquals(1, composers.count())
val composer = composers.first()
assertEquals(aiComposer2.id, composer.id)
assertTrue { composer is AiComposer }
}
}

@Test
fun `where with treat on not loaded relation`() {
transaction.executeWithoutResult {
val aiData1 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data"))
val aiComposer1 = composerRepo.persist(
AiComposer(UUID.randomUUID(), "AI", "GPT", AiParams("1", "2"), aiData1.id)
)
val aiData2 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data2"))
val aiComposer2 = composerRepo.persist(
AiComposer(UUID.randomUUID(),"AI2", "GPT2", AiParams("3", "4"), aiData2.id)
)
val humanData1 = humanDataRepo.persist(HumanData(UUID.randomUUID(), "Bar"))
val humanComposer1 = composerRepo.persist(
HumanComposer(UUID.randomUUID(), "Mario", "Mario", humanData1.id)
)

val selection = BeeSelection.empty()
val composers = composerRepo.select(selection) {
where(ComposerDSL.aiData.data.eq(aiData2.data))
}

assertEquals(1, composers.count())
val composer = composers.first()
assertEquals(aiComposer2.id, composer.id)
assertTrue { composer is AiComposer }
}
}

@Test
fun `where with treat on embedded`() {
transaction.executeWithoutResult {
val aiData1 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data"))
val aiComposer1 = composerRepo.persist(
AiComposer(UUID.randomUUID(), "AI", "GPT", AiParams("1", "2"), aiData1.id)
)
val aiData2 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data2"))
val aiComposer2 = composerRepo.persist(
AiComposer(UUID.randomUUID(),"AI2", "GPT2", AiParams("3", "4"), aiData2.id)
)
val humanData1 = humanDataRepo.persist(HumanData(UUID.randomUUID(), "Bar"))
val humanComposer1 = composerRepo.persist(
HumanComposer(UUID.randomUUID(), "Mario", "Mario", humanData1.id)
)

val selection = ComposerDSL.select {
aiData { }
humanData { }
}
val composers = composerRepo.select(selection) {
where(ComposerDSL.params.eq(AiParams("3", "4")))
}

assertEquals(1, composers.count())
val composer = composers.first()
assertEquals(aiComposer2.id, composer.id)
assertTrue { composer is AiComposer }
}
}

@Test
fun `where with treat on embedded field`() {
transaction.executeWithoutResult {
val aiData1 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data"))
val aiComposer1 = composerRepo.persist(
AiComposer(UUID.randomUUID(), "AI", "GPT", AiParams("1", "2"), aiData1.id)
)
val aiData2 = aiDataRepo.persist(AiData(UUID.randomUUID(), "data2"))
val aiComposer2 = composerRepo.persist(
AiComposer(UUID.randomUUID(),"AI2", "GPT2", AiParams("3", "4"), aiData2.id)
)
val humanData1 = humanDataRepo.persist(HumanData(UUID.randomUUID(), "Bar"))
val humanComposer1 = composerRepo.persist(
HumanComposer(UUID.randomUUID(), "Mario", "Mario", humanData1.id)
)

val selection = ComposerDSL.select {
aiData { }
humanData { }
}
val composers = composerRepo.select(selection) {
where(ComposerDSL.paramsZ1.eq("3"))
}

assertEquals(1, composers.count())
val composer = composers.first()
assertEquals(aiComposer2.id, composer.id)
assertTrue { composer is AiComposer }
}
}

private fun assertComposer(composer: Composer, selection: BeeSelection) {
if (composer is AiComposer) {
val aiData = composer.aiData
if (selection.contains(AiComposer::aiData.name)) {
assertNotNull(aiData)
} else {
assertNull(aiData)
}
} else if (composer is HumanComposer) {
val humanData = composer.humanData
if (selection.contains(HumanComposer::humanData.name)) {
assertNotNull(humanData)
} else {
assertNull(humanData)
}
}
}

private fun assertContainer(container: ComposerContainer, selection: BeeSelection) {
val c1 = container.c1
if (selection.contains(ComposerContainer::c1.name)) {
assertNotNull(c1)
val subselect = selection.subSelect(ComposerContainer::c1.name)
if (subselect != null) assertComposer(c1, subselect)
} else {
assertNull(c1)
}
val c2 = container.c2
if (selection.contains(ComposerContainer::c2.name)) {
assertNotNull(c2)
val subselect = selection.subSelect(ComposerContainer::c2.name)
if (subselect != null) assertComposer(c2, subselect)
} else {
assertNull(c2)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import com.squareup.kotlinpoet.ksp.writeTo
import org.gradle.configurationcache.extensions.capitalized
import java.nio.file.Files
import java.nio.file.Paths
import java.util.*

/**
*
Expand Down Expand Up @@ -312,16 +313,17 @@ class BeePersistentDSLCodegen(
sort: Boolean = false,
): TypeSpec.Builder {

val entitySimpleName = entityView.entity.simpleName
val (allRelations, allColumns)
= viewColumnsWithSubclasses(entityView, views)

val (columns, embedded) = allColumns.partition { !it.property.isEmbedded }
for (column in columns) {
viewDSL.addPath(column, path, sort)
viewDSL.addPath(column, path, entitySimpleName, sort)
}

for (column in embedded) {
viewDSL.addPath(column, path, sort)
viewDSL.addPath(column, path, entitySimpleName, sort)
}

for ((simpleName, subRelation) in allRelations) {
Expand All @@ -330,7 +332,9 @@ class BeePersistentDSLCodegen(

val whereDSLName = "${innerView.name}__Where"
val innerDSL = TypeSpec.objectBuilder(whereDSLName)
val newPath = buildPath(path, simpleName, subRelation.subView)
val subViewMapping = if (subRelation.subView == null) null
else SubViewMapping(entitySimpleName, subRelation.subView)
val newPath = buildPath(path, simpleName, subViewMapping)

val relationProperty = PropertySpec.builder(simpleName, ClassName("", whereDSLName))
.initializer("%L", whereDSLName)
Expand All @@ -345,12 +349,14 @@ class BeePersistentDSLCodegen(
}

private fun TypeSpec.Builder.addPath(
subProperty: SubProperty, path: String,
subProperty: SubProperty, path: String, entitySimpleName: String,
sort: Boolean, embeddedPropertyName: String? = null
) {
val column = subProperty.property
val propertyName = embeddedPropertyName ?: column.simpleName
val newPath = buildPath(path, column.simpleName, subProperty.subView)
val subViewMapping = if (subProperty.subView == null) null
else SubViewMapping(entitySimpleName, subProperty.subView)
val newPath = buildPath(path, column.simpleName, subViewMapping)
val inner = column.innerValue
if (inner != null) {
val innerType = inner.type.toTypeName().copy(nullable = false)
Expand Down Expand Up @@ -387,19 +393,26 @@ class BeePersistentDSLCodegen(
val columnProp = ColumnProperty(embeddedColumn.declaration, embeddedColumn.type, embeddedColumn.annotations, null, null)
val embeddedSubProperty = SubProperty(columnProp)
val overrideName = "$propertyName${embeddedColumn.simpleName.capitalized()}"
addPath(embeddedSubProperty, newPath, sort, overrideName)
addPath(embeddedSubProperty, newPath, entitySimpleName, sort, overrideName)
}
}

private fun buildPath(path: String, simpleName: String, subView: String?): String {
data class SubViewMapping(val entitySimpleName: String, val subEntitySimpleName: String)
private fun buildPath(path: String, simpleName: String, subViewMapping: SubViewMapping?): String {
return when {
path.isEmpty() && subView == null -> { simpleName }
path.isEmpty() && subView != null -> { "TREAT(this as $subView).$simpleName" }
subView == null -> { "$path.$simpleName" }
else -> { "TREAT($path as $subView).$simpleName" }
path.isEmpty() && subViewMapping == null -> { simpleName }
path.isEmpty() && subViewMapping != null -> {
// TREAT alias like CriteriaBuilder<T> create function from blaze: camel cased result of what Class.getSimpleName()
val entityCamelCase = subViewMapping.entitySimpleName.aliasCamelCase()
"TREAT($entityCamelCase as ${subViewMapping.subEntitySimpleName}).$simpleName"
}
subViewMapping == null -> { "$path.$simpleName" }
else -> { "TREAT($path as ${subViewMapping.subEntitySimpleName}.).$simpleName" }
}
}

private fun String.aliasCamelCase() = replaceFirstChar { it.lowercase(Locale.getDefault()) }

private fun buildRegistration() {
if (inlineValues.isEmpty()) return

Expand Down

0 comments on commit f3e5894

Please sign in to comment.