Skip to main content

sqlite_containers/
common.rs

1// Common Data Types
2// This file is part of the SQLite-based containers for Rust project (sqlite-containers)
3// SPDX-License-Identifier: Unlicense
4
5use crate::rusqlite::{Error as RusqliteError, ErrorCode};
6
7// ---------------------------------------------------------------------------
8// Size Type
9// ---------------------------------------------------------------------------
10
11/// The "size" type used by [`len()`](crate::SQLiteSet::len), equal to `usize` on this platform.
12#[cfg(target_pointer_width = "64")]
13pub type SizeT = usize;
14/// The "size" type used by [`len()`](crate::SQLiteSet::len), equal to `u64` on this platform.
15#[cfg(not(target_pointer_width = "64"))]
16pub type SizeT = u64;
17
18// ---------------------------------------------------------------------------
19// SQLite Error
20// ---------------------------------------------------------------------------
21
22/// Indicates that the operation failed due to an SQLite error.
23///
24/// Container operations are generally infallible. However, because our containers are backed by SQLite databases, they may still fail due to an internal SQLite error. Such errors can indicate a bug, but may also occur in out-of-memory situations.
25///
26/// Wraps the underlying [`RusqliteError`](crate::rusqlite::Error).
27#[allow(dead_code)]
28#[derive(Debug)]
29pub struct Error(RusqliteError);
30
31impl Error {
32    pub fn into_inner(self) -> RusqliteError {
33        self.0
34    }
35}
36
37impl From<RusqliteError> for Error {
38    #[inline]
39    fn from(error: RusqliteError) -> Self {
40        Self(error)
41    }
42}
43
44#[inline]
45pub fn check_constraint_violation(error: RusqliteError) -> Result<bool, Error> {
46    match error {
47        RusqliteError::SqliteFailure(sql_error, _) => match sql_error.code {
48            ErrorCode::ConstraintViolation => Ok(false),
49            _ => Err(error.into()),
50        },
51        _ => Err(error.into()),
52    }
53}
54
55#[cfg(test)]
56mod test {
57    use super::*;
58    use crate::rusqlite::ffi::{Error as FfiError, ErrorCode as FfiErrorCode, SQLITE_CONSTRAINT, SQLITE_NOMEM};
59    use std::path::PathBuf;
60
61    #[test]
62    fn test_error() {
63        let error_1 = Error::from(RusqliteError::InvalidQuery);
64        assert_eq!(error_1.into_inner(), RusqliteError::InvalidQuery);
65
66        let error_2 = Error::from(RusqliteError::InvalidPath(PathBuf::from("filename.txt")));
67        assert!(matches!(error_2.into_inner(), RusqliteError::InvalidPath(_)));
68
69        let error_3 = Error::from(RusqliteError::SqliteFailure(FfiError::new(SQLITE_NOMEM), Some("Memory allocation fail!".to_owned())));
70        assert!(matches!(error_3.into_inner(), RusqliteError::SqliteFailure(FfiError { code: FfiErrorCode::OutOfMemory, .. }, Some(_))));
71    }
72
73    #[test]
74    fn test_check_constraint_violation() {
75        let error_1 = check_constraint_violation(RusqliteError::InvalidQuery);
76        assert!(matches!(error_1, Err(Error(..))));
77
78        let error_2 = check_constraint_violation(RusqliteError::SqliteFailure(FfiError::new(SQLITE_CONSTRAINT), None));
79        assert!(matches!(error_2, Ok(false)));
80
81        let error_3 = check_constraint_violation(RusqliteError::SqliteFailure(FfiError::new(SQLITE_NOMEM), None));
82        assert!(matches!(error_3, Err(Error(..))));
83    }
84}