test: cover cteWithExplicitColumnListRenamesOutputColumns
This commit is contained in:
1 parent
eef86e62ef
commit
bdf167469e
1 file changed
+92
@@ -160,3 +160,95 @@ class CompoundQueryTest {
|
|||||||
assertEquals(listOf(listOf(text("linus"))), result.rows)
|
assertEquals(listOf(listOf(text("linus"))), result.rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun cteWithExplicitColumnListRenamesOutputColumns() {
|
||||||
|
seed()
|
||||||
|
val result = select("WITH renamed(label) AS (SELECT name FROM t1) SELECT label FROM renamed ORDER BY label")
|
||||||
|
assertEquals(listOf(listOf(text("ada")), listOf(text("linus"))), result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun cteColumnListSizeMustMatchQueryColumnCount() {
|
||||||
|
seed()
|
||||||
|
assertFailsWith<KestrelException> {
|
||||||
|
select("WITH bad(a, b, c) AS (SELECT id FROM t1) SELECT * FROM bad")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recursiveCteGeneratesABoundedSequence() {
|
||||||
|
seed()
|
||||||
|
val result = select(
|
||||||
|
"WITH RECURSIVE counter(n) AS (" +
|
||||||
|
"SELECT 1 FROM dual " +
|
||||||
|
"UNION ALL " +
|
||||||
|
"SELECT n + 1 FROM counter WHERE n < 5" +
|
||||||
|
") SELECT n FROM counter ORDER BY n"
|
||||||
|
)
|
||||||
|
assertEquals((1..5).map { listOf(int(it.toLong())) }, result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recursiveCteAccumulatesARunningTotal() {
|
||||||
|
seed()
|
||||||
|
val result = select(
|
||||||
|
"WITH RECURSIVE sums(n, total) AS (" +
|
||||||
|
"SELECT 1, 1 FROM dual " +
|
||||||
|
"UNION ALL " +
|
||||||
|
"SELECT n + 1, total + n + 1 FROM sums WHERE n < 5" +
|
||||||
|
") SELECT total FROM sums WHERE n = 5"
|
||||||
|
)
|
||||||
|
assertEquals(listOf(listOf(int(15))), result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recursiveCteWithUnionDeduplicatesAndTerminatesOnACycle() {
|
||||||
|
seed()
|
||||||
|
run("CREATE TABLE edges (from_node INTEGER, to_node INTEGER)")
|
||||||
|
run("INSERT INTO edges VALUES (1, 2), (2, 3), (3, 1), (3, 4)")
|
||||||
|
val result = select(
|
||||||
|
"WITH RECURSIVE reachable(node) AS (" +
|
||||||
|
"SELECT 1 FROM dual " +
|
||||||
|
"UNION " +
|
||||||
|
"SELECT edges.to_node FROM edges JOIN reachable ON edges.from_node = reachable.node" +
|
||||||
|
") SELECT node FROM reachable ORDER BY node"
|
||||||
|
)
|
||||||
|
assertEquals(listOf(1L, 2L, 3L, 4L).map { listOf(int(it)) }, result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recursiveCteWithoutSelfReferenceBehavesAsAPlainCompoundQuery() {
|
||||||
|
seed()
|
||||||
|
val result = select(
|
||||||
|
"WITH RECURSIVE notActuallyRecursive AS (SELECT 1 AS n FROM dual UNION ALL SELECT 2 FROM dual) " +
|
||||||
|
"SELECT n FROM notActuallyRecursive ORDER BY n"
|
||||||
|
)
|
||||||
|
assertEquals(listOf(listOf(int(1)), listOf(int(2))), result.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun recursiveCteReferencingItselfOnBothSidesFails() {
|
||||||
|
seed()
|
||||||
|
assertFailsWith<KestrelException> {
|
||||||
|
select(
|
||||||
|
"WITH RECURSIVE bad(n) AS (" +
|
||||||
|
"SELECT n FROM bad UNION ALL SELECT n FROM bad" +
|
||||||
|
") SELECT n FROM bad"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun nonTerminatingRecursiveCteFailsInsteadOfLoopingForever() {
|
||||||
|
seed()
|
||||||
|
assertFailsWith<KestrelException> {
|
||||||
|
select(
|
||||||
|
"WITH RECURSIVE counter(n) AS (" +
|
||||||
|
"SELECT 1 FROM dual " +
|
||||||
|
"UNION ALL " +
|
||||||
|
"SELECT n + 1 FROM counter" +
|
||||||
|
") SELECT n FROM counter"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user