diff --git a/fuzz/fuzz_seeds/postgres_alter_extension.sql b/fuzz/fuzz_seeds/postgres_alter_extension.sql index 20931ac0fd..aeb19f1ff8 100644 --- a/fuzz/fuzz_seeds/postgres_alter_extension.sql +++ b/fuzz/fuzz_seeds/postgres_alter_extension.sql @@ -34,3 +34,4 @@ ALTER EXTENSION citext ADD AGGREGATE cnt(*); ALTER EXTENSION citext ADD OPERATOR - (NONE, int); ALTER EXTENSION citext DROP OPERATOR CLASS oc USING btree; ALTER EXTENSION citext DROP OPERATOR FAMILY of USING btree; +ALTER EXTENSION citext ADD CAST (int AS text); diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 01d6c392c8..074f8f55e5 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -4934,6 +4934,13 @@ pub enum AlterExtensionMember { AccessMethod(Ident), /// `AGGREGATE aggregate_name ( aggregate_signature )` Aggregate(AggregateSignature), + /// `CAST (source_type AS target_type)` + Cast { + /// Source type. + source_type: DataType, + /// Target type. + target_type: DataType, + }, /// `COLLATION object_name` Collation(ObjectName), /// `CONVERSION object_name` @@ -5035,6 +5042,10 @@ impl fmt::Display for AlterExtensionMember { match self { AlterExtensionMember::AccessMethod(name) => write!(f, "ACCESS METHOD {name}"), AlterExtensionMember::Aggregate(signature) => write!(f, "AGGREGATE {signature}"), + AlterExtensionMember::Cast { + source_type, + target_type, + } => write!(f, "CAST ({source_type} AS {target_type})"), AlterExtensionMember::Collation(name) => write!(f, "COLLATION {name}"), AlterExtensionMember::Conversion(name) => write!(f, "CONVERSION {name}"), AlterExtensionMember::Database(name) => write!(f, "DATABASE {name}"), diff --git a/src/parser/mod.rs b/src/parser/mod.rs index cd78d41dbc..19e9444594 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -12536,6 +12536,16 @@ impl<'a> Parser<'a> { Ok(AlterExtensionMember::Aggregate( self.parse_alter_aggregate_signature()?, )) + } else if self.parse_keyword(Keyword::CAST) { + self.expect_token(&Token::LParen)?; + let source_type = self.parse_data_type()?; + self.expect_keyword_is(Keyword::AS)?; + let target_type = self.parse_data_type()?; + self.expect_token(&Token::RParen)?; + Ok(AlterExtensionMember::Cast { + source_type, + target_type, + }) } else if self.parse_keyword(Keyword::COLLATION) { Ok(AlterExtensionMember::Collation( self.parse_object_name(false)?, diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index dc86429746..3d816c7af1 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -13541,6 +13541,8 @@ fn alter_extension_member_round_trip_forms(action: &str) { format!("ALTER EXTENSION ext_name {action} AGGREGATE agg(IN INT)"), format!("ALTER EXTENSION ext_name {action} AGGREGATE agg(ORDER BY TEXT)"), format!("ALTER EXTENSION ext_name {action} AGGREGATE agg(INT ORDER BY TEXT)"), + format!("ALTER EXTENSION ext_name {action} CAST (INT AS TEXT)"), + format!("ALTER EXTENSION ext_name {action} CAST (src AS tgt)"), format!("ALTER EXTENSION ext_name {action} COLLATION en_US"), format!("ALTER EXTENSION ext_name {action} COLLATION schema.en_US"), format!("ALTER EXTENSION ext_name {action} CONVERSION conv"), @@ -13739,6 +13741,27 @@ fn parse_alter_extension_add_member() { }) ); + match pg_and_generic().verified_stmt("ALTER EXTENSION ext_name ADD CAST (src AS tgt)") { + Statement::AlterExtension(AlterExtension { + operation: + AlterExtensionOperation::Add(AlterExtensionMember::Cast { + source_type, + target_type, + }), + .. + }) => { + assert_eq!( + source_type, + DataType::Custom(ObjectName::from(Ident::new("src")), vec![]) + ); + assert_eq!( + target_type, + DataType::Custom(ObjectName::from(Ident::new("tgt")), vec![]) + ); + } + other => panic!("unexpected statement: {other:?}"), + } + match pg_and_generic().verified_stmt("ALTER EXTENSION ext_name ADD FUNCTION f(INT)") { Statement::AlterExtension(AlterExtension { operation: AlterExtensionOperation::Add(AlterExtensionMember::Function(function)), @@ -13807,6 +13830,10 @@ fn parse_alter_extension_add_member() { "ALTER EXTENSION ext_name ADD ROUTINE 1", "Expected: identifier, found: 1", ), + ( + "ALTER EXTENSION ext_name ADD CAST (INT)", + "Expected: AS, found: )", + ), ( "ALTER EXTENSION ext_name ADD OPERATOR +", "Expected: (, found: EOF", @@ -13819,6 +13846,22 @@ fn parse_alter_extension_add_member() { "ALTER EXTENSION ext_name ADD OPERATOR CLASS oc USING", "Expected: identifier, found: EOF", ), + ( + "ALTER EXTENSION ext_name ADD CAST", + "Expected: (, found: EOF", + ), + ( + "ALTER EXTENSION ext_name ADD CAST (1)", + "Expected: a data type name, found: 1", + ), + ( + "ALTER EXTENSION ext_name ADD CAST (INT AS)", + "Expected: a data type name, found: )", + ), + ( + "ALTER EXTENSION ext_name ADD CAST (INT AS INT", + "Expected: ), found: EOF", + ), ( "ALTER EXTENSION ext_name ADD OPERATOR CLASS", "Expected: identifier, found: EOF",