Skip to content

Commit 9292c63

Browse files
committed
Add OR ALTER support for CREATE TRIGGER
1 parent 74148fe commit 9292c63

File tree

5 files changed

+98
-4
lines changed

5 files changed

+98
-4
lines changed

src/ast/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3648,6 +3648,10 @@ pub enum Statement {
36483648
/// Postgres: <https://www.postgresql.org/docs/current/sql-createtrigger.html>
36493649
/// SQL Server: <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql>
36503650
CreateTrigger {
3651+
/// True if this is a `CREATE OR ALTER TRIGGER` statement
3652+
///
3653+
/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16#arguments)
3654+
or_alter: bool,
36513655
/// The `OR REPLACE` clause is used to re-create the trigger if it already exists.
36523656
///
36533657
/// Example:
@@ -4504,6 +4508,7 @@ impl fmt::Display for Statement {
45044508
}
45054509
Statement::CreateFunction(create_function) => create_function.fmt(f),
45064510
Statement::CreateTrigger {
4511+
or_alter,
45074512
or_replace,
45084513
is_constraint,
45094514
name,
@@ -4521,7 +4526,8 @@ impl fmt::Display for Statement {
45214526
} => {
45224527
write!(
45234528
f,
4524-
"CREATE {or_replace}{is_constraint}TRIGGER {name} {period}",
4529+
"CREATE {or_alter}{or_replace}{is_constraint}TRIGGER {name} {period}",
4530+
or_alter = if *or_alter { "OR ALTER " } else { "" },
45254531
or_replace = if *or_replace { "OR REPLACE " } else { "" },
45264532
is_constraint = if *is_constraint { "CONSTRAINT " } else { "" },
45274533
)?;

src/parser/mod.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4572,9 +4572,9 @@ impl<'a> Parser<'a> {
45724572
} else if self.parse_keyword(Keyword::FUNCTION) {
45734573
self.parse_create_function(or_alter, or_replace, temporary)
45744574
} else if self.parse_keyword(Keyword::TRIGGER) {
4575-
self.parse_create_trigger(or_replace, false)
4575+
self.parse_create_trigger(or_alter, or_replace, false)
45764576
} else if self.parse_keywords(&[Keyword::CONSTRAINT, Keyword::TRIGGER]) {
4577-
self.parse_create_trigger(or_replace, true)
4577+
self.parse_create_trigger(or_alter, or_replace, true)
45784578
} else if self.parse_keyword(Keyword::MACRO) {
45794579
self.parse_create_macro(or_replace, temporary)
45804580
} else if self.parse_keyword(Keyword::SECRET) {
@@ -5275,6 +5275,7 @@ impl<'a> Parser<'a> {
52755275

52765276
pub fn parse_create_trigger(
52775277
&mut self,
5278+
or_alter: bool,
52785279
or_replace: bool,
52795280
is_constraint: bool,
52805281
) -> Result<Statement, ParserError> {
@@ -5284,7 +5285,7 @@ impl<'a> Parser<'a> {
52845285
}
52855286

52865287
if dialect_of!(self is MsSqlDialect) {
5287-
return self.parse_mssql_create_trigger(or_replace, is_constraint);
5288+
return self.parse_mssql_create_trigger(or_alter, or_replace, is_constraint);
52885289
}
52895290

52905291
let name = self.parse_object_name(false)?;
@@ -5328,6 +5329,7 @@ impl<'a> Parser<'a> {
53285329
let exec_body = self.parse_trigger_exec_body()?;
53295330

53305331
Ok(Statement::CreateTrigger {
5332+
or_alter,
53315333
or_replace,
53325334
is_constraint,
53335335
name,
@@ -5350,6 +5352,7 @@ impl<'a> Parser<'a> {
53505352
/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql
53515353
pub fn parse_mssql_create_trigger(
53525354
&mut self,
5355+
or_alter: bool,
53535356
or_replace: bool,
53545357
is_constraint: bool,
53555358
) -> Result<Statement, ParserError> {
@@ -5371,6 +5374,7 @@ impl<'a> Parser<'a> {
53715374
};
53725375

53735376
Ok(Statement::CreateTrigger {
5377+
or_alter,
53745378
or_replace,
53755379
is_constraint,
53765380
name,

tests/sqlparser_mssql.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,6 +2432,7 @@ fn parse_create_trigger() {
24322432
assert_eq!(
24332433
create_stmt,
24342434
Statement::CreateTrigger {
2435+
or_alter: false,
24352436
or_replace: false,
24362437
is_constraint: false,
24372438
name: ObjectName::from(vec![Ident::new("reminder1")]),
@@ -2473,6 +2474,7 @@ fn parse_create_trigger() {
24732474
assert_eq!(
24742475
create_stmt,
24752476
Statement::CreateTrigger {
2477+
or_alter: false,
24762478
or_replace: false,
24772479
is_constraint: false,
24782480
name: ObjectName::from(vec![Ident::new("some_trigger")]),
@@ -2513,6 +2515,80 @@ fn parse_create_trigger() {
25132515
assert_eq!(
25142516
create_stmt,
25152517
Statement::CreateTrigger {
2518+
or_alter: false,
2519+
or_replace: false,
2520+
is_constraint: false,
2521+
name: ObjectName::from(vec![Ident::new("some_trigger")]),
2522+
period: TriggerPeriod::For,
2523+
events: vec![TriggerEvent::Insert],
2524+
table_name: ObjectName::from(vec![Ident::new("some_table")]),
2525+
referenced_table_name: None,
2526+
referencing: vec![],
2527+
trigger_object: TriggerObject::Statement,
2528+
include_each: false,
2529+
condition: None,
2530+
exec_body: None,
2531+
statements: Some(vec![Statement::Return(ReturnStatement { value: None })]),
2532+
characteristics: None,
2533+
}
2534+
);
2535+
}
2536+
2537+
#[test]
2538+
fn parse_mssql_create_trigger() {
2539+
let create_or_alter_trigger = r#"
2540+
CREATE OR ALTER TRIGGER some_trigger ON some_table FOR INSERT
2541+
AS
2542+
BEGIN
2543+
RAISERROR('Trigger fired', 10, 1);
2544+
END
2545+
"#;
2546+
let create_stmt = ms().one_statement_parses_to(create_or_alter_trigger, "");
2547+
assert_eq!(
2548+
create_stmt,
2549+
Statement::CreateTrigger {
2550+
or_alter: true,
2551+
or_replace: false,
2552+
is_constraint: false,
2553+
name: ObjectName::from(vec![Ident::new("some_trigger")]),
2554+
period: TriggerPeriod::For,
2555+
events: vec![TriggerEvent::Insert],
2556+
table_name: ObjectName::from(vec![Ident::new("some_table")]),
2557+
referenced_table_name: None,
2558+
referencing: vec![],
2559+
trigger_object: TriggerObject::Statement,
2560+
include_each: false,
2561+
condition: None,
2562+
exec_body: None,
2563+
statements: Some(vec![Statement::RaisError {
2564+
message: Box::new(Expr::Value(
2565+
(Value::SingleQuotedString("Trigger fired".to_string())).with_empty_span()
2566+
)),
2567+
severity: Box::new(Expr::Value(
2568+
(Value::Number("10".parse().unwrap(), false)).with_empty_span()
2569+
)),
2570+
state: Box::new(Expr::Value(
2571+
(Value::Number("1".parse().unwrap(), false)).with_empty_span()
2572+
)),
2573+
arguments: vec![],
2574+
options: vec![],
2575+
}]),
2576+
characteristics: None,
2577+
}
2578+
);
2579+
2580+
let create_trigger_with_return = r#"
2581+
CREATE TRIGGER some_trigger ON some_table FOR INSERT
2582+
AS
2583+
BEGIN
2584+
RETURN;
2585+
END
2586+
"#;
2587+
let create_stmt = ms().one_statement_parses_to(create_trigger_with_return, "");
2588+
assert_eq!(
2589+
create_stmt,
2590+
Statement::CreateTrigger {
2591+
or_alter: false,
25162592
or_replace: false,
25172593
is_constraint: false,
25182594
name: ObjectName::from(vec![Ident::new("some_trigger")]),
@@ -2546,6 +2622,7 @@ fn parse_create_trigger() {
25462622
assert_eq!(
25472623
create_stmt,
25482624
Statement::CreateTrigger {
2625+
or_alter: false,
25492626
or_replace: false,
25502627
is_constraint: false,
25512628
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
@@ -3521,6 +3521,7 @@ fn parse_create_trigger() {
35213521
assert_eq!(
35223522
create_stmt,
35233523
Statement::CreateTrigger {
3524+
or_alter: false,
35243525
or_replace: false,
35253526
is_constraint: false,
35263527
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
@@ -5084,6 +5084,7 @@ fn test_escaped_string_literal() {
50845084
fn parse_create_simple_before_insert_trigger() {
50855085
let sql = "CREATE TRIGGER check_insert BEFORE INSERT ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_insert";
50865086
let expected = Statement::CreateTrigger {
5087+
or_alter: false,
50875088
or_replace: false,
50885089
is_constraint: false,
50895090
name: ObjectName::from(vec![Ident::new("check_insert")]),
@@ -5113,6 +5114,7 @@ fn parse_create_simple_before_insert_trigger() {
51135114
fn parse_create_after_update_trigger_with_condition() {
51145115
let sql = "CREATE TRIGGER check_update AFTER UPDATE ON accounts FOR EACH ROW WHEN (NEW.balance > 10000) EXECUTE FUNCTION check_account_update";
51155116
let expected = Statement::CreateTrigger {
5117+
or_alter: false,
51165118
or_replace: false,
51175119
is_constraint: false,
51185120
name: ObjectName::from(vec![Ident::new("check_update")]),
@@ -5149,6 +5151,7 @@ fn parse_create_after_update_trigger_with_condition() {
51495151
fn parse_create_instead_of_delete_trigger() {
51505152
let sql = "CREATE TRIGGER check_delete INSTEAD OF DELETE ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_deletes";
51515153
let expected = Statement::CreateTrigger {
5154+
or_alter: false,
51525155
or_replace: false,
51535156
is_constraint: false,
51545157
name: ObjectName::from(vec![Ident::new("check_delete")]),
@@ -5178,6 +5181,7 @@ fn parse_create_instead_of_delete_trigger() {
51785181
fn parse_create_trigger_with_multiple_events_and_deferrable() {
51795182
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";
51805183
let expected = Statement::CreateTrigger {
5184+
or_alter: false,
51815185
or_replace: false,
51825186
is_constraint: true,
51835187
name: ObjectName::from(vec![Ident::new("check_multiple_events")]),
@@ -5215,6 +5219,7 @@ fn parse_create_trigger_with_multiple_events_and_deferrable() {
52155219
fn parse_create_trigger_with_referencing() {
52165220
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";
52175221
let expected = Statement::CreateTrigger {
5222+
or_alter: false,
52185223
or_replace: false,
52195224
is_constraint: false,
52205225
name: ObjectName::from(vec![Ident::new("check_referencing")]),
@@ -5528,6 +5533,7 @@ fn parse_trigger_related_functions() {
55285533
assert_eq!(
55295534
create_trigger,
55305535
Statement::CreateTrigger {
5536+
or_alter: false,
55315537
or_replace: false,
55325538
is_constraint: false,
55335539
name: ObjectName::from(vec![Ident::new("emp_stamp")]),

0 commit comments

Comments
 (0)