test(sql): cover generatedColumnSurvivesAReopen
This commit is contained in:
1 parent
108a2845bc
commit
161fc029bd
1 file changed
+79
@@ -160,3 +160,82 @@ class DiskExecutorGeneratedColumnTest {
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user