Skip to content

Commit ebcd31e

Browse files
committed
Add tests for invalid syntax
1 parent 47ba442 commit ebcd31e

File tree

2 files changed

+94
-3
lines changed

2 files changed

+94
-3
lines changed

src/parser/mod.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7888,7 +7888,9 @@ impl<'a> Parser<'a> {
78887888
let body = self.parse_boxed_query_body(0)?;
78897889

78907890
let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
7891-
self.parse_comma_separated(Parser::parse_order_by_expr)?
7891+
let order_by_exprs = self.parse_comma_separated(Parser::parse_order_by_expr)?;
7892+
self.validate_order_by_exprs_for_interpolate_and_with_fill(&order_by_exprs)?;
7893+
order_by_exprs
78927894
} else {
78937895
vec![]
78947896
};
@@ -10465,6 +10467,35 @@ impl<'a> Parser<'a> {
1046510467
Ok(WithFill { from, to, step })
1046610468
}
1046710469

10470+
pub fn validate_order_by_exprs_for_interpolate_and_with_fill(
10471+
&mut self,
10472+
order_by_exprs: &Vec<OrderByExpr>,
10473+
) -> Result<(), ParserError> {
10474+
if dialect_of!(self is ClickHouseDialect | GenericDialect) {
10475+
let mut has_with_fill = false;
10476+
let mut has_interpolate = false;
10477+
for order_by_expr in order_by_exprs {
10478+
if order_by_expr.with_fill.is_some() {
10479+
has_with_fill = true;
10480+
}
10481+
if order_by_expr.interpolate.is_some() {
10482+
if has_interpolate {
10483+
return Err(ParserError::ParserError(
10484+
"Only the last ORDER BY expression can contain interpolate".to_string(),
10485+
));
10486+
}
10487+
if !has_with_fill {
10488+
return Err(ParserError::ParserError(
10489+
"INTERPOLATE requires WITH FILL".to_string(),
10490+
));
10491+
}
10492+
has_interpolate = true;
10493+
}
10494+
}
10495+
}
10496+
Ok(())
10497+
}
10498+
1046810499
// Parse a set of comma seperated INTERPOLATE expressions (ClickHouse dialect)
1046910500
// that follow the INTERPOLATE keyword in an ORDER BY clause with the WITH FILL modifier
1047010501
pub fn parse_interpolations(&mut self) -> Result<Vec<Interpolate>, ParserError> {

tests/sqlparser_clickhouse.rs

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -727,10 +727,51 @@ fn parse_select_order_by_with_fill_interpolate() {
727727
assert_eq!(Some(Expr::Value(number("2"))), select.limit);
728728
}
729729

730+
#[test]
731+
fn parse_select_order_by_with_fill_interpolate_multi_interpolates() {
732+
let sql = "SELECT id, fname, lname FROM customer ORDER BY fname WITH FILL \
733+
INTERPOLATE (col1 AS col1 + 1) INTERPOLATE (col2 AS col2 + 2)";
734+
clickhouse_and_generic()
735+
.parse_sql_statements(sql)
736+
.expect_err("ORDER BY only accepts a single INTERPOLATE clause");
737+
}
738+
739+
#[test]
740+
fn parse_select_order_by_with_fill_interpolate_multi_with_fill_interpolates() {
741+
let sql = "SELECT id, fname, lname FROM customer \
742+
ORDER BY \
743+
fname WITH FILL INTERPOLATE (col1 AS col1 + 1), \
744+
lname WITH FILL INTERPOLATE (col2 AS col2 + 2)";
745+
clickhouse_and_generic()
746+
.parse_sql_statements(sql)
747+
.expect_err("ORDER BY only accepts a single INTERPOLATE clause");
748+
}
749+
750+
#[test]
751+
fn parse_select_order_by_interpolate_missing_with_fill() {
752+
let sql = "SELECT id, fname, lname FROM customer \
753+
ORDER BY fname, lname \
754+
INTERPOLATE (col2 AS col2 + 2)";
755+
clickhouse_and_generic()
756+
.parse_sql_statements(sql)
757+
.expect_err("ORDER BY INTERPOLATE must have at least one WITH FILL");
758+
}
759+
760+
#[test]
761+
fn parse_select_order_by_interpolate_not_last() {
762+
let sql = "SELECT id, fname, lname FROM customer \
763+
ORDER BY \
764+
fname INTERPOLATE (col2 AS col2 + 2),
765+
lname";
766+
clickhouse_and_generic()
767+
.parse_sql_statements(sql)
768+
.expect_err("ORDER BY INTERPOLATE must be in the last position");
769+
}
770+
730771
#[test]
731772
fn parse_with_fill() {
732-
let sql = "SELECT fname FROM customer \
733-
ORDER BY fname WITH FILL FROM 10 TO 20 STEP 2";
773+
let sql = "SELECT fname FROM customer ORDER BY fname \
774+
WITH FILL FROM 10 TO 20 STEP 2";
734775
let select = clickhouse().verified_query(sql);
735776
assert_eq!(
736777
Some(WithFill {
@@ -742,6 +783,25 @@ fn parse_with_fill() {
742783
);
743784
}
744785

786+
#[test]
787+
fn parse_with_fill_missing_single_argument() {
788+
let sql = "SELECT id, fname, lname FROM customer ORDER BY \
789+
fname WITH FILL FROM TO 20";
790+
clickhouse_and_generic()
791+
.parse_sql_statements(sql)
792+
.expect_err("WITH FILL requires expressions for all arguments");
793+
}
794+
795+
#[test]
796+
fn parse_with_fill_multiple_incomplete_arguments() {
797+
let sql = "SELECT id, fname, lname FROM customer ORDER BY \
798+
fname WITH FILL FROM TO 20, lname WITH FILL FROM TO STEP 1";
799+
clickhouse_and_generic()
800+
.parse_sql_statements(sql)
801+
.expect_err("WITH FILL requires expressions for all arguments");
802+
}
803+
804+
745805
#[test]
746806
fn parse_interpolate_body_with_columns() {
747807
let sql = "SELECT fname FROM customer ORDER BY fname WITH FILL \

0 commit comments

Comments
 (0)