@@ -5173,6 +5173,8 @@ impl<'a> Parser<'a> {
51735173 self.parse_create_secret(or_replace, temporary, persistent)
51745174 } else if self.parse_keyword(Keyword::USER) {
51755175 self.parse_create_user(or_replace).map(Into::into)
5176+ } else if self.parse_keyword(Keyword::AGGREGATE) {
5177+ self.parse_create_aggregate(or_replace).map(Into::into)
51765178 } else if or_replace {
51775179 self.expected_ref(
51785180 "[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION after CREATE OR REPLACE",
@@ -7210,6 +7212,194 @@ impl<'a> Parser<'a> {
72107212 })
72117213 }
72127214
7215+ /// Parse a [Statement::CreateAggregate]
7216+ ///
7217+ /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createaggregate.html)
7218+ pub fn parse_create_aggregate(
7219+ &mut self,
7220+ or_replace: bool,
7221+ ) -> Result<CreateAggregate, ParserError> {
7222+ let name = self.parse_object_name(false)?;
7223+
7224+ // Argument type list: `(input_data_type [, ...])` or `(*)` for zero-arg.
7225+ self.expect_token(&Token::LParen)?;
7226+ let args = if self.consume_token(&Token::Mul) {
7227+ // zero-argument aggregate written as `(*)` — treat as empty arg list.
7228+ vec![]
7229+ } else if self.consume_token(&Token::RParen) {
7230+ self.prev_token();
7231+ vec![]
7232+ } else {
7233+ let parsed = self.parse_comma_separated(|p| p.parse_data_type())?;
7234+ parsed
7235+ };
7236+ self.expect_token(&Token::RParen)?;
7237+
7238+ // Options block: `( SFUNC = ..., STYPE = ..., ... )`
7239+ self.expect_token(&Token::LParen)?;
7240+ let mut options: Vec<CreateAggregateOption> = Vec::new();
7241+ loop {
7242+ let token = self.next_token();
7243+ match &token.token {
7244+ Token::RParen => break,
7245+ Token::Comma => continue,
7246+ Token::Word(word) => {
7247+ let option = self.parse_create_aggregate_option(&word.value.to_uppercase())?;
7248+ options.push(option);
7249+ }
7250+ other => {
7251+ return Err(ParserError::ParserError(format!(
7252+ "Unexpected token in CREATE AGGREGATE options: {other:?}"
7253+ )));
7254+ }
7255+ }
7256+ }
7257+
7258+ Ok(CreateAggregate {
7259+ or_replace,
7260+ name,
7261+ args,
7262+ options,
7263+ })
7264+ }
7265+
7266+ fn parse_create_aggregate_option(
7267+ &mut self,
7268+ key: &str,
7269+ ) -> Result<CreateAggregateOption, ParserError> {
7270+ match key {
7271+ "SFUNC" => {
7272+ self.expect_token(&Token::Eq)?;
7273+ Ok(CreateAggregateOption::Sfunc(
7274+ self.parse_object_name(false)?,
7275+ ))
7276+ }
7277+ "STYPE" => {
7278+ self.expect_token(&Token::Eq)?;
7279+ Ok(CreateAggregateOption::Stype(self.parse_data_type()?))
7280+ }
7281+ "SSPACE" => {
7282+ self.expect_token(&Token::Eq)?;
7283+ let size = self.parse_literal_uint()?;
7284+ Ok(CreateAggregateOption::Sspace(size))
7285+ }
7286+ "FINALFUNC" => {
7287+ self.expect_token(&Token::Eq)?;
7288+ Ok(CreateAggregateOption::Finalfunc(
7289+ self.parse_object_name(false)?,
7290+ ))
7291+ }
7292+ "FINALFUNC_EXTRA" => Ok(CreateAggregateOption::FinalfuncExtra),
7293+ "FINALFUNC_MODIFY" => {
7294+ self.expect_token(&Token::Eq)?;
7295+ Ok(CreateAggregateOption::FinalfuncModify(
7296+ self.parse_aggregate_modify_kind()?,
7297+ ))
7298+ }
7299+ "COMBINEFUNC" => {
7300+ self.expect_token(&Token::Eq)?;
7301+ Ok(CreateAggregateOption::Combinefunc(
7302+ self.parse_object_name(false)?,
7303+ ))
7304+ }
7305+ "SERIALFUNC" => {
7306+ self.expect_token(&Token::Eq)?;
7307+ Ok(CreateAggregateOption::Serialfunc(
7308+ self.parse_object_name(false)?,
7309+ ))
7310+ }
7311+ "DESERIALFUNC" => {
7312+ self.expect_token(&Token::Eq)?;
7313+ Ok(CreateAggregateOption::Deserialfunc(
7314+ self.parse_object_name(false)?,
7315+ ))
7316+ }
7317+ "INITCOND" => {
7318+ self.expect_token(&Token::Eq)?;
7319+ Ok(CreateAggregateOption::Initcond(self.parse_value()?.value))
7320+ }
7321+ "MSFUNC" => {
7322+ self.expect_token(&Token::Eq)?;
7323+ Ok(CreateAggregateOption::Msfunc(
7324+ self.parse_object_name(false)?,
7325+ ))
7326+ }
7327+ "MINVFUNC" => {
7328+ self.expect_token(&Token::Eq)?;
7329+ Ok(CreateAggregateOption::Minvfunc(
7330+ self.parse_object_name(false)?,
7331+ ))
7332+ }
7333+ "MSTYPE" => {
7334+ self.expect_token(&Token::Eq)?;
7335+ Ok(CreateAggregateOption::Mstype(self.parse_data_type()?))
7336+ }
7337+ "MSSPACE" => {
7338+ self.expect_token(&Token::Eq)?;
7339+ let size = self.parse_literal_uint()?;
7340+ Ok(CreateAggregateOption::Msspace(size))
7341+ }
7342+ "MFINALFUNC" => {
7343+ self.expect_token(&Token::Eq)?;
7344+ Ok(CreateAggregateOption::Mfinalfunc(
7345+ self.parse_object_name(false)?,
7346+ ))
7347+ }
7348+ "MFINALFUNC_EXTRA" => Ok(CreateAggregateOption::MfinalfuncExtra),
7349+ "MFINALFUNC_MODIFY" => {
7350+ self.expect_token(&Token::Eq)?;
7351+ Ok(CreateAggregateOption::MfinalfuncModify(
7352+ self.parse_aggregate_modify_kind()?,
7353+ ))
7354+ }
7355+ "MINITCOND" => {
7356+ self.expect_token(&Token::Eq)?;
7357+ Ok(CreateAggregateOption::Minitcond(self.parse_value()?.value))
7358+ }
7359+ "SORTOP" => {
7360+ self.expect_token(&Token::Eq)?;
7361+ Ok(CreateAggregateOption::Sortop(
7362+ self.parse_object_name(false)?,
7363+ ))
7364+ }
7365+ "PARALLEL" => {
7366+ self.expect_token(&Token::Eq)?;
7367+ let parallel = match self.expect_one_of_keywords(&[
7368+ Keyword::SAFE,
7369+ Keyword::RESTRICTED,
7370+ Keyword::UNSAFE,
7371+ ])? {
7372+ Keyword::SAFE => FunctionParallel::Safe,
7373+ Keyword::RESTRICTED => FunctionParallel::Restricted,
7374+ Keyword::UNSAFE => FunctionParallel::Unsafe,
7375+ _ => unreachable!(),
7376+ };
7377+ Ok(CreateAggregateOption::Parallel(parallel))
7378+ }
7379+ "HYPOTHETICAL" => Ok(CreateAggregateOption::Hypothetical),
7380+ other => Err(ParserError::ParserError(format!(
7381+ "Unknown CREATE AGGREGATE option: {other}"
7382+ ))),
7383+ }
7384+ }
7385+
7386+ fn parse_aggregate_modify_kind(&mut self) -> Result<AggregateModifyKind, ParserError> {
7387+ let token = self.next_token();
7388+ match &token.token {
7389+ Token::Word(word) => match word.value.to_uppercase().as_str() {
7390+ "READ_ONLY" => Ok(AggregateModifyKind::ReadOnly),
7391+ "SHAREABLE" => Ok(AggregateModifyKind::Shareable),
7392+ "READ_WRITE" => Ok(AggregateModifyKind::ReadWrite),
7393+ other => Err(ParserError::ParserError(format!(
7394+ "Expected READ_ONLY, SHAREABLE, or READ_WRITE, got: {other}"
7395+ ))),
7396+ },
7397+ other => Err(ParserError::ParserError(format!(
7398+ "Expected READ_ONLY, SHAREABLE, or READ_WRITE, got: {other:?}"
7399+ ))),
7400+ }
7401+ }
7402+
72137403 /// Parse a [Statement::CreateOperatorFamily]
72147404 ///
72157405 /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createopfamily.html)
0 commit comments