mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 06:18:17 +00:00
BigQuery: support for ANY_VALUE HAVING clause (#1258)
This commit is contained in:
parent
a12a8882e7
commit
c4f3ef9600
3 changed files with 63 additions and 0 deletions
|
@ -4962,6 +4962,15 @@ pub enum FunctionArgumentClause {
|
|||
///
|
||||
/// See <https://trino.io/docs/current/functions/aggregate.html>.
|
||||
OnOverflow(ListAggOnOverflow),
|
||||
/// Specifies a minimum or maximum bound on the input to [`ANY_VALUE`] on BigQuery.
|
||||
///
|
||||
/// Syntax:
|
||||
/// ```plaintext
|
||||
/// HAVING { MAX | MIN } expression
|
||||
/// ```
|
||||
///
|
||||
/// [`ANY_VALUE`]: https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#any_value
|
||||
Having(HavingBound),
|
||||
/// The `SEPARATOR` clause to the [`GROUP_CONCAT`] function in MySQL.
|
||||
///
|
||||
/// [`GROUP_CONCAT`]: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
|
||||
|
@ -4979,6 +4988,7 @@ impl fmt::Display for FunctionArgumentClause {
|
|||
}
|
||||
FunctionArgumentClause::Limit(limit) => write!(f, "LIMIT {limit}"),
|
||||
FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
|
||||
FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
|
||||
FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
|
||||
}
|
||||
}
|
||||
|
@ -5087,6 +5097,35 @@ impl fmt::Display for ListAggOnOverflow {
|
|||
}
|
||||
}
|
||||
|
||||
/// The `HAVING` clause in a call to `ANY_VALUE` on BigQuery.
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
pub struct HavingBound(pub HavingBoundKind, pub Expr);
|
||||
|
||||
impl fmt::Display for HavingBound {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "HAVING {} {}", self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
pub enum HavingBoundKind {
|
||||
Min,
|
||||
Max,
|
||||
}
|
||||
|
||||
impl fmt::Display for HavingBoundKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
HavingBoundKind::Min => write!(f, "MIN"),
|
||||
HavingBoundKind::Max => write!(f, "MAX"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
|
|
|
@ -9534,6 +9534,20 @@ impl<'a> Parser<'a> {
|
|||
clauses.push(FunctionArgumentClause::Limit(self.parse_expr()?));
|
||||
}
|
||||
|
||||
if dialect_of!(self is GenericDialect | BigQueryDialect)
|
||||
&& self.parse_keyword(Keyword::HAVING)
|
||||
{
|
||||
let kind = match self.expect_one_of_keywords(&[Keyword::MIN, Keyword::MAX])? {
|
||||
Keyword::MIN => HavingBoundKind::Min,
|
||||
Keyword::MAX => HavingBoundKind::Max,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
clauses.push(FunctionArgumentClause::Having(HavingBound(
|
||||
kind,
|
||||
self.parse_expr()?,
|
||||
)))
|
||||
}
|
||||
|
||||
if dialect_of!(self is GenericDialect | MySqlDialect)
|
||||
&& self.parse_keyword(Keyword::SEPARATOR)
|
||||
{
|
||||
|
|
|
@ -1924,3 +1924,13 @@ fn test_array_agg() {
|
|||
.verified_expr("ARRAY_AGG(DISTINCT state IGNORE NULLS ORDER BY population DESC LIMIT 10)");
|
||||
bigquery_and_generic().verified_expr("ARRAY_CONCAT_AGG(x ORDER BY ARRAY_LENGTH(x))");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_any_value() {
|
||||
bigquery_and_generic().verified_expr("ANY_VALUE(fruit)");
|
||||
bigquery_and_generic().verified_expr(
|
||||
"ANY_VALUE(fruit) OVER (ORDER BY LENGTH(fruit) ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)",
|
||||
);
|
||||
bigquery_and_generic().verified_expr("ANY_VALUE(fruit HAVING MAX sold)");
|
||||
bigquery_and_generic().verified_expr("ANY_VALUE(fruit HAVING MIN sold)");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue