test: cover insertUpdateDeleteAgainstAViewAreRejected

This commit is contained in:
dualfroz committed 2026-09-10 20:01:04 +02:00
1 parent 03072818c2
commit 18deaa3ca0
1 file changed
+131
+131
View File
@@ -155,3 +155,134 @@ class ViewTest {
assertFailsWith<KestrelException> { run("DROP VIEW users") } assertFailsWith<KestrelException> { run("DROP VIEW users") }
} }
@Test
fun insertUpdateDeleteAgainstAViewAreRejected() {
seedUsers()
run("CREATE VIEW adults AS SELECT id, name FROM users WHERE age >= 18")
assertFailsWith<KestrelException> { run("INSERT INTO adults VALUES (9, 'x')") }
assertFailsWith<KestrelException> { run("UPDATE adults SET name = 'x'") }
assertFailsWith<KestrelException> { run("DELETE FROM adults") }
}
@Test
fun creatingAnIndexOnAViewIsRejected() {
seedUsers()
run("CREATE VIEW adults AS SELECT id, name FROM users WHERE age >= 18")
assertFailsWith<KestrelException> { run("CREATE INDEX idx ON adults (id)") }
}
@Test
fun mutuallyRecursiveViewsFailInsteadOfOverflowingTheStack() {
seedUsers()
run("CREATE VIEW a AS SELECT id FROM users")
run("CREATE VIEW b AS SELECT id FROM a")
run("CREATE OR REPLACE VIEW a AS SELECT id FROM b")
assertFailsWith<KestrelException> { run("SELECT * FROM a") }
}
@Test
fun selfReferencingViewFailsCleanly() {
seedUsers()
run("CREATE VIEW a AS SELECT id FROM users")
run("CREATE OR REPLACE VIEW a AS SELECT id FROM a")
assertFailsWith<KestrelException> { run("SELECT * FROM a") }
}
@Test
fun rollbackUndoesCreateViewAndDropView() {
seedUsers()
run("CREATE VIEW adults AS SELECT id FROM users WHERE age >= 18")
run("BEGIN")
run("CREATE VIEW seniors AS SELECT id FROM users WHERE age >= 60")
run("DROP VIEW adults")
run("ROLLBACK")
assertEquals(listOf("adults"), catalog.viewNames)
}
@Test
fun commitKeepsViewChanges() {
seedUsers()
run("BEGIN")
run("CREATE VIEW adults AS SELECT id FROM users WHERE age >= 18")
run("COMMIT")
assertEquals(listOf("adults"), catalog.viewNames)
}
@Test
fun dropTableWithADependentViewFailsByDefaultAndAlsoWithExplicitRestrict() {
seedUsers()
run("CREATE VIEW adults AS SELECT id FROM users WHERE age >= 18")
assertFailsWith<KestrelException> { run("DROP TABLE users") }
assertFailsWith<KestrelException> { run("DROP TABLE users RESTRICT") }
assertEquals(listOf("users"), catalog.tableNames)
assertEquals(listOf("adults"), catalog.viewNames)
}
@Test
fun dropTableCascadeDropsTheTableAndItsDependentView() {
seedUsers()
run("CREATE VIEW adults AS SELECT id FROM users WHERE age >= 18")
run("DROP TABLE users CASCADE")
assertTrue(catalog.tableNames.isEmpty())
assertTrue(catalog.viewNames.isEmpty())
}
@Test
fun dropViewWithADependentViewFailsByDefault() {
seedUsers()
run("CREATE VIEW adults AS SELECT id FROM users WHERE age >= 18")
run("CREATE VIEW seniorAdults AS SELECT id FROM adults WHERE id > 0")
assertFailsWith<KestrelException> { run("DROP VIEW adults") }
assertEquals(listOf("adults", "seniorAdults"), catalog.viewNames)
}
@Test
fun dropViewCascadeDropsATransitiveChainOfDependentViews() {
seedUsers()
run("CREATE VIEW a AS SELECT id FROM users WHERE age >= 18")
run("CREATE VIEW b AS SELECT id FROM a WHERE id > 0")
run("CREATE VIEW c AS SELECT id FROM b WHERE id > 0")
run("DROP VIEW a CASCADE")
assertTrue(catalog.viewNames.isEmpty())
}
@Test
fun dropTableCascadeHandlesADiamondOfDependentViewsWithoutFailing() {
seedUsers()
run("CREATE VIEW b AS SELECT id FROM users WHERE age >= 18")
run("CREATE VIEW c AS SELECT id FROM users WHERE age >= 21")
run("CREATE VIEW d AS SELECT b.id FROM b JOIN c ON b.id = c.id")
run("DROP TABLE users CASCADE")
assertTrue(catalog.tableNames.isEmpty())
assertTrue(catalog.viewNames.isEmpty())
}
@Test
fun rollbackUndoesACascadeDrop() {
seedUsers()
run("CREATE VIEW adults AS SELECT id FROM users WHERE age >= 18")
run("BEGIN")
run("DROP TABLE users CASCADE")
run("ROLLBACK")
assertEquals(listOf("users"), catalog.tableNames)
assertEquals(listOf("adults"), catalog.viewNames)
val result = select("SELECT id FROM adults ORDER BY id ASC")
assertTrue(result.rows.isNotEmpty())
}
@Test
fun explainOverAViewDescribesTheOuterQuery() {
seedUsers()
run("CREATE VIEW adults AS SELECT id, name FROM users WHERE age >= 18")
val explain = exec("EXPLAIN SELECT * FROM adults") as kestrel.engine.ExplainResult
assertTrue(explain.plan.any { it.contains("adults") })
}
@Test
fun columnTypeOfAViewIsInferredFromActualData() {
seedUsers()
run("CREATE VIEW names AS SELECT name FROM users")
val result = select("SELECT name FROM names WHERE name = 'ada'")
assertEquals(listOf(listOf(text("ada"))), result.rows)
}
}