Skip to content

Commit aaa2ab3

Browse files
committed
Add OR ALTER support for CREATE TRIGGER
1 parent d2a8544 commit aaa2ab3

File tree

5 files changed

+100
-4
lines changed

5 files changed

+100
-4
lines changed

src/ast/mod.rs

+7-1
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

+7-3
Original file line numberDiff line numberDiff line change
@@ -4564,9 +4564,9 @@ impl<'a> Parser<'a> {
45644564
} else if self.parse_keyword(Keyword::FUNCTION) {
45654565
self.parse_create_function(or_alter, or_replace, temporary)
45664566
} else if self.parse_keyword(Keyword::TRIGGER) {
4567-
self.parse_create_trigger(or_replace, false)
4567+
self.parse_create_trigger(or_alter, or_replace, false)
45684568
} else if self.parse_keywords(&[Keyword::CONSTRAINT, Keyword::TRIGGER]) {
4569-
self.parse_create_trigger(or_replace, true)
4569+
self.parse_create_trigger(or_alter, or_replace, true)
45704570
} else if self.parse_keyword(Keyword::MACRO) {
45714571
self.parse_create_macro(or_replace, temporary)
45724572
} 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> {
@@ -5376,6 +5379,7 @@ impl<'a> Parser<'a> {
53765379
};
53775380

53785381
Ok(Statement::CreateTrigger {
5382+
or_alter,
53795383
or_replace,
53805384
is_constraint,
53815385
name,

tests/sqlparser_mssql.rs

+79
Original file line numberDiff line numberDiff line change
@@ -2354,6 +2354,7 @@ fn parse_create_trigger() {
23542354
assert_eq!(
23552355
create_stmt,
23562356
Statement::CreateTrigger {
2357+
or_alter: false,
23572358
or_replace: false,
23582359
is_constraint: false,
23592360
name: ObjectName::from(vec![Ident::new("reminder1")]),
@@ -2397,6 +2398,82 @@ fn parse_create_trigger() {
23972398
assert_eq!(
23982399
create_stmt,
23992400
Statement::CreateTrigger {
2401+
or_alter: false,
2402+
or_replace: false,
2403+
is_constraint: false,
2404+
name: ObjectName::from(vec![Ident::new("some_trigger")]),
2405+
period: TriggerPeriod::For,
2406+
events: vec![TriggerEvent::Insert],
2407+
table_name: ObjectName::from(vec![Ident::new("some_table")]),
2408+
referenced_table_name: None,
2409+
referencing: vec![],
2410+
trigger_object: TriggerObject::Statement,
2411+
include_each: false,
2412+
condition: None,
2413+
exec_body: None,
2414+
statements: vec![Statement::RaisError {
2415+
message: Box::new(Expr::Value(
2416+
(Value::SingleQuotedString("Trigger fired".to_string())).with_empty_span()
2417+
)),
2418+
severity: Box::new(Expr::Value(
2419+
(Value::Number("10".parse().unwrap(), false)).with_empty_span()
2420+
)),
2421+
state: Box::new(Expr::Value(
2422+
(Value::Number("1".parse().unwrap(), false)).with_empty_span()
2423+
)),
2424+
arguments: vec![],
2425+
options: vec![],
2426+
}],
2427+
characteristics: None,
2428+
}
2429+
);
2430+
2431+
let create_trigger_with_return = r#"
2432+
CREATE TRIGGER some_trigger ON some_table FOR INSERT
2433+
AS
2434+
BEGIN
2435+
RETURN;
2436+
END
2437+
"#;
2438+
let create_stmt = ms().one_statement_parses_to(create_trigger_with_return, "");
2439+
assert_eq!(
2440+
create_stmt,
2441+
Statement::CreateTrigger {
2442+
or_alter: false,
2443+
or_replace: false,
2444+
is_constraint: false,
2445+
name: ObjectName::from(vec![Ident::new("some_trigger")]),
2446+
period: TriggerPeriod::For,
2447+
events: vec![TriggerEvent::Insert],
2448+
table_name: ObjectName::from(vec![Ident::new("some_table")]),
2449+
referenced_table_name: None,
2450+
referencing: vec![],
2451+
trigger_object: TriggerObject::Statement,
2452+
include_each: false,
2453+
condition: None,
2454+
exec_body: None,
2455+
statements: vec![Statement::Return(ReturnStatement {
2456+
value: None,
2457+
})],
2458+
characteristics: None,
2459+
}
2460+
);
2461+
}
2462+
2463+
#[test]
2464+
fn parse_mssql_create_trigger() {
2465+
let create_or_alter_trigger = r#"
2466+
CREATE OR ALTER TRIGGER some_trigger ON some_table FOR INSERT
2467+
AS
2468+
BEGIN
2469+
RAISERROR('Trigger fired', 10, 1)
2470+
END
2471+
"#;
2472+
let create_stmt = ms().one_statement_parses_to(create_or_alter_trigger, "");
2473+
assert_eq!(
2474+
create_stmt,
2475+
Statement::CreateTrigger {
2476+
or_alter: true,
24002477
or_replace: false,
24012478
is_constraint: false,
24022479
name: ObjectName::from(vec![Ident::new("some_trigger")]),
@@ -2437,6 +2514,7 @@ fn parse_create_trigger() {
24372514
assert_eq!(
24382515
create_stmt,
24392516
Statement::CreateTrigger {
2517+
or_alter: false,
24402518
or_replace: false,
24412519
is_constraint: false,
24422520
name: ObjectName::from(vec![Ident::new("some_trigger")]),
@@ -2472,6 +2550,7 @@ fn parse_create_trigger() {
24722550
assert_eq!(
24732551
create_stmt,
24742552
Statement::CreateTrigger {
2553+
or_alter: false,
24752554
or_replace: false,
24762555
is_constraint: false,
24772556
name: ObjectName::from(vec![Ident::new("some_trigger")]),

tests/sqlparser_mysql.rs

+1
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

+6
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)