dbrest_core/plan/
call_plan.rs1use compact_str::CompactString;
7use std::collections::HashMap;
8
9use crate::api_request::types::FieldName;
10use crate::schema_cache::routine::{Routine, RoutineParam};
11use crate::types::identifiers::QualifiedIdentifier;
12
13use super::types::CoercibleSelectField;
14
15#[derive(Debug, Clone)]
23pub struct CallPlan {
24 pub qi: QualifiedIdentifier,
26 pub params: CallParams,
28 pub args: CallArgs,
30 pub scalar: bool,
32 pub set_of_scalar: bool,
34 pub filter_fields: Vec<FieldName>,
36 pub returning: Vec<CoercibleSelectField>,
38}
39
40#[derive(Debug, Clone)]
46pub enum CallParams {
47 KeyParams(Vec<RoutineParam>),
49 OnePosParam(RoutineParam),
51}
52
53impl CallParams {
54 pub fn params(&self) -> &[RoutineParam] {
56 match self {
57 CallParams::KeyParams(params) => params,
58 CallParams::OnePosParam(param) => std::slice::from_ref(param),
59 }
60 }
61}
62
63#[derive(Debug, Clone)]
69pub enum CallArgs {
70 DirectArgs(HashMap<CompactString, RpcParamValue>),
72 JsonArgs(Option<bytes::Bytes>),
74}
75
76#[derive(Debug, Clone, PartialEq, Eq)]
78pub enum RpcParamValue {
79 Fixed(CompactString),
81 Variadic(Vec<CompactString>),
83}
84
85pub fn to_rpc_params(
94 routine: &Routine,
95 params: &[(CompactString, CompactString)],
96) -> HashMap<CompactString, RpcParamValue> {
97 let mut result = HashMap::new();
98
99 for (key, value) in params {
100 if let Some(rp) = routine.get_param(key) {
101 if rp.is_variadic {
102 let values: Vec<CompactString> = value
103 .split(',')
104 .map(|v| CompactString::from(v.trim()))
105 .collect();
106 result.insert(key.clone(), RpcParamValue::Variadic(values));
107 } else {
108 result.insert(key.clone(), RpcParamValue::Fixed(value.clone()));
109 }
110 } else {
111 result.insert(key.clone(), RpcParamValue::Fixed(value.clone()));
113 }
114 }
115
116 result
117}
118
119#[cfg(test)]
124mod tests {
125 use super::*;
126 use crate::test_helpers::*;
127
128 #[test]
129 fn test_to_rpc_params_fixed() {
130 let routine = test_routine()
131 .param(test_param().name("id").pg_type("integer").build())
132 .param(test_param().name("name").pg_type("text").build())
133 .build();
134
135 let params = vec![("id".into(), "42".into()), ("name".into(), "alice".into())];
136
137 let rpc_params = to_rpc_params(&routine, ¶ms);
138 assert_eq!(
139 rpc_params.get("id"),
140 Some(&RpcParamValue::Fixed("42".into()))
141 );
142 assert_eq!(
143 rpc_params.get("name"),
144 Some(&RpcParamValue::Fixed("alice".into()))
145 );
146 }
147
148 #[test]
149 fn test_to_rpc_params_variadic() {
150 let routine = test_routine()
151 .param(
152 test_param()
153 .name("ids")
154 .pg_type("integer")
155 .is_variadic(true)
156 .build(),
157 )
158 .is_variadic(true)
159 .build();
160
161 let params = vec![("ids".into(), "1,2,3".into())];
162
163 let rpc_params = to_rpc_params(&routine, ¶ms);
164 assert_eq!(
165 rpc_params.get("ids"),
166 Some(&RpcParamValue::Variadic(vec![
167 "1".into(),
168 "2".into(),
169 "3".into()
170 ]))
171 );
172 }
173
174 #[test]
175 fn test_to_rpc_params_unknown_param() {
176 let routine = test_routine()
177 .param(test_param().name("id").build())
178 .build();
179
180 let params = vec![("unknown_key".into(), "value".into())];
181
182 let rpc_params = to_rpc_params(&routine, ¶ms);
183 assert_eq!(
184 rpc_params.get("unknown_key"),
185 Some(&RpcParamValue::Fixed("value".into()))
186 );
187 }
188
189 #[test]
190 fn test_call_params_key_params() {
191 let p = test_param().name("x").build();
192 let cp = CallParams::KeyParams(vec![p]);
193 assert_eq!(cp.params().len(), 1);
194 }
195
196 #[test]
197 fn test_call_params_one_pos() {
198 let p = test_param().name("body").pg_type("json").build();
199 let cp = CallParams::OnePosParam(p);
200 assert_eq!(cp.params().len(), 1);
201 assert_eq!(cp.params()[0].name.as_str(), "body");
202 }
203}