test: cover renameColumnUpdatesAnIndexAndThePlannerStillUsesIt
This commit is contained in:
1 parent
d53bea481c
commit
f8d57f5621
1 file changed
+157
@@ -313,3 +313,160 @@ class AlterTableTest {
|
||||
assertEquals(listOf(listOf(int(30))), select("SELECT years FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameColumnUpdatesAnIndexAndThePlannerStillUsesIt() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, age INTEGER)")
|
||||
run("INSERT INTO t VALUES (1, 30), (2, 40)")
|
||||
run("CREATE INDEX idx_age ON t (age)")
|
||||
run("ALTER TABLE t RENAME COLUMN age TO years")
|
||||
val plan = explain("EXPLAIN SELECT id FROM t WHERE years = 30").joinToString("\n")
|
||||
assertTrue(plan.contains("Index Scan using idx_age"), plan)
|
||||
assertEquals(listOf(listOf(int(1))), select("SELECT id FROM t WHERE years = 30").rows)
|
||||
}
|
||||
|
||||
// ---- RENAME TABLE ----
|
||||
|
||||
@Test
|
||||
fun renameTableRenamesAndPreservesData() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT)")
|
||||
run("INSERT INTO t VALUES (1, 'ada')")
|
||||
val result = exec("ALTER TABLE t RENAME TO people")
|
||||
assertEquals(AlterTableResult("people"), result)
|
||||
assertEquals(listOf(listOf(int(1), text("ada"))), select("SELECT * FROM people").rows)
|
||||
assertFailsWith<KestrelException> { run("SELECT * FROM t") }
|
||||
assertEquals(listOf("people"), catalog.tableNames)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTableRejectsWhenNewNameAlreadyExistsAsTable() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
|
||||
run("CREATE TABLE other (id INTEGER PRIMARY KEY)")
|
||||
val error = assertFailsWith<KestrelException> { run("ALTER TABLE t RENAME TO other") }
|
||||
assertTrue(error.message!!.contains("already exists"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTableRejectsWhenNewNameAlreadyExistsAsView() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
|
||||
run("CREATE TABLE other (id INTEGER PRIMARY KEY)")
|
||||
run("CREATE VIEW v AS SELECT * FROM other")
|
||||
val error = assertFailsWith<KestrelException> { run("ALTER TABLE t RENAME TO v") }
|
||||
assertTrue(error.message!!.contains("already exists"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTableRejectsRenamingAView() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
|
||||
run("CREATE VIEW v AS SELECT * FROM t")
|
||||
val error = assertFailsWith<KestrelException> { run("ALTER TABLE v RENAME TO w") }
|
||||
assertTrue(error.message!!.contains("cannot modify view"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTablePropagatesToOtherTablesForeignKeyReference() {
|
||||
run("CREATE TABLE departments (id INTEGER PRIMARY KEY)")
|
||||
run("CREATE TABLE employees (id INTEGER PRIMARY KEY, dept_id INTEGER REFERENCES departments(id) ON DELETE CASCADE)")
|
||||
run("INSERT INTO departments VALUES (1)")
|
||||
run("INSERT INTO employees VALUES (1, 1)")
|
||||
run("ALTER TABLE departments RENAME TO divisions")
|
||||
run("INSERT INTO divisions VALUES (2)")
|
||||
run("INSERT INTO employees VALUES (2, 2)")
|
||||
assertFailsWith<KestrelException> { run("INSERT INTO employees VALUES (3, 99)") }
|
||||
run("DELETE FROM divisions WHERE id = 1")
|
||||
assertEquals(listOf(listOf(int(2))), select("SELECT id FROM employees").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTableUpdatesItsOwnSelfReferencingForeignKey() {
|
||||
run(
|
||||
"CREATE TABLE staff (id INTEGER PRIMARY KEY, manager_id INTEGER REFERENCES staff(id))"
|
||||
)
|
||||
run("INSERT INTO staff VALUES (1, NULL)")
|
||||
run("ALTER TABLE staff RENAME TO personnel")
|
||||
run("INSERT INTO personnel VALUES (2, 1)")
|
||||
assertFailsWith<KestrelException> { run("INSERT INTO personnel VALUES (3, 99)") }
|
||||
assertEquals(2, select("SELECT * FROM personnel").rows.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTableUpdatesAnIndexAndThePlannerStillUsesIt() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, age INTEGER)")
|
||||
run("INSERT INTO t VALUES (1, 30), (2, 40)")
|
||||
run("CREATE INDEX idx_age ON t (age)")
|
||||
run("ALTER TABLE t RENAME TO people")
|
||||
val plan = explain("EXPLAIN SELECT id FROM people WHERE age = 30").joinToString("\n")
|
||||
assertTrue(plan.contains("Index Scan using idx_age on people"), plan)
|
||||
assertEquals(listOf(listOf(int(1))), select("SELECT id FROM people WHERE age = 30").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTablePropagatesIntoASimpleViewDefinition() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT)")
|
||||
run("INSERT INTO t VALUES (1, 'ada')")
|
||||
run("CREATE VIEW v AS SELECT * FROM t")
|
||||
run("ALTER TABLE t RENAME TO people")
|
||||
assertEquals(listOf(listOf(int(1), text("ada"))), select("SELECT * FROM v").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTablePropagatesIntoAViewJoinAndASubqueryExpression() {
|
||||
run("CREATE TABLE departments (id INTEGER PRIMARY KEY, name TEXT)")
|
||||
run("CREATE TABLE employees (id INTEGER PRIMARY KEY, dept_id INTEGER)")
|
||||
run("INSERT INTO departments VALUES (1, 'eng')")
|
||||
run("INSERT INTO employees VALUES (1, 1)")
|
||||
run(
|
||||
"CREATE VIEW v AS SELECT e.id FROM employees e JOIN departments d ON e.dept_id = d.id " +
|
||||
"WHERE d.id IN (SELECT id FROM departments)"
|
||||
)
|
||||
run("ALTER TABLE departments RENAME TO divisions")
|
||||
assertEquals(listOf(listOf(int(1))), select("SELECT * FROM v").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTablePropagatesIntoADerivedTableAndAUnion() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
|
||||
run("INSERT INTO t VALUES (1), (2)")
|
||||
run(
|
||||
"CREATE VIEW v AS SELECT * FROM (SELECT id FROM t) sub " +
|
||||
"UNION SELECT id FROM t WHERE id = 2"
|
||||
)
|
||||
run("ALTER TABLE t RENAME TO renamed")
|
||||
assertEquals(listOf(listOf(int(1)), listOf(int(2))), select("SELECT * FROM v ORDER BY id").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTableDoesNotTouchATableSourceShadowedByACteOfTheSameName() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
|
||||
run("INSERT INTO t VALUES (1)")
|
||||
run("CREATE VIEW v AS WITH t AS (SELECT 99 AS id FROM t) SELECT * FROM t")
|
||||
run("ALTER TABLE t RENAME TO renamed")
|
||||
// The CTE named "t" shadows the base table for the rest of that WITH clause, so the view
|
||||
// must still yield the CTE's own row (99), not read from the (now renamed) base table.
|
||||
assertEquals(listOf(listOf(int(99))), select("SELECT * FROM v").rows)
|
||||
assertEquals(listOf(listOf(int(1))), select("SELECT * FROM renamed").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameTableRenamingToItsOwnNameIsANoOp() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
|
||||
run("INSERT INTO t VALUES (1)")
|
||||
run("ALTER TABLE t RENAME TO t")
|
||||
assertEquals(listOf(listOf(int(1))), select("SELECT * FROM t").rows)
|
||||
}
|
||||
|
||||
// ---- DEFAULT (CREATE TABLE + INSERT) ----
|
||||
|
||||
@Test
|
||||
fun insertUsesColumnDefaultWhenColumnOmittedFromColumnList() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT DEFAULT 'pending')")
|
||||
run("INSERT INTO t (id) VALUES (1)")
|
||||
assertEquals(listOf(listOf(text("pending"))), select("SELECT status FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertDoesNotUseDefaultWhenExplicitNullIsGiven() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT DEFAULT 'pending')")
|
||||
run("INSERT INTO t (id, status) VALUES (1, NULL)")
|
||||
assertEquals(listOf(listOf(Value.NullValue)), select("SELECT status FROM t").rows)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user