From a22d06cd668734b870eb1009600c3acd9a8ea534 Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Wed, 28 May 2025 11:44:40 -0300 Subject: [PATCH] impl ToSqlString for CREATE TRIGGER stmt --- .../src/to_sql_string/stmt/create_trigger.rs | 236 ++++++++++++++++++ .../src/to_sql_string/stmt/mod.rs | 2 + 2 files changed, 238 insertions(+) create mode 100644 vendored/sqlite3-parser/src/to_sql_string/stmt/create_trigger.rs diff --git a/vendored/sqlite3-parser/src/to_sql_string/stmt/create_trigger.rs b/vendored/sqlite3-parser/src/to_sql_string/stmt/create_trigger.rs new file mode 100644 index 000000000..e524678da --- /dev/null +++ b/vendored/sqlite3-parser/src/to_sql_string/stmt/create_trigger.rs @@ -0,0 +1,236 @@ +use crate::{ast, to_sql_string::ToSqlString}; + +impl ToSqlString for ast::CreateTrigger { + fn to_sql_string(&self, context: &C) -> String { + format!( + "CREATE{} TRIGGER {}{} {}{} ON {} {}{} BEGIN {} END", + self.temporary.then_some(" TEMP").unwrap_or(""), + self.if_not_exists.then_some("IF NOT EXISTS ").unwrap_or(""), + self.trigger_name.to_sql_string(context), + self.time.map_or("".to_string(), |time| format!( + " {}", + time.to_sql_string(context) + )), + self.event.to_sql_string(context), + self.tbl_name.to_sql_string(context), + self.for_each_row.then_some("FOR EACH ROW ").unwrap_or(""), + self.when_clause + .as_ref() + .map_or("".to_string(), |expr| expr.to_string()), + self.commands + .iter() + .map(|command| command.to_sql_string(context)) + .collect::>() + .join("; ") + ) + } +} + +impl ToSqlString for ast::TriggerTime { + fn to_sql_string(&self, _context: &C) -> String { + match self { + Self::After => "AFTER", + Self::Before => "BEFORE", + Self::InsteadOf => "INSTEAD OF", + } + .to_string() + } +} + +impl ToSqlString for ast::TriggerEvent { + fn to_sql_string(&self, _context: &C) -> String { + match self { + Self::Delete => "DELETE".to_string(), + Self::Insert => "INSERT".to_string(), + Self::Update => "UPDATE".to_string(), + Self::UpdateOf(col_names) => format!( + "UPDATE OF {}", + col_names + .iter() + .map(|name| name.0.clone()) + .collect::>() + .join(", ") + ), + } + } +} + +impl ToSqlString for ast::TriggerCmd { + fn to_sql_string(&self, context: &C) -> String { + match self { + Self::Delete(delete) => delete.to_sql_string(context), + Self::Insert(insert) => insert.to_sql_string(context), + Self::Select(select) => select.to_sql_string(context), + Self::Update(update) => update.to_sql_string(context), + } + } +} + +impl ToSqlString for ast::TriggerCmdDelete { + fn to_sql_string(&self, context: &C) -> String { + // https://sqlite.org/lang_createtrigger.html + // TODO: no CTEs and returning clause present in ast for delete + // Also for tbl_name it should be a qualified table name with indexed by clauses + format!( + "DELETE FROM {}{}", + self.tbl_name.0, + self.where_clause + .as_ref() + .map_or("".to_string(), |expr| format!( + " {}", + expr.to_sql_string(context) + )) + ) + } +} + +impl ToSqlString for ast::TriggerCmdInsert { + fn to_sql_string(&self, context: &C) -> String { + // https://sqlite.org/lang_createtrigger.html + // FOR TRIGGER SHOULD JUST USE REGULAR INSERT AST + // TODO: no ALIAS after table name + // TODO: no DEFAULT VALUES + format!( + "INSERT {}INTO {} {}{}{}{}", + self.or_conflict.map_or("".to_string(), |conflict| format!( + "OR {} ", + conflict.to_sql_string(context) + )), + self.tbl_name.0, + self.col_names + .as_ref() + .map_or("".to_string(), |col_names| format!( + "({}) ", + col_names + .iter() + .map(|name| name.0.clone()) + .collect::>() + .join(", ") + )), + self.select.to_sql_string(context), + self.upsert + .as_ref() + .map_or("".to_string(), |upsert| format!( + " {}", + upsert.to_sql_string(context) + )), + self.returning + .as_ref() + .map_or("".to_string(), |returning| format!( + " RETURNING {}", + returning + .iter() + .map(|col| col.to_sql_string(context)) + .collect::>() + .join(", ") + )) + ) + } +} + +impl ToSqlString for ast::Upsert { + fn to_sql_string(&self, context: &C) -> String { + format!( + "ON CONFLICT {}{}{}", + self.index.as_ref().map_or("".to_string(), |index| format!( + "{} ", + index.to_sql_string(context) + )), + self.do_clause.to_sql_string(context), + self.next.as_ref().map_or("".to_string(), |next| format!( + " {}", + next.to_sql_string(context) + )) + ) + } +} + +impl ToSqlString for ast::UpsertIndex { + fn to_sql_string(&self, context: &C) -> String { + format!( + "({}){}", + self.targets + .iter() + .map(|target| target.to_sql_string(context)) + .collect::>() + .join(", "), + self.where_clause + .as_ref() + .map_or("".to_string(), |expr| format!( + " WHERE {}", + expr.to_sql_string(context) + )) + ) + } +} + +impl ToSqlString for ast::UpsertDo { + fn to_sql_string(&self, context: &C) -> String { + match self { + Self::Nothing => "NOTHING".to_string(), + Self::Set { sets, where_clause } => { + format!( + "UPDATE SET {}{}", + sets.iter() + .map(|set| set.to_sql_string(context)) + .collect::>() + .join(", "), + where_clause.as_ref().map_or("".to_string(), |expr| format!( + " WHERE {}", + expr.to_sql_string(context) + )) + ) + } + } + } +} + +impl ToSqlString for ast::Set { + fn to_sql_string(&self, context: &C) -> String { + if self.col_names.len() == 1 { + format!( + "{} = {}", + &self.col_names[0], + self.expr.to_sql_string(context) + ) + } else { + format!( + "({}) = {}", + self.col_names + .iter() + .map(|name| name.0.clone()) + .collect::>() + .join(", "), + self.expr.to_sql_string(context) + ) + } + } +} + +impl ToSqlString for ast::TriggerCmdUpdate { + fn to_sql_string(&self, context: &C) -> String { + format!( + "UPDATE {}{} SET {}{}{}", + self.or_conflict.map_or("".to_string(), |conflict| format!( + "OR {}", + conflict.to_sql_string(context) + )), + self.tbl_name.0, // TODO: should be a qualified table name, + self.sets + .iter() + .map(|set| set.to_sql_string(context)) + .collect::>() + .join(", "), + self.from.as_ref().map_or("".to_string(), |from| format!( + " {}", + from.to_sql_string(context) + )), + self.where_clause + .as_ref() + .map_or("".to_string(), |expr| format!( + " WHERE {}", + expr.to_sql_string(context) + )) + ) + } +} diff --git a/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs b/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs index 8f720d423..f09e45116 100644 --- a/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs +++ b/vendored/sqlite3-parser/src/to_sql_string/stmt/mod.rs @@ -4,6 +4,7 @@ use super::ToSqlString; mod alter_table; mod create_table; +mod create_trigger; mod select; impl ToSqlString for ast::Stmt { @@ -91,6 +92,7 @@ impl ToSqlString for ast::Stmt { body.to_sql_string(context) ) } + Self::CreateTrigger(trigger) => trigger.to_sql_string(context), Self::Select(select) => select.to_sql_string(context), _ => todo!(), }