Skip to content

Adding support for parsing CREATE TRIGGER and DROP TRIGGER statements #1352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 53 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
a3fa3b5
Added tests for the TRIGGERs
LucaCappelletti94 Jul 25, 2024
308b1a7
Added missing keywords needed for triggers
LucaCappelletti94 Jul 25, 2024
764707f
Created new module for the AST-related objects for the TRIGGERs
LucaCappelletti94 Jul 25, 2024
637c632
Integrated TRIGGERS in AST enum
LucaCappelletti94 Jul 25, 2024
e760c07
Added methods to parse triggers
LucaCappelletti94 Jul 25, 2024
7474836
Extended testing and resolved some corner cases in triggers
LucaCappelletti94 Jul 25, 2024
9fa36d9
Formatted code
LucaCappelletti94 Jul 26, 2024
d6c3e51
Derived visitor trait and resolved clippy code smells
LucaCappelletti94 Jul 26, 2024
8104de9
Resolved documentation issue and extended test coverage for Triggers
LucaCappelletti94 Jul 26, 2024
9c72a62
Update src/parser/mod.rs
LucaCappelletti94 Jul 26, 2024
5a9a19e
Added support for optional "EACH" display and extended test suite
LucaCappelletti94 Jul 26, 2024
d5a6af1
Removed empty spaced with cargo fmt
LucaCappelletti94 Jul 26, 2024
e6294c1
Renamed TRIGGER-related struct and fixed a copy-paste error and a typo
LucaCappelletti94 Jul 27, 2024
6f7c9c3
Reformatted code<
LucaCappelletti94 Jul 27, 2024
429b202
Merged DropFunctionDesc and TriggerFunctionDesc into FunctionDesc
LucaCappelletti94 Jul 27, 2024
dbaca3a
Updated struct documentation
LucaCappelletti94 Jul 27, 2024
3b26bc0
Refactored code to make use of expect_keyboard where appropriate
LucaCappelletti94 Jul 27, 2024
552825c
Extended test suite for multiple events
LucaCappelletti94 Jul 27, 2024
40993e0
Added coverage for both function and procedure in triggers
LucaCappelletti94 Jul 27, 2024
e26ef31
Extended trigger testing which now includes also functions with multi…
LucaCappelletti94 Jul 27, 2024
bf9da2a
Formatted code
LucaCappelletti94 Jul 27, 2024
c83dd34
Added support for deferrability in TRIGGERS and extended test suite
LucaCappelletti94 Jul 27, 2024
4dcee7f
Added combinatorial option for Row/Statement
LucaCappelletti94 Jul 27, 2024
5f4de6b
Added testing for referencing tables in TRIGGERs
LucaCappelletti94 Jul 27, 2024
eeb2eb0
Added some negative testig
LucaCappelletti94 Jul 27, 2024
b23c5fd
Added support for DropTrigger
LucaCappelletti94 Jul 27, 2024
2555c1e
Removed optionality of TriggerObject as it must be defined
LucaCappelletti94 Jul 27, 2024
8cb0ac9
Formatted code
LucaCappelletti94 Jul 27, 2024
47c2f40
Changed attribute event to events as it refers to a vector of events
LucaCappelletti94 Jul 27, 2024
e81a58c
Extended the test suite
LucaCappelletti94 Jul 27, 2024
c3a96e0
Added support for the TRIGGER return type
LucaCappelletti94 Jul 28, 2024
430a163
Update tests/sqlparser_postgres.rs
LucaCappelletti94 Jul 28, 2024
498aada
Update src/parser/mod.rs
LucaCappelletti94 Jul 28, 2024
ba5d473
Finished refactoring dialect check to simplify code
LucaCappelletti94 Jul 28, 2024
a27cf33
Finished test semplification changing `when` to `period`
LucaCappelletti94 Jul 28, 2024
3887809
Formatted code
LucaCappelletti94 Jul 28, 2024
459c111
Removed part of the `and_then` to adequate to codebase style
LucaCappelletti94 Jul 28, 2024
c043b58
Formatted code
LucaCappelletti94 Jul 28, 2024
3fc2684
Removed more uses of and_then and then
LucaCappelletti94 Jul 28, 2024
09581e7
Restored and made use in triggers of original ConstraintCharacteristics
LucaCappelletti94 Jul 28, 2024
058cf7f
Reverted change relative to ConstraintCharacteristics
LucaCappelletti94 Jul 30, 2024
30199bf
Merge branch 'main' into main
LucaCappelletti94 Jul 30, 2024
7ab8fdb
Update tests/sqlparser_postgres.rs
LucaCappelletti94 Jul 30, 2024
6c5487f
Added support for the CONSTRAINT keyword in triggers
LucaCappelletti94 Jul 30, 2024
c0aab06
Extended test suite and added support for CONSTRAINT keyword and FROM…
LucaCappelletti94 Jul 30, 2024
c198e24
Formatted code
LucaCappelletti94 Jul 30, 2024
d8db70e
Removed itertools dependency and tried to clean up code as much as po…
LucaCappelletti94 Jul 30, 2024
0f81194
Reformatted code
LucaCappelletti94 Jul 30, 2024
169a0be
Fixed comments
LucaCappelletti94 Jul 30, 2024
459dae1
Replaced complete test with partial tests
LucaCappelletti94 Aug 13, 2024
be1a682
Removed dead code
LucaCappelletti94 Aug 13, 2024
4268a9a
Merge remote-tracking branch 'origin/main' into LucaCappelletti94/main
alamb Aug 13, 2024
0182a50
Fix clippy
alamb Aug 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/ast/data_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@ pub enum DataType {
/// [`SQLiteDialect`](crate::dialect::SQLiteDialect), from statements such
/// as `CREATE TABLE t1 (a)`.
Unspecified,
/// Trigger data type, returned by functions associated with triggers
///
/// [postgresql]: https://www.postgresql.org/docs/current/plpgsql-trigger.html
Trigger,
}

