helios_sof/sqlquery/
params.rs1use serde_json::Value;
10
11#[derive(Debug, Default, Clone)]
14pub struct SqlQueryRunParams {
15 pub format: Option<String>,
18 pub header: Option<bool>,
20 pub parameters: Option<Value>,
28 pub source: Option<String>,
30 pub limit: Option<u32>,
35}
36
37pub fn extract_sqlquery_params_from_json(body: &Value) -> SqlQueryRunParams {
39 let mut out = SqlQueryRunParams::default();
40 if body.get("resourceType").and_then(|v| v.as_str()) != Some("Parameters") {
41 return out;
42 }
43 let Some(entries) = body.get("parameter").and_then(|p| p.as_array()) else {
44 return out;
45 };
46 for p in entries {
47 let Some(name) = p.get("name").and_then(|n| n.as_str()) else {
48 continue;
49 };
50 match name {
51 "_format" | "format" => {
52 if out.format.is_none() {
53 out.format = read_str(p, &["valueCode", "valueString"]);
54 }
55 }
56 "header" => {
57 if out.header.is_none() {
58 if let Some(b) = p.get("valueBoolean").and_then(|v| v.as_bool()) {
59 out.header = Some(b);
60 } else if let Some(s) = p.get("valueString").and_then(|v| v.as_str()) {
61 out.header = Some(s == "true" || s == "1");
62 }
63 }
64 }
65 "parameters" => {
66 if out.parameters.is_none() {
67 if let Some(r) = p.get("resource") {
68 out.parameters = Some(r.clone());
69 }
70 }
71 }
72 "source" => {
73 if out.source.is_none() {
74 out.source = read_str(p, &["valueString", "valueUri"]);
75 }
76 }
77 "_limit" => {
78 if out.limit.is_none() {
79 if let Some(n) = p.get("valueInteger").and_then(|v| v.as_u64()) {
80 out.limit = Some(n as u32);
81 } else if let Some(n) = p
82 .get("valuePositiveInt")
83 .or_else(|| p.get("valueUnsignedInt"))
84 .and_then(|v| v.as_u64())
85 {
86 out.limit = Some(n as u32);
87 }
88 }
89 }
90 _ => {}
91 }
92 }
93 out
94}
95
96fn read_str(p: &Value, keys: &[&str]) -> Option<String> {
97 for k in keys {
98 if let Some(s) = p.get(*k).and_then(|v| v.as_str()) {
99 return Some(s.to_string());
100 }
101 }
102 None
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use serde_json::json;
109
110 #[test]
111 fn extracts_format_and_header() {
112 let body = json!({
113 "resourceType": "Parameters",
114 "parameter": [
115 {"name": "_format", "valueCode": "csv"},
116 {"name": "header", "valueBoolean": false}
117 ]
118 });
119 let p = extract_sqlquery_params_from_json(&body);
120 assert_eq!(p.format.as_deref(), Some("csv"));
121 assert_eq!(p.header, Some(false));
122 }
123
124 #[test]
125 fn extracts_parameter_bindings() {
126 let body = json!({
127 "resourceType": "Parameters",
128 "parameter": [
129 {"name": "_format", "valueCode": "json"},
130 {"name": "parameters", "resource": {
131 "resourceType": "Parameters",
132 "parameter": [{"name": "min_age", "valueInteger": 18}]
133 }}
134 ]
135 });
136 let p = extract_sqlquery_params_from_json(&body);
137 assert_eq!(p.format.as_deref(), Some("json"));
138 assert!(p.parameters.is_some());
139 }
140
141 #[test]
142 fn non_parameters_body_returns_default() {
143 let p = extract_sqlquery_params_from_json(&json!({"resourceType": "Bundle"}));
144 assert!(p.format.is_none());
145 }
146
147 #[test]
148 fn extracts_limit() {
149 let body = json!({
150 "resourceType": "Parameters",
151 "parameter": [
152 {"name": "_limit", "valueInteger": 50}
153 ]
154 });
155 let p = extract_sqlquery_params_from_json(&body);
156 assert_eq!(p.limit, Some(50));
157 }
158
159 #[test]
160 fn pre_ballot_query_parameters_are_ignored() {
161 let body = json!({
165 "resourceType": "Parameters",
166 "parameter": [
167 {"name": "_format", "valueCode": "json"},
168 {"name": "queryReference", "valueReference": {"reference": "Library/foo"}},
169 {"name": "queryResource", "resource": {"resourceType": "Library"}}
170 ]
171 });
172 let p = extract_sqlquery_params_from_json(&body);
173 assert_eq!(p.format.as_deref(), Some("json"));
174 assert!(p.parameters.is_none());
175 }
176}