Formatted code

This commit is contained in:
Luca 2025-11-13 20:49:17 +01:00
parent 4d4573900e
commit 4a413197fc
2 changed files with 76 additions and 32 deletions

View file

@ -6434,12 +6434,14 @@ impl<'a> Parser<'a> {
/// Parse an operator name, which can contain special characters like +, -, <, >, =
/// that are tokenized as operator tokens rather than identifiers.
/// This is used for PostgreSQL CREATE OPERATOR statements.
///
///
/// Examples: `+`, `myschema.+`, `pg_catalog.<=`
pub fn parse_operator_name(&mut self) -> Result<ObjectName, ParserError> {
let mut parts = vec![];
loop {
parts.push(ObjectNamePart::Identifier(Ident::new(self.next_token().to_string())));
parts.push(ObjectNamePart::Identifier(Ident::new(
self.next_token().to_string(),
)));
if !self.consume_token(&Token::Period) {
break;
}
@ -6473,38 +6475,57 @@ impl<'a> Parser<'a> {
loop {
let keyword = self.expect_one_of_keywords(&[
Keyword::FUNCTION, Keyword::PROCEDURE, Keyword::LEFTARG, Keyword::RIGHTARG,
Keyword::COMMUTATOR, Keyword::NEGATOR, Keyword::RESTRICT, Keyword::JOIN,
Keyword::HASHES, Keyword::MERGES,
Keyword::FUNCTION,
Keyword::PROCEDURE,
Keyword::LEFTARG,
Keyword::RIGHTARG,
Keyword::COMMUTATOR,
Keyword::NEGATOR,
Keyword::RESTRICT,
Keyword::JOIN,
Keyword::HASHES,
Keyword::MERGES,
])?;
match keyword {
Keyword::HASHES => {
if hashes { return Err(dup_err!("HASHES")); }
if hashes {
return Err(dup_err!("HASHES"));
}
hashes = true;
}
Keyword::MERGES => {
if merges { return Err(dup_err!("MERGES")); }
if merges {
return Err(dup_err!("MERGES"));
}
merges = true;
}
Keyword::FUNCTION | Keyword::PROCEDURE => {
if function.is_some() { return Err(dup_err!("FUNCTION/PROCEDURE")); }
if function.is_some() {
return Err(dup_err!("FUNCTION/PROCEDURE"));
}
self.expect_token(&Token::Eq)?;
function = Some(self.parse_object_name(false)?);
is_procedure = keyword == Keyword::PROCEDURE;
}
Keyword::LEFTARG => {
if left_arg.is_some() { return Err(dup_err!("LEFTARG")); }
if left_arg.is_some() {
return Err(dup_err!("LEFTARG"));
}
self.expect_token(&Token::Eq)?;
left_arg = Some(self.parse_data_type()?);
}
Keyword::RIGHTARG => {
if right_arg.is_some() { return Err(dup_err!("RIGHTARG")); }
if right_arg.is_some() {
return Err(dup_err!("RIGHTARG"));
}
self.expect_token(&Token::Eq)?;
right_arg = Some(self.parse_data_type()?);
}
Keyword::COMMUTATOR => {
if commutator.is_some() { return Err(dup_err!("COMMUTATOR")); }
if commutator.is_some() {
return Err(dup_err!("COMMUTATOR"));
}
self.expect_token(&Token::Eq)?;
if self.parse_keyword(Keyword::OPERATOR) {
self.expect_token(&Token::LParen)?;
@ -6515,7 +6536,9 @@ impl<'a> Parser<'a> {
}
}
Keyword::NEGATOR => {
if negator.is_some() { return Err(dup_err!("NEGATOR")); }
if negator.is_some() {
return Err(dup_err!("NEGATOR"));
}
self.expect_token(&Token::Eq)?;
if self.parse_keyword(Keyword::OPERATOR) {
self.expect_token(&Token::LParen)?;
@ -6526,18 +6549,25 @@ impl<'a> Parser<'a> {
}
}
Keyword::RESTRICT => {
if restrict.is_some() { return Err(dup_err!("RESTRICT")); }
if restrict.is_some() {
return Err(dup_err!("RESTRICT"));
}
self.expect_token(&Token::Eq)?;
restrict = Some(self.parse_object_name(false)?);
}
Keyword::JOIN => {
if join.is_some() { return Err(dup_err!("JOIN")); }
if join.is_some() {
return Err(dup_err!("JOIN"));
}
self.expect_token(&Token::Eq)?;
join = Some(self.parse_object_name(false)?);
}
_ => return Err(ParserError::ParserError(format!(
"Unexpected keyword {:?} in CREATE OPERATOR", keyword
))),
_ => {
return Err(ParserError::ParserError(format!(
"Unexpected keyword {:?} in CREATE OPERATOR",
keyword
)))
}
}
if !self.consume_token(&Token::Comma) {

View file

@ -6710,7 +6710,12 @@ fn parse_create_operator() {
),
] {
match pg().verified_stmt(&format!("CREATE OPERATOR {name} (FUNCTION = f)")) {
Statement::CreateOperator(CreateOperator { name, hashes: false, merges: false, .. }) => {
Statement::CreateOperator(CreateOperator {
name,
hashes: false,
merges: false,
..
}) => {
assert_eq!(name, expected_name);
}
_ => unreachable!(),
@ -6750,14 +6755,18 @@ fn parse_create_operator() {
fn parse_create_operator_family() {
for index_method in &["btree", "hash", "gist", "gin", "spgist", "brin"] {
assert_eq!(
pg().verified_stmt(&format!("CREATE OPERATOR FAMILY my_family USING {index_method}")),
pg().verified_stmt(&format!(
"CREATE OPERATOR FAMILY my_family USING {index_method}"
)),
Statement::CreateOperatorFamily(CreateOperatorFamily {
name: ObjectName::from(vec![Ident::new("my_family")]),
using: Ident::new(*index_method),
})
);
assert_eq!(
pg().verified_stmt(&format!("CREATE OPERATOR FAMILY myschema.test_family USING {index_method}")),
pg().verified_stmt(&format!(
"CREATE OPERATOR FAMILY myschema.test_family USING {index_method}"
)),
Statement::CreateOperatorFamily(CreateOperatorFamily {
name: ObjectName::from(vec![Ident::new("myschema"), Ident::new("test_family")]),
using: Ident::new(*index_method),
@ -6773,7 +6782,10 @@ fn parse_create_operator_class() {
for (has_family, family_clause) in [(false, ""), (true, " FAMILY int4_family")] {
for (class_name, expected_name) in [
("int4_ops", ObjectName::from(vec![Ident::new("int4_ops")])),
("myschema.test_ops", ObjectName::from(vec![Ident::new("myschema"), Ident::new("test_ops")])),
(
"myschema.test_ops",
ObjectName::from(vec![Ident::new("myschema"), Ident::new("test_ops")]),
),
] {
let sql = format!(
"CREATE OPERATOR CLASS {class_name} {default_clause}FOR TYPE INT4 USING btree{family_clause} AS OPERATOR 1 <"
@ -6793,7 +6805,11 @@ fn parse_create_operator_class() {
assert_eq!(using, &Ident::new("btree"));
assert_eq!(
family,
&if has_family { Some(ObjectName::from(vec![Ident::new("int4_family")])) } else { None }
&if has_family {
Some(ObjectName::from(vec![Ident::new("int4_family")]))
} else {
None
}
);
assert_eq!(items.len(), 1);
}
@ -6823,11 +6839,10 @@ fn parse_create_operator_class() {
}
// Test operator with argument types
match pg().verified_stmt("CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING gist AS OPERATOR 1 < (INT4, INT4)") {
Statement::CreateOperatorClass(CreateOperatorClass {
ref items,
..
}) => {
match pg().verified_stmt(
"CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING gist AS OPERATOR 1 < (INT4, INT4)",
) {
Statement::CreateOperatorClass(CreateOperatorClass { ref items, .. }) => {
assert_eq!(items.len(), 1);
match &items[0] {
OperatorClassItem::Operator {
@ -6845,11 +6860,10 @@ fn parse_create_operator_class() {
}
// Test operator FOR SEARCH
match pg().verified_stmt("CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING gist AS OPERATOR 1 < FOR SEARCH") {
Statement::CreateOperatorClass(CreateOperatorClass {
ref items,
..
}) => {
match pg().verified_stmt(
"CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING gist AS OPERATOR 1 < FOR SEARCH",
) {
Statement::CreateOperatorClass(CreateOperatorClass { ref items, .. }) => {
assert_eq!(items.len(), 1);
match &items[0] {
OperatorClassItem::Operator {