use super::naming::{function_name, Direction, NEEDS_BACKFILL_COLUMN};
use super::Trigger;
use crate::database::versions::quote::{quote_ident, quote_literal};
pub(super) fn function(trigger: &Trigger<'_>) -> String {
let name = quote_ident(&function_name(trigger.table, trigger.physical_column));
let comparison = match trigger.direction {
Direction::Up => "<>",
Direction::Down => "=",
};
format!(
"CREATE OR REPLACE FUNCTION {name}()\n\
RETURNS TRIGGER\n\
LANGUAGE PLPGSQL\n\
AS $$\n\
DECLARE\n \
search_path TEXT;\n\
BEGIN\n \
SELECT btrim(split_part(current_setting('search_path'), ',', 1), ' \"')\n \
INTO search_path;\n \
IF search_path {comparison} {latest} THEN\n \
NEW.{target} = {expression};\n \
NEW.{marker} = false;\n \
END IF;\n \
RETURN NEW;\n\
END; $$",
latest = quote_literal(trigger.latest_schema),
target = quote_ident(trigger.physical_column),
expression = parenthesize(&trigger.resolved_expression()),
marker = quote_ident(NEEDS_BACKFILL_COLUMN),
)
}
fn parenthesize(expression: &str) -> String {
let trimmed = expression.trim();
if trimmed.starts_with('(') && trimmed.ends_with(')') {
return trimmed.to_string();
}
format!("({trimmed})")
}