sz_configtool_lib/functions/
distinct.rs1use crate::error::SzConfigError;
7use crate::helpers::{
8 add_to_config_array, delete_from_config_array, find_in_config_array, get_next_id,
9};
10use serde_json::{Value, json};
11
12#[derive(Debug, Clone, Default)]
18pub struct AddDistinctFunctionParams<'a> {
19 pub connect_str: &'a str,
20 pub description: Option<&'a str>,
21 pub language: Option<&'a str>,
22}
23
24impl<'a> TryFrom<&'a Value> for AddDistinctFunctionParams<'a> {
25 type Error = SzConfigError;
26
27 fn try_from(json: &'a Value) -> Result<Self, SzConfigError> {
28 Ok(Self {
29 connect_str: json
30 .get("connectStr")
31 .and_then(|v| v.as_str())
32 .ok_or_else(|| SzConfigError::MissingField("connectStr".to_string()))?,
33 description: json.get("description").and_then(|v| v.as_str()),
34 language: json.get("language").and_then(|v| v.as_str()),
35 })
36 }
37}
38
39#[derive(Debug, Clone, Default)]
41pub struct SetDistinctFunctionParams<'a> {
42 pub connect_str: Option<&'a str>,
43 pub description: Option<&'a str>,
44 pub language: Option<&'a str>,
45}
46
47pub fn add_distinct_function(
60 config_json: &str,
61 dfunc_code: &str,
62 params: AddDistinctFunctionParams,
63) -> Result<(String, Value), SzConfigError> {
64 let dfunc_code = dfunc_code.to_uppercase();
65
66 if find_in_config_array(config_json, "CFG_DFUNC", "DFUNC_CODE", &dfunc_code)?.is_some() {
68 return Err(SzConfigError::validation(format!(
69 "Distinct function already exists: {dfunc_code}"
70 )));
71 }
72
73 if params.connect_str.trim().is_empty() {
75 return Err(SzConfigError::validation(
76 "CONNECTSTR cannot be blank".to_string(),
77 ));
78 }
79
80 let config_data: Value =
82 serde_json::from_str(config_json).map_err(|e| SzConfigError::json_parse(e.to_string()))?;
83 let dfunc_id = get_next_id(&config_data, "G2_CONFIG.CFG_DFUNC", "DFUNC_ID", 1)?;
84
85 let mut new_record = json!({
87 "DFUNC_ID": dfunc_id,
88 "DFUNC_CODE": dfunc_code,
89 "CONNECT_STR": params.connect_str,
90 });
91
92 new_record["DFUNC_DESC"] = match params.description {
94 Some(desc) => json!(desc),
95 None => Value::Null,
96 };
97 new_record["LANGUAGE"] = match params.language {
98 Some(lang) => json!(lang),
99 None => Value::Null,
100 };
101
102 let modified_json = add_to_config_array(config_json, "CFG_DFUNC", new_record.clone())?;
104
105 Ok((modified_json, new_record))
106}
107
108pub fn delete_distinct_function(
120 config_json: &str,
121 dfunc_code: &str,
122) -> Result<(String, Value), SzConfigError> {
123 let dfunc_code = dfunc_code.to_uppercase();
124
125 let function = find_in_config_array(config_json, "CFG_DFUNC", "DFUNC_CODE", &dfunc_code)?
127 .ok_or_else(|| {
128 SzConfigError::not_found(format!("Distinct function not found: {dfunc_code}"))
129 })?;
130
131 let modified_json =
133 delete_from_config_array(config_json, "CFG_DFUNC", "DFUNC_CODE", &dfunc_code)?;
134
135 Ok((modified_json, function))
136}
137
138pub fn get_distinct_function(config_json: &str, dfunc_code: &str) -> Result<Value, SzConfigError> {
150 let dfunc_code = dfunc_code.to_uppercase();
151
152 find_in_config_array(config_json, "CFG_DFUNC", "DFUNC_CODE", &dfunc_code)?.ok_or_else(|| {
153 SzConfigError::not_found(format!("Distinct function not found: {dfunc_code}"))
154 })
155}
156
157pub fn list_distinct_functions(config_json: &str) -> Result<Vec<Value>, SzConfigError> {
168 let config_data: Value =
169 serde_json::from_str(config_json).map_err(|e| SzConfigError::json_parse(e.to_string()))?;
170
171 let items: Vec<Value> = if let Some(g2_config) = config_data.get("G2_CONFIG")
172 && let Some(array) = g2_config.get("CFG_DFUNC")
173 && let Some(items) = array.as_array()
174 {
175 items
176 .iter()
177 .map(|item| {
178 json!({
179 "id": item.get("DFUNC_ID").and_then(|v| v.as_i64()).unwrap_or(0),
180 "function": item.get("DFUNC_CODE").and_then(|v| v.as_str()).unwrap_or(""),
181 "connectStr": item.get("CONNECT_STR").and_then(|v| v.as_str()).unwrap_or(""),
182 "anonSupport": item.get("ANON_SUPPORT").and_then(|v| v.as_str()).unwrap_or(""),
183 "language": item.get("LANGUAGE").and_then(|v| v.as_str()).unwrap_or("")
184 })
185 })
186 .collect()
187 } else {
188 Vec::new()
189 };
190
191 Ok(items)
192}
193
194pub fn set_distinct_function(
207 config_json: &str,
208 dfunc_code: &str,
209 params: SetDistinctFunctionParams,
210) -> Result<(String, Value), SzConfigError> {
211 let dfunc_code = dfunc_code.to_uppercase();
212
213 let mut function = find_in_config_array(config_json, "CFG_DFUNC", "DFUNC_CODE", &dfunc_code)?
215 .ok_or_else(|| {
216 SzConfigError::not_found(format!("Distinct function not found: {dfunc_code}"))
217 })?;
218
219 if let Some(obj) = function.as_object_mut() {
221 if let Some(conn) = params.connect_str {
222 obj.insert("CONNECT_STR".to_string(), json!(conn));
223 }
224 if let Some(desc) = params.description {
225 obj.insert("DFUNC_DESC".to_string(), json!(desc));
226 }
227 if let Some(lang) = params.language {
228 obj.insert("LANGUAGE".to_string(), json!(lang));
229 }
230 }
231
232 let temp_json = delete_from_config_array(config_json, "CFG_DFUNC", "DFUNC_CODE", &dfunc_code)?;
234 let modified_json = add_to_config_array(&temp_json, "CFG_DFUNC", function.clone())?;
235
236 Ok((modified_json, function))
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242
243 fn get_test_config() -> String {
244 json!({
245 "G2_CONFIG": {
246 "CFG_DFUNC": [
247 {
248 "DFUNC_ID": 1,
249 "DFUNC_CODE": "DIST_NAME",
250 "CONNECT_STR": "g2DistName",
251 "LANGUAGE": "en"
252 }
253 ]
254 }
255 })
256 .to_string()
257 }
258
259 #[test]
260 fn test_add_distinct_function() {
261 let config = get_test_config();
262 let result = add_distinct_function(
263 &config,
264 "custom_dist",
265 AddDistinctFunctionParams {
266 connect_str: "g2CustomDist",
267 description: Some("Custom distinct"),
268 language: Some("en"),
269 },
270 );
271 assert!(result.is_ok());
272 let (modified, record) = result.unwrap();
273 assert!(modified.contains("CUSTOM_DIST"));
274 assert_eq!(record["DFUNC_CODE"], "CUSTOM_DIST");
275 }
276
277 #[test]
278 fn test_list_distinct_functions() {
279 let config = get_test_config();
280 let result = list_distinct_functions(&config);
281 assert!(result.is_ok());
282 let items = result.unwrap();
283 assert_eq!(items.len(), 1);
284 assert_eq!(items[0]["function"], "DIST_NAME");
285 }
286}