uqa_sql/semantics/
parameters.rs1use std::collections::BTreeMap;
10
11pub mod arguments;
12pub mod catalog;
13pub mod custom;
14pub mod datestyle;
15pub mod definition;
16pub mod identifier_list;
17pub mod setting;
18pub(crate) mod timezone;
19pub mod units;
20pub mod value;
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum ParameterAssignment {
24 Session,
25 Local,
26 Save,
27}
28
29#[derive(Clone, Copy, Debug)]
30pub struct ParameterScope(usize);
31
32#[derive(Clone)]
34pub struct ParameterScopes<T> {
35 transaction: BTreeMap<String, T>,
36 functions: Vec<BTreeMap<String, T>>,
37}
38
39impl<T> Default for ParameterScopes<T> {
40 fn default() -> Self {
41 Self {
42 transaction: BTreeMap::new(),
43 functions: Vec::new(),
44 }
45 }
46}
47
48impl<T> ParameterScopes<T> {
49 pub fn session_assignment(&mut self, name: &str) {
51 self.transaction.remove(name);
52 for saved in &mut self.functions {
53 saved.remove(name);
54 }
55 }
56
57 pub fn enter_function(&mut self) -> ParameterScope {
58 self.functions.push(BTreeMap::new());
59 ParameterScope(self.functions.len())
60 }
61
62 pub fn leave_function(&mut self, scope: ParameterScope) -> BTreeMap<String, T> {
63 assert_eq!(scope.0, self.functions.len(), "parameter scope order");
64 self.functions.pop().expect("active parameter scope")
65 }
66
67 pub fn assigned(
69 &mut self,
70 name: String,
71 previous: T,
72 action: ParameterAssignment,
73 in_transaction: bool,
74 ) -> Option<T> {
75 match action {
76 ParameterAssignment::Session => {
77 self.session_assignment(&name);
78 }
79 ParameterAssignment::Local => {
80 if self.functions.iter().any(|saved| saved.contains_key(&name)) {
81 return None;
82 }
83 if !in_transaction {
84 return Some(previous);
85 }
86 self.transaction.entry(name).or_insert(previous);
87 }
88 ParameterAssignment::Save => {
89 self.functions
90 .last_mut()
91 .expect("function configuration requires a parameter scope")
92 .entry(name)
93 .or_insert(previous);
94 }
95 }
96 None
97 }
98
99 pub fn finish_transaction(&mut self) -> BTreeMap<String, T> {
100 std::mem::take(&mut self.transaction)
101 }
102
103 pub fn reset_all(&mut self) {
105 fn authorization(name: &str) -> bool {
106 matches!(name, "role" | "session_authorization")
107 }
108 self.transaction.retain(|name, _| authorization(name));
109 for saved in &mut self.functions {
110 saved.retain(|name, _| authorization(name));
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests;