test: cover ExpressionLanguageTest and run
This commit is contained in:
1 parent
90139e824b
commit
f3a0059bc3
1 file changed
+158
@@ -0,0 +1,158 @@
|
||||
package kestrel
|
||||
|
||||
import java.math.BigDecimal
|
||||
import java.time.LocalDate
|
||||
import kestrel.catalog.Catalog
|
||||
import kestrel.engine.Executor
|
||||
import kestrel.engine.ExplainResult
|
||||
import kestrel.engine.SelectResult
|
||||
import kestrel.engine.StatementResult
|
||||
import kestrel.sql.lexer.Lexer
|
||||
import kestrel.sql.parser.Parser
|
||||
import kestrel.storage.Value
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ExpressionLanguageTest {
|
||||
private val catalog = Catalog()
|
||||
private val executor = Executor(catalog)
|
||||
|
||||
private fun run(sql: String): List<StatementResult> =
|
||||
Parser(Lexer(sql).tokenize()).parseProgram().map { executor.execute(it) }
|
||||
|
||||
private fun select(sql: String): SelectResult = run(sql).single() as SelectResult
|
||||
|
||||
private fun int(value: Long) = Value.IntegerValue(value)
|
||||
private fun text(value: String) = Value.TextValue(value)
|
||||
|
||||
private fun seedUsers() {
|
||||
run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER, bio TEXT)")
|
||||
run(
|
||||
"INSERT INTO users VALUES " +
|
||||
"(1, 'ada', 36, 'mathematician'), (2, 'linus', 54, NULL), " +
|
||||
"(3, 'grace', 85, 'rear admiral')"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun scalarFunctionInProjection() {
|
||||
seedUsers()
|
||||
val result = select("SELECT UPPER(name) FROM users ORDER BY id ASC")
|
||||
assertEquals(listOf("upper"), result.columns)
|
||||
assertEquals(listOf(text("ADA"), text("LINUS"), text("GRACE")), result.rows.map { it[0] })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun scalarFunctionInWhereClause() {
|
||||
seedUsers()
|
||||
val result = select("SELECT name FROM users WHERE LENGTH(name) > 4 ORDER BY name ASC")
|
||||
assertEquals(listOf(listOf(text("grace")), listOf(text("linus"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun scalarFunctionUsableInUpdateAssignment() {
|
||||
seedUsers()
|
||||
run("UPDATE users SET name = UPPER(name) WHERE id = 1")
|
||||
val result = select("SELECT name FROM users WHERE id = 1")
|
||||
assertEquals(listOf(listOf(text("ADA"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nestedFunctionCalls() {
|
||||
seedUsers()
|
||||
val result = select("SELECT SUBSTR(UPPER(name), 1, 1) FROM users WHERE id = 1")
|
||||
assertEquals(listOf(listOf(text("A"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isNullFiltersRowsWithMissingValues() {
|
||||
seedUsers()
|
||||
val result = select("SELECT name FROM users WHERE bio IS NULL")
|
||||
assertEquals(listOf(listOf(text("linus"))), result.rows)
|
||||
val negated = select("SELECT COUNT(*) FROM users WHERE bio IS NOT NULL")
|
||||
assertEquals(listOf(listOf(int(2))), negated.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun inClauseMatchesAgainstLiteralSet() {
|
||||
seedUsers()
|
||||
val result = select("SELECT name FROM users WHERE age IN (36, 85) ORDER BY age ASC")
|
||||
assertEquals(listOf(listOf(text("ada")), listOf(text("grace"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun notInExcludesMatchingRows() {
|
||||
seedUsers()
|
||||
val result = select("SELECT name FROM users WHERE age NOT IN (36, 85)")
|
||||
assertEquals(listOf(listOf(text("linus"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun betweenSelectsInclusiveRange() {
|
||||
seedUsers()
|
||||
val result = select("SELECT name FROM users WHERE age BETWEEN 40 AND 90 ORDER BY age ASC")
|
||||
assertEquals(listOf(listOf(text("linus")), listOf(text("grace"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun likeMatchesWildcardPattern() {
|
||||
seedUsers()
|
||||
val result = select("SELECT name FROM users WHERE bio LIKE '%admiral' ")
|
||||
assertEquals(listOf(listOf(text("grace"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun caseExpressionInProjection() {
|
||||
seedUsers()
|
||||
val result = select(
|
||||
"SELECT name, CASE WHEN age < 50 THEN 'young' WHEN age < 80 THEN 'mid' ELSE 'senior' END " +
|
||||
"FROM users ORDER BY id ASC"
|
||||
)
|
||||
assertEquals(
|
||||
listOf(
|
||||
listOf(text("ada"), text("young")),
|
||||
listOf(text("linus"), text("mid")),
|
||||
listOf(text("grace"), text("senior"))
|
||||
),
|
||||
result.rows
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun caseExpressionUsableInWhereClause() {
|
||||
seedUsers()
|
||||
val result = select(
|
||||
"SELECT name FROM users WHERE CASE WHEN age > 40 THEN TRUE ELSE FALSE END ORDER BY name ASC"
|
||||
)
|
||||
assertEquals(listOf(listOf(text("grace")), listOf(text("linus"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun combiningPredicatesWithLogicalOperators() {
|
||||
seedUsers()
|
||||
val result = select(
|
||||
"SELECT name FROM users WHERE age BETWEEN 30 AND 60 AND name LIKE 'a%'"
|
||||
)
|
||||
assertEquals(listOf(listOf(text("ada"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aggregateOfScalarFunctionResult() {
|
||||
seedUsers()
|
||||
val result = select("SELECT SUM(LENGTH(name)) FROM users")
|
||||
assertEquals(listOf(listOf(int(3 + 5 + 5))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun groupByWithFunctionOnGroupedColumn() {
|
||||
run("CREATE TABLE t (category TEXT, amount INTEGER)")
|
||||
run("INSERT INTO t VALUES ('Eng', 10), ('eng', 20), ('Ops', 5)")
|
||||
val result = select("SELECT LOWER(category), SUM(amount) FROM t GROUP BY LOWER(category) ORDER BY LOWER(category) ASC")
|
||||
assertEquals(
|
||||
listOf(listOf(text("eng"), int(30)), listOf(text("ops"), int(5))),
|
||||
result.rows
|
||||
)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user