1use core::fmt;
6use core::ops::Deref;
7use core::str::FromStr;
8
9use crate::category::Category;
10use crate::character::Char;
11use crate::error::ParseError;
12use crate::sqlstate::SqlState;
13
14#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct Class {
23 pub(crate) code: [Char; 2],
24}
25
26impl Class {
27 #[inline]
45 pub const fn from_str(value: &str) -> Result<Self, ParseError> {
46 Self::from_bytes(value.as_bytes())
47 }
48
49 #[inline]
67 pub const fn from_bytes(value: &[u8]) -> Result<Self, ParseError> {
68 match Char::new_array(value) {
69 Ok(code) => Ok(Self { code }),
70 Err(e) => Err(e),
71 }
72 }
73
74 #[inline]
94 pub const fn from_byte_array(value: [u8; 2]) -> Result<Self, ParseError> {
95 match Char::new_array(&value) {
96 Ok(code) => Ok(Self { code }),
97 Err(e) => Err(e),
98 }
99 }
100
101 #[inline]
110 pub const fn category(&self) -> Category {
111 match self {
112 sqlstate![0 0] => Category::Success,
113 sqlstate![0 1] => Category::Warning,
114 sqlstate![0 2] => Category::NoData,
115 _ => Category::Exception,
116 }
117 }
118
119 #[inline]
132 pub const fn contains(&self, sqlstate: SqlState) -> bool {
133 let class = sqlstate.class();
134 let self_arrayref = Char::array_as_bytes(&self.code);
135 let other_arrayref = Char::array_as_bytes(&class.code);
136 self_arrayref[0] == other_arrayref[0] && self_arrayref[1] == other_arrayref[1]
137 }
138
139 #[inline]
156 pub const fn is_implementation_specific(&self) -> bool {
157 !matches!(
158 self.code[0],
159 Char::_0
160 | Char::_1 | Char::_2
161 | Char::_3 | Char::_4
162 | Char::A | Char::B
163 | Char::C | Char::D
164 | Char::E | Char::F
165 | Char::G | Char::H
166 )
167 }
168}
169
170impl Class {
172 pub const SUCCESSFUL_COMPLETION: Self = sqlstate![0 0];
174 pub const WARNING: Self = sqlstate![0 1];
176 pub const NO_DATA: Self = sqlstate![0 2];
178 pub const DYNAMIC_SQL_ERROR: Self = sqlstate![0 7];
180 pub const CONNECTION_EXCEPTION: Self = sqlstate![0 8];
182 pub const TRIGGERED_ACTION_EXCEPTION: Self = sqlstate![0 9];
184 pub const FEATURE_NOT_SUPPORTED: Self = sqlstate![0 A];
186 pub const INVALID_TARGET_TYPE_SPEC: Self = sqlstate![0 D];
188 pub const INVALID_SCHEMA_NAME_LIST_SPEC: Self = sqlstate![0 E];
190 pub const LOCATOR_EXCEPTION: Self = sqlstate![0 F];
192 pub const RESIGNAL_WHEN_HANDLER_NOT_ACTIVE: Self = sqlstate![0 K];
194 pub const INVALID_GRANTOR: Self = sqlstate![0 L];
196 pub const INVALID_SQL_INVOKED_PROCEDURE_REF: Self = sqlstate![0 M];
198 pub const SQL_XML_MAPPING_ERROR: Self = sqlstate![0 N];
200 pub const INVALID_ROLE_SPEC: Self = sqlstate![0 P];
202 pub const INVALID_TRANSFORM_GROUP_NAME_SPEC: Self = sqlstate![0 S];
204 pub const TARGET_TABLE_DISAGREES_WITH_CURSOR_SPEC: Self = sqlstate![0 T];
206 pub const ATTEMPT_TO_ASSIGN_TO_NON_UPDATABLE_COLUMN: Self = sqlstate![0 U];
208 pub const ATTEMPT_TO_ASSSIGN_TO_ORDERING_COLUMN: Self = sqlstate![0 V];
210 pub const PROHIBITED_STATEMENT_DURING_TRIGGER_EXEC: Self = sqlstate![0 W];
212 pub const INVALID_FOREIGN_SERVER_SPEC: Self = sqlstate![0 X];
214 pub const PASSTHROUGH_SPECIFIC_CONDITION: Self = sqlstate![0 Y];
216 pub const DIAGNOSTICS_EXCEPTION: Self = sqlstate![0 Z];
218 pub const XQUERY_ERROR: Self = sqlstate![1 0];
220 pub const CASE_NOT_FOUND_FOR_CASE_STATEMENT: Self = sqlstate![2 0];
222 pub const CARDINALITY_VIOLATION: Self = sqlstate![2 1];
226 pub const DATA_EXCEPTION: Self = sqlstate![2 2];
230 pub const INTEGRITY_CONSTRAINT_VIOLATION: Self = sqlstate![2 3];
234 pub const INVALID_CURSOR_STATE: Self = sqlstate![2 4];
236 pub const INVALID_TRANSACTION_STATE: Self = sqlstate![2 5];
238 pub const INVALID_SQL_STATEMENT_NAME: Self = sqlstate![2 6];
240 pub const TRIGGERED_DATA_CHANGE_VIOLATION: Self = sqlstate![2 7];
242 pub const INVALID_AUTHORIZATION_SPEC: Self = sqlstate![2 8];
244 pub const DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST: Self = sqlstate![2 B];
246 pub const INVALID_CHARACTER_SET_NAME: Self = sqlstate![2 C];
248 pub const INVALID_TRANSACTION_TERMINATION: Self = sqlstate![2 D];
250 pub const INVALID_CONNECTION_NAME: Self = sqlstate![2 E];
252 pub const SQL_ROUTINE_EXCEPTION: Self = sqlstate![2 F];
254 pub const INVALID_COLLATION_NAME: Self = sqlstate![2 H];
256 pub const INVALID_SQL_STATEMENT_IDENTIFIER: Self = sqlstate![3 0];
258 pub const INVALID_SQL_DESCRIPTOR_NAME: Self = sqlstate![3 3];
260 pub const INVALID_CURSOR_NAME: Self = sqlstate![3 4];
262 pub const INVALID_CONNECTION_NUMBER: Self = sqlstate![3 5];
264 pub const CURSOR_SENSITIVITY_EXCEPTION: Self = sqlstate![3 6];
266 pub const EXTERNAL_ROUTINE_EXCEPTION: Self = sqlstate![3 8];
268 pub const EXTERNAL_ROUTINE_INVOCATION_EXCEPTION: Self = sqlstate![3 9];
270 pub const SAVEPOINT_EXCEPTION: Self = sqlstate![3 B];
272 pub const AMBIGUOUS_CURSOR_NAME: Self = sqlstate![3 C];
274 pub const INVALID_CATALOG_NAME: Self = sqlstate![3 D];
278 pub const INVALID_SCHEMA_NAME: Self = sqlstate![3 F];
280 pub const TRANSACTION_ROLLBACK: Self = sqlstate![4 0];
282 pub const SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION: Self = sqlstate![4 2];
286 pub const WITH_CHECK_OPTION_VIOLATION: Self = sqlstate![4 4];
288 pub const UNHANDLED_USER_DEFINED_EXCEPTION: Self = sqlstate![4 5];
290 pub const OLB_SPECIFIC_ERROR: Self = sqlstate![4 6];
294 pub const DATALINK_EXCEPTION: Self = sqlstate![H W];
296 pub const FDW_SPECIFIC_CONDITION: Self = sqlstate![H V];
298 pub const CLI_SPECIFIC_CONDITION: Self = sqlstate![H Y];
302}
303
304impl Class {
306 pub const DB2_INVALID_APPLICATION_STATE: Self = sqlstate![5 1];
308 pub const DB2_INVALID_OPERAND_OR_INCONSISTENT_SPEC: Self = sqlstate![5 3];
310 pub const DB2_SQL_OR_PRODUCT_LIMIT_EXCEEDED: Self = sqlstate![5 4];
312 pub const DB2_OBJECT_NOT_IN_PREREQUISITE_STATE: Self = sqlstate![5 5];
314 pub const DB2_MISCELLANEOUS_SQL_OR_PRODUCT_ERROR: Self = sqlstate![5 6];
316 pub const DB2_RESOURCE_NOT_AVAILABLE_OR_OPERATOR_INTERVENTION: Self = sqlstate![5 7];
318 pub const DB2_SYSTEM_ERROR: Self = sqlstate![5 8];
320 pub const DB2_COMMON_UTILITIES_AND_TOOLS: Self = sqlstate![5 U];
322}
323
324impl Class {
326 pub const PGSQL_INSUFFICIENT_RESOURCES: Self = sqlstate![5 3];
328 pub const PGSQL_PROGRAM_LIMIT_EXCEEDED: Self = sqlstate![5 4];
330 pub const PGSQL_OBJECT_NOT_IN_PREREQUISITE_STATE: Self = sqlstate![5 5];
332 pub const PGSQL_OPERATOR_INTERVENTION: Self = sqlstate![5 7];
334 pub const PGSQL_SYSTEM_ERROR: Self = sqlstate![5 8];
336 pub const PGSQL_SNAPSHOT_FAILURE: Self = sqlstate![7 2];
338 pub const PGSQL_CONFIGURATION_FILE_ERROR: Self = sqlstate![F 0];
340 pub const PGSQL_PL_PGSQL_ERROR: Self = sqlstate![P 0];
342 pub const PGSQL_INTERNAL_ERROR: Self = sqlstate![X X];
344}
345
346impl Class {
348 pub const MYSQL_INTERRUPTION: Self = sqlstate![7 0];
350 pub const MYSQL_XA_ERROR: Self = sqlstate![X A];
352}
353
354impl Class {
356 pub const ODBC_DRIVER_ERROR: Self = sqlstate![I M];
358}
359
360impl Class {
362 pub const ORACLE_SYSTEM_ERROR: Self = sqlstate![6 0];
364 pub const ORACLE_RESOURCE_ERROR: Self = sqlstate![6 1];
366 pub const ORACLE_PATH_NAME_SERVER_AND_DETACHED_PROCESS_ERROR: Self = sqlstate![6 2];
368 pub const ORACLE_CA_OR_TWO_TASK_INTERFACE_ERROR: Self = sqlstate![6 3];
370 pub const ORACLE_FILE_OR_MEDIA_RECOVERY_ERROR: Self = sqlstate![6 4];
372 pub const ORACLE_PL_SQL_ERROR: Self = sqlstate![6 5];
374 pub const ORACLE_SQL_NET_DRIVER_ERROR: Self = sqlstate![6 6];
376 pub const ORACLE_LICENSING_ERROR: Self = sqlstate![6 7];
378 pub const ORACLE_SQL_CONNECT_ERROR: Self = sqlstate![6 9];
380 pub const ORACLE_SQL_EXECUTE_PHASE_ERROR: Self = sqlstate![7 2];
382 pub const ORACLE_INTERNAL_ERROR: Self = sqlstate![8 2];
384 pub const ORACLE_DEBUG_EVENT: Self = sqlstate![9 0];
386}
387
388impl fmt::Debug for Class {
389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
390 f.debug_tuple("Class").field(&&**self).finish()
391 }
392}
393
394impl fmt::Display for Class {
395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
396 f.write_str(self)
397 }
398}
399
400impl AsRef<str> for Class {
401 #[inline]
402 fn as_ref(&self) -> &str {
403 self
404 }
405}
406
407impl AsRef<[u8]> for Class {
408 #[inline]
409 fn as_ref(&self) -> &[u8] {
410 Char::array_as_bytes(&self.code)
411 }
412}
413
414impl AsRef<[u8; 2]> for Class {
415 #[inline]
416 fn as_ref(&self) -> &[u8; 2] {
417 Char::array_as_bytes(&self.code)
418 }
419}
420
421impl From<Class> for [u8; 2] {
422 #[inline]
423 fn from(class: Class) -> Self {
424 class.code.map(Char::as_byte)
425 }
426}
427
428impl Deref for Class {
429 type Target = str;
430 #[inline]
431 fn deref(&self) -> &Self::Target {
432 Char::array_as_str(&self.code)
433 }
434}
435
436impl PartialEq<str> for Class {
437 fn eq(&self, other: &str) -> bool {
438 &**self == other
439 }
440}
441
442impl PartialEq<[u8]> for Class {
443 fn eq(&self, other: &[u8]) -> bool {
444 AsRef::<[u8]>::as_ref(self) == other
445 }
446}
447
448impl FromStr for Class {
449 type Err = ParseError;
450
451 fn from_str(s: &str) -> Result<Self, Self::Err> {
452 Self::from_bytes(s.as_bytes())
453 }
454}
455
456impl TryFrom<&[u8]> for Class {
457 type Error = ParseError;
458
459 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
460 Self::from_bytes(bytes)
461 }
462}
463
464impl TryFrom<[u8; 2]> for Class {
465 type Error = ParseError;
466
467 fn try_from(bytes: [u8; 2]) -> Result<Self, Self::Error> {
468 Self::from_byte_array(bytes)
469 }
470}
471
472impl TryFrom<&str> for Class {
473 type Error = ParseError;
474
475 fn try_from(string: &str) -> Result<Self, Self::Error> {
476 Self::from_str(string)
477 }
478}
479
480#[cfg(feature = "serde")]
481impl serde::Serialize for Class {
482 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
483 where
484 S: serde::Serializer,
485 {
486 serializer.serialize_str(self)
487 }
488}
489
490#[cfg(feature = "serde")]
491impl<'de> serde::Deserialize<'de> for Class {
492 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
493 where
494 D: serde::Deserializer<'de>,
495 {
496 deserializer
497 .deserialize_str(crate::character::de::ArrayVisitor::new())
498 .map(|code| Self { code })
499 }
500}
501
502const _: () = assert!(core::mem::size_of::<Class>() == 2);
504const _: () = assert!(core::mem::size_of::<Option<Class>>() == 2);
505const _: () = assert!(core::mem::size_of::<Option<Option<Class>>>() == 2);