From 2d9a24062a398df018a9ad780d0321b6db52657d Mon Sep 17 00:00:00 2001 From: Luca Date: 2025年9月10日 10:28:21 +0200 Subject: [PATCH 1/2] Moved `CreateTrigger` and `DropTrigger` out of `Statement` enum and into their own struct --- src/ast/ddl.rs | 237 ++++++++++++++++++++++++++++++++++-- src/ast/mod.rs | 213 ++------------------------------ src/dialect/mssql.rs | 8 +- src/parser/mod.rs | 8 +- tests/sqlparser_mssql.rs | 8 +- tests/sqlparser_mysql.rs | 8 +- tests/sqlparser_postgres.rs | 32 ++--- 7 files changed, 270 insertions(+), 244 deletions(-) diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index db1cb61f6..a15474755 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -20,7 +20,7 @@ #[cfg(not(feature = "std"))] use alloc::{boxed::Box, string::String, vec::Vec}; -use core::fmt::{self, Write}; +use core::fmt::{self, Display, Write}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -30,14 +30,15 @@ use sqlparser_derive::{Visit, VisitMut}; use crate::ast::value::escape_single_quote_string; use crate::ast::{ - display_comma_separated, display_separated, ArgMode, CommentDef, CreateFunctionBody, - CreateFunctionUsing, CreateTableLikeKind, CreateTableOptions, DataType, Expr, FileFormat, - FunctionBehavior, FunctionCalledOnNull, FunctionDeterminismSpecifier, FunctionParallel, - HiveDistributionStyle, HiveFormat, HiveIOFormat, HiveRowFormat, Ident, InitializeKind, - MySQLColumnPosition, ObjectName, OnCommit, OneOrManyWithParens, OperateFunctionArg, - OrderByExpr, ProjectionSelect, Query, RefreshModeKind, RowAccessPolicy, SequenceOptions, - Spanned, SqlOption, StorageSerializationPolicy, TableVersion, Tag, Value, ValueWithSpan, - WrappedCollection, + display_comma_separated, display_separated, ArgMode, CommentDef, ConditionalStatements, + CreateFunctionBody, CreateFunctionUsing, CreateTableLikeKind, CreateTableOptions, DataType, + Expr, FileFormat, FunctionBehavior, FunctionCalledOnNull, FunctionDeterminismSpecifier, + FunctionParallel, HiveDistributionStyle, HiveFormat, HiveIOFormat, HiveRowFormat, Ident, + InitializeKind, MySQLColumnPosition, ObjectName, OnCommit, OneOrManyWithParens, + OperateFunctionArg, OrderByExpr, ProjectionSelect, Query, RefreshModeKind, RowAccessPolicy, + SequenceOptions, Spanned, SqlOption, StorageSerializationPolicy, TableVersion, Tag, + TriggerEvent, TriggerExecBody, TriggerObject, TriggerPeriod, TriggerReferencing, Value, + ValueWithSpan, WrappedCollection, }; use crate::display_utils::{DisplayCommaSeparated, Indent, NewLine, SpaceOrNewline}; use crate::keywords::Keyword; @@ -3176,3 +3177,221 @@ impl Spanned for RenameTableNameKind { } } } + +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// CREATE TRIGGER +/// +/// Examples: +/// +/// ```sql +/// CREATE TRIGGER trigger_name +/// BEFORE INSERT ON table_name +/// FOR EACH ROW +/// EXECUTE FUNCTION trigger_function(); +/// ``` +/// +/// Postgres: +/// SQL Server: +pub struct CreateTrigger { + /// True if this is a `CREATE OR ALTER TRIGGER` statement + /// + /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16#arguments) + pub or_alter: bool, + /// The `OR REPLACE` clause is used to re-create the trigger if it already exists. + /// + /// Example: + /// ```sql + /// CREATE OR REPLACE TRIGGER trigger_name + /// AFTER INSERT ON table_name + /// FOR EACH ROW + /// EXECUTE FUNCTION trigger_function(); + /// ``` + pub or_replace: bool, + /// The `CONSTRAINT` keyword is used to create a trigger as a constraint. + pub is_constraint: bool, + /// The name of the trigger to be created. + pub name: ObjectName, + /// Determines whether the function is called before, after, or instead of the event. + /// + /// Example of BEFORE: + /// + /// ```sql + /// CREATE TRIGGER trigger_name + /// BEFORE INSERT ON table_name + /// FOR EACH ROW + /// EXECUTE FUNCTION trigger_function(); + /// ``` + /// + /// Example of AFTER: + /// + /// ```sql + /// CREATE TRIGGER trigger_name + /// AFTER INSERT ON table_name + /// FOR EACH ROW + /// EXECUTE FUNCTION trigger_function(); + /// ``` + /// + /// Example of INSTEAD OF: + /// + /// ```sql + /// CREATE TRIGGER trigger_name + /// INSTEAD OF INSERT ON table_name + /// FOR EACH ROW + /// EXECUTE FUNCTION trigger_function(); + /// ``` + pub period: TriggerPeriod, + /// Whether the trigger period was specified before the target table name. + /// + /// ```sql + /// -- period_before_table == true: Postgres, MySQL, and standard SQL + /// CREATE TRIGGER t BEFORE INSERT ON table_name ...; + /// -- period_before_table == false: MSSQL + /// CREATE TRIGGER t ON table_name BEFORE INSERT ...; + /// ``` + pub period_before_table: bool, + /// Multiple events can be specified using OR, such as `INSERT`, `UPDATE`, `DELETE`, or `TRUNCATE`. + pub events: Vec
, + /// The table on which the trigger is to be created. + pub table_name: ObjectName, + /// The optional referenced table name that can be referenced via + /// the `FROM` keyword. + pub referenced_table_name: Option, + /// This keyword immediately precedes the declaration of one or two relation names that provide access to the transition relations of the triggering statement. + pub referencing: Vec
, + /// This specifies whether the trigger function should be fired once for + /// every row affected by the trigger event, or just once per SQL statement. + pub trigger_object: TriggerObject, + /// Whether to include the `EACH` term of the `FOR EACH`, as it is optional syntax. + pub include_each: bool, + /// Triggering conditions + pub condition: Option, + /// Execute logic block + pub exec_body: Option
, + /// For MSSQL and dialects where statements are preceded by `AS` + pub statements_as: bool, + /// For SQL dialects with statement(s) for a body + pub statements: Option, + /// The characteristic of the trigger, which include whether the trigger is `DEFERRABLE`, `INITIALLY DEFERRED`, or `INITIALLY IMMEDIATE`, + pub characteristics: Option, +} + +impl Display for CreateTrigger { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let CreateTrigger { + or_alter, + or_replace, + is_constraint, + name, + period_before_table, + period, + events, + table_name, + referenced_table_name, + referencing, + trigger_object, + condition, + include_each, + exec_body, + statements_as, + statements, + characteristics, + } = self; + write!( + f, + "CREATE {or_alter}{or_replace}{is_constraint}TRIGGER {name} ", + or_alter = if *or_alter { "OR ALTER " } else { "" }, + or_replace = if *or_replace { "OR REPLACE " } else { "" }, + is_constraint = if *is_constraint { "CONSTRAINT " } else { "" }, + )?; + + if *period_before_table { + write!(f, "{period}")?; + if !events.is_empty() { + write!(f, " {}", display_separated(events, " OR "))?; + } + write!(f, " ON {table_name}")?; + } else { + write!(f, "ON {table_name}")?; + write!(f, " {period}")?; + if !events.is_empty() { + write!(f, " {}", display_separated(events, ", "))?; + } + } + + if let Some(referenced_table_name) = referenced_table_name { + write!(f, " FROM {referenced_table_name}")?; + } + + if let Some(characteristics) = characteristics { + write!(f, " {characteristics}")?; + } + + if !referencing.is_empty() { + write!(f, " REFERENCING {}", display_separated(referencing, " "))?; + } + + if *include_each { + write!(f, " FOR EACH {trigger_object}")?; + } else if exec_body.is_some() { + write!(f, " FOR {trigger_object}")?; + } + if let Some(condition) = condition { + write!(f, " WHEN {condition}")?; + } + if let Some(exec_body) = exec_body { + write!(f, " EXECUTE {exec_body}")?; + } + if let Some(statements) = statements { + if *statements_as { + write!(f, " AS")?; + } + write!(f, " {statements}")?; + } + Ok(()) + } +} + +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// DROP TRIGGER +/// +/// ```sql +/// DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ] +/// ``` +/// +pub struct DropTrigger { + /// Whether to include the `IF EXISTS` clause. + pub if_exists: bool, + /// The name of the trigger to be dropped. + pub trigger_name: ObjectName, + /// The name of the table from which the trigger is to be dropped. + pub table_name: Option, + /// `CASCADE` or `RESTRICT` + pub option: Option, +} + +impl fmt::Display for DropTrigger { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let DropTrigger { + if_exists, + trigger_name, + table_name, + option, + } = self; + write!(f, "DROP TRIGGER")?; + if *if_exists { + write!(f, " IF EXISTS")?; + } + match &table_name { + Some(table_name) => write!(f, " {trigger_name} ON {table_name}")?, + None => write!(f, " {trigger_name}")?, + }; + if let Some(option) = option { + write!(f, " {option}")?; + } + Ok(()) + } +} diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 5b8e23259..ee43ccc51 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -63,10 +63,10 @@ pub use self::ddl::{ AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain, - CreateFunction, CreateIndex, CreateTable, Deduplicate, DeferrableInitial, DropBehavior, - GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty, - IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, - IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition, + CreateFunction, CreateIndex, CreateTable, CreateTrigger, Deduplicate, DeferrableInitial, + DropBehavior, DropTrigger, GeneratedAs, GeneratedExpressionMode, IdentityParameters, + IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, + IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TableConstraint, TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef, @@ -3914,114 +3914,10 @@ pub enum Statement { /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement) /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql) CreateFunction(CreateFunction), - /// CREATE TRIGGER - /// - /// Examples: - /// - /// ```sql - /// CREATE TRIGGER trigger_name - /// BEFORE INSERT ON table_name - /// FOR EACH ROW - /// EXECUTE FUNCTION trigger_function(); - /// ``` - /// - /// Postgres: - /// SQL Server: - CreateTrigger { - /// True if this is a `CREATE OR ALTER TRIGGER` statement - /// - /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16#arguments) - or_alter: bool, - /// The `OR REPLACE` clause is used to re-create the trigger if it already exists. - /// - /// Example: - /// ```sql - /// CREATE OR REPLACE TRIGGER trigger_name - /// AFTER INSERT ON table_name - /// FOR EACH ROW - /// EXECUTE FUNCTION trigger_function(); - /// ``` - or_replace: bool, - /// The `CONSTRAINT` keyword is used to create a trigger as a constraint. - is_constraint: bool, - /// The name of the trigger to be created. - name: ObjectName, - /// Determines whether the function is called before, after, or instead of the event. - /// - /// Example of BEFORE: - /// - /// ```sql - /// CREATE TRIGGER trigger_name - /// BEFORE INSERT ON table_name - /// FOR EACH ROW - /// EXECUTE FUNCTION trigger_function(); - /// ``` - /// - /// Example of AFTER: - /// - /// ```sql - /// CREATE TRIGGER trigger_name - /// AFTER INSERT ON table_name - /// FOR EACH ROW - /// EXECUTE FUNCTION trigger_function(); - /// ``` - /// - /// Example of INSTEAD OF: - /// - /// ```sql - /// CREATE TRIGGER trigger_name - /// INSTEAD OF INSERT ON table_name - /// FOR EACH ROW - /// EXECUTE FUNCTION trigger_function(); - /// ``` - period: TriggerPeriod, - /// Whether the trigger period was specified before the target table name. - /// - /// ```sql - /// -- period_before_table == true: Postgres, MySQL, and standard SQL - /// CREATE TRIGGER t BEFORE INSERT ON table_name ...; - /// -- period_before_table == false: MSSQL - /// CREATE TRIGGER t ON table_name BEFORE INSERT ...; - /// ``` - period_before_table: bool, - /// Multiple events can be specified using OR, such as `INSERT`, `UPDATE`, `DELETE`, or `TRUNCATE`. - events: Vec
, - /// The table on which the trigger is to be created. - table_name: ObjectName, - /// The optional referenced table name that can be referenced via - /// the `FROM` keyword. - referenced_table_name: Option, - /// This keyword immediately precedes the declaration of one or two relation names that provide access to the transition relations of the triggering statement. - referencing: Vec
, - /// This specifies whether the trigger function should be fired once for - /// every row affected by the trigger event, or just once per SQL statement. - trigger_object: TriggerObject, - /// Whether to include the `EACH` term of the `FOR EACH`, as it is optional syntax. - include_each: bool, - /// Triggering conditions - condition: Option, - /// Execute logic block - exec_body: Option
, - /// For MSSQL and dialects where statements are preceded by `AS` - statements_as: bool, - /// For SQL dialects with statement(s) for a body - statements: Option, - /// The characteristic of the trigger, which include whether the trigger is `DEFERRABLE`, `INITIALLY DEFERRED`, or `INITIALLY IMMEDIATE`, - characteristics: Option, - }, - /// DROP TRIGGER - /// - /// ```sql - /// DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ] - /// ``` - /// - DropTrigger { - if_exists: bool, - trigger_name: ObjectName, - table_name: Option, - /// `CASCADE` or `RESTRICT` - option: Option, - }, + /// CREATE TRIGGER statement. See struct `CreateTrigger` for details. + CreateTrigger(CreateTrigger), + /// DROP TRIGGER statement. See struct `DropTrigger` for details. + DropTrigger(DropTrigger), /// ```sql /// CREATE PROCEDURE /// ``` @@ -4984,97 +4880,8 @@ impl fmt::Display for Statement { } Statement::CreateFunction(create_function) => create_function.fmt(f), Statement::CreateDomain(create_domain) => create_domain.fmt(f), - Statement::CreateTrigger { - or_alter, - or_replace, - is_constraint, - name, - period_before_table, - period, - events, - table_name, - referenced_table_name, - referencing, - trigger_object, - condition, - include_each, - exec_body, - statements_as, - statements, - characteristics, - } => { - write!( - f, - "CREATE {or_alter}{or_replace}{is_constraint}TRIGGER {name} ", - or_alter = if *or_alter { "OR ALTER " } else { "" }, - or_replace = if *or_replace { "OR REPLACE " } else { "" }, - is_constraint = if *is_constraint { "CONSTRAINT " } else { "" }, - )?; - - if *period_before_table { - write!(f, "{period}")?; - if !events.is_empty() { - write!(f, " {}", display_separated(events, " OR "))?; - } - write!(f, " ON {table_name}")?; - } else { - write!(f, "ON {table_name}")?; - write!(f, " {period}")?; - if !events.is_empty() { - write!(f, " {}", display_separated(events, ", "))?; - } - } - - if let Some(referenced_table_name) = referenced_table_name { - write!(f, " FROM {referenced_table_name}")?; - } - - if let Some(characteristics) = characteristics { - write!(f, " {characteristics}")?; - } - - if !referencing.is_empty() { - write!(f, " REFERENCING {}", display_separated(referencing, " "))?; - } - - if *include_each { - write!(f, " FOR EACH {trigger_object}")?; - } else if exec_body.is_some() { - write!(f, " FOR {trigger_object}")?; - } - if let Some(condition) = condition { - write!(f, " WHEN {condition}")?; - } - if let Some(exec_body) = exec_body { - write!(f, " EXECUTE {exec_body}")?; - } - if let Some(statements) = statements { - if *statements_as { - write!(f, " AS")?; - } - write!(f, " {statements}")?; - } - Ok(()) - } - Statement::DropTrigger { - if_exists, - trigger_name, - table_name, - option, - } => { - write!(f, "DROP TRIGGER")?; - if *if_exists { - write!(f, " IF EXISTS")?; - } - match &table_name { - Some(table_name) => write!(f, " {trigger_name} ON {table_name}")?, - None => write!(f, " {trigger_name}")?, - }; - if let Some(option) = option { - write!(f, " {option}")?; - } - Ok(()) - } + Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f), + Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f), Statement::CreateProcedure { name, or_alter, diff --git a/src/dialect/mssql.rs b/src/dialect/mssql.rs index 518dab248..15946d5db 100644 --- a/src/dialect/mssql.rs +++ b/src/dialect/mssql.rs @@ -17,8 +17,8 @@ use crate::ast::helpers::attached_token::AttachedToken; use crate::ast::{ - BeginEndStatements, ConditionalStatementBlock, ConditionalStatements, GranteesType, - IfStatement, Statement, TriggerObject, + BeginEndStatements, ConditionalStatementBlock, ConditionalStatements, CreateTrigger, + GranteesType, IfStatement, Statement, TriggerObject, }; use crate::dialect::Dialect; use crate::keywords::{self, Keyword}; @@ -251,7 +251,7 @@ impl MsSqlDialect { parser.expect_keyword_is(Keyword::AS)?; let statements = Some(parser.parse_conditional_statements(&[Keyword::END])?); - Ok(Statement::CreateTrigger { + Ok(Statement::CreateTrigger(CreateTrigger { or_alter, or_replace: false, is_constraint: false, @@ -269,7 +269,7 @@ impl MsSqlDialect { statements_as: true, statements, characteristics: None, - }) + })) } /// Parse a sequence of statements, optionally separated by semicolon. diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 54db367d8..1bc2a3d6f 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -5564,12 +5564,12 @@ impl<'a> Parser<'a> { Keyword::RESTRICT => ReferentialAction::Restrict, _ => unreachable!(), }); - Ok(Statement::DropTrigger { + Ok(Statement::DropTrigger(DropTrigger { if_exists, trigger_name, table_name, option, - }) + })) } pub fn parse_create_trigger( @@ -5627,7 +5627,7 @@ impl<'a> Parser<'a> { statements = Some(self.parse_conditional_statements(&[Keyword::END])?); } - Ok(Statement::CreateTrigger { + Ok(Statement::CreateTrigger(CreateTrigger { or_alter, or_replace, is_constraint, @@ -5645,7 +5645,7 @@ impl<'a> Parser<'a> { statements_as: false, statements, characteristics, - }) + })) } pub fn parse_trigger_period(&mut self) -> Result
{ diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs index a1e05d030..b1ad422ec 100644 --- a/tests/sqlparser_mssql.rs +++ b/tests/sqlparser_mssql.rs @@ -2384,7 +2384,7 @@ fn parse_create_trigger() { let create_stmt = ms().verified_stmt(create_trigger); assert_eq!( create_stmt, - Statement::CreateTrigger { + Statement::CreateTrigger(CreateTrigger { or_alter: true, or_replace: false, is_constraint: false, @@ -2417,7 +2417,7 @@ fn parse_create_trigger() { }], }), characteristics: None, - } + }) ); let multi_statement_as_trigger = "\ @@ -2476,12 +2476,12 @@ fn parse_drop_trigger() { let drop_stmt = ms().one_statement_parses_to(sql_drop_trigger, ""); assert_eq!( drop_stmt, - Statement::DropTrigger { + Statement::DropTrigger(DropTrigger { if_exists: false, trigger_name: ObjectName::from(vec![Ident::new("emp_stamp")]), table_name: None, option: None, - } + }) ); } diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index 184532035..0857bae3b 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -3922,7 +3922,7 @@ fn parse_create_trigger() { let create_stmt = mysql().verified_stmt(sql_create_trigger); assert_eq!( create_stmt, - Statement::CreateTrigger { + Statement::CreateTrigger(CreateTrigger { or_alter: false, or_replace: false, is_constraint: false, @@ -3946,7 +3946,7 @@ fn parse_create_trigger() { statements_as: false, statements: None, characteristics: None, - } + }) ); } @@ -3962,12 +3962,12 @@ fn parse_drop_trigger() { let drop_stmt = mysql().one_statement_parses_to(sql_drop_trigger, ""); assert_eq!( drop_stmt, - Statement::DropTrigger { + Statement::DropTrigger(DropTrigger { if_exists: false, trigger_name: ObjectName::from(vec![Ident::new("emp_stamp")]), table_name: None, option: None, - } + }) ); } diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 287b828a8..5b95bb300 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -5671,7 +5671,7 @@ fn parse_create_domain() { #[test] fn parse_create_simple_before_insert_trigger() { let sql = "CREATE TRIGGER check_insert BEFORE INSERT ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_insert"; - let expected = Statement::CreateTrigger { + let expected = Statement::CreateTrigger(CreateTrigger { or_alter: false, or_replace: false, is_constraint: false, @@ -5695,7 +5695,7 @@ fn parse_create_simple_before_insert_trigger() { statements_as: false, statements: None, characteristics: None, - }; + }); assert_eq!(pg().verified_stmt(sql), expected); } @@ -5703,7 +5703,7 @@ fn parse_create_simple_before_insert_trigger() { #[test] fn parse_create_after_update_trigger_with_condition() { let sql = "CREATE TRIGGER check_update AFTER UPDATE ON accounts FOR EACH ROW WHEN (NEW.balance> 10000) EXECUTE FUNCTION check_account_update"; - let expected = Statement::CreateTrigger { + let expected = Statement::CreateTrigger(CreateTrigger { or_alter: false, or_replace: false, is_constraint: false, @@ -5734,7 +5734,7 @@ fn parse_create_after_update_trigger_with_condition() { statements_as: false, statements: None, characteristics: None, - }; + }); assert_eq!(pg().verified_stmt(sql), expected); } @@ -5742,7 +5742,7 @@ fn parse_create_after_update_trigger_with_condition() { #[test] fn parse_create_instead_of_delete_trigger() { let sql = "CREATE TRIGGER check_delete INSTEAD OF DELETE ON accounts FOR EACH ROW EXECUTE FUNCTION check_account_deletes"; - let expected = Statement::CreateTrigger { + let expected = Statement::CreateTrigger(CreateTrigger { or_alter: false, or_replace: false, is_constraint: false, @@ -5766,7 +5766,7 @@ fn parse_create_instead_of_delete_trigger() { statements_as: false, statements: None, characteristics: None, - }; + }); assert_eq!(pg().verified_stmt(sql), expected); } @@ -5774,7 +5774,7 @@ fn parse_create_instead_of_delete_trigger() { #[test] fn parse_create_trigger_with_multiple_events_and_deferrable() { 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"; - let expected = Statement::CreateTrigger { + let expected = Statement::CreateTrigger(CreateTrigger { or_alter: false, or_replace: false, is_constraint: true, @@ -5806,7 +5806,7 @@ fn parse_create_trigger_with_multiple_events_and_deferrable() { initially: Some(DeferrableInitial::Deferred), enforced: None, }), - }; + }); assert_eq!(pg().verified_stmt(sql), expected); } @@ -5814,7 +5814,7 @@ fn parse_create_trigger_with_multiple_events_and_deferrable() { #[test] fn parse_create_trigger_with_referencing() { 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"; - let expected = Statement::CreateTrigger { + let expected = Statement::CreateTrigger(CreateTrigger { or_alter: false, or_replace: false, is_constraint: false, @@ -5849,7 +5849,7 @@ fn parse_create_trigger_with_referencing() { statements_as: false, statements: None, characteristics: None, - }; + }); assert_eq!(pg().verified_stmt(sql), expected); } @@ -5901,12 +5901,12 @@ fn parse_drop_trigger() { ); assert_eq!( pg().verified_stmt(sql), - Statement::DropTrigger { + Statement::DropTrigger(DropTrigger { if_exists, trigger_name: ObjectName::from(vec![Ident::new("check_update")]), table_name: Some(ObjectName::from(vec![Ident::new("table_name")])), option - } + }) ); } } @@ -6130,7 +6130,7 @@ fn parse_trigger_related_functions() { assert_eq!( create_trigger, - Statement::CreateTrigger { + Statement::CreateTrigger(CreateTrigger { or_alter: false, or_replace: false, is_constraint: false, @@ -6154,18 +6154,18 @@ fn parse_trigger_related_functions() { statements_as: false, statements: None, characteristics: None - } + }) ); // Check the fourth statement assert_eq!( drop_trigger, - Statement::DropTrigger { + Statement::DropTrigger(DropTrigger { if_exists: false, trigger_name: ObjectName::from(vec![Ident::new("emp_stamp")]), table_name: Some(ObjectName::from(vec![Ident::new("emp")])), option: None - } + }) ); } From 5a70bcc90aecbf70836a553aa72a978e3c1a93ec Mon Sep 17 00:00:00 2001 From: Luca Cappelletti Date: 2025年9月10日 10:43:54 +0200 Subject: [PATCH 2/2] Update src/ast/mod.rs Co-authored-by: Ifeanyi Ubah --- src/ast/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index ee43ccc51..6efe1f748 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3914,9 +3914,9 @@ pub enum Statement { /// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement) /// 4. [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql) CreateFunction(CreateFunction), - /// CREATE TRIGGER statement. See struct `CreateTrigger` for details. + /// CREATE TRIGGER statement. See struct [CreateTrigger] for details. CreateTrigger(CreateTrigger), - /// DROP TRIGGER statement. See struct `DropTrigger` for details. + /// DROP TRIGGER statement. See struct [DropTrigger] for details. DropTrigger(DropTrigger), /// ```sql /// CREATE PROCEDURE

AltStyle によって変換されたページ (->オリジナル) /