test(sql): cover countStarOverPartitionCountsRowsRegardlessOfNulls
This commit is contained in:
1 parent
c971037db6
commit
c538b9f421
1 file changed
+158
@@ -2057,3 +2057,161 @@ class DiskExecutorTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun countStarOverPartitionCountsRowsRegardlessOfNulls() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
db.run("INSERT INTO employees VALUES (7, 3, 'unpaid', NULL)")
|
||||||
|
val result = db.select(
|
||||||
|
"SELECT COUNT(*) OVER (PARTITION BY deptId) AS n, COUNT(salary) OVER (PARTITION BY deptId) AS paid " +
|
||||||
|
"FROM employees WHERE deptId = 3"
|
||||||
|
)
|
||||||
|
assertEquals(listOf(listOf(int(1), int(0))), result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun windowFunctionOverAJoinPartitionsByTheJoinedColumn() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val result = db.select(
|
||||||
|
"SELECT e.name, d.name AS dept, " +
|
||||||
|
"ROW_NUMBER() OVER (PARTITION BY d.name ORDER BY e.salary DESC) AS rn " +
|
||||||
|
"FROM employees e JOIN departments d ON e.deptId = d.id " +
|
||||||
|
"WHERE d.name = 'eng' ORDER BY rn ASC"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(
|
||||||
|
listOf(text("ada"), text("eng"), int(1)),
|
||||||
|
listOf(text("linus"), text("eng"), int(2)),
|
||||||
|
listOf(text("grace"), text("eng"), int(3))
|
||||||
|
),
|
||||||
|
result.rows
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun orderByCanReferenceAWindowFunctionByItsProjectionAlias() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val result = db.select("SELECT id, RANK() OVER (ORDER BY salary DESC) AS r FROM employees ORDER BY r ASC, id ASC")
|
||||||
|
assertEquals((1..6).map { it.toLong() }, result.rows.map { (it[0] as Value.IntegerValue).value })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun selectStarWithAWindowFunctionOnlyInOrderByDoesNotLeakTheExtraColumn() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val result = db.select("SELECT * FROM departments ORDER BY ROW_NUMBER() OVER (ORDER BY id) DESC")
|
||||||
|
assertEquals(listOf("id", "name"), result.columns)
|
||||||
|
assertEquals(listOf(listOf(int(2), text("sales")), listOf(int(1), text("eng"))), result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun windowFunctionIsRejectedInWhere() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val error = assertFailsWith<DiskExecutorException> {
|
||||||
|
db.run("SELECT id FROM employees WHERE ROW_NUMBER() OVER (ORDER BY id) = 1")
|
||||||
|
}
|
||||||
|
assertTrue(error.message!!.contains("WHERE"), error.message!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun windowFunctionIsRejectedInGroupBy() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
assertFailsWith<DiskExecutorException> {
|
||||||
|
db.run("SELECT COUNT(*) FROM employees GROUP BY ROW_NUMBER() OVER (ORDER BY id)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun windowFunctionIsRejectedInHaving() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
assertFailsWith<DiskExecutorException> {
|
||||||
|
db.run("SELECT deptId, COUNT(*) FROM employees GROUP BY deptId HAVING ROW_NUMBER() OVER (ORDER BY deptId) > 1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun windowFunctionIsRejectedInAnOnCondition() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val error = assertFailsWith<DiskExecutorException> {
|
||||||
|
db.run("SELECT e.id FROM employees e JOIN departments d ON ROW_NUMBER() OVER (ORDER BY e.id) = d.id")
|
||||||
|
}
|
||||||
|
assertTrue(error.message!!.contains("ON condition"), error.message!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun windowFunctionCannotBeCombinedWithGroupByInTheSameQuery() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val error = assertFailsWith<DiskExecutorException> {
|
||||||
|
db.run("SELECT deptId, COUNT(*), ROW_NUMBER() OVER (ORDER BY deptId) FROM employees GROUP BY deptId")
|
||||||
|
}
|
||||||
|
assertTrue(error.message!!.contains("combined"), error.message!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rankRequiresAnOrderByInsideOver() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val error = assertFailsWith<DiskExecutorException> {
|
||||||
|
db.run("SELECT RANK() OVER (PARTITION BY deptId) FROM employees")
|
||||||
|
}
|
||||||
|
assertTrue(error.message!!.contains("ORDER BY"), error.message!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun denseRankRequiresAnOrderByInsideOver() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
assertFailsWith<DiskExecutorException> {
|
||||||
|
db.run("SELECT DENSE_RANK() OVER (PARTITION BY deptId) FROM employees")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun nestedWindowFunctionsAreRejected() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val error = assertFailsWith<DiskExecutorException> {
|
||||||
|
db.run("SELECT SUM(salary) OVER (ORDER BY ROW_NUMBER() OVER (ORDER BY id)) FROM employees")
|
||||||
|
}
|
||||||
|
assertTrue(error.message!!.contains("nested"), error.message!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun lagReturnsThePreviousRowsValueWithinEachPartitionAndNullAtTheEdge() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val result = db.select(
|
||||||
|
"SELECT id, LAG(salary) OVER (PARTITION BY deptId ORDER BY id) AS prev FROM employees ORDER BY id ASC"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(
|
||||||
|
listOf(int(1), Value.NullValue), listOf(int(2), int(400)), listOf(int(3), int(400)),
|
||||||
|
listOf(int(4), Value.NullValue), listOf(int(5), int(200)), listOf(int(6), int(200))
|
||||||
|
),
|
||||||
|
result.rows
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun leadReturnsTheNextRowsValueWithinEachPartitionAndNullAtTheEdge() {
|
||||||
|
val db = newDatabase()
|
||||||
|
db.seedWindowEmployees()
|
||||||
|
val result = db.select(
|
||||||
|
"SELECT id, LEAD(salary) OVER (PARTITION BY deptId ORDER BY id) AS next FROM employees ORDER BY id ASC"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(
|
||||||
|
listOf(int(1), int(400)), listOf(int(2), int(300)), listOf(int(3), Value.NullValue),
|
||||||
|
listOf(int(4), int(200)), listOf(int(5), int(100)), listOf(int(6), Value.NullValue)
|
||||||
|
),
|
||||||
|
result.rows
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user