impl fmt::Display for DataType {
Expand Down Expand Up @@ -543,6 +547,7 @@ impl fmt::Display for DataType {
write!(f, "Nested({})", display_comma_separated(fields))
}
DataType::Unspecified => Ok(()),
DataType::Trigger => write!(f, "TRIGGER"),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/ast/ddl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ fn display_option_spaced<T: fmt::Display>(option: &Option<T>) -> impl fmt::Displ
/// `<constraint_characteristics> = [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ]`
///
/// Used in UNIQUE and foreign key constraints. The individual settings may occur in any order.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Default, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct ConstraintCharacteristics {
Expand Down
172 changes: 167 additions & 5 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ pub use self::query::{
TableAlias, TableFactor, TableFunctionArgs, TableVersion, TableWithJoins, Top, TopQuantity,
ValueTableMode, Values, WildcardAdditionalOptions, With, WithFill,
};

pub use self::trigger::{
TriggerEvent, TriggerExecBody, TriggerExecBodyType, TriggerObject, TriggerPeriod,
TriggerReferencing, TriggerReferencingType,
};

pub use self::value::{
escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
TrimWhereField, Value,
Expand All @@ -71,6 +77,7 @@ mod dml;
pub mod helpers;
mod operator;
mod query;
mod trigger;
mod value;

#[cfg(feature = "visitor")]
Expand Down Expand Up @@ -2282,7 +2289,7 @@ pub enum Statement {
DropFunction {
if_exists: bool,
/// One or more function to drop
func_desc: Vec<DropFunctionDesc>,
func_desc: Vec<FunctionDesc>,
/// `CASCADE` or `RESTRICT`
option: Option<ReferentialAction>,
},
Expand All @@ -2292,7 +2299,7 @@ pub enum Statement {
DropProcedure {
if_exists: bool,
/// One or more function to drop
proc_desc: Vec<DropFunctionDesc>,
proc_desc: Vec<FunctionDesc>,
/// `CASCADE` or `RESTRICT`
option: Option<ReferentialAction>,
},
Expand Down Expand Up @@ -2618,6 +2625,96 @@ pub enum Statement {
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_remote_function)
remote_connection: Option<ObjectName>,
},
/// CREATE TRIGGER
///
/// Examples:
///
/// ```sql
/// CREATE TRIGGER trigger_name
/// BEFORE INSERT ON table_name
/// FOR EACH ROW
/// EXECUTE FUNCTION trigger_function();
/// ```
///
/// Postgres: <https://www.postgresql.org/docs/current/sql-createtrigger.html>
CreateTrigger {
/// 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,
/// Multiple events can be specified using OR, such as `INSERT`, `UPDATE`, `DELETE`, or `TRUNCATE`.
events: Vec<TriggerEvent>,
/// 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<ObjectName>,
/// 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<TriggerReferencing>,
/// 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<Expr>,
/// Execute logic block
exec_body: TriggerExecBody,
/// The characteristic of the trigger, which include whether the trigger is `DEFERRABLE`, `INITIALLY DEFERRED`, or `INITIALLY IMMEDIATE`,
characteristics: Option<ConstraintCharacteristics>,
},
/// DROP TRIGGER
///
/// ```sql
/// DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
/// ```
///
DropTrigger {
if_exists: bool,
trigger_name: ObjectName,
table_name: ObjectName,
/// `CASCADE` or `RESTRICT`
option: Option<ReferentialAction>,
},
/// ```sql
/// CREATE PROCEDURE
/// ```
Expand Down Expand Up @@ -3394,6 +3491,71 @@ impl fmt::Display for Statement {
}
Ok(())
}
Statement::CreateTrigger {
or_replace,
is_constraint,
name,
period,
events,
table_name,
referenced_table_name,
referencing,
trigger_object,
condition,
include_each,
exec_body,
characteristics,
} => {
write!(
f,
"CREATE {or_replace}{is_constraint}TRIGGER {name} {period}",
or_replace = if *or_replace { "OR REPLACE " } else { "" },
is_constraint = if *is_constraint { "CONSTRAINT " } else { "" },
)?;

if !events.is_empty() {
write!(f, " {}", display_separated(events, " OR "))?;
}
write!(f, " ON {table_name}")?;

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 {
write!(f, " FOR {trigger_object}")?;
}
if let Some(condition) = condition {
write!(f, " WHEN {condition}")?;
}
write!(f, " EXECUTE {exec_body}")
}
Statement::DropTrigger {
if_exists,
trigger_name,
table_name,
option,
} => {
write!(f, "DROP TRIGGER")?;
if *if_exists {
write!(f, " IF EXISTS")?;
}
write!(f, " {trigger_name} ON {table_name}")?;
if let Some(option) = option {
write!(f, " {option}")?;
}
Ok(())
}
Statement::CreateProcedure {
name,
or_alter,
Expand Down Expand Up @@ -6026,16 +6188,16 @@ impl fmt::Display for DropFunctionOption {
}
}

/// Function describe in DROP FUNCTION.
/// Generic function description for DROP FUNCTION and CREATE TRIGGER.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct DropFunctionDesc {
pub struct FunctionDesc {
pub name: ObjectName,
pub args: Option<Vec<OperateFunctionArg>>,
}

impl fmt::Display for DropFunctionDesc {
impl fmt::Display for FunctionDesc {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)?;
if let Some(args) = &self.args {
Expand Down
Loading
Loading