test: cover leftParsesAsAScalarFunctionCallDespiteAlsoBeingTheLeftJoi...
This commit is contained in:
1 parent
b05e8b2e37
commit
7cbdfb2a0e
1 file changed
+173
@@ -592,4 +592,177 @@ class ParserTest {
|
||||
|
||||
@Test
|
||||
fun filterColumnNamedFilterIsStillUsableAsAPlainIdentifier() {
|
||||
val expression = firstProjection("SELECT filter FROM t") as ColumnExpression
|
||||
assertEquals("filter", expression.name)
|
||||
}
|
||||
|
||||
// LEFT/RIGHT are otherwise reserved (LEFT/RIGHT JOIN), so LEFT(str, n)/RIGHT(str, n) as scalar
|
||||
// functions each need their own disambiguation in the parser.
|
||||
@Test
|
||||
fun leftParsesAsAScalarFunctionCallDespiteAlsoBeingTheLeftJoinKeyword() {
|
||||
val expression = firstProjection("SELECT LEFT(name, 3) FROM t")
|
||||
assertEquals(CallExpression("LEFT", listOf(ColumnExpression("name"), intLit(3))), expression)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rightParsesAsAScalarFunctionCallDespiteAlsoBeingTheRightJoinKeyword() {
|
||||
val expression = firstProjection("SELECT RIGHT(name, 3) FROM t")
|
||||
assertEquals(CallExpression("RIGHT", listOf(ColumnExpression("name"), intLit(3))), expression)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun leftJoinStillParsesAsAJoinNotAFunctionCall() {
|
||||
val statement = parseOne("SELECT * FROM t LEFT JOIN u ON t.id = u.id") as SelectStatement
|
||||
assertEquals(1, statement.joins.size)
|
||||
assertEquals(JoinType.Left, statement.joins[0].type)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bareLeftKeywordWithoutAFollowingParenIsAParseError() {
|
||||
assertFailsWith<ParseException> { parse("SELECT LEFT FROM t") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bareRightKeywordWithoutAFollowingParenIsAParseError() {
|
||||
assertFailsWith<ParseException> { parse("SELECT RIGHT FROM t") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rightJoinAndFullJoinParseWithOptionalOuter() {
|
||||
val right = parseOne("SELECT * FROM t RIGHT JOIN u ON t.id = u.id") as SelectStatement
|
||||
assertEquals(JoinType.Right, right.joins[0].type)
|
||||
val rightOuter = parseOne("SELECT * FROM t RIGHT OUTER JOIN u ON t.id = u.id") as SelectStatement
|
||||
assertEquals(JoinType.Right, rightOuter.joins[0].type)
|
||||
val full = parseOne("SELECT * FROM t FULL JOIN u ON t.id = u.id") as SelectStatement
|
||||
assertEquals(JoinType.Full, full.joins[0].type)
|
||||
val fullOuter = parseOne("SELECT * FROM t FULL OUTER JOIN u ON t.id = u.id") as SelectStatement
|
||||
assertEquals(JoinType.Full, fullOuter.joins[0].type)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rightAndFullJoinLateralAreRejected() {
|
||||
assertFailsWith<ParseException> {
|
||||
parse("SELECT * FROM t RIGHT JOIN LATERAL (SELECT * FROM u WHERE u.id = t.id) x ON true")
|
||||
}
|
||||
assertFailsWith<ParseException> {
|
||||
parse("SELECT * FROM t FULL JOIN LATERAL (SELECT * FROM u WHERE u.id = t.id) x ON true")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun crossJoinParsesWithoutAnOnClauseAndOnIsNull() {
|
||||
val statement = parseOne("SELECT * FROM t CROSS JOIN u") as SelectStatement
|
||||
assertEquals(JoinType.Cross, statement.joins[0].type)
|
||||
assertEquals(null, statement.joins[0].on)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun crossJoinWithAnExplicitOnClauseIsAParseError() {
|
||||
assertFailsWith<ParseException> { parse("SELECT * FROM t CROSS JOIN u ON t.id = u.id") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun crossJoinLateralIsAccepted() {
|
||||
val statement = parseOne(
|
||||
"SELECT * FROM t CROSS JOIN LATERAL (SELECT * FROM u WHERE u.id = t.id) x"
|
||||
) as SelectStatement
|
||||
assertEquals(JoinType.Cross, statement.joins[0].type)
|
||||
assertEquals(null, statement.joins[0].on)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesIsNullAndIsNotNull() {
|
||||
assertEquals(IsNullExpression(ColumnExpression("age"), negated = false), whereOf("SELECT 1 FROM t WHERE age IS NULL"))
|
||||
assertEquals(
|
||||
IsNullExpression(ColumnExpression("age"), negated = true),
|
||||
whereOf("SELECT 1 FROM t WHERE age IS NOT NULL")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesInAndNotIn() {
|
||||
assertEquals(
|
||||
InExpression(ColumnExpression("id"), listOf(intLit(1), intLit(2), intLit(3)), negated = false),
|
||||
whereOf("SELECT 1 FROM t WHERE id IN (1, 2, 3)")
|
||||
)
|
||||
assertEquals(
|
||||
InExpression(ColumnExpression("id"), listOf(intLit(1)), negated = true),
|
||||
whereOf("SELECT 1 FROM t WHERE id NOT IN (1)")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesBetweenAndNotBetween() {
|
||||
assertEquals(
|
||||
BetweenExpression(ColumnExpression("age"), intLit(18), intLit(65), negated = false),
|
||||
whereOf("SELECT 1 FROM t WHERE age BETWEEN 18 AND 65")
|
||||
)
|
||||
assertEquals(
|
||||
BetweenExpression(ColumnExpression("age"), intLit(18), intLit(65), negated = true),
|
||||
whereOf("SELECT 1 FROM t WHERE age NOT BETWEEN 18 AND 65")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesLikeAndNotLike() {
|
||||
assertEquals(
|
||||
LikeExpression(ColumnExpression("name"), LiteralExpression(Value.TextValue("a%")), negated = false),
|
||||
whereOf("SELECT 1 FROM t WHERE name LIKE 'a%'")
|
||||
)
|
||||
assertEquals(
|
||||
LikeExpression(ColumnExpression("name"), LiteralExpression(Value.TextValue("a%")), negated = true),
|
||||
whereOf("SELECT 1 FROM t WHERE name NOT LIKE 'a%'")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun notInWithoutInOrBetweenOrLikeFails() {
|
||||
assertFailsWith<ParseException> { parse("SELECT 1 FROM t WHERE id NOT = 1") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesSearchedCaseExpression() {
|
||||
val expression = firstProjection(
|
||||
"SELECT CASE WHEN age < 18 THEN 'minor' WHEN age < 65 THEN 'adult' ELSE 'senior' END FROM t"
|
||||
) as CaseExpression
|
||||
assertNull(expression.operand)
|
||||
assertEquals(2, expression.branches.size)
|
||||
assertEquals(LiteralExpression(Value.TextValue("senior")), expression.elseExpression)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesSimpleCaseExpressionWithoutElse() {
|
||||
val expression = firstProjection("SELECT CASE grade WHEN 1 THEN 'a' END FROM t") as CaseExpression
|
||||
assertEquals(ColumnExpression("grade"), expression.operand)
|
||||
assertEquals(1, expression.branches.size)
|
||||
assertNull(expression.elseExpression)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun caseWithoutWhenClauseFails() {
|
||||
assertFailsWith<ParseException> { parse("SELECT CASE WHEN THEN 1 END FROM t") }
|
||||
assertFailsWith<ParseException> { parse("SELECT CASE ELSE 1 END FROM t") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun caseMissingEndFails() {
|
||||
assertFailsWith<ParseException> { parse("SELECT CASE WHEN 1 THEN 2 FROM t") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesScalarSubqueryInWhereClause() {
|
||||
val expression = whereOf("SELECT 1 FROM t WHERE age > (SELECT AVG(age) FROM t)") as BinaryExpression
|
||||
val subquery = expression.right as ScalarSubqueryExpression
|
||||
assertEquals("t", tableName(subquery.select))
|
||||
assertEquals(BinaryOperator.Greater, expression.operator)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun parsesInSubquery() {
|
||||
val expression = whereOf("SELECT 1 FROM t WHERE id IN (SELECT id FROM other)") as InSubqueryExpression
|
||||
assertEquals(ColumnExpression("id"), expression.operand)
|
||||
assertEquals("other", tableName(expression.select))
|
||||
assertEquals(false, expression.negated)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user