test: cover columnLevelCollateWithAnUnknownSequenceNameFailsToParse

This commit is contained in:
dualfroz committed 2026-09-09 16:52:43 +02:00
1 parent 40197f5dc9
commit 6556fa2316
1 file changed
+173
+173
View File
@@ -1111,4 +1111,177 @@ class ParserTest {
fun columnLevelCollateBeforeDefaultAttachesToTheColumnNotTheDefaultExpression() {
val statement = parseOne("CREATE TABLE t (name TEXT COLLATE NOCASE DEFAULT 'x')") as CreateTableStatement
assertEquals(Collation.NoCase, statement.columns[0].collation)
assertEquals(LiteralExpression(Value.TextValue("x")), statement.columns[0].default)
}
@Test
fun columnLevelCollateWithAnUnknownSequenceNameFailsToParse() {
assertFailsWith<ParseException> { parse("CREATE TABLE t (name TEXT COLLATE BOGUS)") }
}
@Test
fun columnLevelCollateWithoutAFollowingNameFailsToParse() {
assertFailsWith<ParseException> { parse("CREATE TABLE t (name TEXT COLLATE)") }
}
@Test
fun parsesColumnLevelCollateInAlterTableAddColumn() {
val statement = parseOne("ALTER TABLE t ADD COLUMN name TEXT COLLATE NOCASE") as AlterTableStatement
val action = statement.action as AddColumn
assertEquals(Collation.NoCase, action.column.collation)
}
@Test
fun parsesDerivedTableInFromWithRequiredAlias() {
val statement = parseOne("SELECT s.id FROM (SELECT id FROM users) AS s") as SelectStatement
val from = statement.from as SubquerySource
assertEquals("s", from.alias)
assertEquals("users", tableName(from.select))
}
@Test
fun parsesDerivedTableWithImplicitAlias() {
val statement = parseOne("SELECT s.id FROM (SELECT id FROM users) s") as SelectStatement
assertEquals("s", (statement.from as SubquerySource).alias)
}
@Test
fun derivedTableWithoutAliasFails() {
assertFailsWith<ParseException> { parseOne("SELECT id FROM (SELECT id FROM users)") }
}
@Test
fun parsesDerivedTableAsJoinTarget() {
val statement = parseOne(
"SELECT * FROM users JOIN (SELECT dept, COUNT(*) AS n FROM users GROUP BY dept) AS d ON users.dept = d.dept"
) as SelectStatement
val joinFrom = statement.joins.single().from as SubquerySource
assertEquals("d", joinFrom.alias)
}
@Test
fun parsesLateralJoinMarksTheSubquerySource() {
val statement = parseOne(
"SELECT * FROM users u JOIN LATERAL (SELECT id FROM orders WHERE orders.userId = u.id) AS o ON TRUE"
) as SelectStatement
val joinFrom = statement.joins.single().from as SubquerySource
assertEquals("o", joinFrom.alias)
assertTrue(joinFrom.lateral)
}
@Test
fun nonLateralDerivedTableJoinIsNotMarkedLateral() {
val statement = parseOne("SELECT * FROM users JOIN (SELECT id FROM orders) AS o ON TRUE") as SelectStatement
assertFalse((statement.joins.single().from as SubquerySource).lateral)
}
@Test
fun lateralBeforeAPlainTableFails() {
assertFailsWith<ParseException> { parseOne("SELECT * FROM users JOIN LATERAL orders ON TRUE") }
}
@Test
fun parsesRankingWindowFunctionWithPartitionAndOrder() {
val statement = parseOne(
"SELECT ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn FROM users"
) as SelectStatement
val item = (statement.projection as ExpressionProjection).items.single()
val window = item.expression as WindowExpression
assertEquals("ROW_NUMBER", window.name)
assertEquals(WindowFunctionKind.RowNumber, window.kind)
assertNull(window.argument)
assertFalse(window.star)
assertEquals(listOf(ColumnExpression("dept")), window.partitionBy)
assertEquals(1, window.orderBy.size)
assertEquals(ColumnExpression("salary"), window.orderBy.single().expression)
assertTrue(window.orderBy.single().descending)
assertEquals("rn", item.alias)
}
@Test
fun parsesAggregateWindowFunctionWithStarAndNoPartition() {
val statement = parseOne("SELECT COUNT(*) OVER () FROM users") as SelectStatement
val window = (statement.projection as ExpressionProjection).items.single().expression as WindowExpression
assertEquals(WindowFunctionKind.Aggregate, window.kind)
assertTrue(window.star)
assertNull(window.argument)
assertTrue(window.partitionBy.isEmpty())
assertTrue(window.orderBy.isEmpty())
}
@Test
fun aggregateWindowFunctionWithSingleArgumentAndOrderBy() {
val statement = parseOne("SELECT SUM(salary) OVER (ORDER BY id) FROM users") as SelectStatement
val window = (statement.projection as ExpressionProjection).items.single().expression as WindowExpression
assertEquals("SUM", window.name)
assertEquals(ColumnExpression("salary"), window.argument)
assertFalse(window.star)
assertEquals(listOf(ColumnExpression("id")), window.orderBy.map { it.expression })
}
@Test
fun windowOverOrderByParsesAnExplicitNullsFirstClause() {
val statement = parseOne("SELECT SUM(salary) OVER (ORDER BY bonus NULLS FIRST) FROM users") as SelectStatement
val window = (statement.projection as ExpressionProjection).items.single().expression as WindowExpression
val key = window.orderBy.single()
assertEquals(ColumnExpression("bonus"), key.expression)
assertEquals(false, key.descending)
assertEquals(true, key.nullsFirst)
}
@Test
fun functionNameWithoutOverIsNotTreatedAsAWindowFunction() {
val statement = parseOne("SELECT ROW_NUMBER() FROM users") as SelectStatement
val expression = (statement.projection as ExpressionProjection).items.single().expression
assertTrue(expression is CallExpression)
assertEquals("ROW_NUMBER", (expression as CallExpression).name)
}
@Test
fun rowNumberWithArgumentsFailsToParse() {
assertFailsWith<ParseException> { parseOne("SELECT ROW_NUMBER(id) OVER () FROM users") }
}
@Test
fun rankWithAnArgumentFailsToParse() {
assertFailsWith<ParseException> { parseOne("SELECT RANK(id) OVER (ORDER BY id) FROM users") }
}
@Test
fun nonWindowableFunctionBeforeOverFailsToParse() {
assertFailsWith<ParseException> { parseOne("SELECT UPPER(name) OVER () FROM users") }
}
@Test
fun lagWithOffsetAndDefaultParsesIntoTheirOwnFields() {
val statement = parseOne(
"SELECT LAG(salary, 2, 0) OVER (PARTITION BY dept ORDER BY id) AS prev FROM users"
) as SelectStatement
val window = (statement.projection as ExpressionProjection).items.single().expression as WindowExpression
assertEquals("LAG", window.name)
assertEquals(WindowFunctionKind.Lag, window.kind)
assertEquals(ColumnExpression("salary"), window.argument)
assertEquals(LiteralExpression(Value.IntegerValue(2)), window.offset)
assertEquals(LiteralExpression(Value.IntegerValue(0)), window.defaultValue)
assertFalse(window.star)
}
@Test
fun leadWithASingleArgumentLeavesOffsetAndDefaultNull() {
val statement = parseOne("SELECT LEAD(salary) OVER (ORDER BY id) FROM users") as SelectStatement
val window = (statement.projection as ExpressionProjection).items.single().expression as WindowExpression
assertEquals(WindowFunctionKind.Lead, window.kind)
assertEquals(ColumnExpression("salary"), window.argument)
assertNull(window.offset)
assertNull(window.defaultValue)
}
@Test
fun parsesFirstValueLastValueAndNtile() {
val statement = parseOne(
"SELECT FIRST_VALUE(salary) OVER (ORDER BY id), LAST_VALUE(salary) OVER (ORDER BY id), " +
"NTILE(4) OVER (ORDER BY id) FROM users"
) as SelectStatement
val windows = (statement.projection as ExpressionProjection).items.map { it.expression as WindowExpression }
assertEquals(WindowFunctionKind.FirstValue, windows[0].kind)
}