test(sql): cover updateAndDeleteByFullCompositePrimaryKeyUsePointLook...
This commit is contained in:
1 parent
aece1cdc22
commit
2501e873a3
1 file changed
+155
@@ -1432,3 +1432,158 @@ class DiskExecutorTest {
|
||||
assertEquals(0, table.rangeScanCount)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateAndDeleteByFullCompositePrimaryKeyUsePointLookups() {
|
||||
val db = newDatabase()
|
||||
db.seedOrderLines()
|
||||
val table = db.catalog.table("order_lines")
|
||||
|
||||
val updated = db.run("UPDATE order_lines SET sku = 'sprocket' WHERE order_id = 1 AND line_no = 1").single()
|
||||
assertEquals(UpdateResult(1), updated)
|
||||
assertEquals(1, table.pointLookupCount)
|
||||
|
||||
val deleted = db.run("DELETE FROM order_lines WHERE order_id = 2 AND line_no = 1").single()
|
||||
assertEquals(DeleteResult(1), deleted)
|
||||
assertEquals(2, table.pointLookupCount)
|
||||
assertEquals(0, table.scanCount)
|
||||
assertEquals(2, db.select("SELECT * FROM order_lines").rows.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aTableCannotDeclareBothAnInlinePrimaryKeyColumnAndATableLevelCompositePrimaryKey() {
|
||||
val db = newDatabase()
|
||||
assertFailsWith<DiskExecutorException> {
|
||||
db.run("CREATE TABLE bad (id INTEGER PRIMARY KEY, other INTEGER, PRIMARY KEY (id, other))")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aCompositePrimaryKeyReferencingAnUnknownColumnIsRejectedWithAClearError() {
|
||||
val db = newDatabase()
|
||||
val failure = assertFailsWith<DiskExecutorException> {
|
||||
db.run("CREATE TABLE bad (order_id INTEGER, line_no INTEGER, PRIMARY KEY (order_id, missing_column))")
|
||||
}
|
||||
assertTrue(failure.message!!.contains("missing_column"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun compositePrimaryKeyDataAndUniquenessSurviveClosingAndReopeningTheCatalog() {
|
||||
val db = newDatabase()
|
||||
db.seedOrderLines()
|
||||
db.reopen()
|
||||
|
||||
assertFailsWith<DiskTableException> { db.run("INSERT INTO order_lines VALUES (1, 1, 'duplicate')") }
|
||||
val result = db.select("SELECT sku FROM order_lines WHERE order_id = 1 AND line_no = 2")
|
||||
assertEquals(listOf(listOf(text("gadget"))), result.rows)
|
||||
val table = db.catalog.table("order_lines")
|
||||
assertEquals(0, table.scanCount, "the point lookup above must not have fallen back to a full scan after reopening")
|
||||
}
|
||||
|
||||
private fun Database.seedDepartments() {
|
||||
run("CREATE TABLE departments (id INTEGER PRIMARY KEY, name TEXT NOT NULL, budget INTEGER)")
|
||||
run("CREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT NOT NULL, department_id INTEGER, salary INTEGER)")
|
||||
run("INSERT INTO departments VALUES (1, 'eng', 1000), (2, 'sales', 500), (3, 'ops', 0)")
|
||||
run(
|
||||
"INSERT INTO employees VALUES " +
|
||||
"(1, 'ada', 1, 120), (2, 'linus', 1, 90), (3, 'grace', 2, 80), (4, 'guido', 2, 70)"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun scalarSubqueryComparesAgainstAnUncorrelatedAggregate() {
|
||||
val db = newDatabase()
|
||||
db.seedDepartments()
|
||||
val result = db.select("SELECT name FROM employees WHERE salary > (SELECT AVG(salary) FROM employees) ORDER BY name")
|
||||
assertEquals(listOf(listOf(text("ada"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun scalarSubqueryReturningNoRowsEvaluatesToNull() {
|
||||
val db = newDatabase()
|
||||
db.seedDepartments()
|
||||
val result = db.select("SELECT (SELECT id FROM departments WHERE name = 'nope') FROM departments WHERE id = 1")
|
||||
assertEquals(listOf(listOf(Value.NullValue)), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun scalarSubqueryReturningMoreThanOneRowFails() {
|
||||
val db = newDatabase()
|
||||
db.seedDepartments()
|
||||
val failure = assertFailsWith<KestrelException> {
|
||||
db.select("SELECT (SELECT salary FROM employees) FROM departments WHERE id = 1")
|
||||
}
|
||||
assertTrue(failure.message!!.contains("more than one row"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun scalarSubqueryReturningMoreThanOneColumnFails() {
|
||||
val db = newDatabase()
|
||||
db.seedDepartments()
|
||||
val failure = assertFailsWith<KestrelException> {
|
||||
db.select("SELECT (SELECT id, name FROM departments) FROM departments WHERE id = 1")
|
||||
}
|
||||
assertTrue(failure.message!!.contains("exactly one column"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun correlatedScalarSubqueryInProjectionCountsPerOuterRow() {
|
||||
val db = newDatabase()
|
||||
db.seedDepartments()
|
||||
val result = db.select(
|
||||
"SELECT d.name, (SELECT COUNT(*) FROM employees e WHERE e.department_id = d.id) " +
|
||||
"FROM departments d ORDER BY d.id"
|
||||
)
|
||||
assertEquals(
|
||||
listOf(listOf(text("eng"), int(2)), listOf(text("sales"), int(2)), listOf(text("ops"), int(0))),
|
||||
result.rows
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun correlatedScalarSubqueryInWhereComparesAgainstTheEmployeesOwnDepartmentAverage() {
|
||||
val db = newDatabase()
|
||||
db.seedDepartments()
|
||||
val result = db.select(
|
||||
"SELECT name FROM employees e WHERE e.salary > " +
|
||||
"(SELECT AVG(salary) FROM employees e2 WHERE e2.department_id = e.department_id) ORDER BY name"
|
||||
)
|
||||
assertEquals(listOf(listOf(text("ada")), listOf(text("grace"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun inSubqueryMatchesAnUncorrelatedResultSet() {
|
||||
val db = newDatabase()
|
||||
db.seedDepartments()
|
||||
val result = db.select("SELECT name FROM departments WHERE id IN (SELECT department_id FROM employees) ORDER BY name")
|
||||
assertEquals(listOf(listOf(text("eng")), listOf(text("sales"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun notInSubqueryExcludesMatchingRows() {
|
||||
val db = newDatabase()
|
||||
db.seedDepartments()
|
||||
val result = db.select("SELECT name FROM departments WHERE id NOT IN (SELECT department_id FROM employees)")
|
||||
assertEquals(listOf(listOf(text("ops"))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun notInSubqueryWithANullInTheResultSetExcludesEverythingByThreeValuedLogic() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE d (id INTEGER)")
|
||||
db.run("CREATE TABLE e (dept INTEGER)")
|
||||
db.run("INSERT INTO d VALUES (1), (2)")
|
||||
db.run("INSERT INTO e VALUES (1), (NULL)")
|
||||
val result = db.select("SELECT id FROM d WHERE id NOT IN (SELECT dept FROM e)")
|
||||
assertEquals(emptyList(), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun inSubqueryRequiresExactlyOneColumn() {
|
||||
val db = newDatabase()
|
||||
db.seedDepartments()
|
||||
val failure = assertFailsWith<KestrelException> {
|
||||
db.select("SELECT name FROM departments WHERE id IN (SELECT id, name FROM departments)")
|
||||
}
|
||||
assertTrue(failure.message!!.contains("exactly one column"))
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user