test: cover insertUpdateDeleteAgainstAViewAreRejected
This commit is contained in:
1 parent
03072818c2
commit
18deaa3ca0
1 file changed
+131
@@ -155,3 +155,134 @@ class ViewTest {
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user