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 pub volatility: FuncVolatility,
22 pub has_variadic: bool,
24 pub isolation_level: Option<String>,
26 pub settings: Vec<(String, String)>,
28 pub is_procedure: bool,
30}
31
32impl Routine {
33 pub fn qualified_identifier(&self) -> QualifiedIdentifier {
35 QualifiedIdentifier::new(&self.schema, &self.name)
36 }
37
38 pub fn is_safe_for_get(&self) -> bool {
40 matches!(self.volatility, FuncVolatility::Immutable | FuncVolatility::Stable)
41 }
42
43 pub fn required_params(&self) -> impl Iterator<Item = &RoutineParam> {
45 self.params.iter().filter(|p| p.required)
46 }
47
48 pub fn find_param(&self, name: &str) -> Option<&RoutineParam> {
50 self.params.iter().find(|p| p.name == name)
51 }
52}
53
54#[derive(Clone, Debug, Serialize, Deserialize)]
56pub struct RoutineParam {
57 pub name: String,
59 pub param_type: String,
61 pub type_max_length: String,
63 pub required: bool,
65 pub variadic: bool,
67}
68
69#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
71pub enum RetType {
72 Single(String),
74 SetOf(String),
76 Table(Vec<(String, String)>),
78 Void,
80}
81
82impl RetType {
83 pub fn is_set_returning(&self) -> bool {
85 matches!(self, Self::SetOf(_) | Self::Table(_))
86 }
87
88 pub fn type_name(&self) -> Option<&str> {
90 match self {
91 Self::Single(t) => Some(t),
92 Self::SetOf(t) => Some(t),
93 Self::Table(_) => None,
94 Self::Void => None,
95 }
96 }
97}
98
99#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
101pub enum FuncVolatility {
102 Immutable,
104 Stable,
106 Volatile,
108}
109
110impl FuncVolatility {
111 pub fn from_char(c: char) -> Self {
112 match c {
113 'i' => Self::Immutable,
114 's' => Self::Stable,
115 _ => Self::Volatile,
116 }
117 }
118}
119
120pub type RoutineMap = HashMap<QualifiedIdentifier, Vec<Routine>>;
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_routine_is_safe_for_get() {
129 let mut routine = Routine {
130 schema: "public".into(),
131 name: "get_users".into(),
132 description: None,
133 params: vec![],
134 return_type: RetType::SetOf("users".into()),
135 volatility: FuncVolatility::Stable,
136 has_variadic: false,
137 isolation_level: None,
138 settings: vec![],
139 is_procedure: false,
140 };
141
142 assert!(routine.is_safe_for_get());
143
144 routine.volatility = FuncVolatility::Volatile;
145 assert!(!routine.is_safe_for_get());
146 }
147
148 #[test]
149 fn test_ret_type_is_set_returning() {
150 assert!(!RetType::Single("text".into()).is_set_returning());
151 assert!(RetType::SetOf("users".into()).is_set_returning());
152 assert!(RetType::Table(vec![("id".into(), "int".into())]).is_set_returning());
153 assert!(!RetType::Void.is_set_returning());
154 }
155
156 #[test]
157 fn test_func_volatility_from_char() {
158 assert_eq!(FuncVolatility::from_char('i'), FuncVolatility::Immutable);
159 assert_eq!(FuncVolatility::from_char('s'), FuncVolatility::Stable);
160 assert_eq!(FuncVolatility::from_char('v'), FuncVolatility::Volatile);
161 assert_eq!(FuncVolatility::from_char('x'), FuncVolatility::Volatile);
162 }
163}