postrust_core/schema_cache/
routine.rs1use crate::api_request::QualifiedIdentifier;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Clone, Debug, Serialize, Deserialize)]
9pub struct Routine {
10 pub schema: String,
12 pub name: String,
14 pub description: Option<String>,
16 pub params: Vec<RoutineParam>,
18 pub return_type: RetType,
20 #[serde(default)]
24 pub returns_composite: bool,
25 pub volatility: FuncVolatility,
27 pub has_variadic: bool,
29 pub isolation_level: Option<String>,
31 pub settings: Vec<(String, String)>,
33 pub is_procedure: bool,
35}
36
37impl Routine {
38 pub fn qualified_identifier(&self) -> QualifiedIdentifier {
40 QualifiedIdentifier::new(&self.schema, &self.name)
41 }
42
43 pub fn is_safe_for_get(&self) -> bool {
45 matches!(
46 self.volatility,
47 FuncVolatility::Immutable | FuncVolatility::Stable
48 )
49 }
50
51 pub fn required_params(&self) -> impl Iterator<Item = &RoutineParam> {
53 self.params.iter().filter(|p| p.required)
54 }
55
56 pub fn find_param(&self, name: &str) -> Option<&RoutineParam> {
58 self.params.iter().find(|p| p.name == name)
59 }
60}
61
62#[derive(Clone, Debug, Serialize, Deserialize)]
64pub struct RoutineParam {
65 pub name: String,
67 pub param_type: String,
69 pub type_max_length: String,
71 pub required: bool,
73 pub variadic: bool,
75}
76
77#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
79pub enum RetType {
80 Single(String),
82 SetOf(String),
84 Table(Vec<(String, String)>),
86 Void,
88}
89
90impl RetType {
91 pub fn is_set_returning(&self) -> bool {
93 matches!(self, Self::SetOf(_) | Self::Table(_))
94 }
95
96 pub fn type_name(&self) -> Option<&str> {
98 match self {
99 Self::Single(t) => Some(t),
100 Self::SetOf(t) => Some(t),
101 Self::Table(_) => None,
102 Self::Void => None,
103 }
104 }
105}
106
107#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
109pub enum FuncVolatility {
110 Immutable,
112 Stable,
114 Volatile,
116}
117
118impl FuncVolatility {
119 pub fn from_char(c: char) -> Self {
120 match c {
121 'i' => Self::Immutable,
122 's' => Self::Stable,
123 _ => Self::Volatile,
124 }
125 }
126}
127
128pub type RoutineMap = HashMap<QualifiedIdentifier, Vec<Routine>>;
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn test_routine_is_safe_for_get() {
137 let mut routine = Routine {
138 schema: "public".into(),
139 name: "get_users".into(),
140 description: None,
141 params: vec![],
142 return_type: RetType::SetOf("users".into()),
143 returns_composite: true,
144 volatility: FuncVolatility::Stable,
145 has_variadic: false,
146 isolation_level: None,
147 settings: vec![],
148 is_procedure: false,
149 };
150
151 assert!(routine.is_safe_for_get());
152
153 routine.volatility = FuncVolatility::Volatile;
154 assert!(!routine.is_safe_for_get());
155 }
156
157 #[test]
158 fn test_ret_type_is_set_returning() {
159 assert!(!RetType::Single("text".into()).is_set_returning());
160 assert!(RetType::SetOf("users".into()).is_set_returning());
161 assert!(RetType::Table(vec![("id".into(), "int".into())]).is_set_returning());
162 assert!(!RetType::Void.is_set_returning());
163 }
164
165 #[test]
166 fn test_func_volatility_from_char() {
167 assert_eq!(FuncVolatility::from_char('i'), FuncVolatility::Immutable);
168 assert_eq!(FuncVolatility::from_char('s'), FuncVolatility::Stable);
169 assert_eq!(FuncVolatility::from_char('v'), FuncVolatility::Volatile);
170 assert_eq!(FuncVolatility::from_char('x'), FuncVolatility::Volatile);
171 }
172}