Skip to content

Commit 4b4c31b

Browse files
committed
bq: be much more flexible with parsing function args
1 parent 391e685 commit 4b4c31b

2 files changed

Lines changed: 102 additions & 8 deletions

File tree

src/ast/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,13 @@ pub struct Function {
10361036
pub over: Option<WindowSpec>,
10371037
// aggregate functions may specify eg `COUNT(DISTINCT x)`
10381038
pub distinct: bool,
1039+
// bq agg functions can have a whole lot of options, e.g.
1040+
// https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#array_agg
1041+
/// Some(true) for IGNORE NULLS, Some(false) for RESPECT NULLS
1042+
pub ignore_respect_nulls: Option<bool>,
1043+
/// Some(true) for ASC, Some(false) for DESC
1044+
pub order_by: Vec<OrderByExpr>,
1045+
pub limit: Option<Box<Expr>>,
10391046
}
10401047

10411048
impl fmt::Display for Function {

src/parser.rs

Lines changed: 95 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ impl fmt::Display for ParserError {
8282

8383
impl Error for ParserError {}
8484

85+
pub struct FunctionArgsRes {
86+
pub args: Vec<FunctionArg>,
87+
/// Some(true) for IGNORE NULLS, Some(false) for RESPECT NULLS
88+
pub ignore_respect_nulls: Option<bool>,
89+
pub order_by: Vec<OrderByExpr>,
90+
pub limit: Option<Box<Expr>>,
91+
}
92+
8593
pub struct Parser<'a> {
8694
tokens: Vec<Token>,
8795
/// The index of the first unprocessed token in `self.tokens`
@@ -363,7 +371,7 @@ impl<'a> Parser<'a> {
363371
pub fn parse_function(&mut self, name: ObjectName) -> Result<Expr, ParserError> {
364372
self.expect_token(&Token::LParen)?;
365373
let distinct = self.parse_all_or_distinct()?;
366-
let args = self.parse_optional_args()?;
374+
let args_res = self.parse_optional_args()?;
367375
let within_group = if self.parse_keywords(&[Keyword::WITHIN, Keyword::GROUP]) {
368376
self.expect_token(&Token::LParen)?;
369377
self.expect_keywords(&[Keyword::ORDER, Keyword::BY])?;
@@ -406,10 +414,13 @@ impl<'a> Parser<'a> {
406414

407415
Ok(Expr::Function(Function {
408416
name,
409-
args,
417+
args: args_res.args,
410418
within_group,
411419
over,
412420
distinct,
421+
ignore_respect_nulls: args_res.ignore_respect_nulls,
422+
order_by: args_res.order_by,
423+
limit: args_res.limit,
413424
}))
414425
}
415426

@@ -530,6 +541,9 @@ impl<'a> Parser<'a> {
530541
within_group: vec![],
531542
over: None,
532543
distinct: false,
544+
ignore_respect_nulls: None,
545+
order_by: vec![],
546+
limit: None,
533547
}))
534548
}
535549

@@ -2440,7 +2454,8 @@ impl<'a> Parser<'a> {
24402454
if self.parse_keyword(Keyword::LATERAL) {
24412455
if dialect_of!(self is SnowflakeDialect) && self.parse_keyword(Keyword::FLATTEN) {
24422456
self.expect_token(&Token::LParen)?;
2443-
let args = self.parse_optional_args()?;
2457+
let args_res = self.parse_optional_args()?;
2458+
let args = self.strip_func_args_res(args_res)?;
24442459
let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?;
24452460
Ok(TableFactor::Flatten { args, alias })
24462461
} else {
@@ -2544,7 +2559,8 @@ impl<'a> Parser<'a> {
25442559
let name = self.parse_object_name()?;
25452560
// Postgres, MSSQL: table-valued functions:
25462561
let args = if self.consume_token(&Token::LParen) {
2547-
self.parse_optional_args()?
2562+
let args_res = self.parse_optional_args()?;
2563+
self.strip_func_args_res(args_res)?
25482564
} else {
25492565
vec![]
25502566
};
@@ -2670,13 +2686,84 @@ impl<'a> Parser<'a> {
26702686
}
26712687
}
26722688

2673-
pub fn parse_optional_args(&mut self) -> Result<Vec<FunctionArg>, ParserError> {
2689+
pub fn parse_args_end(
2690+
&mut self,
2691+
args: Vec<FunctionArg>,
2692+
must_be_end: bool,
2693+
) -> Result<Option<FunctionArgsRes>, ParserError> {
2694+
let mut is_end = must_be_end;
2695+
let ignore_respect_nulls = if dialect_of!(self is BigQueryDialect) {
2696+
if self.parse_keyword(Keyword::IGNORE) {
2697+
is_end = true;
2698+
Some(true)
2699+
} else if self.parse_keyword(Keyword::RESPECT) {
2700+
is_end = true;
2701+
Some(false)
2702+
} else {
2703+
None
2704+
}
2705+
} else {
2706+
None
2707+
};
2708+
2709+
let order_by = if dialect_of!(self is BigQueryDialect)
2710+
&& self.parse_keywords(&[Keyword::ORDER, Keyword::BY])
2711+
{
2712+
is_end = true;
2713+
self.parse_comma_separated(Parser::parse_order_by_expr)?
2714+
} else {
2715+
vec![]
2716+
};
2717+
2718+
let limit = if dialect_of!(self is BigQueryDialect) && self.parse_keyword(Keyword::LIMIT) {
2719+
is_end = true;
2720+
self.parse_limit()?.map(Box::new)
2721+
} else {
2722+
None
2723+
};
2724+
2725+
if is_end {
2726+
self.expect_token(&Token::RParen)?;
2727+
return Ok(Some(FunctionArgsRes {
2728+
args,
2729+
ignore_respect_nulls,
2730+
order_by,
2731+
limit,
2732+
}));
2733+
}
2734+
26742735
if self.consume_token(&Token::RParen) {
2675-
Ok(vec![])
2736+
Ok(Some(FunctionArgsRes {
2737+
args,
2738+
ignore_respect_nulls,
2739+
order_by,
2740+
limit,
2741+
}))
2742+
} else {
2743+
Ok(None)
2744+
}
2745+
}
2746+
2747+
pub fn strip_func_args_res(
2748+
&mut self,
2749+
args_res: FunctionArgsRes,
2750+
) -> Result<Vec<FunctionArg>, ParserError> {
2751+
if args_res.ignore_respect_nulls.is_some() {
2752+
return parser_err!(self, format!("Unexpected IGNORE|RESPECT NULLS clause"));
2753+
} else if args_res.order_by.len() > 0 {
2754+
return parser_err!(self, format!("Unexpected ORDER BY clause"));
2755+
} else if args_res.limit.is_some() {
2756+
return parser_err!(self, format!("Unexpected LIMIT clause"));
2757+
}
2758+
return Ok(args_res.args);
2759+
}
2760+
2761+
pub fn parse_optional_args(&mut self) -> Result<FunctionArgsRes, ParserError> {
2762+
if let Some(args_res) = self.parse_args_end(vec![], false)? {
2763+
Ok(args_res)
26762764
} else {
26772765
let args = self.parse_comma_separated(Parser::parse_function_args)?;
2678-
self.expect_token(&Token::RParen)?;
2679-
Ok(args)
2766+
Ok(self.parse_args_end(args, true)?.unwrap())
26802767
}
26812768
}
26822769

0 commit comments

Comments
 (0)