From 65da441ad19ded0e6c339c9caa5d827b4867e5a5 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 1 May 2024 08:32:36 -0400 Subject: [PATCH 1/5] Simple case "then" functions can be infix --- .../sql/util/kotlin/elements/CaseDSLs.kt | 37 ++++++++----------- .../kotlin/animal/data/KCaseExpressionTest.kt | 33 +++++------------ 2 files changed, 25 insertions(+), 45 deletions(-) diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt index 98653f434..487b52ad5 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt @@ -66,25 +66,24 @@ class KSimpleCaseDSL : KElseDSL { } internal val whenConditions = mutableListOf>() - fun `when`(firstCondition: VisitableCondition, vararg subsequentConditions: VisitableCondition, - completer: SimpleCaseThenGatherer.() -> Unit) = - SimpleCaseThenGatherer().apply(completer).run { + fun `when`(firstCondition: VisitableCondition, vararg subsequentConditions: VisitableCondition) = + SimpleCaseThenGatherer { val allConditions = buildList { add(firstCondition) addAll(subsequentConditions) } - whenConditions.add(ConditionBasedWhenCondition(allConditions, thenValue)) + whenConditions.add(ConditionBasedWhenCondition(allConditions, it)) } - fun `when`(firstValue: T, vararg subsequentValues: T, completer: SimpleCaseThenGatherer.() -> Unit) = - SimpleCaseThenGatherer().apply(completer).run { + fun `when`(firstValue: T, vararg subsequentValues: T) = + SimpleCaseThenGatherer { val allConditions = buildList { add(firstValue) addAll(subsequentValues) } - whenConditions.add(BasicWhenCondition(allConditions, thenValue)) + whenConditions.add(BasicWhenCondition(allConditions, it)) } override fun `else`(column: BasicColumn) { @@ -92,40 +91,34 @@ class KSimpleCaseDSL : KElseDSL { } } -class SimpleCaseThenGatherer: KThenDSL { - internal var thenValue: BasicColumn? = null - private set(value) { - assertNull(field, "ERROR.41") //$NON-NLS-1$ - field = value - } - - override fun then(column: BasicColumn) { - thenValue = column +class SimpleCaseThenGatherer(private val consumer: (BasicColumn) -> Unit): KThenDSL { + override infix fun then(column: BasicColumn) { + consumer.invoke(column) } } interface KThenDSL { - fun then(value: String) { + infix fun then(value: String) { then(stringConstant(value)) } - fun then(value: Boolean) { + infix fun then(value: Boolean) { then(constant(value.toString())) } - fun then(value: Int) { + infix fun then(value: Int) { then(constant(value.toString())) } - fun then(value: Long) { + infix fun then(value: Long) { then(constant(value.toString())) } - fun then(value: Double) { + infix fun then(value: Double) { then(constant(value.toString())) } - fun then(column: BasicColumn) + infix fun then(column: BasicColumn) } interface KElseDSL { diff --git a/src/test/kotlin/examples/kotlin/animal/data/KCaseExpressionTest.kt b/src/test/kotlin/examples/kotlin/animal/data/KCaseExpressionTest.kt index b86db19af..0fd1fdaed 100644 --- a/src/test/kotlin/examples/kotlin/animal/data/KCaseExpressionTest.kt +++ b/src/test/kotlin/examples/kotlin/animal/data/KCaseExpressionTest.kt @@ -457,7 +457,7 @@ class KCaseExpressionTest { val selectStatement = select( animalName, case(animalName) { - `when` (isEqualTo("Artic fox"), isEqualTo("Red fox")) { then("yes") } + `when` (isEqualTo("Artic fox"), isEqualTo("Red fox")) then "yes" `else`("no") } `as` "IsAFox" ) { @@ -511,7 +511,7 @@ class KCaseExpressionTest { val selectStatement = select( animalName, case(animalName) { - `when` ("Artic fox", "Red fox") { then("yes") } + `when` ("Artic fox", "Red fox") then "yes" `else`("no") } `as` "IsAFox" ) { @@ -565,7 +565,7 @@ class KCaseExpressionTest { val selectStatement = select( animalName, case(animalName) { - `when` (isEqualTo("Artic fox"), isEqualTo("Red fox")) { then(true) } + `when` (isEqualTo("Artic fox"), isEqualTo("Red fox")) then true `else`(false) } `as` "IsAFox" ) { @@ -619,7 +619,7 @@ class KCaseExpressionTest { val selectStatement = select( animalName, case(animalName) { - `when` ("Artic fox", "Red fox") { then(true) } + `when` ("Artic fox", "Red fox") then true `else`(false) } `as` "IsAFox" ) { @@ -673,7 +673,7 @@ class KCaseExpressionTest { val selectStatement = select( animalName, case(animalName) { - `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) { then("yes") } + `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) then "yes" } `as` "IsAFox" ) { from(animalData) @@ -720,7 +720,7 @@ class KCaseExpressionTest { val selectStatement = select( animalName, case(animalName) { - `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) { then(cast { "It's a fox" `as` "VARCHAR(30)" })} + `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) then cast { "It's a fox" `as` "VARCHAR(30)" } `else`("It's not a fox") } `as` "IsAFox" ) { @@ -763,7 +763,7 @@ class KCaseExpressionTest { val selectStatement = select( animalName, case(animalName) { - `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) { then( 1L) } + `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) then 1L `else`(2L) } `as` "IsAFox" ) { @@ -806,7 +806,7 @@ class KCaseExpressionTest { val selectStatement = select( animalName, case(animalName) { - `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) { then( 1.1) } + `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) then 1.1 `else`(2.2) } `as` "IsAFox" ) { @@ -849,7 +849,7 @@ class KCaseExpressionTest { val selectStatement = select( animalName, case(animalName) { - `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) { then( 1.1) } + `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) then 1.1 `else`(cast { 2.2 `as` "DOUBLE" }) } `as` "IsAFox" ) { @@ -888,26 +888,13 @@ class KCaseExpressionTest { fun testInvalidDoubleElseSimple() { assertThatExceptionOfType(KInvalidSQLException::class.java).isThrownBy { case(animalName) { - `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) { then("'yes'") } + `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) then "'yes'" `else`("Fred") `else`("Wilma") } }.withMessage(Messages.getString("ERROR.42")) } - @Test - fun testInvalidDoubleThenSimple() { - assertThatExceptionOfType(KInvalidSQLException::class.java).isThrownBy { - case(animalName) { - `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) { - then("'yes'") - then("no") - } - `else`("Fred") - } - }.withMessage(Messages.getString("ERROR.41")) - } - @Test fun testInvalidDoubleElseSearched() { assertThatExceptionOfType(KInvalidSQLException::class.java).isThrownBy { From d5afd69392138aaba8c7aaa02616ec0fb9f90d4a Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 1 May 2024 09:09:27 -0400 Subject: [PATCH 2/5] Set maintenance release version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c5b04639a..b17a77d72 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.mybatis.dynamic-sql mybatis-dynamic-sql - 1.6.0-SNAPSHOT + 1.5.2-SNAPSHOT MyBatis Dynamic SQL MyBatis framework for generating dynamic SQL From 95713da6992c5323904c37ad36f75eda1ec45ecd Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 1 May 2024 10:02:18 -0400 Subject: [PATCH 3/5] Else functions can be infix Infix not as useful in this case because using it requires an explicit "this", but some might prefer that syntax. --- .../sql/util/kotlin/elements/CaseDSLs.kt | 27 +++++++++---------- .../kotlin/animal/data/KCaseExpressionTest.kt | 10 +++---- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt index 487b52ad5..cd735f43a 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt @@ -38,10 +38,9 @@ class KSearchedCaseDSL : KElseDSL { .withSubCriteria(subCriteria) .withThenValue(thenValue) .build()) - } - override fun `else`(column: BasicColumn) { + override infix fun `else`(column: BasicColumn) { this.elseValue = column } } @@ -53,7 +52,7 @@ class SearchedCaseCriteriaCollector : GroupingCriteriaCollector(), KThenDSL { field = value } - override fun then(column: BasicColumn) { + override infix fun then(column: BasicColumn) { thenValue = column } } @@ -67,26 +66,26 @@ class KSimpleCaseDSL : KElseDSL { internal val whenConditions = mutableListOf>() fun `when`(firstCondition: VisitableCondition, vararg subsequentConditions: VisitableCondition) = - SimpleCaseThenGatherer { + SimpleCaseThenGatherer { thenValue -> val allConditions = buildList { add(firstCondition) addAll(subsequentConditions) } - whenConditions.add(ConditionBasedWhenCondition(allConditions, it)) + whenConditions.add(ConditionBasedWhenCondition(allConditions, thenValue)) } fun `when`(firstValue: T, vararg subsequentValues: T) = - SimpleCaseThenGatherer { + SimpleCaseThenGatherer { thenValue -> val allConditions = buildList { add(firstValue) addAll(subsequentValues) } - whenConditions.add(BasicWhenCondition(allConditions, it)) + whenConditions.add(BasicWhenCondition(allConditions, thenValue)) } - override fun `else`(column: BasicColumn) { + override infix fun `else`(column: BasicColumn) { this.elseValue = column } } @@ -122,25 +121,25 @@ interface KThenDSL { } interface KElseDSL { - fun `else`(value: String) { + infix fun `else`(value: String) { `else`(stringConstant(value)) } - fun `else`(value: Boolean) { + infix fun `else`(value: Boolean) { `else`(constant(value.toString())) } - fun `else`(value: Int) { + infix fun `else`(value: Int) { `else`(constant(value.toString())) } - fun `else`(value: Long) { + infix fun `else`(value: Long) { `else`(constant(value.toString())) } - fun `else`(value: Double) { + infix fun `else`(value: Double) { `else`(constant(value.toString())) } - fun `else`(column: BasicColumn) + infix fun `else`(column: BasicColumn) } diff --git a/src/test/kotlin/examples/kotlin/animal/data/KCaseExpressionTest.kt b/src/test/kotlin/examples/kotlin/animal/data/KCaseExpressionTest.kt index 0fd1fdaed..8f6eb7aa8 100644 --- a/src/test/kotlin/examples/kotlin/animal/data/KCaseExpressionTest.kt +++ b/src/test/kotlin/examples/kotlin/animal/data/KCaseExpressionTest.kt @@ -888,7 +888,7 @@ class KCaseExpressionTest { fun testInvalidDoubleElseSimple() { assertThatExceptionOfType(KInvalidSQLException::class.java).isThrownBy { case(animalName) { - `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) then "'yes'" + `when`(isEqualTo("Artic fox"), isEqualTo("Red fox")) then "yes" `else`("Fred") `else`("Wilma") } @@ -901,9 +901,9 @@ class KCaseExpressionTest { case { `when` { id isEqualTo 22 - then("'yes'") + this then "yes" } - `else`("Fred") + this `else` "Fred" `else`("Wilma") } }.withMessage(Messages.getString("ERROR.42")) @@ -915,8 +915,8 @@ class KCaseExpressionTest { case { `when` { id isEqualTo 22 - then("'yes'") - then("'no'") + then("yes") + then("no") } } }.withMessage(Messages.getString("ERROR.41")) From 07cb1329d458ae5418c3c6c3558e4069798e6406 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 1 May 2024 10:02:34 -0400 Subject: [PATCH 4/5] Update docs with new syntax --- CHANGELOG.md | 8 ++++++-- src/site/markdown/docs/kotlinCaseExpressions.md | 14 +++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8540619ec..04122d5f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,16 @@ This log will detail notable changes to MyBatis Dynamic SQL. Full details are available on the GitHub milestone pages. -## Release 1.5.1 - April 30, 2024 +## Release 1.5.2 - Unreleased -This is a minor release with several enhancements. +This is a small maintenance release with improvements to the Kotlin DSL for CASE expressions. **Important:** This is the last release that will be compatible with Java 8. +## Release 1.5.1 - April 30, 2024 + +This is a minor release with several enhancements. + GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/milestone/13?closed=1](https://github.com/mybatis/mybatis-dynamic-sql/milestone/13?closed=1) ### Case Expressions and Cast Function diff --git a/src/site/markdown/docs/kotlinCaseExpressions.md b/src/site/markdown/docs/kotlinCaseExpressions.md index f35a298da..5366db40b 100644 --- a/src/site/markdown/docs/kotlinCaseExpressions.md +++ b/src/site/markdown/docs/kotlinCaseExpressions.md @@ -72,7 +72,7 @@ A simple case expression can be coded like the following in the Kotlin DSL: ```kotlin select(case(id) { - `when`(1, 2, 3) { then(true) } + `when`(1, 2, 3) then true `else`(false) } `as` "small_id" ) { @@ -91,7 +91,7 @@ you can write the query as follows: ```kotlin select(case(id) { - `when`(1, 2, 3) { then(value(true)) } + `when`(1, 2, 3) then value(true) `else`(value(false)) } `as` "small_id" ) { @@ -111,7 +111,7 @@ expected data type. Here's an example of using the `cast` function: ```kotlin select(case(id) { - `when`(1, 2, 3) { then(value(true)) } + `when`(1, 2, 3) then value(true) `else`(cast { value(false) `as` "BOOLEAN" }) } `as` "small_id" ) { @@ -134,8 +134,8 @@ A simple case expression can be coded like the following in the Kotlin DSL: ```kotlin select(case(total_length) { - `when`(isLessThan(10)) { then("small") } - `when`(isGreaterThan(20)) { then("large") } + `when`(isLessThan(10)) then "small" + `when`(isGreaterThan(20)) then "large" `else`("medium") } `as` "tshirt_size" ) { @@ -158,8 +158,8 @@ VARCHAR, you can use the `cast` function as follows: ```kotlin select(case(total_length) { - `when`(isLessThan(10)) { then("small") } - `when`(isGreaterThan(20)) { then("large") } + `when`(isLessThan(10)) then "small" + `when`(isGreaterThan(20)) then "large" `else`(cast { "medium" `as` "VARCHAR(6)" }) } `as` "tshirt_size" ) { From 15d258e42126f7af414e940089202516162794d7 Mon Sep 17 00:00:00 2001 From: Jeff Butler Date: Wed, 1 May 2024 10:18:15 -0400 Subject: [PATCH 5/5] Better vararg handling --- .../sql/util/kotlin/elements/CaseDSLs.kt | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt index cd735f43a..027b5b187 100644 --- a/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt +++ b/src/main/kotlin/org/mybatis/dynamic/sql/util/kotlin/elements/CaseDSLs.kt @@ -65,24 +65,14 @@ class KSimpleCaseDSL : KElseDSL { } internal val whenConditions = mutableListOf>() - fun `when`(firstCondition: VisitableCondition, vararg subsequentConditions: VisitableCondition) = + fun `when`(vararg conditions: VisitableCondition) = SimpleCaseThenGatherer { thenValue -> - val allConditions = buildList { - add(firstCondition) - addAll(subsequentConditions) - } - - whenConditions.add(ConditionBasedWhenCondition(allConditions, thenValue)) + whenConditions.add(ConditionBasedWhenCondition(conditions.asList(), thenValue)) } - fun `when`(firstValue: T, vararg subsequentValues: T) = + fun `when`(vararg values: T) = SimpleCaseThenGatherer { thenValue -> - val allConditions = buildList { - add(firstValue) - addAll(subsequentValues) - } - - whenConditions.add(BasicWhenCondition(allConditions, thenValue)) + whenConditions.add(BasicWhenCondition(values.asList(), thenValue)) } override infix fun `else`(column: BasicColumn) {