test(sql): cover aNameCanBeReparedAfterBeingDeallocated

This commit is contained in:
dualfroz committed 2026-09-13 18:31:25 +02:00
1 parent 9e4e76b945
commit 48693b00ab
1 file changed
+75
@@ -3962,3 +3962,78 @@ class DiskExecutorTest {
assertFailsWith<DiskExecutorException> { db.run("EXECUTE p2(1)") }
}
@Test
fun aNameCanBeReparedAfterBeingDeallocated() {
val db = newDatabase()
db.seedUsers()
db.run("PREPARE byId AS SELECT name FROM users WHERE id = \$1")
db.run("DEALLOCATE byId")
db.run("PREPARE byId AS SELECT age FROM users WHERE id = \$1")
assertEquals(listOf(listOf(int(36))), db.select("EXECUTE byId(1)").rows)
}
@Test
fun preparedStatementsAreNotUndoneByRollback() {
val db = newDatabase()
db.seedUsers()
db.run("BEGIN")
db.run("PREPARE byId AS SELECT name FROM users WHERE id = \$1")
db.run("ROLLBACK")
// Session-scoped, deliberately outside the storage-engine transaction that ROLLBACK undoes -
// see DiskExecutor's own doc on preparedStatements for why.
assertEquals(listOf(listOf(text("ada"))), db.select("EXECUTE byId(1)").rows)
}
@Test
fun executeArgumentsMustBeConstantNotColumnReferences() {
val db = newDatabase()
db.seedUsers()
db.run("PREPARE byId AS SELECT name FROM users WHERE id = \$1")
// The bare Evaluator() resolveExecute uses to evaluate EXECUTE arguments as constants is
// shared with the in-memory engine and throws the shared KestrelException directly, not a
// DiskExecutorException - unlike disk-executor-specific validation elsewhere in this class.
assertFailsWith<KestrelException> { db.run("EXECUTE byId(id)") }
}
@Test
fun preparedStatementDoesNotSurviveReopen() {
val db = newDatabase()
db.seedUsers()
db.run("PREPARE byId AS SELECT name FROM users WHERE id = \$1")
assertEquals(listOf(listOf(text("ada"))), db.select("EXECUTE byId(1)").rows)
db.reopen()
assertFailsWith<DiskExecutorException> { db.run("EXECUTE byId(1)") }
}
@Test
fun aPreparedInsertsRowSurvivesReopenEvenThoughThePrepareItselfDoesNot() {
val db = newDatabase()
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER DEFAULT 0)")
db.run("PREPARE addUser AS INSERT INTO users VALUES (\$1, \$2, \$3)")
db.run("EXECUTE addUser(1, 'ada', 36)")
db.reopen()
assertEquals(listOf(listOf(int(1), text("ada"), int(36))), db.select("SELECT * FROM users").rows)
assertFailsWith<DiskExecutorException> { db.run("EXECUTE addUser(2, 'linus', 54)") }
}
/**
* `CREATE TEMP TABLE`/`CREATE TEMPORARY TABLE` used to be rejected outright here - see
* [DiskExecutorTemporaryTableTest] for the full feature (now a real, live in-memory-only table
* on this executor) this pair of tests only confirms is reachable through both spellings.
*/
@Test
fun createTempTableIsAcceptedByTheDiskBackedExecutor() {
val db = newDatabase()
assertEquals(CreateTableResult("scratch"), db.run("CREATE TEMP TABLE scratch (id INTEGER PRIMARY KEY)").single())
db.run("INSERT INTO scratch VALUES (1)")
assertEquals(listOf(listOf(int(1))), db.select("SELECT * FROM scratch").rows)
}
@Test
fun createTemporaryTableIsAcceptedByTheDiskBackedExecutor() {
val db = newDatabase()
assertEquals(CreateTableResult("scratch"), db.run("CREATE TEMPORARY TABLE scratch (id INTEGER PRIMARY KEY)").single())
}
}