test(sql): cover whereFiltersRowsUsingTheSharedEvaluator

This commit is contained in:
dualfroz committed 2026-09-12 16:42:52 +02:00
1 parent 8858671825
commit ae50dd1aa7
1 file changed
+157
@@ -153,3 +153,160 @@ class DiskExecutorTest {
assertTrue(listOf(int(1), text("ada"), int(36)) in result.rows)
}
@Test
fun whereFiltersRowsUsingTheSharedEvaluator() {
val db = newDatabase()
db.seedUsers()
val result = db.select("SELECT name FROM users WHERE age > 40")
assertEquals(setOf(text("linus"), text("grace")), result.rows.map { it.single() }.toSet())
}
@Test
fun orderByAndLimitApplyAfterFilteringAndBeforeProjection() {
val db = newDatabase()
db.seedUsers()
val result = db.select("SELECT name, age FROM users ORDER BY age DESC LIMIT 2")
assertEquals(listOf(listOf(text("grace"), int(85)), listOf(text("linus"), int(54))), result.rows)
}
@Test
fun offsetSkipsLeadingRowsWithoutALimit() {
val db = newDatabase()
db.seedUsers()
val result = db.select("SELECT name FROM users ORDER BY age ASC OFFSET 1")
assertEquals(listOf(listOf(text("linus")), listOf(text("grace"))), result.rows)
}
@Test
fun limitAndOffsetTogetherPageThroughTheOrderedResult() {
val db = newDatabase()
db.seedUsers()
val result = db.select("SELECT name FROM users ORDER BY age ASC LIMIT 1 OFFSET 1")
assertEquals(listOf(listOf(text("linus"))), result.rows)
}
@Test
fun offsetWrittenBeforeLimitStillAppliesLimitAfterTheSkip() {
val db = newDatabase()
db.seedUsers()
val result = db.select("SELECT name FROM users ORDER BY age ASC OFFSET 1 LIMIT 1")
assertEquals(listOf(listOf(text("linus"))), result.rows)
}
@Test
fun offsetPastTheEndOfTheResultReturnsNoRows() {
val db = newDatabase()
db.seedUsers()
val result = db.select("SELECT name FROM users ORDER BY age ASC OFFSET 100")
assertEquals(emptyList<List<Value>>(), result.rows)
}
@Test
fun offsetSurvivesCloseAndReopen() {
val db = newDatabase()
db.seedUsers()
db.reopen()
val result = db.select("SELECT name FROM users ORDER BY age ASC LIMIT 1 OFFSET 1")
assertEquals(listOf(listOf(text("linus"))), result.rows)
}
@Test
fun expressionProjectionEvaluatesFunctionsAndUsesAliasesOrGeneratedLabels() {
val db = newDatabase()
db.seedUsers()
val result = db.select("SELECT UPPER(name) AS loud, age + 1 FROM users WHERE id = 1")
assertEquals(listOf("loud", "column2"), result.columns)
assertEquals(listOf(listOf(text("ADA"), int(37))), result.rows)
}
@Test
fun updateAppliesExpressionsAgainstTheOldRowAndReportsMatchedCount() {
val db = newDatabase()
db.seedUsers()
val updated = db.run("UPDATE users SET age = age + 1 WHERE age > 40").single()
assertEquals(UpdateResult(2), updated)
val ages = db.select("SELECT name, age FROM users ORDER BY name").rows.associate { (it[0] as Value.TextValue).value to it[1] }
assertEquals(mapOf("ada" to int(36), "linus" to int(55), "grace" to int(86)), ages)
}
@Test
fun updateSetToDefaultKeywordResetsTheColumn() {
val db = newDatabase()
db.seedUsers()
db.run("UPDATE users SET age = DEFAULT WHERE id = 2")
assertEquals(int(0), db.select("SELECT age FROM users WHERE id = 2").rows.single().single())
}
@Test
fun deleteRemovesMatchingRowsAndReportsCount() {
val db = newDatabase()
db.seedUsers()
val deleted = db.run("DELETE FROM users WHERE age > 40").single()
assertEquals(DeleteResult(2), deleted)
assertEquals(listOf(listOf(int(1), text("ada"), int(36))), db.select("SELECT * FROM users").rows)
}
@Test
fun dropTableRemovesItFromTheCatalog() {
val db = newDatabase()
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)")
val dropped = db.run("DROP TABLE users").single()
assertEquals(DropTableResult("users"), dropped)
assertFailsWith<DiskCatalogException> { db.select("SELECT * FROM users") }
}
@Test
fun aFailedStatementInAMultiRowInsertLeavesNoPartialRowsBehind() {
val db = newDatabase()
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)")
// The second row duplicates the first row's primary key: DiskTable rejects it mid-batch,
// so the whole INSERT statement (including the already-applied first row) must abort.
assertFailsWith<DiskTableException> {
db.run("INSERT INTO users VALUES (1, 'ada'), (1, 'ada-again')")
}
assertEquals(emptyList<List<Value>>(), db.select("SELECT * FROM users").rows)
}
@Test
fun notNullViolationOnUpdateAbortsTheWholeStatement() {
val db = newDatabase()
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)")
db.run("INSERT INTO users VALUES (1, 'ada'), (2, 'linus')")
assertFailsWith<DiskTableException> { db.run("UPDATE users SET name = NULL") }
// Neither row's name was actually cleared, because the failure aborted the transaction.
assertEquals(setOf(text("ada"), text("linus")), db.select("SELECT name FROM users").rows.map { it.single() }.toSet())
}
@Test
fun integerLiteralIsCoercedToRealForARealColumn() {
val db = newDatabase()
db.run("CREATE TABLE readings (id INTEGER PRIMARY KEY, value REAL NOT NULL)")
db.run("INSERT INTO readings VALUES (1, 5)")
assertEquals(Value.RealValue(5.0), db.select("SELECT value FROM readings").rows.single().single())
}
@Test
fun textLiteralIntoAnIntegerColumnIsRejectedWithATypeMismatch() {
val db = newDatabase()
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)")
assertFailsWith<DiskExecutorException> { db.run("INSERT INTO users VALUES ('x', 'ada')") }
}
@Test
fun dataSurvivesClosingAndReopeningTheCatalogInWhatActsAsAFreshProcess() {
val db = newDatabase()
db.seedUsers()
db.run("UPDATE users SET age = 100 WHERE id = 1")
db.reopen()
val ages = db.select("SELECT name, age FROM users ORDER BY name").rows
assertEquals(listOf(listOf(text("ada"), int(100)), listOf(text("grace"), int(85)), listOf(text("linus"), int(54))), ages)
}
private fun Database.seedOrders() {
run("CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT NOT NULL)")
run("INSERT INTO customers VALUES (1, 'ada'), (2, 'linus'), (3, 'grace')")
run("CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER NOT NULL, amount INTEGER NOT NULL)")
// grace (id 3) has no orders, so LEFT JOIN has something to pad and INNER JOIN has something to drop.
run("INSERT INTO orders VALUES (1, 1, 100), (2, 1, 50), (3, 2, 200)")
}