test(sql): cover renameColumnUpdatesAUniqueConstraint

This commit is contained in:
dualfroz committed 2026-09-13 16:01:15 +02:00
1 parent decfe2c8d7
commit aaa90ad4ab
1 file changed
+159
@@ -3646,3 +3646,162 @@ class DiskExecutorTest {
assertTrue(db.select("SELECT * FROM employees").rows.isEmpty())
}
@Test
fun renameColumnUpdatesAUniqueConstraint() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY, email TEXT UNIQUE)")
db.run("INSERT INTO t VALUES (1, 'a@x.com')")
db.run("ALTER TABLE t RENAME COLUMN email TO contact_email")
assertFailsWith<KestrelException> { db.run("INSERT INTO t VALUES (2, 'a@x.com')") }
}
@Test
fun renameColumnUpdatesACheckConstraintAndStillEnforcesIt() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY, age INTEGER CHECK (age > 0))")
db.run("ALTER TABLE t RENAME COLUMN age TO years")
assertFailsWith<KestrelException> { db.run("INSERT INTO t VALUES (1, -5)") }
db.run("INSERT INTO t VALUES (1, 30)")
assertEquals(listOf(listOf(int(30))), db.select("SELECT years FROM t").rows)
}
@Test
fun renameColumnUpdatesASecondaryIndexAndPushdownStillWorks() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY, age INTEGER)")
db.run("INSERT INTO t VALUES (1, 30), (2, 40)")
db.run("CREATE INDEX idx_age ON t (age)")
db.run("ALTER TABLE t RENAME COLUMN age TO years")
val table = db.catalog.table("t")
val result = db.select("SELECT id FROM t WHERE years = 30")
assertEquals(listOf(listOf(int(1))), result.rows)
assertEquals(1, table.secondaryLookupCount)
assertEquals(listOf("years"), table.secondaryIndexes.single().columnNames)
}
@Test
fun renameColumnDefinitionSurvivesClosingAndReopeningTheCatalog() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY, bio TEXT)")
db.run("INSERT INTO t VALUES (1, 'mathematician')")
db.run("ALTER TABLE t RENAME COLUMN bio TO biography")
db.reopen()
assertEquals(listOf("id", "biography"), db.select("SELECT * FROM t").columns)
assertEquals(listOf(listOf(int(1), text("mathematician"))), db.select("SELECT * FROM t").rows)
}
// ---- ALTER TABLE RENAME TO ----
@Test
fun renameTableRenamesAndPreservesData() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT)")
db.run("INSERT INTO t VALUES (1, 'ada')")
val result = db.run("ALTER TABLE t RENAME TO people").single()
assertEquals(AlterTableResult("people"), result)
assertEquals(listOf(listOf(int(1), text("ada"))), db.select("SELECT * FROM people").rows)
assertFailsWith<DiskCatalogException> { db.run("SELECT * FROM t") }
assertEquals(listOf("people"), db.catalog.tableNames)
}
@Test
fun renameTableRejectsWhenNewNameAlreadyExistsAsTable() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
db.run("CREATE TABLE other (id INTEGER PRIMARY KEY)")
val error = assertFailsWith<DiskCatalogException> { db.run("ALTER TABLE t RENAME TO other") }
assertTrue(error.message!!.contains("already exists"))
}
@Test
fun renameTableRejectsWhenNewNameAlreadyExistsAsView() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
db.run("CREATE TABLE other (id INTEGER PRIMARY KEY)")
db.run("CREATE VIEW v AS SELECT * FROM other")
val error = assertFailsWith<DiskCatalogException> { db.run("ALTER TABLE t RENAME TO v") }
assertTrue(error.message!!.contains("already exists"))
}
@Test
fun renameTableRejectsRenamingAView() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
db.run("CREATE VIEW v AS SELECT * FROM t")
val error = assertFailsWith<DiskCatalogException> { db.run("ALTER TABLE v RENAME TO w") }
assertTrue(error.message!!.contains("cannot modify view"))
}
@Test
fun renameTablePropagatesToOtherTablesForeignKeyReference() {
val db = newDatabase()
db.run("CREATE TABLE departments (id INTEGER PRIMARY KEY)")
db.run("CREATE TABLE employees (id INTEGER PRIMARY KEY, dept_id INTEGER REFERENCES departments(id) ON DELETE CASCADE)")
db.run("INSERT INTO departments VALUES (1)")
db.run("INSERT INTO employees VALUES (1, 1)")
db.run("ALTER TABLE departments RENAME TO divisions")
db.run("INSERT INTO divisions VALUES (2)")
db.run("INSERT INTO employees VALUES (2, 2)")
assertFailsWith<KestrelException> { db.run("INSERT INTO employees VALUES (3, 99)") }
db.run("DELETE FROM divisions WHERE id = 1")
assertEquals(listOf(listOf(int(2))), db.select("SELECT id FROM employees").rows)
}
@Test
fun renameTableUpdatesItsOwnSelfReferencingForeignKey() {
val db = newDatabase()
db.run("CREATE TABLE staff (id INTEGER PRIMARY KEY, manager_id INTEGER REFERENCES staff(id))")
db.run("INSERT INTO staff VALUES (1, NULL)")
db.run("ALTER TABLE staff RENAME TO personnel")
db.run("INSERT INTO personnel VALUES (2, 1)")
assertFailsWith<KestrelException> { db.run("INSERT INTO personnel VALUES (3, 99)") }
assertEquals(2, db.select("SELECT * FROM personnel").rows.size)
}
@Test
fun renameTableUpdatesASecondaryIndexAndPushdownStillWorks() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY, age INTEGER)")
db.run("INSERT INTO t VALUES (1, 30), (2, 40)")
db.run("CREATE INDEX idx_age ON t (age)")
db.run("ALTER TABLE t RENAME TO people")
val table = db.catalog.table("people")
val result = db.select("SELECT id FROM people WHERE age = 30")
assertEquals(listOf(listOf(int(1))), result.rows)
assertEquals(1, table.secondaryLookupCount)
}
@Test
fun renameTablePropagatesIntoASimpleViewDefinition() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT)")
db.run("INSERT INTO t VALUES (1, 'ada')")
db.run("CREATE VIEW v AS SELECT * FROM t")
db.run("ALTER TABLE t RENAME TO people")
assertEquals(listOf(listOf(int(1), text("ada"))), db.select("SELECT * FROM v").rows)
}
@Test
fun renameTableRenamingToItsOwnNameIsANoOp() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY)")
db.run("INSERT INTO t VALUES (1)")
db.run("ALTER TABLE t RENAME TO t")
assertEquals(listOf(listOf(int(1))), db.select("SELECT * FROM t").rows)
}
@Test
fun renameTableDefinitionAndViewSurviveClosingAndReopeningTheCatalog() {
val db = newDatabase()
db.run("CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT)")
db.run("INSERT INTO t VALUES (1, 'ada')")
db.run("CREATE VIEW v AS SELECT * FROM t")
db.run("ALTER TABLE t RENAME TO people")
db.reopen()
assertEquals(listOf("people"), db.catalog.tableNames)
assertEquals(listOf(listOf(int(1), text("ada"))), db.select("SELECT * FROM v").rows)
assertFailsWith<DiskCatalogException> { db.run("SELECT * FROM t") }
}