Skip to content

[Kotlin] Update Join DSL #447

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

Merged
merged 5 commits into from
Feb 7, 2022
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
14 changes: 8 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@ GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=miles
([#438](https://github.com/mybatis/mybatis-dynamic-sql/pull/438))
4. Major update to the Kotlin where clause DSL. Where clauses now support the "group" and "not" features from above. In
addition, the where clause DSL has been fully updated to make it feel more like natural SQL. The previous version
of the where clause DSL yielded almost unreadable code when the "group" and "not" functions were added. This update
is better all around and yields a DSL that is very similar to native SQL. The new DSL includes many Kotlin DSL
construction features including infix functions, operator overloads, and functions with receivers. We believe it
will be well worth the effort to migrate to the new DSL. The prior where clause DSL remains in the library for now,
but is deprecated. It will be removed in version 1.5.0 of the library. Documentation for the new DSL is here:
https://github.com/mybatis/mybatis-dynamic-sql/blob/master/src/site/markdown/docs/kotlinWhereClauses.md
of the where clause DSL would have yielded almost unreadable code had the "group" and "not" functions been added.
This update is better all around and yields a DSL that is very similar to native SQL. The new DSL includes many
Kotlin DSL construction features including infix functions, operator overloads, and functions with receivers.
We believe it will be well worth the effort to migrate to the new DSL. The prior where clause DSL remains in the
library for now, but is deprecated. It will be removed in version 1.5.0 of the library. Documentation for the new
DSL is here: https://github.com/mybatis/mybatis-dynamic-sql/blob/master/src/site/markdown/docs/kotlinWhereClauses.md
([#442](https://github.com/mybatis/mybatis-dynamic-sql/pull/442))
5. General cleanup of the Kotlin DSL. The Kotlin DSL functions are now mostly Unit functions. This should have
no impact on most users and is source code compatible with prior versions of the library when the library was used
as described in the documentation. This change greatly simplifies the type hierarchy of the Kotlin builders.
([#446](https://github.com/mybatis/mybatis-dynamic-sql/pull/446))
6. Minor update the Kotlin join DSL to make it closer to natural SQL. The existing join methods are deprecated and
will be removed in version 1.5.0. ([#447](https://github.com/mybatis/mybatis-dynamic-sql/pull/447))

## Release 1.3.1 - December 18, 2021

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.mybatis.dynamic.sql.util.kotlin

import org.mybatis.dynamic.sql.BasicColumn
import org.mybatis.dynamic.sql.SqlBuilder
import org.mybatis.dynamic.sql.select.join.JoinCondition
import org.mybatis.dynamic.sql.select.join.JoinCriterion

Expand All @@ -27,6 +28,25 @@ class JoinCollector {
val andJoinCriteria = mutableListOf<JoinCriterion>()
private lateinit var internalOnCriterion: JoinCriterion

fun on(leftColumn: BasicColumn): RightColumnCollector = RightColumnCollector {
internalOnCriterion = JoinCriterion.Builder()
.withConnector("on")
.withJoinColumn(leftColumn)
.withJoinCondition(it)
.build()
}

fun and(leftColumn: BasicColumn): RightColumnCollector = RightColumnCollector {
andJoinCriteria.add(
JoinCriterion.Builder()
.withConnector("and")
.withJoinColumn(leftColumn)
.withJoinCondition(it)
.build()
)
}

@Deprecated("Please use: on(leftColumn) equalTo rightColumn")
fun on(column: BasicColumn, condition: JoinCondition) {
internalOnCriterion = JoinCriterion.Builder()
.withConnector("on")
Expand All @@ -35,6 +55,7 @@ class JoinCollector {
.build()
}

@Deprecated("Please use: and(leftColumn) equalTo rightColumn")
fun and(column: BasicColumn, condition: JoinCondition) {
andJoinCriteria.add(
JoinCriterion.Builder()
Expand All @@ -45,3 +66,7 @@ class JoinCollector {
)
}
}

class RightColumnCollector(private val joinConditionConsumer: (JoinCondition) -> Unit) {
infix fun equalTo(rightColumn: BasicColumn) = joinConditionConsumer.invoke(SqlBuilder.equalTo(rightColumn))
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import org.mybatis.dynamic.sql.where.condition.IsNotNull
import org.mybatis.dynamic.sql.where.condition.IsNull

// join support
@Deprecated("Please use the infix function in the JoinCollector")
fun equalTo(column: BasicColumn): EqualTo = SqlBuilder.equalTo(column)

// aggregate support
Expand Down
2 changes: 1 addition & 1 deletion src/site/markdown/docs/kotlinMyBatis3.md
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,7 @@ fun PersonWithAddressMapper.select(completer: SelectCompleter): List<PersonWithA
) {
from(person, "p")
fullJoin(address) {
on(person.addressId, equalTo(address.id))
on(person.addressId) equalTo address.id
}
completer()
}.run(this::selectMany)
Expand Down
32 changes: 21 additions & 11 deletions src/site/markdown/docs/kotlinOverview.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,25 +396,35 @@ This method creates models or providers depending on which package is used:
Select statement support enables the creation of methods that execute a query allowing a user to specify a where clause,
join specifications, order by clauses, group by clauses, pagination clauses, etc.

The DSL for select statements looks like this:
The full DSL for select statements looks like this:

```kotlin
val selectStatement = select(id, firstName, lastName, birthDate, employed, occupation, addressId) {
from(person)
where { id isLessThan 5 }
and {
id isLessThan 4
and {
id isLessThan 3
or { id isLessThan 2 }
}
val selectStatement = select(orderMaster.orderId, orderMaster.orderDate, orderDetail.lineNumber,
orderDetail.description, orderDetail.quantity
) {
from(orderMaster, "om")
join(orderDetail, "od") {
on(orderMaster.orderId) equalTo orderDetail.orderId
and(orderMaster.orderId) equalTo orderDetail.orderId
}
orderBy(id)
where { orderMaster.orderId isEqualTo 1 }
or {
orderMaster.orderId isEqualTo 2
and { orderDetail.quantity isLessThan 6 }
}
orderBy(orderMaster.orderId)
limit(3)
}
```

In a select statement you must specify a table in a `from` clause. Everything else is optional.

Multiple join clauses can be specified if you need to join additional tables. In a join clause, you must
specify an `on` condition, and you may specify additional `and` conditions as necessary. Full, left, right, inner,
and outer joins are supported.

Where clauses can be of arbitrary complexity and support all SQL operators including exists operators, subqueries, etc.
You can nest `and`, `or`, and `not` clauses as necessary in where clauses.

There is also a method that will create a "distinct" query (`select distinct ...`) as follows:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.id
import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.lastName
import examples.kotlin.mybatis3.canonical.PersonDynamicSqlSupport.occupation
import org.mybatis.dynamic.sql.util.kotlin.SelectCompleter
import org.mybatis.dynamic.sql.util.kotlin.elements.equalTo
import org.mybatis.dynamic.sql.util.kotlin.mybatis3.select
import org.mybatis.dynamic.sql.util.kotlin.mybatis3.selectDistinct

Expand All @@ -36,7 +35,7 @@ fun PersonWithAddressMapper.selectOne(completer: SelectCompleter): PersonWithAdd
select(columnList) {
from(person)
fullJoin(address) {
on(person.addressId, equalTo(address.id))
on(person.addressId) equalTo address.id
}
completer()
}.run(this::selectOne)
Expand All @@ -45,7 +44,7 @@ fun PersonWithAddressMapper.select(completer: SelectCompleter): List<PersonWithA
select(columnList) {
from(person, "p")
fullJoin(address) {
on(person.addressId, equalTo(address.id))
on(person.addressId) equalTo address.id
}
completer()
}.run(this::selectMany)
Expand All @@ -54,7 +53,7 @@ fun PersonWithAddressMapper.selectDistinct(completer: SelectCompleter): List<Per
selectDistinct(columnList) {
from(person)
fullJoin(address) {
on(person.addressId, equalTo(address.id))
on(person.addressId) equalTo address.id
}
completer()
}.run(this::selectMany)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.junit.jupiter.api.Test
import org.mybatis.dynamic.sql.util.kotlin.elements.count
import org.mybatis.dynamic.sql.util.kotlin.elements.equalTo
import org.mybatis.dynamic.sql.util.kotlin.elements.insert
import org.mybatis.dynamic.sql.util.kotlin.elements.insertMultiple
import org.mybatis.dynamic.sql.util.kotlin.mybatis3.count
Expand Down Expand Up @@ -453,7 +452,7 @@ class GeneralKotlinTest {
) {
from(person)
join(address) {
on(addressId, equalTo(address.id))
on(addressId) equalTo address.id
}
where { id isLessThan 4 }
orderBy(id)
Expand Down Expand Up @@ -489,7 +488,7 @@ class GeneralKotlinTest {
) {
from(person)
join(address) {
on(addressId, equalTo(address.id))
on(addressId) equalTo address.id
}
where { id isLessThan 5 }
and {
Expand Down Expand Up @@ -530,7 +529,7 @@ class GeneralKotlinTest {
) {
from(person)
join(address) {
on(addressId, equalTo(address.id))
on(addressId) equalTo address.id
}
where { id isEqualTo 5 }
or {
Expand Down
Loading