test: cover leftParsesAsAScalarFunctionCallDespiteAlsoBeingTheLeftJoi...
This commit is contained in:
1 parent
b05e8b2e37
commit
7cbdfb2a0e
1 file changed
+173
@@ -592,4 +592,177 @@ class ParserTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun filterColumnNamedFilterIsStillUsableAsAPlainIdentifier() {
|
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