From d34dcb3000cd8f17e28d14c40ae268c72a63b050 Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Sun, 25 Oct 2026 20:12:32 +0100 Subject: [PATCH] PostgreSQL: Share operator-purpose parsing --- src/parser/mod.rs | 44 ++++++++++++++----------------------- tests/sqlparser_postgres.rs | 34 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index a14b902e5a..5ecd6e437a 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7992,20 +7992,7 @@ impl<'a> Parser<'a> { None }; - // Optional purpose - let purpose = if self.parse_keyword(Keyword::FOR) { - if self.parse_keyword(Keyword::SEARCH) { - Some(OperatorPurpose::ForSearch) - } else if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) { - let sort_family = self.parse_object_name(false)?; - Some(OperatorPurpose::ForOrderBy { sort_family }) - } else { - return self - .expected_ref("SEARCH or ORDER BY after FOR", self.peek_token_ref()); - } - } else { - None - }; + let purpose = self.parse_operator_purpose()?; items.push(OperatorClassItem::Operator { strategy_number, @@ -12247,6 +12234,21 @@ impl<'a> Parser<'a> { }) } + fn parse_operator_purpose(&mut self) -> Result, ParserError> { + if !self.parse_keyword(Keyword::FOR) { + return Ok(None); + } + + if self.parse_keyword(Keyword::SEARCH) { + Ok(Some(OperatorPurpose::ForSearch)) + } else if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) { + let sort_family = self.parse_object_name(false)?; + Ok(Some(OperatorPurpose::ForOrderBy { sort_family })) + } else { + self.expected_ref("SEARCH or ORDER BY after FOR", self.peek_token_ref()) + } + } + /// Parse an operator item for ALTER OPERATOR FAMILY ADD operations fn parse_operator_family_add_operator(&mut self) -> Result { let strategy_number = self.parse_literal_uint()?; @@ -12257,19 +12259,7 @@ impl<'a> Parser<'a> { let op_types = self.parse_comma_separated(Parser::parse_data_type)?; self.expect_token(&Token::RParen)?; - // Optional purpose - let purpose = if self.parse_keyword(Keyword::FOR) { - if self.parse_keyword(Keyword::SEARCH) { - Some(OperatorPurpose::ForSearch) - } else if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) { - let sort_family = self.parse_object_name(false)?; - Some(OperatorPurpose::ForOrderBy { sort_family }) - } else { - return self.expected_ref("SEARCH or ORDER BY after FOR", self.peek_token_ref()); - } - } else { - None - }; + let purpose = self.parse_operator_purpose()?; Ok(OperatorFamilyItem::Operator { strategy_number, diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index c99a0651aa..74072e9f51 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -11039,3 +11039,37 @@ fn operator_function_display_preserves_empty_operator_types() { assert_eq!(item.to_string(), expected); } } + +#[test] +fn parse_alter_operator_family_order_by_followed_by_search() { + let sql = r#"ALTER OPERATOR FAMILY my_ops USING gist ADD OPERATOR 1 < (INT4, INT4) FOR ORDER BY sort_schema."sort family", OPERATOR 2 > (INT4, INT4) FOR SEARCH"#; + let Statement::AlterOperatorFamily(AlterOperatorFamily { + operation: AlterOperatorFamilyOperation::Add { items }, + .. + }) = pg_and_generic().verified_stmt(sql) + else { + panic!("Expected ALTER OPERATOR FAMILY"); + }; + assert_eq!( + items, + vec![ + OperatorFamilyItem::Operator { + strategy_number: 1, + operator_name: ObjectName::from(vec![Ident::new("<")]), + op_types: vec![DataType::Int4(None), DataType::Int4(None)], + purpose: Some(OperatorPurpose::ForOrderBy { + sort_family: ObjectName::from(vec![ + Ident::new("sort_schema"), + Ident::with_quote('"', "sort family"), + ]), + }), + }, + OperatorFamilyItem::Operator { + strategy_number: 2, + operator_name: ObjectName::from(vec![Ident::new(">")]), + op_types: vec![DataType::Int4(None), DataType::Int4(None)], + purpose: Some(OperatorPurpose::ForSearch), + }, + ] + ); +}