session/
session_config.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt::Display;
16
17use common_macro::stack_trace_debug;
18use snafu::{Location, Snafu};
19use sql::ast::Value;
20
21#[derive(Snafu)]
22#[snafu(visibility(pub))]
23#[stack_trace_debug]
24pub enum Error {
25    #[snafu(display("Invalid value for parameter \"{}\": {}\nHint: {}", name, value, hint,))]
26    InvalidConfigValue {
27        name: String,
28        value: String,
29        hint: String,
30        #[snafu(implicit)]
31        location: Location,
32    },
33}
34
35#[derive(Clone, Copy, Debug, Default)]
36pub enum PGByteaOutputValue {
37    #[default]
38    HEX,
39    ESCAPE,
40}
41
42impl TryFrom<Value> for PGByteaOutputValue {
43    type Error = Error;
44
45    fn try_from(value: Value) -> Result<Self, Self::Error> {
46        match &value {
47            Value::DoubleQuotedString(s) | Value::SingleQuotedString(s) => {
48                match s.to_uppercase().as_str() {
49                    "ESCAPE" => Ok(PGByteaOutputValue::ESCAPE),
50                    "HEX" => Ok(PGByteaOutputValue::HEX),
51                    _ => InvalidConfigValueSnafu {
52                        name: "BYTEA_OUTPUT",
53                        value: value.to_string(),
54                        hint: "Available values: escape, hex",
55                    }
56                    .fail(),
57                }
58            }
59            _ => InvalidConfigValueSnafu {
60                name: "BYTEA_OUTPUT",
61                value: value.to_string(),
62                hint: "Available values: escape, hex",
63            }
64            .fail(),
65        }
66    }
67}
68
69impl Display for PGByteaOutputValue {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        match self {
72            PGByteaOutputValue::HEX => write!(f, "hex"),
73            PGByteaOutputValue::ESCAPE => write!(f, "escape"),
74        }
75    }
76}
77
78// Refers to: https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-DATESTYLE
79#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)]
80pub enum PGDateOrder {
81    #[default]
82    MDY,
83    DMY,
84    YMD,
85}
86
87impl Display for PGDateOrder {
88    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89        match self {
90            PGDateOrder::MDY => write!(f, "MDY"),
91            PGDateOrder::DMY => write!(f, "DMY"),
92            PGDateOrder::YMD => write!(f, "YMD"),
93        }
94    }
95}
96
97impl TryFrom<&str> for PGDateOrder {
98    type Error = Error;
99
100    fn try_from(s: &str) -> Result<Self, Self::Error> {
101        match s.to_uppercase().as_str() {
102            "US" | "NONEURO" | "NONEUROPEAN" | "MDY" => Ok(PGDateOrder::MDY),
103            "EUROPEAN" | "EURO" | "DMY" => Ok(PGDateOrder::DMY),
104            "YMD" => Ok(PGDateOrder::YMD),
105            _ => InvalidConfigValueSnafu {
106                name: "DateStyle",
107                value: s,
108                hint: format!("Unrecognized key word: {}", s),
109            }
110            .fail(),
111        }
112    }
113}
114impl TryFrom<&Value> for PGDateOrder {
115    type Error = Error;
116
117    fn try_from(value: &Value) -> Result<Self, Self::Error> {
118        match value {
119            Value::DoubleQuotedString(s) | Value::SingleQuotedString(s) => {
120                Self::try_from(s.as_str())
121            }
122            _ => InvalidConfigValueSnafu {
123                name: "DateStyle",
124                value: value.to_string(),
125                hint: format!("Unrecognized key word: {}", value),
126            }
127            .fail(),
128        }
129    }
130}
131
132#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)]
133pub enum PGDateTimeStyle {
134    #[default]
135    ISO,
136    SQL,
137    Postgres,
138    German,
139}
140
141impl Display for PGDateTimeStyle {
142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143        match self {
144            PGDateTimeStyle::ISO => write!(f, "ISO"),
145            PGDateTimeStyle::SQL => write!(f, "SQL"),
146            PGDateTimeStyle::Postgres => write!(f, "Postgres"),
147            PGDateTimeStyle::German => write!(f, "German"),
148        }
149    }
150}
151
152impl TryFrom<&str> for PGDateTimeStyle {
153    type Error = Error;
154
155    fn try_from(s: &str) -> Result<Self, Self::Error> {
156        match s.to_uppercase().as_str() {
157            "ISO" => Ok(PGDateTimeStyle::ISO),
158            "SQL" => Ok(PGDateTimeStyle::SQL),
159            "POSTGRES" => Ok(PGDateTimeStyle::Postgres),
160            "GERMAN" => Ok(PGDateTimeStyle::German),
161            _ => InvalidConfigValueSnafu {
162                name: "DateStyle",
163                value: s,
164                hint: format!("Unrecognized key word: {}", s),
165            }
166            .fail(),
167        }
168    }
169}
170
171impl TryFrom<&Value> for PGDateTimeStyle {
172    type Error = Error;
173
174    fn try_from(value: &Value) -> Result<Self, Self::Error> {
175        match value {
176            Value::DoubleQuotedString(s) | Value::SingleQuotedString(s) => {
177                Self::try_from(s.as_str())
178            }
179            _ => InvalidConfigValueSnafu {
180                name: "DateStyle",
181                value: value.to_string(),
182                hint: format!("Unrecognized key word: {}", value),
183            }
184            .fail(),
185        }
186    }
187}
188
189#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)]
190pub enum PGIntervalStyle {
191    ISO,
192    SQL,
193    #[default]
194    Postgres,
195    PostgresVerbose,
196}
197
198impl Display for PGIntervalStyle {
199    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200        match self {
201            PGIntervalStyle::ISO => write!(f, "iso_8601"),
202            PGIntervalStyle::SQL => write!(f, "sql_standard"),
203            PGIntervalStyle::Postgres => write!(f, "postgres"),
204            PGIntervalStyle::PostgresVerbose => write!(f, "postgres_verbose"),
205        }
206    }
207}
208
209impl TryFrom<&str> for PGIntervalStyle {
210    type Error = Error;
211
212    fn try_from(s: &str) -> Result<Self, Self::Error> {
213        match s.to_uppercase().as_str() {
214            "ISO" | "ISO_8601" => Ok(PGIntervalStyle::ISO),
215            "SQL" | "SQL_STANDARD" => Ok(PGIntervalStyle::SQL),
216            "POSTGRES" => Ok(PGIntervalStyle::Postgres),
217            "POSTGRES_VERBOSE" | "POSTGRES, VERBOSE" => Ok(PGIntervalStyle::PostgresVerbose),
218            _ => InvalidConfigValueSnafu {
219                name: "IntervalStyle",
220                value: s,
221                hint: format!("Unrecognized key word: {}", s),
222            }
223            .fail(),
224        }
225    }
226}
227
228impl TryFrom<&Value> for PGIntervalStyle {
229    type Error = Error;
230
231    fn try_from(value: &Value) -> Result<Self, Self::Error> {
232        match value {
233            Value::DoubleQuotedString(s) | Value::SingleQuotedString(s) => {
234                Self::try_from(s.as_str())
235            }
236            _ => InvalidConfigValueSnafu {
237                name: "IntervalStyle",
238                value: value.to_string(),
239                hint: format!("Unrecognized key word: {}", value),
240            }
241            .fail(),
242        }
243    }
244}