@@ -6431,32 +6431,33 @@ impl<'a> Parser<'a> {
64316431 }))
64326432 }
64336433
6434- /// Helper function to parse an operator name (which can contain special characters)
6435- /// Operator names can be schema-qualified (e.g., schema.operator)
6436- fn parse_operator_name(&mut self) -> Result<ObjectName, ParserError> {
6437- let mut name_parts = vec![];
6434+ /// Parse an operator name, which can contain special characters like +, -, <, >, =
6435+ /// that are tokenized as operator tokens rather than identifiers.
6436+ /// This is used for PostgreSQL CREATE OPERATOR statements.
6437+ ///
6438+ /// Examples: `+`, `myschema.+`, `pg_catalog.<=`
6439+ pub fn parse_operator_name(&mut self) -> Result<ObjectName, ParserError> {
6440+ let mut parts = vec![];
64386441 loop {
6439- let token = self.next_token();
6440- let part = ObjectNamePart::Identifier(Ident::new(token.to_string()));
6441- name_parts.push(part);
6442-
6442+ parts.push(ObjectNamePart::Identifier(Ident::new(self.next_token().to_string())));
64436443 if !self.consume_token(&Token::Period) {
64446444 break;
64456445 }
64466446 }
6447- Ok(ObjectName(name_parts ))
6447+ Ok(ObjectName(parts ))
64486448 }
64496449
64506450 /// Parse a `CREATE OPERATOR` statement
64516451 ///
64526452 /// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createoperator.html)
64536453 pub fn parse_create_operator(&mut self) -> Result<Statement, ParserError> {
6454- // Parse the operator name (can be schema-qualified)
6455- // Operators can contain special characters like +, -, *, /, <, >, =, ~, !, @, #, %, ^, &, |, `, ?
6456- // See https://www.postgresql.org/docs/current/sql-createoperator.html
6457- let name = self.parse_operator_name()?;
6454+ macro_rules! dup_err {
6455+ ($name:expr) => {
6456+ ParserError::ParserError(format!("Duplicate {} clause in CREATE OPERATOR", $name))
6457+ };
6458+ }
64586459
6459- // Expect opening parenthesis
6460+ let name = self.parse_operator_name()?;
64606461 self.expect_token(&Token::LParen)?;
64616462
64626463 let mut function: Option<ObjectName> = None;
@@ -6471,82 +6472,74 @@ impl<'a> Parser<'a> {
64716472 let mut merges = false;
64726473
64736474 loop {
6474- // Parse parameter name as keyword
64756475 let keyword = self.expect_one_of_keywords(&[
6476- Keyword::FUNCTION,
6477- Keyword::PROCEDURE,
6478- Keyword::LEFTARG,
6479- Keyword::RIGHTARG,
6480- Keyword::COMMUTATOR,
6481- Keyword::NEGATOR,
6482- Keyword::RESTRICT,
6483- Keyword::JOIN,
6484- Keyword::HASHES,
6485- Keyword::MERGES,
6476+ Keyword::FUNCTION, Keyword::PROCEDURE, Keyword::LEFTARG, Keyword::RIGHTARG,
6477+ Keyword::COMMUTATOR, Keyword::NEGATOR, Keyword::RESTRICT, Keyword::JOIN,
6478+ Keyword::HASHES, Keyword::MERGES,
64866479 ])?;
64876480
6488- // Check if this is a flag (HASHES or MERGES) - no '=' expected
64896481 match keyword {
64906482 Keyword::HASHES => {
6483+ if hashes { return Err(dup_err!("HASHES")); }
64916484 hashes = true;
64926485 }
64936486 Keyword::MERGES => {
6487+ if merges { return Err(dup_err!("MERGES")); }
64946488 merges = true;
64956489 }
64966490 Keyword::FUNCTION | Keyword::PROCEDURE => {
6491+ if function.is_some() { return Err(dup_err!("FUNCTION/PROCEDURE")); }
64976492 self.expect_token(&Token::Eq)?;
6498- let func_name = self.parse_object_name(false)?;
6499- function = Some(func_name);
6493+ function = Some(self.parse_object_name(false)?);
65006494 is_procedure = keyword == Keyword::PROCEDURE;
65016495 }
65026496 Keyword::LEFTARG => {
6497+ if left_arg.is_some() { return Err(dup_err!("LEFTARG")); }
65036498 self.expect_token(&Token::Eq)?;
6504- let data_type = self.parse_data_type()?;
6505- left_arg = Some(data_type);
6499+ left_arg = Some(self.parse_data_type()?);
65066500 }
65076501 Keyword::RIGHTARG => {
6502+ if right_arg.is_some() { return Err(dup_err!("RIGHTARG")); }
65086503 self.expect_token(&Token::Eq)?;
6509- let data_type = self.parse_data_type()?;
6510- right_arg = Some(data_type);
6504+ right_arg = Some(self.parse_data_type()?);
65116505 }
65126506 Keyword::COMMUTATOR => {
6507+ if commutator.is_some() { return Err(dup_err!("COMMUTATOR")); }
65136508 self.expect_token(&Token::Eq)?;
6514- let op_name = if self.parse_keyword(Keyword::OPERATOR) {
6509+ if self.parse_keyword(Keyword::OPERATOR) {
65156510 self.expect_token(&Token::LParen)?;
6516- let op = self.parse_operator_name()?;
6511+ commutator = Some( self.parse_operator_name()?) ;
65176512 self.expect_token(&Token::RParen)?;
6518- op
65196513 } else {
6520- self.parse_operator_name()?
6521- };
6522- commutator = Some(op_name);
6514+ commutator = Some(self.parse_operator_name()?);
6515+ }
65236516 }
65246517 Keyword::NEGATOR => {
6518+ if negator.is_some() { return Err(dup_err!("NEGATOR")); }
65256519 self.expect_token(&Token::Eq)?;
6526- let op_name = if self.parse_keyword(Keyword::OPERATOR) {
6520+ if self.parse_keyword(Keyword::OPERATOR) {
65276521 self.expect_token(&Token::LParen)?;
6528- let op = self.parse_operator_name()?;
6522+ negator = Some( self.parse_operator_name()?) ;
65296523 self.expect_token(&Token::RParen)?;
6530- op
65316524 } else {
6532- self.parse_operator_name()?
6533- };
6534- negator = Some(op_name);
6525+ negator = Some(self.parse_operator_name()?);
6526+ }
65356527 }
65366528 Keyword::RESTRICT => {
6529+ if restrict.is_some() { return Err(dup_err!("RESTRICT")); }
65376530 self.expect_token(&Token::Eq)?;
6538- let func_name = self.parse_object_name(false)?;
6539- restrict = Some(func_name);
6531+ restrict = Some(self.parse_object_name(false)?);
65406532 }
65416533 Keyword::JOIN => {
6534+ if join.is_some() { return Err(dup_err!("JOIN")); }
65426535 self.expect_token(&Token::Eq)?;
6543- let func_name = self.parse_object_name(false)?;
6544- join = Some(func_name);
6536+ join = Some(self.parse_object_name(false)?);
65456537 }
6546- _ => unreachable!("unexpected keyword in CREATE OPERATOR"),
6538+ _ => return Err(ParserError::ParserError(format!(
6539+ "Unexpected keyword {:?} in CREATE OPERATOR", keyword
6540+ ))),
65476541 }
65486542
6549- // Check for comma or closing parenthesis
65506543 if !self.consume_token(&Token::Comma) {
65516544 break;
65526545 }
0 commit comments