Skip to content
Open
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
27 changes: 27 additions & 0 deletions squash-core/src/org/jetbrains/squash/dialect/BaseSQLDialect.kt
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ open class BaseSQLDialect(val name: String) : SQLDialect {
is FunctionExpression -> {
appendFunctionExpression(this, expression)
}
is CaseExpression<*> -> {
appendCaseExpression(this, expression)
}
is DialectExtension -> {
expression.appendTo(this, this@BaseSQLDialect)
}
Expand Down Expand Up @@ -141,6 +144,30 @@ open class BaseSQLDialect(val name: String) : SQLDialect {
})
}

open fun <T> appendCaseExpression(builder: SQLStatementBuilder, expression: CaseExpression<T>) = with(builder) {
if (expression.target == null) {
append("CASE")
} else {
append("CASE (")
appendExpression(this, expression.target)
append(")")
}

for (whenThenClause in expression.clauses) {
append(" WHEN (")
appendExpression(this, whenThenClause.whenClause)
append(") THEN ")
appendExpression(this, whenThenClause.thenClause)
}

if (expression.finalClause != null) {
append(" ELSE ")
appendExpression(this, expression.finalClause!!)
}

append(" END")
}

open fun <T> appendFunctionExpression(builder: SQLStatementBuilder, expression: FunctionExpression<T>) = with(builder) {
when (expression) {
is CountExpression -> {
Expand Down
28 changes: 28 additions & 0 deletions squash-core/src/org/jetbrains/squash/expressions/CaseExpression.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.jetbrains.squash.expressions

class CaseExpression<T>(val target:Expression<*>? = null) : Expression<T> {
val clauses = mutableListOf<WhenThenClause<T>>()
var finalClause:Expression<T>? = null

fun whenClause(expression:Expression<*>):WhenThenClause<T> = WhenThenClause(this, expression).apply {
this@CaseExpression.clauses.add(this)
}

fun elseClause(expression:Expression<T>):CaseExpression<T> = this.apply {
finalClause = expression
}

class WhenThenClause<T>(
val caseExpression:CaseExpression<T>,
val whenClause:Expression<*>
) {
lateinit var thenClause:Expression<T>

fun thenClause(expression:Expression<T>):CaseExpression<T> {
thenClause = expression
return caseExpression
}
}
}

inline fun <T> case(target:Expression<*>? = null, clauses:CaseExpression<T>.() -> Unit) = CaseExpression<T>(target).apply(clauses)
45 changes: 41 additions & 4 deletions squash-core/test/org/jetbrains/squash/tests/QueryTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ package org.jetbrains.squash.tests
import org.jetbrains.squash.definition.*
import org.jetbrains.squash.expressions.*
import org.jetbrains.squash.query.*
import org.jetbrains.squash.results.*
import org.jetbrains.squash.statements.*
import org.jetbrains.squash.results.get
import org.jetbrains.squash.statements.insertInto
import org.jetbrains.squash.statements.values
import org.jetbrains.squash.tests.data.*
import kotlin.test.*

abstract class QueryTests : DatabaseTests {
open fun nullsLast(sql: String): String = "$sql NULLS LAST"

@Test fun selectLiteral() {
withTables() {
withTables {
val eugene = literal("eugene")
val query = select { eugene }

Expand Down Expand Up @@ -447,7 +448,43 @@ abstract class QueryTests : DatabaseTests {

}
}


@Test fun selectCaseStatementTrue() {
withTables {
val query = select(
case<String>(literal(5)) {
whenClause(literal(6)).thenClause(literal("false"))
whenClause(literal(5)).thenClause(literal("true"))
whenClause(literal(4)).thenClause(literal("false"))
elseClause(literal("false"))
})

connection.dialect.statementSQL(query).assertSQL {
"SELECT CASE (?) WHEN (?) THEN ? WHEN (?) THEN ? WHEN (?) THEN ? ELSE ? END"
}

assertTrue { query.execute().single().get<String>(0).toBoolean() }
}
}

@Test fun selectCaseStatementFalse() {
withTables {
val query = select(
case<String>(literal(-1)) {
whenClause(literal(6)).thenClause(literal("false"))
whenClause(literal(5)).thenClause(literal("true"))
whenClause(literal(4)).thenClause(literal("false"))
elseClause(literal("false"))
})

connection.dialect.statementSQL(query).assertSQL {
"SELECT CASE (?) WHEN (?) THEN ? WHEN (?) THEN ? WHEN (?) THEN ? ELSE ? END"
}

assertFalse { query.execute().single().get<String>(0).toBoolean() }
}
}

@Test fun selectFromNestedQuery() {
withCities {
val query = from(select(Citizens.name, Citizens.id).from(Citizens).alias("Citizens"))
Expand Down