diff --git a/src/dialect/duckdb.rs b/src/dialect/duckdb.rs index 4e27d042b5..6f329ab2f8 100644 --- a/src/dialect/duckdb.rs +++ b/src/dialect/duckdb.rs @@ -69,6 +69,10 @@ impl Dialect for DuckDbDialect { true } + fn supports_aggregate_order_by_with_empty_args(&self) -> bool { + true + } + fn supports_named_fn_args_with_eq_operator(&self) -> bool { true } diff --git a/src/dialect/generic.rs b/src/dialect/generic.rs index fb3f2c254f..6aae6acaea 100644 --- a/src/dialect/generic.rs +++ b/src/dialect/generic.rs @@ -189,6 +189,10 @@ impl Dialect for GenericDialect { true } + fn supports_aggregate_order_by_with_empty_args(&self) -> bool { + true + } + fn supports_comment_on(&self) -> bool { true } diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs index 847d042418..094687af34 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -2138,6 +2138,15 @@ pub trait Dialect: Debug + Any { fn supports_cast_empty_data_type_to_unspecified(&self) -> bool { false } + + /// Returns true if the dialect allows an `ORDER BY` clause inside an aggregate function + /// call with no preceding arguments, e.g. `count(ORDER BY a)`. + /// + /// [SQLite](https://www.sqlite.org/lang_aggfunc.html#aggorderby), + /// [DuckDB](https://duckdb.org/docs/current/sql/functions/aggregates#order-by-clause-in-aggregate-functions) + fn supports_aggregate_order_by_with_empty_args(&self) -> bool { + false + } } /// Operators for which precedence must be defined. diff --git a/src/dialect/sqlite.rs b/src/dialect/sqlite.rs index 16be3303bb..0224a0d834 100644 --- a/src/dialect/sqlite.rs +++ b/src/dialect/sqlite.rs @@ -226,4 +226,8 @@ impl Dialect for SQLiteDialect { fn supports_comma_join_constraint(&self) -> bool { true } + + fn supports_aggregate_order_by_with_empty_args(&self) -> bool { + true + } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 608e6c364f..2338a2d145 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -19437,7 +19437,14 @@ impl<'a> Parser<'a> { } let duplicate_treatment = self.parse_duplicate_treatment()?; - let args = self.parse_comma_separated(Parser::parse_function_args)?; + let args = if duplicate_treatment != Some(DuplicateTreatment::Distinct) + && self.dialect.supports_aggregate_order_by_with_empty_args() + && self.peek_keywords(&[Keyword::ORDER, Keyword::BY]) + { + vec![] + } else { + self.parse_comma_separated(Parser::parse_function_args)? + }; if self.parse_keyword(Keyword::WHERE) { clauses.push(FunctionArgumentClause::Where(self.parse_expr()?)); diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 6c047d17fb..f83a34be20 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -3937,6 +3937,28 @@ fn parse_agg_with_order_by() { } } +#[test] +fn parse_aggregate_order_by_with_empty_args() { + let dialects = all_dialects_where(|d| d.supports_aggregate_order_by_with_empty_args()); + dialects.verified_stmt("SELECT count(ORDER BY a) FROM t"); + dialects.verified_stmt("SELECT count(ORDER BY a ASC, b DESC) FROM t"); + dialects.verified_stmt("SELECT count(ALL ORDER BY a) FROM t"); + assert_eq!( + dialects.parse_sql_statements("SELECT count(DISTINCT ORDER BY a) FROM t"), + Err(ParserError::ParserError( + "Expected: ), found: BY".to_string() + )) + ); + + assert_eq!( + all_dialects_where(|d| !d.supports_aggregate_order_by_with_empty_args()) + .parse_sql_statements("SELECT count(ORDER BY a) FROM t"), + Err(ParserError::ParserError( + "Expected: ), found: BY".to_string() + )) + ); +} + #[test] fn parse_window_rank_function() { let supported_dialects = TestedDialects::new(vec![