Skip to main content

uqa_sql/semantics/
parameters.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Configuration parameters: their definitions and values, and the lifetimes of SET, SET LOCAL and temporary function configuration over values the host retains.
8
9use 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/// Values remain owned by the host; SQL decides which assignment lifetime restores them.
33#[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    /// A session assignment supersedes pending LOCAL and function configuration restoration for this parameter.
50    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    /// Record a successful assignment. An out-of-transaction LOCAL returns its immediate restoration value.
68    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    /// RESET ALL overrides ordinary settings while leaving both authorization parameters alone.
104    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;