test(sql): cover seedOrdersWithOrphan
This commit is contained in:
1 parent
ae50dd1aa7
commit
c49338826f
1 file changed
+163
@@ -310,3 +310,166 @@ class DiskExecutorTest {
|
|||||||
run("INSERT INTO orders VALUES (1, 1, 100), (2, 1, 50), (3, 2, 200)")
|
run("INSERT INTO orders VALUES (1, 1, 100), (2, 1, 50), (3, 2, 200)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adds an order referencing a customer id that does not exist, so RIGHT/FULL JOIN has an
|
||||||
|
// unmatched *right* row to pad with NULLs on top of grace's unmatched left row from seedOrders.
|
||||||
|
private fun Database.seedOrdersWithOrphan() {
|
||||||
|
seedOrders()
|
||||||
|
run("INSERT INTO orders VALUES (4, 99, 999)")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rightJoinPadsUnmatchedRightRowsWithNulls() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedOrdersWithOrphan()
|
||||||
|
val result = db.select(
|
||||||
|
"SELECT customers.name, orders.amount FROM customers RIGHT JOIN orders ON customers.id = orders.customer_id ORDER BY orders.id"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(
|
||||||
|
listOf(text("ada"), int(100)),
|
||||||
|
listOf(text("ada"), int(50)),
|
||||||
|
listOf(text("linus"), int(200)),
|
||||||
|
listOf(Value.NullValue, int(999))
|
||||||
|
),
|
||||||
|
result.rows
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun fullJoinKeepsBothUnmatchedLeftAndRightRows() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedOrdersWithOrphan()
|
||||||
|
val result = db.select(
|
||||||
|
"SELECT customers.name, orders.amount FROM customers FULL JOIN orders ON customers.id = orders.customer_id"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
setOf(
|
||||||
|
listOf(text("ada"), int(100)),
|
||||||
|
listOf(text("ada"), int(50)),
|
||||||
|
listOf(text("linus"), int(200)),
|
||||||
|
listOf(text("grace"), Value.NullValue),
|
||||||
|
listOf(Value.NullValue, int(999))
|
||||||
|
),
|
||||||
|
result.rows.toSet()
|
||||||
|
)
|
||||||
|
assertEquals(5, result.rows.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun crossJoinProducesTheFullCartesianProductWithNoOnClause() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.run("CREATE TABLE colors (name TEXT)")
|
||||||
|
db.run("CREATE TABLE sizes (label TEXT)")
|
||||||
|
db.run("INSERT INTO colors VALUES ('red'), ('blue')")
|
||||||
|
db.run("INSERT INTO sizes VALUES ('s'), ('m')")
|
||||||
|
val result = db.select("SELECT colors.name, sizes.label FROM colors CROSS JOIN sizes ORDER BY colors.name, sizes.label")
|
||||||
|
assertEquals(
|
||||||
|
listOf(
|
||||||
|
listOf(text("blue"), text("m")), listOf(text("blue"), text("s")),
|
||||||
|
listOf(text("red"), text("m")), listOf(text("red"), text("s"))
|
||||||
|
),
|
||||||
|
result.rows
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rightOuterAndFullOuterJoinSpellingsAreAccepted() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedOrders()
|
||||||
|
val right = db.select(
|
||||||
|
"SELECT customers.name FROM customers RIGHT OUTER JOIN orders ON customers.id = orders.customer_id ORDER BY orders.id"
|
||||||
|
)
|
||||||
|
assertEquals(listOf(listOf(text("ada")), listOf(text("ada")), listOf(text("linus"))), right.rows)
|
||||||
|
val full = db.select(
|
||||||
|
"SELECT customers.name FROM customers FULL OUTER JOIN orders ON customers.id = orders.customer_id ORDER BY customers.id"
|
||||||
|
)
|
||||||
|
assertEquals(4, full.rows.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun innerJoinCombinesMatchingRowsAndDropsUnmatchedLeftRows() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedOrders()
|
||||||
|
val result = db.select(
|
||||||
|
"SELECT customers.name, orders.amount FROM customers JOIN orders ON customers.id = orders.customer_id ORDER BY orders.id"
|
||||||
|
)
|
||||||
|
assertEquals(listOf("name", "amount"), result.columns)
|
||||||
|
assertEquals(
|
||||||
|
listOf(listOf(text("ada"), int(100)), listOf(text("ada"), int(50)), listOf(text("linus"), int(200))),
|
||||||
|
result.rows
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun leftJoinPadsUnmatchedLeftRowsWithNulls() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedOrders()
|
||||||
|
val result = db.select(
|
||||||
|
"SELECT customers.name, orders.amount FROM customers LEFT JOIN orders ON customers.id = orders.customer_id ORDER BY customers.id, orders.id"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(
|
||||||
|
listOf(text("ada"), int(100)),
|
||||||
|
listOf(text("ada"), int(50)),
|
||||||
|
listOf(text("linus"), int(200)),
|
||||||
|
listOf(text("grace"), Value.NullValue)
|
||||||
|
),
|
||||||
|
result.rows
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun joinUsesTableAliasesToQualifyColumnsWithTheSameName() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.run("CREATE TABLE a (id INTEGER PRIMARY KEY, tag TEXT NOT NULL)")
|
||||||
|
db.run("CREATE TABLE b (id INTEGER PRIMARY KEY, tag TEXT NOT NULL)")
|
||||||
|
db.run("INSERT INTO a VALUES (1, 'left')")
|
||||||
|
db.run("INSERT INTO b VALUES (1, 'right')")
|
||||||
|
val result = db.select("SELECT x.tag, y.tag FROM a x JOIN b y ON x.id = y.id")
|
||||||
|
assertEquals(listOf(listOf(text("left"), text("right"))), result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun anUnqualifiedColumnPresentInBothJoinedTablesIsRejectedAsAmbiguous() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.run("CREATE TABLE a (id INTEGER PRIMARY KEY)")
|
||||||
|
db.run("CREATE TABLE b (id INTEGER PRIMARY KEY)")
|
||||||
|
db.run("INSERT INTO a VALUES (1)")
|
||||||
|
db.run("INSERT INTO b VALUES (1)")
|
||||||
|
val failure = assertFailsWith<DiskExecutorException> { db.select("SELECT id FROM a JOIN b ON a.id = b.id") }
|
||||||
|
assertTrue(failure.message!!.contains("ambiguous"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun aDuplicateTableAliasAcrossJoinedSourcesIsRejected() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.run("CREATE TABLE a (id INTEGER PRIMARY KEY)")
|
||||||
|
val failure = assertFailsWith<DiskExecutorException> { db.select("SELECT * FROM a x JOIN a x ON x.id = x.id") }
|
||||||
|
assertTrue(failure.message!!.contains("duplicate table alias"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun joiningThreeTablesChainsLeftToRight() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedOrders()
|
||||||
|
db.run("CREATE TABLE shipments (id INTEGER PRIMARY KEY, order_id INTEGER NOT NULL, carrier TEXT NOT NULL)")
|
||||||
|
db.run("INSERT INTO shipments VALUES (1, 1, 'ups')")
|
||||||
|
val result = db.select(
|
||||||
|
"SELECT customers.name, orders.amount, shipments.carrier " +
|
||||||
|
"FROM customers JOIN orders ON customers.id = orders.customer_id " +
|
||||||
|
"JOIN shipments ON orders.id = shipments.order_id"
|
||||||
|
)
|
||||||
|
assertEquals(listOf(listOf(text("ada"), int(100), text("ups"))), result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun joinAgainstADerivedTableWorks() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.run("CREATE TABLE a (id INTEGER PRIMARY KEY, name TEXT NOT NULL)")
|
||||||
|
db.run("CREATE TABLE b (id INTEGER PRIMARY KEY)")
|
||||||
|
db.run("INSERT INTO a VALUES (1, 'ada'), (2, 'linus')")
|
||||||
|
db.run("INSERT INTO b VALUES (1)")
|
||||||
|
val result = db.select("SELECT a.name FROM a JOIN (SELECT id FROM b) sub ON a.id = sub.id")
|
||||||
|
assertEquals(listOf(listOf(text("ada"))), result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user