Skip to content

Commit 39517ce

Browse files
committed
Add OR ALTER support for CREATE TRIGGER
1 parent 9e19adb commit 39517ce

File tree

5 files changed

+64
-5
lines changed

5 files changed

+64
-5
lines changed

src/ast/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -3611,7 +3611,7 @@ pub enum Statement {
36113611
/// 2. [PostgreSQL](https://www.postgresql.org/docs/15/sql-createfunction.html)
36123612
/// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
36133613
CreateFunction(CreateFunction),
3614-
/// CREATE TRIGGER
3614+
/// CREATE [OR ALTER] TRIGGER
36153615
///
36163616
/// Examples:
36173617
///
@@ -3625,6 +3625,10 @@ pub enum Statement {
36253625
/// Postgres: <https://www.postgresql.org/docs/current/sql-createtrigger.html>
36263626
/// SQL Server: <https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql>
36273627
CreateTrigger {
3628+
// Conditionally alters the trigger only if it already exists.
3629+
//
3630+
// [SQL Server](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16#arguments)
3631+
or_alter: bool,
36283632
/// The `OR REPLACE` clause is used to re-create the trigger if it already exists.
36293633
///
36303634
/// Example:
@@ -4469,6 +4473,7 @@ impl fmt::Display for Statement {
44694473
}
44704474
Statement::CreateFunction(create_function) => create_function.fmt(f),
44714475
Statement::CreateTrigger {
4476+
or_alter,
44724477
or_replace,
44734478
is_constraint,
44744479
name,
@@ -4486,7 +4491,8 @@ impl fmt::Display for Statement {
44864491
} => {
44874492
write!(
44884493
f,
4489-
"CREATE {or_replace}{is_constraint}TRIGGER {name} {period}",
4494+
"CREATE {or_alter}{or_replace}{is_constraint}TRIGGER {name} {period}",
4495+
or_alter = if *or_alter { "OR ALTER " } else { "" },
44904496
or_replace = if *or_replace { "OR REPLACE " } else { "" },
44914497
is_constraint = if *is_constraint { "CONSTRAINT " } else { "" },
44924498
)?;

src/parser/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -4563,9 +4563,9 @@ impl<'a> Parser<'a> {
45634563
} else if self.parse_keyword(Keyword::FUNCTION) {
45644564
self.parse_create_function(or_replace, temporary)
45654565
} else if self.parse_keyword(Keyword::TRIGGER) {
4566-
self.parse_create_trigger(or_replace, false)
4566+
self.parse_create_trigger(or_alter, or_replace, false)
45674567
} else if self.parse_keywords(&[Keyword::CONSTRAINT, Keyword::TRIGGER]) {
4568-
self.parse_create_trigger(or_replace, true)
4568+
self.parse_create_trigger(or_alter, or_replace, true)
45694569
} else if self.parse_keyword(Keyword::MACRO) {
45704570
self.parse_create_macro(or_replace, temporary)
45714571
} else if self.parse_keyword(Keyword::SECRET) {
@@ -5205,6 +5205,7 @@ impl<'a> Parser<'a> {
52055205

52065206
pub fn parse_create_trigger(
52075207
&mut self,
5208+
or_alter: bool,
52085209
or_replace: bool,
52095210
is_constraint: bool,
52105211
) -> Result<Statement, ParserError> {
@@ -5214,7 +5215,7 @@ impl<'a> Parser<'a> {
52145215
}
52155216

52165217
if dialect_of!(self is MsSqlDialect) {
5217-
return self.parse_mssql_create_trigger(or_replace, is_constraint);
5218+
return self.parse_mssql_create_trigger(or_alter, or_replace, is_constraint);
52185219
}
52195220

52205221
let name = self.parse_object_name(false)?;
@@ -5258,6 +5259,7 @@ impl<'a> Parser<'a> {
52585259
let exec_body = self.parse_trigger_exec_body()?;
52595260

52605261
Ok(Statement::CreateTrigger {
5262+
or_alter,
52615263
or_replace,
52625264
is_constraint,
52635265
name,
@@ -5280,6 +5282,7 @@ impl<'a> Parser<'a> {
52805282
/// [SQL Server]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql
52815283
pub fn parse_mssql_create_trigger(
52825284
&mut self,
5285+
or_alter: bool,
52835286
or_replace: bool,
52845287
is_constraint: bool,
52855288
) -> Result<Statement, ParserError> {
@@ -5306,6 +5309,7 @@ impl<'a> Parser<'a> {
53065309
};
53075310

53085311
Ok(Statement::CreateTrigger {
5312+
or_alter,
53095313
or_replace,
53105314
is_constraint,
53115315
name,

tests/sqlparser_mssql.rs

+42
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,48 @@ fn parse_create_trigger() {
20932093
assert_eq!(
20942094
create_stmt,
20952095
Statement::CreateTrigger {
2096+
or_alter: false,
2097+
or_replace: false,
2098+
is_constraint: false,
2099+
name: ObjectName::from(vec![Ident::new("some_trigger")]),
2100+
period: TriggerPeriod::For,
2101+
events: vec![TriggerEvent::Insert],
2102+
table_name: ObjectName::from(vec![Ident::new("some_table")]),
2103+
referenced_table_name: None,
2104+
referencing: vec![],
2105+
trigger_object: TriggerObject::Statement,
2106+
include_each: false,
2107+
condition: None,
2108+
exec_body: None,
2109+
statements: vec![Statement::RaisError {
2110+
message: Box::new(Expr::Value(
2111+
(Value::SingleQuotedString("Trigger fired".to_string())).with_empty_span()
2112+
)),
2113+
severity: Box::new(Expr::Value(
2114+
(Value::Number("10".parse().unwrap(), false)).with_empty_span()
2115+
)),
2116+
state: Box::new(Expr::Value(
2117+
(Value::Number("1".parse().unwrap(), false)).with_empty_span()
2118+
)),
2119+
arguments: vec![],
2120+
options: vec![],
2121+
}],
2122+
characteristics: None,
2123+
}
2124+
);
2125+
2126+
let create_or_alter_trigger = r#"
2127+
CREATE OR ALTER TRIGGER some_trigger ON some_table FOR INSERT
2128+
AS
2129+
BEGIN
2130+
RAISERROR('Trigger fired', 10, 1)
2131+
END
2132+
"#;
2133+
let create_stmt = ms().one_statement_parses_to(create_or_alter_trigger, "");
2134+
assert_eq!(
2135+
create_stmt,
2136+
Statement::CreateTrigger {
2137+
or_alter: true,
20962138
or_replace: false,
20972139
is_constraint: false,
20982140
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
@@ -5048,6 +5048,7 @@ fn test_escaped_string_literal() {
50485048
fn parse_create_simple_before_insert_trigger() {
50495049
let sql = "CREATE TRIGGER check_insert BEFORE INSERT ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_insert";
50505050
let expected = Statement::CreateTrigger {
5051+
or_alter: false,
50515052
or_replace: false,
50525053
is_constraint: false,
50535054
name: ObjectName::from(vec![Ident::new("check_insert")]),
@@ -5077,6 +5078,7 @@ fn parse_create_simple_before_insert_trigger() {
50775078
fn parse_create_after_update_trigger_with_condition() {
50785079
let sql = "CREATE TRIGGER check_update AFTER UPDATE ON accounts FOR EACH ROW WHEN (NEW.balance > 10000) EXECUTE FUNCTION check_account_update";
50795080
let expected = Statement::CreateTrigger {
5081+
or_alter: false,
50805082
or_replace: false,
50815083
is_constraint: false,
50825084
name: ObjectName::from(vec![Ident::new("check_update")]),
@@ -5113,6 +5115,7 @@ fn parse_create_after_update_trigger_with_condition() {
51135115
fn parse_create_instead_of_delete_trigger() {
51145116
let sql = "CREATE TRIGGER check_delete INSTEAD OF DELETE ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_deletes";
51155117
let expected = Statement::CreateTrigger {
5118+
or_alter: false,
51165119
or_replace: false,
51175120
is_constraint: false,
51185121
name: ObjectName::from(vec![Ident::new("check_delete")]),
@@ -5142,6 +5145,7 @@ fn parse_create_instead_of_delete_trigger() {
51425145
fn parse_create_trigger_with_multiple_events_and_deferrable() {
51435146
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";
51445147
let expected = Statement::CreateTrigger {
5148+
or_alter: false,
51455149
or_replace: false,
51465150
is_constraint: true,
51475151
name: ObjectName::from(vec![Ident::new("check_multiple_events")]),
@@ -5179,6 +5183,7 @@ fn parse_create_trigger_with_multiple_events_and_deferrable() {
51795183
fn parse_create_trigger_with_referencing() {
51805184
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";
51815185
let expected = Statement::CreateTrigger {
5186+
or_alter: false,
51825187
or_replace: false,
51835188
is_constraint: false,
51845189
name: ObjectName::from(vec![Ident::new("check_referencing")]),
@@ -5490,6 +5495,7 @@ fn parse_trigger_related_functions() {
54905495
assert_eq!(
54915496
create_trigger,
54925497
Statement::CreateTrigger {
5498+
or_alter: false,
54935499
or_replace: false,
54945500
is_constraint: false,
54955501
name: ObjectName::from(vec![Ident::new("emp_stamp")]),

0 commit comments

Comments
 (0)