test: cover parsesGroupByGroupingSetsWithAnEmptySet
This commit is contained in:
1 parent
33a0168223
commit
8a381f8703
1 file changed
+185
@@ -1976,4 +1976,189 @@ class ParserTest {
|
|||||||
assertEquals(listOf("dept", "region"), spec.expressions.map { (it as ColumnExpression).name })
|
assertEquals(listOf("dept", "region"), spec.expressions.map { (it as ColumnExpression).name })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parsesGroupByGroupingSetsWithAnEmptySet() {
|
||||||
|
val statement = parseOne(
|
||||||
|
"SELECT dept, region, SUM(amount) FROM sales GROUP BY GROUPING SETS ((dept, region), (dept), ())"
|
||||||
|
) as SelectStatement
|
||||||
|
val spec = statement.groupingSpec as GroupingSetsSpec
|
||||||
|
assertEquals(3, spec.sets.size)
|
||||||
|
assertEquals(listOf("dept", "region"), spec.sets[0].map { (it as ColumnExpression).name })
|
||||||
|
assertEquals(listOf("dept"), spec.sets[1].map { (it as ColumnExpression).name })
|
||||||
|
assertTrue(spec.sets[2].isEmpty())
|
||||||
|
assertEquals(listOf("dept", "region"), statement.groupBy.map { (it as ColumnExpression).name })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rollupCubeAndGroupingSetsAreNotReservedWordsAsPlainColumnNames() {
|
||||||
|
val statement = parseOne("SELECT rollup FROM t GROUP BY rollup") as SelectStatement
|
||||||
|
assertNull(statement.groupingSpec)
|
||||||
|
assertEquals(listOf("rollup"), statement.groupBy.map { (it as ColumnExpression).name })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun groupByRollupRequiresAClosingParenthesis() {
|
||||||
|
assertFailsWith<ParseException> { parse("SELECT 1 FROM t GROUP BY ROLLUP (dept") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun groupByGroupingSetsRequiresParenthesizedElements() {
|
||||||
|
assertFailsWith<ParseException> { parse("SELECT 1 FROM t GROUP BY GROUPING SETS (dept)") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parsesGroupingFunctionCallLikeAnyOtherFunction() {
|
||||||
|
val statement = parseOne("SELECT dept, GROUPING(dept) FROM sales GROUP BY ROLLUP (dept)") as SelectStatement
|
||||||
|
val projection = statement.projection as ExpressionProjection
|
||||||
|
val call = projection.items[1].expression as CallExpression
|
||||||
|
assertEquals("GROUPING", call.name)
|
||||||
|
assertEquals(listOf("dept"), call.arguments.map { (it as ColumnExpression).name })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun plainSelectDefaultsToNotDistinct() {
|
||||||
|
val statement = parseOne("SELECT dept FROM sales") as SelectStatement
|
||||||
|
assertFalse(statement.distinct)
|
||||||
|
assertTrue(statement.distinctOn.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun selectAllParsesTheSameAsNoModifierAtAll() {
|
||||||
|
val statement = parseOne("SELECT ALL dept FROM sales") as SelectStatement
|
||||||
|
assertFalse(statement.distinct)
|
||||||
|
assertTrue(statement.distinctOn.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun selectDistinctSetsTheFlagWithNoDistinctOnExpressions() {
|
||||||
|
val statement = parseOne("SELECT DISTINCT dept, region FROM sales") as SelectStatement
|
||||||
|
assertTrue(statement.distinct)
|
||||||
|
assertTrue(statement.distinctOn.isEmpty())
|
||||||
|
val projection = statement.projection as ExpressionProjection
|
||||||
|
assertEquals(listOf("dept", "region"), projection.items.map { (it.expression as ColumnExpression).name })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun selectDistinctOnParsesItsParenthesizedExpressionList() {
|
||||||
|
val statement = parseOne("SELECT DISTINCT ON (dept, region) dept, region, amount FROM sales") as SelectStatement
|
||||||
|
assertTrue(statement.distinct)
|
||||||
|
assertEquals(listOf("dept", "region"), statement.distinctOn.map { (it as ColumnExpression).name })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun selectDistinctOnAcceptsAnArbitraryExpressionNotJustAColumn() {
|
||||||
|
val statement = parseOne("SELECT DISTINCT ON (amount + 1) dept FROM sales") as SelectStatement
|
||||||
|
assertTrue(statement.distinctOn.single() is BinaryExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun selectDistinctOnRequiresParenthesesAfterOn() {
|
||||||
|
assertFailsWith<ParseException> { parse("SELECT DISTINCT ON dept FROM sales") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun selectDistinctOnRequiresAtLeastOneExpression() {
|
||||||
|
assertFailsWith<ParseException> { parse("SELECT DISTINCT ON () dept FROM sales") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun selectDistinctOnRequiresAClosingParenthesis() {
|
||||||
|
assertFailsWith<ParseException> { parse("SELECT DISTINCT ON (dept dept FROM sales") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun distinctWorksInsideADerivedTableSubquery() {
|
||||||
|
val statement = parseOne("SELECT * FROM (SELECT DISTINCT dept FROM sales) AS d") as SelectStatement
|
||||||
|
val source = statement.from as SubquerySource
|
||||||
|
assertTrue((source.select as SelectStatement).distinct)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun distinctSurvivesOrderByAndLimitBeingAttachedAfterward() {
|
||||||
|
val statement = parseOne("SELECT DISTINCT dept FROM sales ORDER BY dept LIMIT 5") as SelectStatement
|
||||||
|
assertTrue(statement.distinct)
|
||||||
|
assertNotNull(statement.orderBy)
|
||||||
|
assertEquals(5, statement.limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun dollarDigitParsesAsAParameterExpression() {
|
||||||
|
val statement = parseOne("SELECT \$1 FROM sales") as SelectStatement
|
||||||
|
val projection = statement.projection as ExpressionProjection
|
||||||
|
assertEquals(ParameterExpression(1), projection.items.single().expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun multiDigitParameterIndexParses() {
|
||||||
|
val statement = parseOne("SELECT \$12 FROM sales") as SelectStatement
|
||||||
|
val projection = statement.projection as ExpressionProjection
|
||||||
|
assertEquals(ParameterExpression(12), projection.items.single().expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parameterIndexZeroIsAParseError() {
|
||||||
|
assertFailsWith<ParseException> { parse("SELECT \$0 FROM sales") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun prepareParsesTheNameAndWrapsTheTargetStatement() {
|
||||||
|
val statement = parseOne("PREPARE byId AS SELECT * FROM sales WHERE id = \$1") as PrepareStatement
|
||||||
|
assertEquals("byId", statement.name)
|
||||||
|
val target = statement.target as SelectStatement
|
||||||
|
val where = target.where as BinaryExpression
|
||||||
|
assertEquals(BinaryOperator.Equal, where.operator)
|
||||||
|
assertEquals(ParameterExpression(1), where.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun prepareAcceptsInsertUpdateDeleteAndMergeAsItsTarget() {
|
||||||
|
assertTrue((parseOne("PREPARE p AS INSERT INTO sales VALUES (\$1)") as PrepareStatement).target is InsertStatement)
|
||||||
|
assertTrue((parseOne("PREPARE p AS UPDATE sales SET dept = \$1") as PrepareStatement).target is UpdateStatement)
|
||||||
|
assertTrue((parseOne("PREPARE p AS DELETE FROM sales WHERE dept = \$1") as PrepareStatement).target is DeleteStatement)
|
||||||
|
assertTrue(
|
||||||
|
(parseOne("PREPARE p AS MERGE INTO sales USING sales2 ON sales.id = sales2.id WHEN MATCHED THEN DELETE") as PrepareStatement)
|
||||||
|
.target is MergeStatement
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun prepareRejectsDdlAndTransactionControlTargets() {
|
||||||
|
assertFailsWith<ParseException> { parse("PREPARE p AS CREATE TABLE t (id INTEGER)") }
|
||||||
|
assertFailsWith<ParseException> { parse("PREPARE p AS BEGIN") }
|
||||||
|
assertFailsWith<ParseException> { parse("PREPARE p AS EXPLAIN SELECT 1") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun executeParsesNameAndPositionalArguments() {
|
||||||
|
val statement = parseOne("EXECUTE byId(1, 'ada')") as ExecuteStatement
|
||||||
|
assertEquals("byId", statement.name)
|
||||||
|
assertEquals(listOf(intLit(1), LiteralExpression(Value.TextValue("ada"))), statement.arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun executeWithNoParenthesesHasNoArguments() {
|
||||||
|
val statement = parseOne("EXECUTE byId") as ExecuteStatement
|
||||||
|
assertEquals(emptyList(), statement.arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun executeWithEmptyParenthesesHasNoArguments() {
|
||||||
|
val statement = parseOne("EXECUTE byId()") as ExecuteStatement
|
||||||
|
assertEquals(emptyList(), statement.arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deallocateParsesAName() {
|
||||||
|
assertEquals(DeallocateStatement("byId"), parseOne("DEALLOCATE byId"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deallocatePrepareKeywordIsOptional() {
|
||||||
|
assertEquals(DeallocateStatement("byId"), parseOne("DEALLOCATE PREPARE byId"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deallocateAllHasNoName() {
|
||||||
|
assertEquals(DeallocateStatement(null, all = true), parseOne("DEALLOCATE ALL"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user