Skip to main content

uqa_sql/semantics/parameters/
definition.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! The definition of one configuration parameter as `PostgreSQL`'s `guc_tables.c` declares it: its type and bounds, when a session may change it, and the descriptions that `pg_settings` and `SHOW ALL` report.
8
9use super::units::ParameterUnit;
10
11/// When a session may change a parameter (`GucContext`).
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub enum ParameterContext {
14    /// Fixed for the server: `SET` reports `parameter "..." cannot be changed`.
15    Internal,
16    /// Changed only by superusers and roles granted `SET` on the parameter.
17    Superuser,
18    /// Changed by any user.
19    User,
20}
21
22impl ParameterContext {
23    /// The name that `pg_settings.context` reports.
24    pub const fn name(self) -> &'static str {
25        match self {
26            Self::Internal => "internal",
27            Self::Superuser => "superuser",
28            Self::User => "user",
29        }
30    }
31}
32
33/// One accepted value of an enumerated parameter (`config_enum_entry`). Values that share `value` are spellings of one setting, which displays as the first of them.
34#[derive(Clone, Copy, Debug)]
35pub struct EnumOption {
36    pub name: &'static str,
37    pub value: u8,
38    /// Accepted but left out of `pg_settings.enumvals` and of the hint that lists the available values.
39    pub hidden: bool,
40}
41
42impl EnumOption {
43    pub const fn listed(name: &'static str, value: u8) -> Self {
44        Self {
45            name,
46            value,
47            hidden: false,
48        }
49    }
50
51    pub const fn hidden(name: &'static str, value: u8) -> Self {
52        Self {
53            name,
54            value,
55            hidden: true,
56        }
57    }
58}
59
60/// The type of a parameter's value with its boot value and bounds.
61#[derive(Clone, Copy, Debug)]
62pub enum ParameterKind {
63    Bool {
64        boot: bool,
65    },
66    Integer {
67        boot: i32,
68        min: i32,
69        max: i32,
70        unit: Option<ParameterUnit>,
71    },
72    Enum {
73        boot: u8,
74        options: &'static [EnumOption],
75    },
76    String {
77        boot: &'static str,
78    },
79}
80
81impl ParameterKind {
82    /// The name that `pg_settings.vartype` reports.
83    pub const fn type_name(&self) -> &'static str {
84        match self {
85            Self::Bool { .. } => "bool",
86            Self::Integer { .. } => "integer",
87            Self::Enum { .. } => "enum",
88            Self::String { .. } => "string",
89        }
90    }
91}
92
93/// The `GUC_*` flags of a parameter that change how SQL treats it.
94#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
95pub struct ParameterFlags(u16);
96
97impl ParameterFlags {
98    pub const NONE: Self = Self(0);
99    /// `SET` accepts a list of values, which it joins with `, ` (`GUC_LIST_INPUT`).
100    pub const LIST_INPUT: Self = Self(1 << 0);
101    /// `SET` quotes each string of the list as an identifier needs (`GUC_LIST_QUOTE`).
102    pub const LIST_QUOTE: Self = Self(1 << 1);
103    /// Left out of `SHOW ALL` and `pg_settings` (`GUC_NO_SHOW_ALL`).
104    pub const NO_SHOW_ALL: Self = Self(1 << 2);
105    /// `RESET` and `SET ... TO DEFAULT` do not apply to it (`GUC_NO_RESET`).
106    pub const NO_RESET: Self = Self(1 << 3);
107    /// `RESET ALL` leaves it alone (`GUC_NO_RESET_ALL`).
108    pub const NO_RESET_ALL: Self = Self(1 << 4);
109    /// The server reports every change to the client in a `ParameterStatus` message (`GUC_REPORT`).
110    pub const REPORT: Self = Self(1 << 5);
111    /// A string value is truncated to the length of an identifier (`GUC_IS_NAME`).
112    pub const IS_NAME: Self = Self(1 << 6);
113
114    pub const fn union(self, other: Self) -> Self {
115        Self(self.0 | other.0)
116    }
117
118    pub const fn contains(self, other: Self) -> bool {
119        self.0 & other.0 == other.0
120    }
121}
122
123/// One configuration parameter.
124#[derive(Clone, Copy, Debug)]
125pub struct ParameterDefinition {
126    /// The canonical spelling, which `SHOW` reports as its column name.
127    pub name: &'static str,
128    pub kind: ParameterKind,
129    pub context: ParameterContext,
130    pub category: &'static str,
131    pub short_desc: &'static str,
132    pub extra_desc: Option<&'static str>,
133    pub flags: ParameterFlags,
134    /// The library that defines the parameter when a session loads it; until then the name is an ordinary custom parameter of the library's reserved prefix.
135    pub library: Option<&'static str>,
136}
137
138impl ParameterDefinition {
139    pub fn has_flag(&self, flag: ParameterFlags) -> bool {
140        self.flags.contains(flag)
141    }
142
143    /// The setting a session starts with, as `pg_settings.boot_val` reports it.
144    pub fn boot_setting(&self) -> String {
145        match self.kind {
146            ParameterKind::Bool { boot } => if boot { "on" } else { "off" }.into(),
147            ParameterKind::Integer { boot, .. } => boot.to_string(),
148            ParameterKind::Enum { boot, options } => {
149                super::value::enum_display(options, boot).into()
150            }
151            ParameterKind::String { boot } => boot.into(),
152        }
153    }
154
155    /// The unit of an integer parameter, as `pg_settings.unit` reports it.
156    pub fn unit(&self) -> Option<ParameterUnit> {
157        match self.kind {
158            ParameterKind::Integer { unit, .. } => unit,
159            _ => None,
160        }
161    }
162}