uqa_sql/routines/lifecycle/
diagnostics.rs1use super::{RoutineDropTarget, RoutineObjectDependents};
10use crate::SQLError;
11
12pub fn append_routine_cascade_notice(
13 notices: &mut Vec<(&'static str, String)>,
14 cascaded_routines: &[RoutineDropTarget],
15 dependents: &RoutineObjectDependents,
16) {
17 let mut cascaded = cascaded_routines
18 .iter()
19 .map(|target| format!("{} {}", target.kind(), target.label()))
20 .collect::<Vec<_>>();
21 cascaded.extend(dependents.columns.iter().map(|(table, column, foreign)| {
22 format!(
23 "column {column} of {} {table}",
24 routine_schema_relation_kind(*foreign)
25 )
26 }));
27 cascaded.extend(dependents.defaults.iter().map(|(table, column, foreign)| {
28 format!(
29 "default value for column {column} of {} {table}",
30 routine_schema_relation_kind(*foreign)
31 )
32 }));
33 cascaded.extend(
34 dependents
35 .checks
36 .iter()
37 .map(|(table, constraint, foreign)| {
38 format!(
39 "constraint {constraint} on {} {table}",
40 routine_schema_relation_kind(*foreign)
41 )
42 }),
43 );
44 cascaded.extend(dependents.views.iter().map(|view| format!("view {view}")));
45 cascaded.extend(
46 dependents
47 .triggers
48 .iter()
49 .map(|(table, trigger)| format!("trigger {trigger} on table {table}")),
50 );
51 cascaded.extend(
52 dependents
53 .rules
54 .iter()
55 .map(|(table, rule)| format!("rule {rule} on table {table}")),
56 );
57 cascaded.sort();
58 cascaded.dedup();
59 match cascaded.as_slice() {
60 [] => {}
61 [object] => notices.push(("NOTICE", format!("drop cascades to {object}"))),
62 objects => notices.push((
63 "NOTICE",
64 format!("drop cascades to {} other objects", objects.len()),
65 )),
66 }
67}
68
69pub fn routine_schema_relation_kind(foreign: bool) -> &'static str {
70 if foreign {
71 "foreign table"
72 } else {
73 "table"
74 }
75}
76
77pub fn ensure_no_function_dependencies(
78 target: &RoutineDropTarget,
79 dependents: &RoutineObjectDependents,
80) -> Result<(), SQLError> {
81 if dependents.columns.is_empty()
82 && dependents.defaults.is_empty()
83 && dependents.checks.is_empty()
84 && dependents.views.is_empty()
85 && dependents.triggers.is_empty()
86 && dependents.rules.is_empty()
87 && dependents.indexes.is_empty()
88 {
89 return Ok(());
90 }
91 let mut dependency_kinds = Vec::new();
92 if !dependents.columns.is_empty() {
93 dependency_kinds.push(format!(
94 "generated column(s) `{}`",
95 dependents
96 .columns
97 .iter()
98 .map(|(table, column, _)| format!("{table}.{column}"))
99 .collect::<Vec<_>>()
100 .join("`, `")
101 ));
102 }
103 if !dependents.defaults.is_empty() {
104 dependency_kinds.push(format!(
105 "default value(s) `{}`",
106 dependents
107 .defaults
108 .iter()
109 .map(|(table, column, _)| format!("{table}.{column}"))
110 .collect::<Vec<_>>()
111 .join("`, `")
112 ));
113 }
114 if !dependents.checks.is_empty() {
115 dependency_kinds.push(format!(
116 "CHECK constraint(s) `{}`",
117 dependents
118 .checks
119 .iter()
120 .map(|(table, constraint, _)| format!("{constraint} on {table}"))
121 .collect::<Vec<_>>()
122 .join("`, `")
123 ));
124 }
125 if !dependents.views.is_empty() {
126 dependency_kinds.push(format!("view(s) `{}`", dependents.views.join("`, `")));
127 }
128 if !dependents.triggers.is_empty() {
129 dependency_kinds.push(format!(
130 "trigger(s) `{}`",
131 dependents
132 .triggers
133 .iter()
134 .map(|(table, trigger)| format!("{trigger} on {table}"))
135 .collect::<Vec<_>>()
136 .join("`, `")
137 ));
138 }
139 if !dependents.indexes.is_empty() {
140 dependency_kinds.push(format!(
141 "indexes {}",
142 dependents
143 .indexes
144 .iter()
145 .map(uqa_core::RelationIdentity::qualified_name)
146 .collect::<Vec<_>>()
147 .join(", ")
148 ));
149 }
150 if !dependents.rules.is_empty() {
151 dependency_kinds.push(format!(
152 "rule(s) `{}`",
153 dependents
154 .rules
155 .iter()
156 .map(|(table, rule)| format!("{rule} on {table}"))
157 .collect::<Vec<_>>()
158 .join("`, `")
159 ));
160 }
161 Err(SQLError::Routine {
162 sqlstate: "2BP01".into(),
163 message: format!(
164 "cannot drop function {} because {} depend on it",
165 target.label(),
166 dependency_kinds.join(" and ")
167 ),
168 })
169}