test: cover parsesEveryExcludeMode and excludeOf
This commit is contained in:
1 parent
2377d79672
commit
327e8f2431
1 file changed
+173
@@ -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
|
||||
}
|
||||
Reference in new issue
Block a user