Skip to content

Commit 164e92c

Browse files
committed
review: address feedback — operator name, value spans, parser idioms
- SORTOP now parses via parse_operator_name so bare operators (SORTOP = <) work correctly. - INITCOND / MINITCOND now store ValueWithSpan, preserving source location and matching the rest of the DDL layer. - Replace the hand-rolled option loop with parse_comma_separated, rejecting leading and doubled commas. - Simplify empty arg-list detection (no more prev_token dance). - Replace the PARALLEL match-with-fallthrough with the if/else-if shape used elsewhere in the parser. - Extend the 'after CREATE OR REPLACE' error message to mention AGGREGATE.
1 parent 31adcd6 commit 164e92c

File tree

2 files changed

+26
-44
lines changed

2 files changed

+26
-44
lines changed

src/ast/ddl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5826,7 +5826,7 @@ pub enum CreateAggregateOption {
58265826
/// `DESERIALFUNC = deserial_function`
58275827
Deserialfunc(ObjectName),
58285828
/// `INITCOND = initial_condition` (a string literal)
5829-
Initcond(Value),
5829+
Initcond(ValueWithSpan),
58305830
/// `MSFUNC = moving_state_transition_function`
58315831
Msfunc(ObjectName),
58325832
/// `MINVFUNC = moving_inverse_transition_function`
@@ -5842,7 +5842,7 @@ pub enum CreateAggregateOption {
58425842
/// `MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE }`
58435843
MfinalfuncModify(AggregateModifyKind),
58445844
/// `MINITCOND = moving_initial_condition` (a string literal)
5845-
Minitcond(Value),
5845+
Minitcond(ValueWithSpan),
58465846
/// `SORTOP = sort_operator`
58475847
Sortop(ObjectName),
58485848
/// `PARALLEL = { SAFE | RESTRICTED | UNSAFE }`

src/parser/mod.rs

Lines changed: 24 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5176,7 +5176,7 @@ impl<'a> Parser<'a> {
51765176
self.parse_create_aggregate(or_replace).map(Into::into)
51775177
} else if or_replace {
51785178
self.expected_ref(
5179-
"[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION after CREATE OR REPLACE",
5179+
"[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION or AGGREGATE after CREATE OR REPLACE",
51805180
self.peek_token_ref(),
51815181
)
51825182
} else if self.parse_keyword(Keyword::EXTENSION) {
@@ -7222,36 +7222,22 @@ impl<'a> Parser<'a> {
72227222

72237223
// Argument type list: `(input_data_type [, ...])` or `(*)` for zero-arg.
72247224
self.expect_token(&Token::LParen)?;
7225-
let args = if self.consume_token(&Token::Mul) {
7226-
// zero-argument aggregate written as `(*)` — treat as empty arg list.
7227-
vec![]
7228-
} else if self.consume_token(&Token::RParen) {
7229-
self.prev_token();
7225+
let args = if self.consume_token(&Token::Mul)
7226+
|| self.peek_token().token == Token::RParen
7227+
{
72307228
vec![]
72317229
} else {
72327230
self.parse_comma_separated(|p| p.parse_data_type())?
72337231
};
72347232
self.expect_token(&Token::RParen)?;
72357233

7236-
// Options block: `( SFUNC = ..., STYPE = ..., ... )`
7234+
// Options block: `( SFUNC = ..., STYPE = ..., ... )`.
72377235
self.expect_token(&Token::LParen)?;
7238-
let mut options: Vec<CreateAggregateOption> = Vec::new();
7239-
loop {
7240-
let token = self.next_token();
7241-
match &token.token {
7242-
Token::RParen => break,
7243-
Token::Comma => continue,
7244-
Token::Word(word) => {
7245-
let option = self.parse_create_aggregate_option(&word.value.to_uppercase())?;
7246-
options.push(option);
7247-
}
7248-
other => {
7249-
return Err(ParserError::ParserError(format!(
7250-
"Unexpected token in CREATE AGGREGATE options: {other:?}"
7251-
)));
7252-
}
7253-
}
7254-
}
7236+
let options = self.parse_comma_separated(|parser| {
7237+
let key = parser.parse_identifier()?;
7238+
parser.parse_create_aggregate_option(&key.value.to_uppercase())
7239+
})?;
7240+
self.expect_token(&Token::RParen)?;
72557241

72567242
Ok(CreateAggregate {
72577243
or_replace,
@@ -7312,7 +7298,7 @@ impl<'a> Parser<'a> {
73127298
}
73137299
"INITCOND" => {
73147300
self.expect_token(&Token::Eq)?;
7315-
Ok(CreateAggregateOption::Initcond(self.parse_value()?.value))
7301+
Ok(CreateAggregateOption::Initcond(self.parse_value()?))
73167302
}
73177303
"MSFUNC" => {
73187304
self.expect_token(&Token::Eq)?;
@@ -7350,29 +7336,25 @@ impl<'a> Parser<'a> {
73507336
}
73517337
"MINITCOND" => {
73527338
self.expect_token(&Token::Eq)?;
7353-
Ok(CreateAggregateOption::Minitcond(self.parse_value()?.value))
7339+
Ok(CreateAggregateOption::Minitcond(self.parse_value()?))
73547340
}
73557341
"SORTOP" => {
73567342
self.expect_token(&Token::Eq)?;
7357-
Ok(CreateAggregateOption::Sortop(
7358-
self.parse_object_name(false)?,
7359-
))
7343+
Ok(CreateAggregateOption::Sortop(self.parse_operator_name()?))
73607344
}
73617345
"PARALLEL" => {
73627346
self.expect_token(&Token::Eq)?;
7363-
let parallel = match self.expect_one_of_keywords(&[
7364-
Keyword::SAFE,
7365-
Keyword::RESTRICTED,
7366-
Keyword::UNSAFE,
7367-
])? {
7368-
Keyword::SAFE => FunctionParallel::Safe,
7369-
Keyword::RESTRICTED => FunctionParallel::Restricted,
7370-
Keyword::UNSAFE => FunctionParallel::Unsafe,
7371-
unexpected_keyword => {
7372-
return Err(ParserError::ParserError(format!(
7373-
"Internal parser error: unexpected keyword `{unexpected_keyword}` in PARALLEL"
7374-
)))
7375-
}
7347+
let parallel = if self.parse_keyword(Keyword::SAFE) {
7348+
FunctionParallel::Safe
7349+
} else if self.parse_keyword(Keyword::RESTRICTED) {
7350+
FunctionParallel::Restricted
7351+
} else if self.parse_keyword(Keyword::UNSAFE) {
7352+
FunctionParallel::Unsafe
7353+
} else {
7354+
return self.expected_ref(
7355+
"SAFE, RESTRICTED, or UNSAFE after PARALLEL =",
7356+
self.peek_token_ref(),
7357+
);
73767358
};
73777359
Ok(CreateAggregateOption::Parallel(parallel))
73787360
}

0 commit comments

Comments
 (0)