test: cover parsesEveryExcludeMode and excludeOf

This commit is contained in:
dualfroz committed 2026-09-09 17:25:56 +02:00
1 parent 2377d79672
commit 327e8f2431
1 file changed
+173
+173
View File
@@ -1457,4 +1457,177 @@ class ParserTest {
@Test
fun frameWithNoExcludeClauseDefaultsToNoOthers() {
val statement = parseOne(
"SELECT SUM(salary) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM users"
) as SelectStatement
val window = (statement.projection as ExpressionProjection).items.single().expression as WindowExpression
assertEquals(FrameExclude.NoOthers, window.frame!!.exclude)
}
@Test
fun parsesEveryExcludeMode() {
fun excludeOf(clause: String): FrameExclude {
val statement = parseOne(
"SELECT SUM(salary) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING $clause) FROM users"
) as SelectStatement
val window = (statement.projection as ExpressionProjection).items.single().expression as WindowExpression
return window.frame!!.exclude
}
assertEquals(FrameExclude.CurrentRow, excludeOf("EXCLUDE CURRENT ROW"))
assertEquals(FrameExclude.Group, excludeOf("EXCLUDE GROUP"))
assertEquals(FrameExclude.Ties, excludeOf("EXCLUDE TIES"))
assertEquals(FrameExclude.NoOthers, excludeOf("EXCLUDE NO OTHERS"))
}
@Test
fun excludeWithoutAValidModeFailsToParse() {
assertFailsWith<ParseException> {
parseOne(
"SELECT SUM(salary) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE FOO) FROM users"
)
}
}
@Test
fun parsesUnionAsASetOperationStatement() {
val statement = parseOne("SELECT id FROM a UNION SELECT id FROM b") as SetOperationStatement
assertEquals(SetOperator.Union, statement.operator)
assertEquals("a", tableName(statement.left))
assertEquals("b", tableName(statement.right))
}
@Test
fun parsesUnionAllIntersectAndExcept() {
assertEquals(SetOperator.UnionAll, (parseOne("SELECT id FROM a UNION ALL SELECT id FROM b") as SetOperationStatement).operator)
assertEquals(SetOperator.Intersect, (parseOne("SELECT id FROM a INTERSECT SELECT id FROM b") as SetOperationStatement).operator)
assertEquals(SetOperator.Except, (parseOne("SELECT id FROM a EXCEPT SELECT id FROM b") as SetOperationStatement).operator)
}
@Test
fun parsesIntersectAllAndExceptAll() {
assertEquals(SetOperator.IntersectAll, (parseOne("SELECT id FROM a INTERSECT ALL SELECT id FROM b") as SetOperationStatement).operator)
assertEquals(SetOperator.ExceptAll, (parseOne("SELECT id FROM a EXCEPT ALL SELECT id FROM b") as SetOperationStatement).operator)
}
@Test
fun parsesCreateIndexAndCreateUniqueIndex() {
val plain = parseOne("CREATE INDEX idx ON t (a)") as CreateIndexStatement
assertEquals(false, plain.unique)
assertEquals("idx", plain.indexName)
assertEquals("t", plain.tableName)
assertEquals(listOf("a"), plain.columnNames)
val unique = parseOne("CREATE UNIQUE INDEX idx ON t (a)") as CreateIndexStatement
assertEquals(true, unique.unique)
}
@Test
fun chainedCompoundOperatorsAreLeftAssociative() {
val statement = parseOne("SELECT id FROM a UNION SELECT id FROM b INTERSECT SELECT id FROM c") as SetOperationStatement
assertEquals(SetOperator.Intersect, statement.operator)
val left = statement.left as SetOperationStatement
assertEquals(SetOperator.Union, left.operator)
assertEquals("a", tableName(left.left))
assertEquals("b", tableName(left.right))
assertEquals("c", tableName(statement.right))
}
@Test
fun trailingOrderByAndLimitAttachToTheWholeCompoundQuery() {
val statement = parseOne("SELECT id FROM a UNION SELECT id FROM b ORDER BY id DESC LIMIT 3") as SetOperationStatement
val key = statement.orderBy!!.keys.single()
assertEquals("id", (key.expression as ColumnExpression).name)
assertEquals(true, key.descending)
assertEquals(3, statement.limit)
}
@Test
fun individualSelectCoresInACompoundQueryDoNotOwnOrderByOrLimit() {
val statement = parseOne("SELECT id FROM a UNION SELECT id FROM b") as SetOperationStatement
assertNull((statement.left as SelectStatement).orderBy)
assertNull((statement.left as SelectStatement).limit)
}
@Test
fun parsesWithClauseAsAWithQuery() {
val statement = parseOne("WITH recent AS (SELECT id FROM a) SELECT id FROM recent") as WithQuery
assertEquals(false, statement.recursive)
val cte = statement.ctes.single()
assertEquals("recent", cte.name)
assertNull(cte.columns)
assertEquals("a", tableName(cte.query))
assertEquals("recent", tableName(statement.body))
}
@Test
fun parsesWithRecursiveAndMultipleCtesWithColumnLists() {
val statement = parseOne(
"WITH RECURSIVE first_cte(x) AS (SELECT id FROM a), second_cte AS (SELECT id FROM b) SELECT x FROM first_cte"
) as WithQuery
assertEquals(true, statement.recursive)
assertEquals(2, statement.ctes.size)
assertEquals(listOf("x"), statement.ctes[0].columns)
assertNull(statement.ctes[1].columns)
}
@Test
fun explainAcceptsAUnionQuery() {
val statement = parseOne("EXPLAIN SELECT id FROM a UNION SELECT id FROM b") as ExplainStatement
assertTrue(statement.select is SetOperationStatement)
}
@Test
fun createViewAcceptsAUnionQuery() {
val statement = parseOne("CREATE VIEW v AS SELECT id FROM a UNION SELECT id FROM b") as CreateViewStatement
assertTrue(statement.query is SetOperationStatement)
}
@Test
fun derivedTableAcceptsACompoundQuery() {
val statement = parseOne("SELECT * FROM (SELECT id FROM a UNION SELECT id FROM b) AS u") as SelectStatement
val from = statement.from as SubquerySource
assertTrue(from.select is SetOperationStatement)
}
@Test
fun derivedTableAcceptsAWithQuery() {
val statement = parseOne("SELECT * FROM (WITH x AS (SELECT id FROM a) SELECT id FROM x) AS u") as SelectStatement
val from = statement.from as SubquerySource
assertTrue(from.select is WithQuery)
}
@Test
fun parsesColumnLevelForeignKeyWithDefaultActions() {
val statement = parseOne(
"CREATE TABLE t (id INTEGER PRIMARY KEY, dept_id INTEGER REFERENCES departments(id))"
) as CreateTableStatement
val fk = statement.foreignKeys.single()
assertEquals(listOf("dept_id"), fk.columns)
assertEquals("departments", fk.referencedTable)
assertEquals(listOf("id"), fk.referencedColumns)
assertEquals(ForeignKeyAction.NoAction, fk.onDelete)
assertEquals(ForeignKeyAction.NoAction, fk.onUpdate)
}
@Test
fun parsesForeignKeyActionsInEitherOrder() {
val cascade = parseOne(
"CREATE TABLE t (id INTEGER PRIMARY KEY, x INTEGER REFERENCES d(id) ON DELETE CASCADE ON UPDATE RESTRICT)"
) as CreateTableStatement
val fk1 = cascade.foreignKeys.single()
assertEquals(ForeignKeyAction.Cascade, fk1.onDelete)
assertEquals(ForeignKeyAction.Restrict, fk1.onUpdate)
val reordered = parseOne(
"CREATE TABLE t (id INTEGER PRIMARY KEY, x INTEGER REFERENCES d(id) ON UPDATE SET NULL ON DELETE NO ACTION)"
) as CreateTableStatement
val fk2 = reordered.foreignKeys.single()
assertEquals(ForeignKeyAction.NoAction, fk2.onDelete)
assertEquals(ForeignKeyAction.SetNull, fk2.onUpdate)
}
@Test
fun parsesTableLevelForeignKeyConstraint() {
val statement = parseOne(
"CREATE TABLE t (id INTEGER PRIMARY KEY, dept_id INTEGER, FOREIGN KEY (dept_id) REFERENCES departments(id))"
) as CreateTableStatement
}