diff --git a/src/dialect/duckdb.rs b/src/dialect/duckdb.rs index 5e4d32ce40..7347a14eaa 100644 --- a/src/dialect/duckdb.rs +++ b/src/dialect/duckdb.rs @@ -65,6 +65,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 f6a6682ec9..b873f6f286 100644 --- a/src/dialect/generic.rs +++ b/src/dialect/generic.rs @@ -173,6 +173,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 3ce71eb0be..9383822273 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -2081,6 +2081,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 41b0e8be16..868e61039d 100644 --- a/src/dialect/sqlite.rs +++ b/src/dialect/sqlite.rs @@ -160,4 +160,8 @@ impl Dialect for SQLiteDialect { fn supports_unterminated_block_comments(&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 276b252ed2..48887515e8 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -19413,7 +19413,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 87fb61dc17..69cf689089 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -21022,3 +21022,25 @@ fn parse_window_spec_keyword_base_window_name() { "SELECT count(*) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM t", ); } + +#[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() + )) + ); +}