test(sql): cover countStarWithNoGroupByAggregatesTheWholeTable

This commit is contained in:
dualfroz committed 2026-09-12 19:23:28 +02:00
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())
}