1use super::{
8 Deserialize, Expr, FunctionParallel, RoutineAclEntry, RoutineConfigAction,
9 RoutineSecurityAttributes, Serialize, Statement,
10};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
15pub enum FunctionParamMode {
16 In,
18 Out,
21 InOut,
23 Variadic,
25 Table,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct FunctionParam {
33 pub name: String,
36 pub type_name: String,
39 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub type_reference: Option<RoutineColumnTypeReference>,
42 pub mode: FunctionParamMode,
43 #[serde(default, skip_serializing_if = "Option::is_none")]
45 pub default: Option<Expr>,
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
50pub struct RoutineColumnTypeReference {
51 pub schema: Option<String>,
52 pub relation: String,
53 pub column: String,
54}
55
56impl RoutineColumnTypeReference {
57 pub fn new(schema: Option<String>, relation: String, column: String) -> Self {
58 Self {
59 schema,
60 relation,
61 column,
62 }
63 }
64
65 pub fn relation_reference(&self) -> String {
66 match self.schema.as_deref() {
67 Some(schema) => format!(
68 "{}.{}",
69 render_identifier_component(schema),
70 render_identifier_component(&self.relation)
71 ),
72 None => render_identifier_component(&self.relation),
73 }
74 }
75
76 pub fn type_reference(&self) -> String {
77 format!(
78 "{}.{}%type",
79 self.relation_reference(),
80 render_identifier_component(&self.column)
81 )
82 }
83}
84
85fn render_identifier_component(component: &str) -> String {
86 let can_render_bare = component
87 .bytes()
88 .enumerate()
89 .all(|(index, byte)| match byte {
90 b'a'..=b'z' | b'_' => true,
91 b'0'..=b'9' | b'$' => index != 0,
92 _ => false,
93 });
94 if can_render_bare && !component.is_empty() {
95 component.to_string()
96 } else {
97 format!("\"{}\"", component.replace('"', "\"\""))
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub enum FunctionReturns {
104 None,
107 Scalar { type_name: String },
109 SetOf { type_name: String },
111 Table,
115}
116
117#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
119pub enum FunctionVolatility {
120 Immutable,
121 Stable,
122 #[default]
123 Volatile,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub enum FunctionBody {
129 Source(String),
132 Statements(Vec<Statement>),
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct CreateFunction {
140 #[serde(default, skip_serializing_if = "Option::is_none")]
142 pub object_id: Option<[u8; 16]>,
143 pub name: String,
144 pub or_replace: bool,
145 pub is_procedure: bool,
146 pub params: Vec<FunctionParam>,
147 pub returns: FunctionReturns,
148 #[serde(default, skip_serializing_if = "Option::is_none")]
150 pub return_type_reference: Option<RoutineColumnTypeReference>,
151 pub language: String,
153 pub body: FunctionBody,
154 #[serde(default, skip_serializing_if = "Vec::is_empty")]
156 pub creation_search_path: Vec<String>,
157 pub volatility: FunctionVolatility,
158 pub strict: bool,
161 #[serde(default)]
163 pub owner: String,
164 #[serde(default, flatten)]
166 pub security: RoutineSecurityAttributes,
167 #[serde(default)]
169 pub parallel: FunctionParallel,
170 #[serde(default, skip_serializing_if = "Option::is_none")]
172 pub support: Option<String>,
173 #[serde(default, skip_serializing_if = "Vec::is_empty")]
175 pub config: Vec<(String, String)>,
176 #[serde(default, skip_serializing_if = "Vec::is_empty")]
178 pub config_actions: Vec<RoutineConfigAction>,
179 #[serde(default, skip_serializing_if = "Option::is_none")]
181 pub execute_acl: Option<Vec<RoutineAclEntry>>,
182}
183
184impl CreateFunction {
185 pub fn identity_params(&self) -> Vec<&FunctionParam> {
187 self.params
188 .iter()
189 .filter(|param| Self::is_identity_param(param))
190 .collect()
191 }
192
193 pub fn identity_arity(&self) -> usize {
195 self.params
196 .iter()
197 .filter(|param| Self::is_identity_param(param))
198 .count()
199 }
200
201 fn is_identity_param(param: &FunctionParam) -> bool {
202 matches!(
203 param.mode,
204 FunctionParamMode::In | FunctionParamMode::InOut | FunctionParamMode::Variadic
205 )
206 }
207
208 pub fn call_params(&self) -> Vec<&FunctionParam> {
210 self.params
211 .iter()
212 .filter(|param| self.is_call_param(param))
213 .collect()
214 }
215
216 pub fn call_arity(&self) -> usize {
218 self.params
219 .iter()
220 .filter(|param| self.is_call_param(param))
221 .count()
222 }
223
224 pub fn required_call_arity(&self) -> usize {
226 self.params
227 .iter()
228 .filter(|param| {
229 self.is_call_param(param)
230 && param.default.is_none()
231 && param.mode != FunctionParamMode::Variadic
232 })
233 .count()
234 }
235
236 fn is_call_param(&self, param: &FunctionParam) -> bool {
237 match param.mode {
238 FunctionParamMode::In | FunctionParamMode::InOut | FunctionParamMode::Variadic => true,
239 FunctionParamMode::Out => self.is_procedure,
240 FunctionParamMode::Table => false,
241 }
242 }
243
244 pub fn signature_arity(&self) -> usize {
246 self.call_arity()
247 }
248
249 pub fn required_arity(&self) -> usize {
251 self.required_call_arity()
252 }
253
254 pub fn signature_params(&self) -> Vec<&FunctionParam> {
256 self.call_params()
257 }
258
259 pub fn output_params(&self) -> Vec<&FunctionParam> {
262 self.params
263 .iter()
264 .filter(|p| {
265 matches!(
266 p.mode,
267 FunctionParamMode::Out | FunctionParamMode::InOut | FunctionParamMode::Table
268 )
269 })
270 .collect()
271 }
272
273 pub fn returns_set(&self) -> bool {
276 matches!(
277 self.returns,
278 FunctionReturns::SetOf { .. } | FunctionReturns::Table
279 )
280 }
281}
282
283#[derive(Debug, Clone, Serialize, Deserialize)]
285pub struct DropFunctionItem {
286 pub name: String,
287 pub arg_types: Option<Vec<String>>,
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize)]
297pub struct DropFunctionStmt {
298 pub is_procedure: bool,
299 pub if_exists: bool,
300 #[serde(default)]
301 pub cascade: bool,
302 pub items: Vec<DropFunctionItem>,
303}