test(sql): cover countStarWithNoGroupByAggregatesTheWholeTable
This commit is contained in:
1 parent
fa16fcb0a0
commit
71ee4dfabc
1 file changed
+162
@@ -795,3 +795,165 @@ class DiskExecutorTest {
|
||||
assertEquals(listOf(listOf(text("ops"), int(1))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun countStarWithNoGroupByAggregatesTheWholeTable() {
|
||||
val db = newDatabase()
|
||||
db.seedOrders()
|
||||
assertEquals(listOf(listOf(int(3))), db.select("SELECT COUNT(*) FROM orders").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun countStarOverAnEmptyTableStillProducesOneRow() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE orders (id INTEGER PRIMARY KEY, amount INTEGER NOT NULL)")
|
||||
assertEquals(listOf(listOf(int(0))), db.select("SELECT COUNT(*) FROM orders").rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun groupByRollupAddsPerCustomerSubtotalsAndAGrandTotal() {
|
||||
val db = newDatabase()
|
||||
db.seedOrders()
|
||||
val result = db.select(
|
||||
"SELECT customer_id, SUM(amount) AS total FROM orders GROUP BY ROLLUP (customer_id) " +
|
||||
"ORDER BY GROUPING(customer_id), customer_id"
|
||||
)
|
||||
assertEquals(
|
||||
listOf(
|
||||
listOf(int(1), int(150)),
|
||||
listOf(int(2), int(200)),
|
||||
listOf(Value.NullValue, int(350))
|
||||
),
|
||||
result.rows
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun havingFiltersOutGroupsThatDoNotMatch() {
|
||||
val db = newDatabase()
|
||||
db.seedOrders()
|
||||
val result = db.select("SELECT customer_id, SUM(amount) FROM orders GROUP BY customer_id HAVING SUM(amount) > 150")
|
||||
assertEquals(listOf(listOf(int(2), int(200))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun orderByOnAnAggregateSortsTheGroupedResult() {
|
||||
val db = newDatabase()
|
||||
db.seedOrders()
|
||||
val result = db.select("SELECT customer_id, SUM(amount) AS total FROM orders GROUP BY customer_id ORDER BY total DESC")
|
||||
assertEquals(listOf(listOf(int(2), int(200)), listOf(int(1), int(150))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aProjectedColumnNotInGroupByOrAnAggregateIsRejected() {
|
||||
val db = newDatabase()
|
||||
db.seedOrders()
|
||||
val failure = assertFailsWith<DiskExecutorException> {
|
||||
db.select("SELECT customer_id, amount FROM orders GROUP BY customer_id")
|
||||
}
|
||||
assertTrue(failure.message!!.contains("must appear in GROUP BY"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun starProjectionCombinedWithGroupByIsRejected() {
|
||||
val db = newDatabase()
|
||||
db.seedOrders()
|
||||
val failure = assertFailsWith<DiskExecutorException> { db.select("SELECT * FROM orders GROUP BY customer_id") }
|
||||
assertTrue(failure.message!!.contains("cannot use *"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun groupByAggregatesOverAJoinedResult() {
|
||||
val db = newDatabase()
|
||||
db.seedOrders()
|
||||
val result = db.select(
|
||||
"SELECT customers.name, SUM(orders.amount) FROM customers JOIN orders ON customers.id = orders.customer_id " +
|
||||
"GROUP BY customers.name ORDER BY customers.name"
|
||||
)
|
||||
assertEquals(listOf(listOf(text("ada"), int(150)), listOf(text("linus"), int(200))), result.rows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dropTableCascadeWithNoDependentsBehavesLikeAPlainDrop() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY)")
|
||||
db.run("DROP TABLE users CASCADE")
|
||||
assertTrue(db.catalog.tableNames.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createIndexBuildsANonUniqueSingleColumnSecondaryIndex() {
|
||||
val db = newDatabase()
|
||||
db.seedUsers()
|
||||
val created = db.run("CREATE INDEX idx_age ON users(age)").single()
|
||||
assertEquals(CreateIndexResult("idx_age"), created)
|
||||
assertEquals(1, db.catalog.table("users").secondaryIndexes.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createUniqueIndexBuildsAUniqueSingleColumnSecondaryIndex() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, age INTEGER)")
|
||||
val created = db.run("CREATE UNIQUE INDEX idx_age ON users(age)").single()
|
||||
assertEquals(CreateIndexResult("idx_age"), created)
|
||||
assertTrue(db.catalog.table("users").secondaryIndexes.single().unique)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createUniqueIndexRejectsAnInsertThatWouldDuplicateAnExistingValue() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)")
|
||||
db.run("CREATE UNIQUE INDEX idx_email ON users(email)")
|
||||
db.run("INSERT INTO users VALUES (1, 'ada@example.com')")
|
||||
assertFailsWith<DiskTableException> { db.run("INSERT INTO users VALUES (2, 'ada@example.com')") }
|
||||
assertEquals(1, db.select("SELECT * FROM users").rows.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createUniqueIndexAllowsMultipleNullsSinceNullsAreNeverDuplicates() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)")
|
||||
db.run("CREATE UNIQUE INDEX idx_email ON users(email)")
|
||||
db.run("INSERT INTO users VALUES (1, NULL), (2, NULL)")
|
||||
assertEquals(2, db.select("SELECT * FROM users").rows.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createUniqueIndexOverExistingDuplicateValuesFailsAndLeavesNoTraceOfTheIndex() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)")
|
||||
db.run("INSERT INTO users VALUES (1, 'dup@example.com'), (2, 'dup@example.com')")
|
||||
assertFailsWith<DiskTableException> { db.run("CREATE UNIQUE INDEX idx_email ON users(email)") }
|
||||
assertTrue(db.catalog.table("users").secondaryIndexes.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createUniqueIndexRejectsAnUpdateThatWouldDuplicateAnotherRowsValue() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)")
|
||||
db.run("CREATE UNIQUE INDEX idx_email ON users(email)")
|
||||
db.run("INSERT INTO users VALUES (1, 'ada@example.com'), (2, 'grace@example.com')")
|
||||
assertFailsWith<DiskTableException> { db.run("UPDATE users SET email = 'ada@example.com' WHERE id = 2") }
|
||||
assertEquals(text("grace@example.com"), db.select("SELECT email FROM users WHERE id = 2").rows.single().single())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun createUniqueIndexDataAndConstraintSurviveClosingAndReopeningTheCatalog() {
|
||||
val db = newDatabase()
|
||||
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)")
|
||||
db.run("CREATE UNIQUE INDEX idx_email ON users(email)")
|
||||
db.run("INSERT INTO users VALUES (1, 'ada@example.com')")
|
||||
db.reopen()
|
||||
assertFailsWith<DiskTableException> { db.run("INSERT INTO users VALUES (2, 'ada@example.com')") }
|
||||
assertTrue(db.catalog.table("users").secondaryIndexes.single().unique)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dropIndexRemovesItFromTheCatalog() {
|
||||
val db = newDatabase()
|
||||
db.seedUsers()
|
||||
db.run("CREATE INDEX idx_age ON users(age)")
|
||||
val dropped = db.run("DROP INDEX idx_age").single()
|
||||
assertEquals(DropIndexResult("idx_age"), dropped)
|
||||
assertTrue(db.catalog.table("users").secondaryIndexes.isEmpty())
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user