Skip to content

Commit bd6d624

Browse files
committed
Add OR ALTER support for CREATE TRIGGER
1 parent 761cb24 commit bd6d624

File tree

5 files changed

+99
-4
lines changed

5 files changed

+99
-4
lines changed

src/ast/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3626,6 +3626,10 @@ pub enum Statement {
36263626
/// Postgres: <https://www.postgresql.org/docs/current/sql-createtrigger.html>
36273627
/// SQL Server: <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql>
36283628
CreateTrigger {
3629+
/// True if this is a `CREATE OR ALTER TRIGGER` statement
3630+
///
3631+
/// [Mssql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16#arguments)
3632+
or_alter: bool,
36293633
/// The `OR REPLACE` clause is used to re-create the trigger if it already exists.
36303634
///
36313635
/// Example:
@@ -4482,6 +4486,7 @@ impl fmt::Display for Statement {
44824486
}
44834487
Statement::CreateFunction(create_function) => create_function.fmt(f),
44844488
Statement::CreateTrigger {
4489+
or_alter,
44854490
or_replace,
44864491
is_constraint,
44874492
name,
@@ -4499,7 +4504,8 @@ impl fmt::Display for Statement {
44994504
} => {
45004505
write!(
45014506
f,
4502-
"CREATE {or_replace}{is_constraint}TRIGGER {name} {period}",
4507+
"CREATE {or_alter}{or_replace}{is_constraint}TRIGGER {name} {period}",
4508+
or_alter = if *or_alter { "OR ALTER " } else { "" },
45034509
or_replace = if *or_replace { "OR REPLACE " } else { "" },
45044510
is_constraint = if *is_constraint { "CONSTRAINT " } else { "" },
45054511
)?;

src/parser/mod.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4558,9 +4558,9 @@ impl<'a> Parser<'a> {
45584558
} else if self.parse_keyword(Keyword::FUNCTION) {
45594559
self.parse_create_function(or_alter, or_replace, temporary)
45604560
} else if self.parse_keyword(Keyword::TRIGGER) {
4561-
self.parse_create_trigger(or_replace, false)
4561+
self.parse_create_trigger(or_alter, or_replace, false)
45624562
} else if self.parse_keywords(&[Keyword::CONSTRAINT, Keyword::TRIGGER]) {
4563-
self.parse_create_trigger(or_replace, true)
4563+
self.parse_create_trigger(or_alter, or_replace, true)
45644564
} else if self.parse_keyword(Keyword::MACRO) {
45654565
self.parse_create_macro(or_replace, temporary)
45664566
} else if self.parse_keyword(Keyword::SECRET) {
@@ -5263,6 +5263,7 @@ impl<'a> Parser<'a> {
52635263

52645264
pub fn parse_create_trigger(
52655265
&mut self,
5266+
or_alter: bool,
52665267
or_replace: bool,
52675268
is_constraint: bool,
52685269
) -> Result<Statement, ParserError> {
@@ -5272,7 +5273,7 @@ impl<'a> Parser<'a> {
52725273
}
52735274

52745275
if dialect_of!(self is MsSqlDialect) {
5275-
return self.parse_mssql_create_trigger(or_replace, is_constraint);
5276+
return self.parse_mssql_create_trigger(or_alter, or_replace, is_constraint);
52765277
}
52775278

52785279
let name = self.parse_object_name(false)?;
@@ -5316,6 +5317,7 @@ impl<'a> Parser<'a> {
53165317
let exec_body = self.parse_trigger_exec_body()?;
53175318

53185319
Ok(Statement::CreateTrigger {
5320+
or_alter,
53195321
or_replace,
53205322
is_constraint,
53215323
name,
@@ -5338,6 +5340,7 @@ impl<'a> Parser<'a> {
53385340
/// [Mssql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql
53395341
pub fn parse_mssql_create_trigger(
53405342
&mut self,
5343+
or_alter: bool,
53415344
or_replace: bool,
53425345
is_constraint: bool,
53435346
) -> Result<Statement, ParserError> {
@@ -5364,6 +5367,7 @@ impl<'a> Parser<'a> {
53645367
};
53655368

53665369
Ok(Statement::CreateTrigger {
5370+
or_alter,
53675371
or_replace,
53685372
is_constraint,
53695373
name,

tests/sqlparser_mssql.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,7 @@ fn parse_create_trigger() {
22762276
assert_eq!(
22772277
create_stmt,
22782278
Statement::CreateTrigger {
2279+
or_alter: false,
22792280
or_replace: false,
22802281
is_constraint: false,
22812282
name: ObjectName::from(vec![Ident::new("reminder1")]),
@@ -2319,6 +2320,7 @@ fn parse_create_trigger() {
23192320
assert_eq!(
23202321
create_stmt,
23212322
Statement::CreateTrigger {
2323+
or_alter: false,
23222324
or_replace: false,
23232325
is_constraint: false,
23242326
name: ObjectName::from(vec![Ident::new("some_trigger")]),
@@ -2359,6 +2361,82 @@ fn parse_create_trigger() {
23592361
assert_eq!(
23602362
create_stmt,
23612363
Statement::CreateTrigger {
2364+
or_alter: false,
2365+
or_replace: false,
2366+
is_constraint: false,
2367+
name: ObjectName::from(vec![Ident::new("some_trigger")]),
2368+
period: TriggerPeriod::For,
2369+
events: vec![TriggerEvent::Insert],
2370+
table_name: ObjectName::from(vec![Ident::new("some_table")]),
2371+
referenced_table_name: None,
2372+
referencing: vec![],
2373+
trigger_object: TriggerObject::Statement,
2374+
include_each: false,
2375+
condition: None,
2376+
exec_body: None,
2377+
statements: vec![Statement::Return(ReturnStatement {
2378+
value: None,
2379+
})],
2380+
characteristics: None,
2381+
}
2382+
);
2383+
}
2384+
2385+
#[test]
2386+
fn parse_mssql_create_trigger() {
2387+
let create_or_alter_trigger = r#"
2388+
CREATE OR ALTER TRIGGER some_trigger ON some_table FOR INSERT
2389+
AS
2390+
BEGIN
2391+
RAISERROR('Trigger fired', 10, 1)
2392+
END
2393+
"#;
2394+
let create_stmt = ms().one_statement_parses_to(create_or_alter_trigger, "");
2395+
assert_eq!(
2396+
create_stmt,
2397+
Statement::CreateTrigger {
2398+
or_alter: true,
2399+
or_replace: false,
2400+
is_constraint: false,
2401+
name: ObjectName::from(vec![Ident::new("some_trigger")]),
2402+
period: TriggerPeriod::For,
2403+
events: vec![TriggerEvent::Insert],
2404+
table_name: ObjectName::from(vec![Ident::new("some_table")]),
2405+
referenced_table_name: None,
2406+
referencing: vec![],
2407+
trigger_object: TriggerObject::Statement,
2408+
include_each: false,
2409+
condition: None,
2410+
exec_body: None,
2411+
statements: vec![Statement::RaisError {
2412+
message: Box::new(Expr::Value(
2413+
(Value::SingleQuotedString("Trigger fired".to_string())).with_empty_span()
2414+
)),
2415+
severity: Box::new(Expr::Value(
2416+
(Value::Number("10".parse().unwrap(), false)).with_empty_span()
2417+
)),
2418+
state: Box::new(Expr::Value(
2419+
(Value::Number("1".parse().unwrap(), false)).with_empty_span()
2420+
)),
2421+
arguments: vec![],
2422+
options: vec![],
2423+
}],
2424+
characteristics: None,
2425+
}
2426+
);
2427+
2428+
let create_trigger_with_return = r#"
2429+
CREATE TRIGGER some_trigger ON some_table FOR INSERT
2430+
AS
2431+
BEGIN
2432+
RETURN;
2433+
END
2434+
"#;
2435+
let create_stmt = ms().one_statement_parses_to(create_trigger_with_return, "");
2436+
assert_eq!(
2437+
create_stmt,
2438+
Statement::CreateTrigger {
2439+
or_alter: false,
23622440
or_replace: false,
23632441
is_constraint: false,
23642442
name: ObjectName::from(vec![Ident::new("some_trigger")]),

tests/sqlparser_mysql.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3399,6 +3399,7 @@ fn parse_create_trigger() {
33993399
assert_eq!(
34003400
create_stmt,
34013401
Statement::CreateTrigger {
3402+
or_alter: false,
34023403
or_replace: false,
34033404
is_constraint: false,
34043405
name: ObjectName::from(vec![Ident::new("emp_stamp")]),

tests/sqlparser_postgres.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5049,6 +5049,7 @@ fn test_escaped_string_literal() {
50495049
fn parse_create_simple_before_insert_trigger() {
50505050
let sql = "CREATE TRIGGER check_insert BEFORE INSERT ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_insert";
50515051
let expected = Statement::CreateTrigger {
5052+
or_alter: false,
50525053
or_replace: false,
50535054
is_constraint: false,
50545055
name: ObjectName::from(vec![Ident::new("check_insert")]),
@@ -5078,6 +5079,7 @@ fn parse_create_simple_before_insert_trigger() {
50785079
fn parse_create_after_update_trigger_with_condition() {
50795080
let sql = "CREATE TRIGGER check_update AFTER UPDATE ON accounts FOR EACH ROW WHEN (NEW.balance > 10000) EXECUTE FUNCTION check_account_update";
50805081
let expected = Statement::CreateTrigger {
5082+
or_alter: false,
50815083
or_replace: false,
50825084
is_constraint: false,
50835085
name: ObjectName::from(vec![Ident::new("check_update")]),
@@ -5114,6 +5116,7 @@ fn parse_create_after_update_trigger_with_condition() {
51145116
fn parse_create_instead_of_delete_trigger() {
51155117
let sql = "CREATE TRIGGER check_delete INSTEAD OF DELETE ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_deletes";
51165118
let expected = Statement::CreateTrigger {
5119+
or_alter: false,
51175120
or_replace: false,
51185121
is_constraint: false,
51195122
name: ObjectName::from(vec![Ident::new("check_delete")]),
@@ -5143,6 +5146,7 @@ fn parse_create_instead_of_delete_trigger() {
51435146
fn parse_create_trigger_with_multiple_events_and_deferrable() {
51445147
let sql = "CREATE CONSTRAINT TRIGGER check_multiple_events BEFORE INSERT OR UPDATE OR DELETE ON accounts DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION check_account_changes";
51455148
let expected = Statement::CreateTrigger {
5149+
or_alter: false,
51465150
or_replace: false,
51475151
is_constraint: true,
51485152
name: ObjectName::from(vec![Ident::new("check_multiple_events")]),
@@ -5180,6 +5184,7 @@ fn parse_create_trigger_with_multiple_events_and_deferrable() {
51805184
fn parse_create_trigger_with_referencing() {
51815185
let sql = "CREATE TRIGGER check_referencing BEFORE INSERT ON accounts REFERENCING NEW TABLE AS new_accounts OLD TABLE AS old_accounts FOR EACH ROW EXECUTE FUNCTION check_account_referencing";
51825186
let expected = Statement::CreateTrigger {
5187+
or_alter: false,
51835188
or_replace: false,
51845189
is_constraint: false,
51855190
name: ObjectName::from(vec![Ident::new("check_referencing")]),
@@ -5492,6 +5497,7 @@ fn parse_trigger_related_functions() {
54925497
assert_eq!(
54935498
create_trigger,
54945499
Statement::CreateTrigger {
5500+
or_alter: false,
54955501
or_replace: false,
54965502
is_constraint: false,
54975503
name: ObjectName::from(vec![Ident::new("emp_stamp")]),

0 commit comments

Comments
 (0)