uqa_sql/routines/lifecycle/
diagnostics.rs1use super::{RoutineDropTarget, RoutineObjectDependents};
10use crate::SQLError;
11
12pub fn append_routine_cascade_notice(
13 notices: &mut Vec<crate::SQLNotice>,
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(crate::SQLNotice::notice(format!(
62 "drop cascades to {object}"
63 ))),
64 objects => notices.push(crate::SQLNotice::notice(format!(
65 "drop cascades to {} other objects",
66 objects.len()
67 ))),
68 }
69}
70
71pub fn routine_schema_relation_kind(foreign: bool) -> &'static str {
72 if foreign {
73 "foreign table"
74 } else {
75 "table"
76 }
77}
78
79pub fn ensure_no_function_dependencies(
80 target: &RoutineDropTarget,
81 dependents: &RoutineObjectDependents,
82) -> Result<(), SQLError> {
83 if dependents.columns.is_empty()
84 && dependents.defaults.is_empty()
85 && dependents.checks.is_empty()
86 && dependents.views.is_empty()
87 && dependents.triggers.is_empty()
88 && dependents.rules.is_empty()
89 && dependents.indexes.is_empty()
90 {
91 return Ok(());
92 }
93 let mut dependency_kinds = Vec::new();
94 if !dependents.columns.is_empty() {
95 dependency_kinds.push(format!(
96 "generated column(s) `{}`",
97 dependents
98 .columns
99 .iter()
100 .map(|(table, column, _)| format!("{table}.{column}"))
101 .collect::<Vec<_>>()
102 .join("`, `")
103 ));
104 }
105 if !dependents.defaults.is_empty() {
106 dependency_kinds.push(format!(
107 "default value(s) `{}`",
108 dependents
109 .defaults
110 .iter()
111 .map(|(table, column, _)| format!("{table}.{column}"))
112 .collect::<Vec<_>>()
113 .join("`, `")
114 ));
115 }
116 if !dependents.checks.is_empty() {
117 dependency_kinds.push(format!(
118 "CHECK constraint(s) `{}`",
119 dependents
120 .checks
121 .iter()
122 .map(|(table, constraint, _)| format!("{constraint} on {table}"))
123 .collect::<Vec<_>>()
124 .join("`, `")
125 ));
126 }
127 if !dependents.views.is_empty() {
128 dependency_kinds.push(format!("view(s) `{}`", dependents.views.join("`, `")));
129 }
130 if !dependents.triggers.is_empty() {
131 dependency_kinds.push(format!(
132 "trigger(s) `{}`",
133 dependents
134 .triggers
135 .iter()
136 .map(|(table, trigger)| format!("{trigger} on {table}"))
137 .collect::<Vec<_>>()
138 .join("`, `")
139 ));
140 }
141 if !dependents.indexes.is_empty() {
142 dependency_kinds.push(format!(
143 "indexes {}",
144 dependents
145 .indexes
146 .iter()
147 .map(uqa_core::RelationIdentity::qualified_name)
148 .collect::<Vec<_>>()
149 .join(", ")
150 ));
151 }
152 if !dependents.rules.is_empty() {
153 dependency_kinds.push(format!(
154 "rule(s) `{}`",
155 dependents
156 .rules
157 .iter()
158 .map(|(table, rule)| format!("{rule} on {table}"))
159 .collect::<Vec<_>>()
160 .join("`, `")
161 ));
162 }
163 Err(SQLError::Routine {
164 sqlstate: "2BP01".into(),
165 message: format!(
166 "cannot drop function {} because {} depend on it",
167 target.label(),
168 dependency_kinds.join(" and ")
169 ),
170 })
171}