mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-27 07:59:11 +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>.
|
/// See <https://trino.io/docs/current/functions/aggregate.html>.
|
||||||
OnOverflow(ListAggOnOverflow),
|
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.
|
/// 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
|
/// [`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::Limit(limit) => write!(f, "LIMIT {limit}"),
|
||||||
FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
|
FunctionArgumentClause::OnOverflow(on_overflow) => write!(f, "{on_overflow}"),
|
||||||
|
FunctionArgumentClause::Having(bound) => write!(f, "{bound}"),
|
||||||
FunctionArgumentClause::Separator(sep) => write!(f, "SEPARATOR {sep}"),
|
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)]
|
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
|
|
@ -9534,6 +9534,20 @@ impl<'a> Parser<'a> {
|
||||||
clauses.push(FunctionArgumentClause::Limit(self.parse_expr()?));
|
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)
|
if dialect_of!(self is GenericDialect | MySqlDialect)
|
||||||
&& self.parse_keyword(Keyword::SEPARATOR)
|
&& 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)");
|
.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))");
|
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