test(sql): cover generatedColumnSurvivesAReopen

This commit is contained in:
dualfroz committed 2026-09-11 19:31:34 +02:00
1 parent 108a2845bc
commit 161fc029bd
1 file changed
+79
@@ -160,3 +160,82 @@ class DiskExecutorGeneratedColumnTest {
assertEquals(listOf(listOf(Value.TextValue("x"))), result.rows) assertEquals(listOf(listOf(Value.TextValue("x"))), result.rows)
} }
@Test
fun generatedColumnSurvivesAReopen() {
val db = newDatabase()
db.run("CREATE TABLE t (a INTEGER, b INTEGER GENERATED ALWAYS AS (a * 2) STORED)")
db.run("INSERT INTO t (a) VALUES (5)")
db.reopen()
assertEquals(listOf(listOf(int(5), int(10))), db.select("SELECT a, b FROM t").rows)
// The GENERATED expression itself (not just data already computed before the reopen) must
// have round-tripped through DirectoryEntryCodec - proven by inserting a NEW row after the
// reopen and getting a freshly computed value, not a stale/missing one.
db.run("INSERT INTO t (a) VALUES (7)")
assertEquals(listOf(listOf(int(14))), db.select("SELECT b FROM t WHERE a = 7").rows)
}
// ---- ALTER TABLE ADD COLUMN GENERATED ALWAYS AS ----
@Test
fun alterTableAddColumnGeneratedBackfillsEachExistingRowFromItsOwnOtherColumns() {
val db = newDatabase()
db.run("CREATE TABLE t (a INTEGER)")
db.run("INSERT INTO t (a) VALUES (1), (2), (3)")
db.run("ALTER TABLE t ADD COLUMN b INTEGER GENERATED ALWAYS AS (a * 2) STORED")
assertEquals(
listOf(listOf(int(1), int(2)), listOf(int(2), int(4)), listOf(int(3), int(6))),
db.select("SELECT a, b FROM t ORDER BY a ASC").rows
)
}
@Test
fun afterAlterTableAddColumnGeneratedAnInsertStillRejectsAnExplicitValue() {
val db = newDatabase()
db.run("CREATE TABLE t (a INTEGER)")
db.run("ALTER TABLE t ADD COLUMN b INTEGER GENERATED ALWAYS AS (a * 2) STORED")
val error = assertFailsWith<KestrelException> { db.run("INSERT INTO t (a, b) VALUES (5, 99)") }
assertTrue(error.message!!.contains("GENERATED"))
}
@Test
fun alterTableAddColumnGeneratedNotNullSkipsTheDefaultRequirementOnANonEmptyTable() {
val db = newDatabase()
db.run("CREATE TABLE t (a INTEGER)")
db.run("INSERT INTO t (a) VALUES (1), (2)")
db.run("ALTER TABLE t ADD COLUMN b INTEGER NOT NULL GENERATED ALWAYS AS (a * 2) STORED")
assertEquals(listOf(listOf(int(2)), listOf(int(4))), db.select("SELECT b FROM t ORDER BY a ASC").rows)
}
@Test
fun alterTableAddColumnGeneratedNotNullRejectsARowWhoseBackfilledValueIsNull() {
val db = newDatabase()
db.run("CREATE TABLE t (a INTEGER)")
db.run("INSERT INTO t (a) VALUES (NULL)")
val error = assertFailsWith<KestrelException> {
db.run("ALTER TABLE t ADD COLUMN b INTEGER NOT NULL GENERATED ALWAYS AS (a) STORED")
}
assertTrue(error.message!!.contains("NOT NULL"))
}
@Test
fun alterTableAddColumnGeneratedRejectsReferencingAnAlreadyExistingGeneratedColumn() {
val db = newDatabase()
db.run("CREATE TABLE t (a INTEGER, b INTEGER GENERATED ALWAYS AS (a * 2) STORED)")
val error = assertFailsWith<KestrelException> {
db.run("ALTER TABLE t ADD COLUMN c INTEGER GENERATED ALWAYS AS (b + 1) STORED")
}
assertTrue(error.message!!.contains("GENERATED"))
}
@Test
fun alterTableAddColumnGeneratedSurvivesAReopenAndBackfilledRowsKeepTheirValue() {
val db = newDatabase()
db.run("CREATE TABLE t (a INTEGER)")
db.run("INSERT INTO t (a) VALUES (5)")
db.run("ALTER TABLE t ADD COLUMN b INTEGER GENERATED ALWAYS AS (a * 2) STORED")
db.reopen()
assertEquals(listOf(listOf(int(5), int(10))), db.select("SELECT a, b FROM t").rows)
db.run("INSERT INTO t (a) VALUES (7)")
assertEquals(listOf(listOf(int(14))), db.select("SELECT b FROM t WHERE a = 7").rows)
}
}