1use core::error::Error as StdError;
2use core::fmt;
3use core::str::FromStr;
4
5#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for SqlState {
}
#[automatically_derived]impl ::core::clone::Clone for SqlState {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<[u8; 5]>;
*self
}
}Clone, #[automatically_derived]impl ::core::marker::Copy for SqlState { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for SqlState
{
}
#[automatically_derived]impl ::core::cmp::PartialEq for SqlState {
#[inline]
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for SqlState {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<[u8; 5]>;
}
}Eq, #[automatically_derived]impl ::core::hash::Hash for SqlState {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, #[automatically_derived]impl ::core::cmp::PartialOrd for SqlState {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for SqlState {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord)]
24pub struct SqlState([u8; 5]);
25
26impl SqlState {
27 pub const fn new(code: [u8; 5]) -> Option<Self> {
29 let mut i = 0;
30 while i < code.len() {
31 if !#[allow(non_exhaustive_omitted_patterns)] match code[i] {
b'0'..=b'9' | b'A'..=b'Z' => true,
_ => false,
}matches!(code[i], b'0'..=b'9' | b'A'..=b'Z') {
32 return None;
33 }
34 i += 1;
35 }
36 Some(Self(code))
37 }
38
39 pub fn as_str(&self) -> &str {
41 core::str::from_utf8(&self.0).expect("a SQLSTATE consists of ASCII bytes")
42 }
43
44 pub fn class(&self) -> SqlStateClass {
46 SqlStateClass([self.0[0], self.0[1]])
47 }
48
49 pub fn subclass(&self) -> &str {
51 &self.as_str()[2..]
52 }
53}
54
55impl fmt::Debug for SqlState {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 f.debug_tuple("SqlState").field(&self.as_str()).finish()
58 }
59}
60
61impl fmt::Display for SqlState {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 f.write_str(self.as_str())
64 }
65}
66
67impl FromStr for SqlState {
68 type Err = InvalidSqlState;
69
70 fn from_str(s: &str) -> Result<Self, Self::Err> {
71 <[u8; 5]>::try_from(s.as_bytes())
72 .ok()
73 .and_then(Self::new)
74 .ok_or(InvalidSqlState)
75 }
76}
77
78#[derive(#[automatically_derived]impl ::core::fmt::Debug for InvalidSqlState {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "InvalidSqlState")
}
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for InvalidSqlState {
}
#[automatically_derived]impl ::core::clone::Clone for InvalidSqlState {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for InvalidSqlState { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
InvalidSqlState {
}
#[automatically_derived]impl ::core::cmp::PartialEq for InvalidSqlState {
#[inline]
fn eq(&self, other: &Self) -> bool { true }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for InvalidSqlState { }Eq)]
81pub struct InvalidSqlState;
82
83impl fmt::Display for InvalidSqlState {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 f.write_str("a SQLSTATE consists of five characters from `0`-`9` and `A`-`Z`")
86 }
87}
88
89impl StdError for InvalidSqlState {}
90
91#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for SqlStateClass {
}
#[automatically_derived]impl ::core::clone::Clone for SqlStateClass {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<[u8; 2]>;
*self
}
}Clone, #[automatically_derived]impl ::core::marker::Copy for SqlStateClass { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
SqlStateClass {
}
#[automatically_derived]impl ::core::cmp::PartialEq for SqlStateClass {
#[inline]
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for SqlStateClass {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<[u8; 2]>;
}
}Eq, #[automatically_derived]impl ::core::hash::Hash for SqlStateClass {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, #[automatically_derived]impl ::core::cmp::PartialOrd for SqlStateClass {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for SqlStateClass {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord)]
94pub struct SqlStateClass([u8; 2]);
95
96impl SqlStateClass {
97 pub fn as_str(&self) -> &str {
99 core::str::from_utf8(&self.0).expect("a SQLSTATE consists of ASCII bytes")
100 }
101
102 pub fn is_standard(&self) -> bool {
104 #[allow(non_exhaustive_omitted_patterns)] match self.0[0] {
b'0'..=b'4' | b'A'..=b'H' => true,
_ => false,
}matches!(self.0[0], b'0'..=b'4' | b'A'..=b'H')
105 }
106}
107
108impl fmt::Debug for SqlStateClass {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 f.debug_tuple("SqlStateClass")
111 .field(&self.as_str())
112 .finish()
113 }
114}
115
116impl fmt::Display for SqlStateClass {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.write_str(self.as_str())
119 }
120}
121
122macro_rules! sql_state_classes {
123 ($($name:ident = $code:literal, $condition:literal;)*) => {
124 impl SqlStateClass {
125 $(
126 #[doc = concat!("`", $code, "`, ", $condition, ".")]
127 pub const $name: Self = {
128 let code = $code.as_bytes();
129 Self([code[0], code[1]])
130 };
131 )*
132 }
133 };
134}
135
136impl SqlStateClass {
#[doc = "`00`, successful completion."]
pub const SUCCESSFUL_COMPLETION: Self =
{ let code = "00".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`01`, warning."]
pub const WARNING: Self =
{ let code = "01".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`02`, no data."]
pub const NO_DATA: Self =
{ let code = "02".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`07`, dynamic SQL error."]
pub const DYNAMIC_SQL_ERROR: Self =
{ let code = "07".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`08`, connection exception."]
pub const CONNECTION_EXCEPTION: Self =
{ let code = "08".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`09`, triggered action exception."]
pub const TRIGGERED_ACTION_EXCEPTION: Self =
{ let code = "09".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0A`, feature not supported."]
pub const FEATURE_NOT_SUPPORTED: Self =
{ let code = "0A".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0D`, invalid target type specification."]
pub const INVALID_TARGET_TYPE_SPECIFICATION: Self =
{ let code = "0D".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0E`, invalid schema name list specification."]
pub const INVALID_SCHEMA_NAME_LIST_SPECIFICATION: Self =
{ let code = "0E".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0F`, locator exception."]
pub const LOCATOR_EXCEPTION: Self =
{ let code = "0F".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0K`, resignal when handler not active."]
pub const RESIGNAL_WHEN_HANDLER_NOT_ACTIVE: Self =
{ let code = "0K".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0L`, invalid grantor."]
pub const INVALID_GRANTOR: Self =
{ let code = "0L".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0M`, invalid SQL-invoked procedure reference."]
pub const INVALID_SQL_INVOKED_PROCEDURE_REFERENCE: Self =
{ let code = "0M".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0N`, SQL/XML mapping error."]
pub const SQL_XML_MAPPING_ERROR: Self =
{ let code = "0N".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0P`, invalid role specification."]
pub const INVALID_ROLE_SPECIFICATION: Self =
{ let code = "0P".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0S`, invalid transform group name specification."]
pub const INVALID_TRANSFORM_GROUP_NAME_SPECIFICATION: Self =
{ let code = "0S".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0T`, target table disagrees with cursor specification."]
pub const TARGET_TABLE_DISAGREES_WITH_CURSOR_SPECIFICATION: Self =
{ let code = "0T".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0U`, attempt to assign to non-updatable column."]
pub const ATTEMPT_TO_ASSIGN_TO_NON_UPDATABLE_COLUMN: Self =
{ let code = "0U".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0V`, attempt to assign to ordering column."]
pub const ATTEMPT_TO_ASSIGN_TO_ORDERING_COLUMN: Self =
{ let code = "0V".as_bytes(); Self([code[0], code[1]]) };
#[doc =
"`0W`, prohibited statement encountered during trigger execution."]
pub const PROHIBITED_STATEMENT_ENCOUNTERED_DURING_TRIGGER_EXECUTION: Self
=
{ let code = "0W".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0X`, invalid foreign server specification."]
pub const INVALID_FOREIGN_SERVER_SPECIFICATION: Self =
{ let code = "0X".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0Y`, pass-through specific condition."]
pub const PASS_THROUGH_SPECIFIC_CONDITION: Self =
{ let code = "0Y".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`0Z`, diagnostics exception."]
pub const DIAGNOSTICS_EXCEPTION: Self =
{ let code = "0Z".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`10`, XQuery error."]
pub const XQUERY_ERROR: Self =
{ let code = "10".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`20`, case not found for case statement."]
pub const CASE_NOT_FOUND_FOR_CASE_STATEMENT: Self =
{ let code = "20".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`21`, cardinality violation."]
pub const CARDINALITY_VIOLATION: Self =
{ let code = "21".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`22`, data exception."]
pub const DATA_EXCEPTION: Self =
{ let code = "22".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`23`, integrity constraint violation."]
pub const INTEGRITY_CONSTRAINT_VIOLATION: Self =
{ let code = "23".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`24`, invalid cursor state."]
pub const INVALID_CURSOR_STATE: Self =
{ let code = "24".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`25`, invalid transaction state."]
pub const INVALID_TRANSACTION_STATE: Self =
{ let code = "25".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`26`, invalid SQL statement name."]
pub const INVALID_SQL_STATEMENT_NAME: Self =
{ let code = "26".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`27`, triggered data change violation."]
pub const TRIGGERED_DATA_CHANGE_VIOLATION: Self =
{ let code = "27".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`28`, invalid authorization specification."]
pub const INVALID_AUTHORIZATION_SPECIFICATION: Self =
{ let code = "28".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`2B`, dependent privilege descriptors still exist."]
pub const DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST: Self =
{ let code = "2B".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`2C`, invalid character set name."]
pub const INVALID_CHARACTER_SET_NAME: Self =
{ let code = "2C".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`2D`, invalid transaction termination."]
pub const INVALID_TRANSACTION_TERMINATION: Self =
{ let code = "2D".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`2E`, invalid connection name."]
pub const INVALID_CONNECTION_NAME: Self =
{ let code = "2E".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`2F`, SQL routine exception."]
pub const SQL_ROUTINE_EXCEPTION: Self =
{ let code = "2F".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`2H`, invalid collation name."]
pub const INVALID_COLLATION_NAME: Self =
{ let code = "2H".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`30`, invalid SQL statement identifier."]
pub const INVALID_SQL_STATEMENT_IDENTIFIER: Self =
{ let code = "30".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`33`, invalid SQL descriptor name."]
pub const INVALID_SQL_DESCRIPTOR_NAME: Self =
{ let code = "33".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`34`, invalid cursor name."]
pub const INVALID_CURSOR_NAME: Self =
{ let code = "34".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`35`, invalid condition number."]
pub const INVALID_CONDITION_NUMBER: Self =
{ let code = "35".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`36`, cursor sensitivity exception."]
pub const CURSOR_SENSITIVITY_EXCEPTION: Self =
{ let code = "36".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`38`, external routine exception."]
pub const EXTERNAL_ROUTINE_EXCEPTION: Self =
{ let code = "38".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`39`, external routine invocation exception."]
pub const EXTERNAL_ROUTINE_INVOCATION_EXCEPTION: Self =
{ let code = "39".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`3B`, savepoint exception."]
pub const SAVEPOINT_EXCEPTION: Self =
{ let code = "3B".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`3C`, ambiguous cursor name."]
pub const AMBIGUOUS_CURSOR_NAME: Self =
{ let code = "3C".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`3D`, invalid catalog name."]
pub const INVALID_CATALOG_NAME: Self =
{ let code = "3D".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`3F`, invalid schema name."]
pub const INVALID_SCHEMA_NAME: Self =
{ let code = "3F".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`40`, transaction rollback."]
pub const TRANSACTION_ROLLBACK: Self =
{ let code = "40".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`42`, syntax error or access rule violation."]
pub const SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION: Self =
{ let code = "42".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`44`, with check option violation."]
pub const WITH_CHECK_OPTION_VIOLATION: Self =
{ let code = "44".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`45`, unhandled user-defined exception."]
pub const UNHANDLED_USER_DEFINED_EXCEPTION: Self =
{ let code = "45".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`46`, OLB-specific error."]
pub const OLB_SPECIFIC_ERROR: Self =
{ let code = "46".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`HV`, FDW-specific condition."]
pub const FDW_SPECIFIC_CONDITION: Self =
{ let code = "HV".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`HW`, datalink exception."]
pub const DATALINK_EXCEPTION: Self =
{ let code = "HW".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`HY`, CLI-specific condition."]
pub const CLI_SPECIFIC_CONDITION: Self =
{ let code = "HY".as_bytes(); Self([code[0], code[1]]) };
#[doc = "`HZ`, remote database access."]
pub const REMOTE_DATABASE_ACCESS: Self =
{ let code = "HZ".as_bytes(); Self([code[0], code[1]]) };
}sql_state_classes! {
137 SUCCESSFUL_COMPLETION = "00", "successful completion";
138 WARNING = "01", "warning";
139 NO_DATA = "02", "no data";
140 DYNAMIC_SQL_ERROR = "07", "dynamic SQL error";
141 CONNECTION_EXCEPTION = "08", "connection exception";
142 TRIGGERED_ACTION_EXCEPTION = "09", "triggered action exception";
143 FEATURE_NOT_SUPPORTED = "0A", "feature not supported";
144 INVALID_TARGET_TYPE_SPECIFICATION = "0D", "invalid target type specification";
145 INVALID_SCHEMA_NAME_LIST_SPECIFICATION = "0E", "invalid schema name list specification";
146 LOCATOR_EXCEPTION = "0F", "locator exception";
147 RESIGNAL_WHEN_HANDLER_NOT_ACTIVE = "0K", "resignal when handler not active";
148 INVALID_GRANTOR = "0L", "invalid grantor";
149 INVALID_SQL_INVOKED_PROCEDURE_REFERENCE = "0M", "invalid SQL-invoked procedure reference";
150 SQL_XML_MAPPING_ERROR = "0N", "SQL/XML mapping error";
151 INVALID_ROLE_SPECIFICATION = "0P", "invalid role specification";
152 INVALID_TRANSFORM_GROUP_NAME_SPECIFICATION = "0S", "invalid transform group name specification";
153 TARGET_TABLE_DISAGREES_WITH_CURSOR_SPECIFICATION = "0T", "target table disagrees with cursor specification";
154 ATTEMPT_TO_ASSIGN_TO_NON_UPDATABLE_COLUMN = "0U", "attempt to assign to non-updatable column";
155 ATTEMPT_TO_ASSIGN_TO_ORDERING_COLUMN = "0V", "attempt to assign to ordering column";
156 PROHIBITED_STATEMENT_ENCOUNTERED_DURING_TRIGGER_EXECUTION = "0W", "prohibited statement encountered during trigger execution";
157 INVALID_FOREIGN_SERVER_SPECIFICATION = "0X", "invalid foreign server specification";
158 PASS_THROUGH_SPECIFIC_CONDITION = "0Y", "pass-through specific condition";
159 DIAGNOSTICS_EXCEPTION = "0Z", "diagnostics exception";
160 XQUERY_ERROR = "10", "XQuery error";
161 CASE_NOT_FOUND_FOR_CASE_STATEMENT = "20", "case not found for case statement";
162 CARDINALITY_VIOLATION = "21", "cardinality violation";
163 DATA_EXCEPTION = "22", "data exception";
164 INTEGRITY_CONSTRAINT_VIOLATION = "23", "integrity constraint violation";
165 INVALID_CURSOR_STATE = "24", "invalid cursor state";
166 INVALID_TRANSACTION_STATE = "25", "invalid transaction state";
167 INVALID_SQL_STATEMENT_NAME = "26", "invalid SQL statement name";
168 TRIGGERED_DATA_CHANGE_VIOLATION = "27", "triggered data change violation";
169 INVALID_AUTHORIZATION_SPECIFICATION = "28", "invalid authorization specification";
170 DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST = "2B", "dependent privilege descriptors still exist";
171 INVALID_CHARACTER_SET_NAME = "2C", "invalid character set name";
172 INVALID_TRANSACTION_TERMINATION = "2D", "invalid transaction termination";
173 INVALID_CONNECTION_NAME = "2E", "invalid connection name";
174 SQL_ROUTINE_EXCEPTION = "2F", "SQL routine exception";
175 INVALID_COLLATION_NAME = "2H", "invalid collation name";
176 INVALID_SQL_STATEMENT_IDENTIFIER = "30", "invalid SQL statement identifier";
177 INVALID_SQL_DESCRIPTOR_NAME = "33", "invalid SQL descriptor name";
178 INVALID_CURSOR_NAME = "34", "invalid cursor name";
179 INVALID_CONDITION_NUMBER = "35", "invalid condition number";
180 CURSOR_SENSITIVITY_EXCEPTION = "36", "cursor sensitivity exception";
181 EXTERNAL_ROUTINE_EXCEPTION = "38", "external routine exception";
182 EXTERNAL_ROUTINE_INVOCATION_EXCEPTION = "39", "external routine invocation exception";
183 SAVEPOINT_EXCEPTION = "3B", "savepoint exception";
184 AMBIGUOUS_CURSOR_NAME = "3C", "ambiguous cursor name";
185 INVALID_CATALOG_NAME = "3D", "invalid catalog name";
186 INVALID_SCHEMA_NAME = "3F", "invalid schema name";
187 TRANSACTION_ROLLBACK = "40", "transaction rollback";
188 SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION = "42", "syntax error or access rule violation";
189 WITH_CHECK_OPTION_VIOLATION = "44", "with check option violation";
190 UNHANDLED_USER_DEFINED_EXCEPTION = "45", "unhandled user-defined exception";
191 OLB_SPECIFIC_ERROR = "46", "OLB-specific error";
192 FDW_SPECIFIC_CONDITION = "HV", "FDW-specific condition";
193 DATALINK_EXCEPTION = "HW", "datalink exception";
194 CLI_SPECIFIC_CONDITION = "HY", "CLI-specific condition";
195 REMOTE_DATABASE_ACCESS = "HZ", "remote database access";
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn new_accepts_only_digits_and_uppercase_letters() {
204 assert!(SqlState::new(*b"09AZ0").is_some());
205 for invalid in [b'/', b':', b'@', b'[', b'a', b'z', b' ', 0, 0xC3] {
206 let mut code = *b"23505";
207 code[4] = invalid;
208 assert_eq!(SqlState::new(code), None, "byte {invalid:#04x}");
209 }
210 }
211
212 #[test]
213 fn from_str_requires_exactly_five_bytes() {
214 assert_eq!("23505".parse::<SqlState>().unwrap().as_str(), "23505");
215 for invalid in ["", "2350", "235050", "2350\u{e9}", "2350\u{0}", "23505 "] {
216 assert_eq!(
217 invalid.parse::<SqlState>(),
218 Err(InvalidSqlState),
219 "{invalid:?}"
220 );
221 }
222 }
223
224 #[test]
225 fn class_and_subclass_split_after_two_characters() {
226 let code: SqlState = "40P01".parse().unwrap();
227 assert_eq!(code.class(), SqlStateClass::TRANSACTION_ROLLBACK);
228 assert_eq!(code.class().as_str(), "40");
229 assert_eq!(code.subclass(), "P01");
230 }
231
232 #[test]
233 fn standard_classes_start_with_0_to_4_or_a_to_h() {
234 for code in [
235 "00000", "40001", "0A000", "B0000", "G0000", "HV000", "H0000",
236 ] {
237 let code: SqlState = code.parse().unwrap();
238 assert!(code.class().is_standard(), "{code}");
239 }
240 for code in ["50000", "9Z000", "I0000", "P0001", "XX000"] {
241 let code: SqlState = code.parse().unwrap();
242 assert!(!code.class().is_standard(), "{code}");
243 }
244 }
245
246 #[test]
247 fn constants_match_as_patterns() {
248 const UNIQUE_VIOLATION: SqlState = SqlState::new(*b"23505").unwrap();
249 let code: SqlState = "23505".parse().unwrap();
250 assert!(matches!(code, UNIQUE_VIOLATION));
251 assert!(matches!(
252 code.class(),
253 SqlStateClass::INTEGRITY_CONSTRAINT_VIOLATION
254 ));
255 let other: SqlState = "22012".parse().unwrap();
256 assert!(!matches!(other, UNIQUE_VIOLATION));
257 assert!(!matches!(
258 other.class(),
259 SqlStateClass::INTEGRITY_CONSTRAINT_VIOLATION
260 ));
261 }
262}