test: cover defaultAppliesIndependentlyToEachOmittedColumn
This commit is contained in:
1 parent
f8d57f5621
commit
4216c1c5eb
1 file changed
+163
@@ -470,3 +470,166 @@ class AlterTableTest {
|
||||
assertEquals(listOf(listOf(Value.NullValue)), select("SELECT status FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultAppliesIndependentlyToEachOmittedColumn() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT DEFAULT 'new', score INTEGER DEFAULT 0)")
|
||||
run("INSERT INTO t (id) VALUES (1)")
|
||||
val result = exec("INSERT INTO t (id) VALUES (2)")
|
||||
assertEquals(InsertResult(1), result)
|
||||
assertEquals(
|
||||
listOf(listOf(text("new"), int(0)), listOf(text("new"), int(0))),
|
||||
select("SELECT status, score FROM t ORDER BY id ASC").rows
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createTableRejectsColumnReferenceInDefault() {
|
||||
val error = assertFailsWith<KestrelException> {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, twice INTEGER DEFAULT id)")
|
||||
}
|
||||
assertTrue(error.message!!.contains("DEFAULT"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createTableRejectsSubqueryInDefault() {
|
||||
run("CREATE TABLE other (x INTEGER)")
|
||||
assertFailsWith<KestrelException> {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, x INTEGER DEFAULT (SELECT COUNT(*) FROM other))")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createTableRejectsAggregateInDefault() {
|
||||
val error = assertFailsWith<KestrelException> {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, x INTEGER DEFAULT COUNT(*))")
|
||||
}
|
||||
assertTrue(error.message!!.contains("aggregate"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createTableValidatesDefaultTypeEagerly() {
|
||||
assertFailsWith<KestrelException> {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, age INTEGER DEFAULT 'not a number')")
|
||||
}
|
||||
}
|
||||
|
||||
// ---- DEFAULT (UPDATE) ----
|
||||
|
||||
@Test
|
||||
fun updateSetToDefaultResetsTheColumnToItsDeclaredDefault() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT DEFAULT 'pending')")
|
||||
run("INSERT INTO t VALUES (1, 'shipped')")
|
||||
val result = exec("UPDATE t SET status = DEFAULT WHERE id = 1")
|
||||
assertEquals(UpdateResult(1), result)
|
||||
assertEquals(listOf(listOf(text("pending"))), select("SELECT status FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateSetToDefaultFallsBackToNullWhenTheColumnHasNoDeclaredDefault() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, note TEXT)")
|
||||
run("INSERT INTO t VALUES (1, 'keep me')")
|
||||
run("UPDATE t SET note = DEFAULT WHERE id = 1")
|
||||
assertEquals(listOf(listOf(Value.NullValue)), select("SELECT note FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateSetToDefaultIsEvaluatedFreshPerRowJustLikeInsert() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, score INTEGER DEFAULT 0)")
|
||||
run("INSERT INTO t VALUES (1, 10), (2, 20), (3, 30)")
|
||||
val result = exec("UPDATE t SET score = DEFAULT WHERE id IN (1, 2)")
|
||||
assertEquals(UpdateResult(2), result)
|
||||
assertEquals(
|
||||
listOf(listOf(int(1), int(0)), listOf(int(2), int(0)), listOf(int(3), int(30))),
|
||||
select("SELECT id, score FROM t ORDER BY id ASC").rows
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateCanMixADefaultAssignmentWithARegularAssignmentInTheSameStatement() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT, status TEXT DEFAULT 'pending')")
|
||||
run("INSERT INTO t VALUES (1, 'ada', 'shipped')")
|
||||
run("UPDATE t SET name = 'grace', status = DEFAULT WHERE id = 1")
|
||||
assertEquals(listOf(listOf(text("grace"), text("pending"))), select("SELECT name, status FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateSetToDefaultFailsNotNullValidationWhenThereIsNoDefaultToFallBackOn() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT NOT NULL)")
|
||||
run("INSERT INTO t VALUES (1, 'shipped')")
|
||||
val error = assertFailsWith<KestrelException> {
|
||||
run("UPDATE t SET status = DEFAULT WHERE id = 1")
|
||||
}
|
||||
assertTrue(error.message!!.contains("status"), error.message!!)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateSetToDefaultRoundTripsThroughSqlWriter() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT DEFAULT 'pending')")
|
||||
run("INSERT INTO t VALUES (1, 'shipped')")
|
||||
val statement = Parser(Lexer("UPDATE t SET status = DEFAULT WHERE id = 1").tokenize()).parseProgram().single()
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("status = DEFAULT"), rendered)
|
||||
run(rendered)
|
||||
assertEquals(listOf(listOf(text("pending"))), select("SELECT status FROM t").rows)
|
||||
}
|
||||
|
||||
// ---- DEFAULT (INSERT VALUES) ----
|
||||
|
||||
@Test
|
||||
fun insertValuesWithLiteralDefaultUsesTheColumnsDeclaredDefault() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT DEFAULT 'pending')")
|
||||
val result = exec("INSERT INTO t VALUES (1, DEFAULT)")
|
||||
assertEquals(InsertResult(1), result)
|
||||
assertEquals(listOf(listOf(text("pending"))), select("SELECT status FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertValuesWithLiteralDefaultFallsBackToNullWhenTheColumnHasNoDeclaredDefault() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, note TEXT)")
|
||||
run("INSERT INTO t VALUES (1, DEFAULT)")
|
||||
assertEquals(listOf(listOf(Value.NullValue)), select("SELECT note FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertValuesLiteralDefaultIsDistinctFromAnExplicitNullLiteral() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT DEFAULT 'pending')")
|
||||
run("INSERT INTO t VALUES (1, NULL)")
|
||||
assertEquals(listOf(listOf(Value.NullValue)), select("SELECT status FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertValuesLiteralDefaultAppliesIndependentlyToEachRowInAMultiRowInsert() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, score INTEGER DEFAULT 0)")
|
||||
run("INSERT INTO t VALUES (1, DEFAULT), (2, 20), (3, DEFAULT)")
|
||||
assertEquals(
|
||||
listOf(listOf(int(1), int(0)), listOf(int(2), int(20)), listOf(int(3), int(0))),
|
||||
select("SELECT id, score FROM t ORDER BY id ASC").rows
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertValuesLiteralDefaultWorksWithAnExplicitColumnList() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT, status TEXT DEFAULT 'pending')")
|
||||
run("INSERT INTO t (id, status, name) VALUES (1, DEFAULT, 'ada')")
|
||||
assertEquals(listOf(listOf(text("ada"), text("pending"))), select("SELECT name, status FROM t").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertValuesLiteralDefaultFailsNotNullValidationWhenThereIsNoDefaultToFallBackOn() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT NOT NULL)")
|
||||
val error = assertFailsWith<KestrelException> {
|
||||
run("INSERT INTO t VALUES (1, DEFAULT)")
|
||||
}
|
||||
assertTrue(error.message!!.contains("status"), error.message!!)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun insertValuesLiteralDefaultRoundTripsThroughSqlWriter() {
|
||||
run("CREATE TABLE t (id INTEGER PRIMARY KEY, status TEXT DEFAULT 'pending')")
|
||||
val statement = Parser(Lexer("INSERT INTO t VALUES (1, DEFAULT)").tokenize()).parseProgram().single()
|
||||
val rendered = SqlWriter.write(statement)
|
||||
assertTrue(rendered.contains("DEFAULT"), rendered)
|
||||
run(rendered)
|
||||
assertEquals(listOf(listOf(text("pending"))), select("SELECT status FROM t").rows)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user