Skip to content

Commit

Permalink
draft triggers create and drop
Browse files Browse the repository at this point in the history
  • Loading branch information
gronke committed Dec 26, 2024
1 parent 605ec44 commit d65dd04
Show file tree
Hide file tree
Showing 15 changed files with 632 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,20 @@ mod index_builder;
mod query_builder;
mod table_builder;
mod table_ref_builder;
mod trigger_builder;
// mod trigger_ref_builder;

pub use self::foreign_key_builder::*;
pub use self::index_builder::*;
pub use self::query_builder::*;
pub use self::table_builder::*;
pub use self::table_ref_builder::*;
pub use self::trigger_builder::*;
// pub use self::trigger_ref_builder::*;

pub trait GenericBuilder: QueryBuilder + SchemaBuilder {}

pub trait SchemaBuilder: TableBuilder + IndexBuilder + ForeignKeyBuilder {}
pub trait SchemaBuilder: TableBuilder + IndexBuilder + ForeignKeyBuilder + TriggerBuilder {}

pub trait QuotedBuilder {
/// The type of quote the builder uses.
Expand Down
1 change: 1 addition & 0 deletions src/backend/mysql/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub(crate) mod foreign_key;
pub(crate) mod index;
pub(crate) mod query;
pub(crate) mod table;
pub(crate) mod trigger;

use super::*;

Expand Down
3 changes: 3 additions & 0 deletions src/backend/mysql/trigger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use super::*;

impl TriggerBuilder for MysqlQueryBuilder {}
1 change: 1 addition & 0 deletions src/backend/postgres/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub(crate) mod foreign_key;
pub(crate) mod index;
pub(crate) mod query;
pub(crate) mod table;
pub(crate) mod trigger;
pub(crate) mod types;

use super::*;
Expand Down
3 changes: 3 additions & 0 deletions src/backend/postgres/trigger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use super::*;

impl TriggerBuilder for PostgresQueryBuilder {}
1 change: 1 addition & 0 deletions src/backend/sqlite/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub(crate) mod foreign_key;
pub(crate) mod index;
pub(crate) mod query;
pub(crate) mod table;
pub(crate) mod trigger;

use super::*;

Expand Down
3 changes: 3 additions & 0 deletions src/backend/sqlite/trigger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use super::*;

impl TriggerBuilder for SqliteQueryBuilder {}
48 changes: 48 additions & 0 deletions src/backend/trigger_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use crate::*;

pub trait TriggerBuilder: TableRefBuilder {
/// Translate [`TriggerCreateStatement`] into SQL statement.
fn prepare_trigger_create_statement(
&self,
create: &TriggerCreateStatement,
sql: &mut dyn SqlWriter,
) {
write!(sql, "CREATE TRIGGER ").unwrap();
self.prepare_create_trigger_if_not_exists(create, sql);

let trigger_ref = match &create.trigger.name {
Some(value) => value,
// auto-generate trigger name
_ => &create.trigger.trigger_ref(),
};
let trigger_ref: TableRef = trigger_ref.into();
self.prepare_table_ref_iden(&trigger_ref, sql);
write!(sql, " {} {} ON ", create.trigger.time, create.trigger.event).unwrap();
self.prepare_table_ref_iden(&create.trigger.table, sql);
write!(sql, " FOR EACH ROW\nBEGIN\n").unwrap();

write!(sql, "\nEND").unwrap();
}

/// Translate IF NOT EXISTS expression in [`TriggerCreateStatement`].
fn prepare_create_trigger_if_not_exists(
&self,
create: &TriggerCreateStatement,
sql: &mut dyn SqlWriter,
) {
if create.if_not_exists {
write!(sql, "IF NOT EXISTS ").unwrap();
}
}

// /// Translate [`TriggerRef`] into SQL statement.
// fn prepare_table_ref(&self, trigger_ref: &TableRef, sql: &mut dyn SqlWriter) {
// self.prepare_table_ref_iden(trigger_ref, sql)
// }

/// Translate [`TriggerDropStatement`] into SQL statement.
fn prepare_trigger_drop_statement(&self, drop: &TriggerDropStatement, sql: &mut dyn SqlWriter) {
write!(sql, "DROP TRIGGER ").unwrap();
self.prepare_table_ref_iden(&drop.name.clone().into(), sql);
}
}
12 changes: 12 additions & 0 deletions src/backend/trigger_ref_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::*;

pub trait TriggerRefBuilder: QuotedBuilder {
/// Translate [`TriggerRef`] that without values into SQL statement.
fn prepare_trigger_ref_iden(&self, table_ref: &TriggerRef, sql: &mut dyn SqlWriter) {
match table_ref {
TriggerRef::Trigger(iden) => {
iden.prepare(sql.as_writer(), self.quote());
}
}
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@ pub mod query;
pub mod schema;
pub mod table;
pub mod token;
pub mod trigger;
pub mod types;
pub mod value;

Expand All @@ -841,6 +842,7 @@ pub use query::*;
pub use schema::*;
pub use table::*;
pub use token::*;
pub use trigger::*;
pub use types::*;
pub use value::*;

Expand Down
40 changes: 40 additions & 0 deletions src/trigger/create.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use super::DefinedTrigger;
use crate::{backend::SchemaBuilder, SchemaStatementBuilder};
use inherent::inherent;

#[derive(Debug, Clone)]
pub struct TriggerCreateStatement {
pub(crate) trigger: DefinedTrigger,
pub(crate) if_not_exists: bool,
}

impl TriggerCreateStatement {
pub fn new(trigger: DefinedTrigger) -> Self {
TriggerCreateStatement {
trigger,
if_not_exists: false,
}
}

pub fn if_not_exists(&mut self) -> &mut Self {
self.if_not_exists = true;
self
}
}

#[inherent]
impl SchemaStatementBuilder for TriggerCreateStatement {
pub fn build<T: SchemaBuilder>(&self, schema_builder: T) -> String {
let mut sql = String::with_capacity(256);
schema_builder.prepare_trigger_create_statement(self, &mut sql);
sql
}

pub fn build_any(&self, schema_builder: &dyn SchemaBuilder) -> String {
let mut sql = String::with_capacity(256);
schema_builder.prepare_trigger_create_statement(self, &mut sql);
sql
}

pub fn to_string<T: SchemaBuilder>(&self, schema_builder: T) -> String;
}
99 changes: 99 additions & 0 deletions src/trigger/drop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use super::TriggerRef;
use crate::{backend::SchemaBuilder, SchemaStatementBuilder};
use inherent::inherent;

/// Drop a trigger
///
/// # Examples
///
/// ```
/// use sea_query::{tests_cfg::*, *};
///
/// let trigger = NamedTrigger::new("my_trigger")
/// .to_owned();
///
/// let drop_stmt = trigger.drop();
///
/// assert_eq!(
/// drop_stmt.to_string(MysqlQueryBuilder),
/// r#"DROP TRIGGER `my_trigger`"#
/// );
/// assert_eq!(
/// drop_stmt.to_string(PostgresQueryBuilder),
/// r#"DROP TRIGGER "my_trigger""#
/// );
/// assert_eq!(
/// drop_stmt.to_string(SqliteQueryBuilder),
/// r#"DROP TRIGGER "my_trigger""#
/// );
/// ```
///
/// # Trigger names can be derived from table name, action and action time
///
/// ```
/// use sea_query::{tests_cfg::*, *};
///
/// let trigger = UnnamedTrigger::new()
/// .before_insert(Glyph::Table);
///
/// let drop_stmt = trigger.drop();
///
/// assert_eq!(
/// drop_stmt.to_string(MysqlQueryBuilder),
/// r#"DROP TRIGGER `t_glyph_before_insert`"#
/// );
/// assert_eq!(
/// drop_stmt.to_string(PostgresQueryBuilder),
/// r#"DROP TRIGGER "t_glyph_before_insert""#
/// );
/// assert_eq!(
/// drop_stmt.to_string(SqliteQueryBuilder),
/// r#"DROP TRIGGER "t_glyph_before_insert""#
/// );
///
/// ```
#[derive(Debug, Clone)]
pub struct TriggerDropStatement {
pub(crate) name: TriggerRef,
pub(crate) if_exists: bool,
}

impl TriggerDropStatement {
/// Construct drop table statement
pub fn new(name: TriggerRef) -> Self {
Self {
name: name,
if_exists: false,
}
}

/// Drop table if exists
pub fn if_exists(&mut self) -> &mut Self {
self.if_exists = true;
self
}

pub fn take(&mut self) -> Self {
Self {
name: std::mem::take(&mut self.name),
if_exists: self.if_exists,
}
}
}

#[inherent]
impl SchemaStatementBuilder for TriggerDropStatement {
pub fn build<T: SchemaBuilder>(&self, schema_builder: T) -> String {
let mut sql = String::with_capacity(256);
schema_builder.prepare_trigger_drop_statement(self, &mut sql);
sql
}

pub fn build_any(&self, schema_builder: &dyn SchemaBuilder) -> String {
let mut sql = String::with_capacity(256);
schema_builder.prepare_trigger_drop_statement(self, &mut sql);
sql
}

pub fn to_string<T: SchemaBuilder>(&self, schema_builder: T) -> String;
}
Loading

0 comments on commit d65dd04

Please sign in to comment.