Skip to main content

drizzle_sqlite/
common.rs

1//! `SQLite` schema marker, the [`Number`] type, and the [`Join`] re-export.
2
3use drizzle_core::traits::SQLViewInfo;
4use drizzle_core::{SQLIndexInfo, SQLSchemaType, TableRef};
5
6/// The `SQLite` dialect marker for schema items.
7///
8/// Used as a type parameter (`SQLTable<'a, SQLiteSchemaType, SQLiteValue<'a>>`)
9/// to tie tables, views and indexes to `SQLite`. The variants name the kinds
10/// of schema object.
11#[derive(Debug, Clone)]
12pub enum SQLiteSchemaType {
13    /// A regular table
14    Table(&'static TableRef),
15    /// A view
16    View(&'static dyn SQLViewInfo),
17    /// An index
18    Index(&'static dyn SQLIndexInfo),
19    /// A trigger
20    Trigger,
21}
22
23impl SQLSchemaType for SQLiteSchemaType {}
24
25//------------------------------------------------------------------------------
26// Number Type
27//------------------------------------------------------------------------------
28
29/// A number that is either an integer or a floating-point value.
30///
31/// Defaults to `Integer(0)`.
32#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
33pub enum Number {
34    /// Integer value
35    Integer(i64),
36    /// Floating point value
37    Real(f64),
38}
39
40impl Default for Number {
41    fn default() -> Self {
42        Self::Integer(Default::default())
43    }
44}
45
46impl From<i64> for Number {
47    fn from(value: i64) -> Self {
48        Self::Integer(value)
49    }
50}
51
52impl From<f64> for Number {
53    fn from(value: f64) -> Self {
54        Self::Real(value)
55    }
56}
57
58// Join types live in drizzle-core; re-exported here for `SQLite` users.
59pub use drizzle_core::{Join, JoinType};
60
61//------------------------------------------------------------------------------
62// Tests
63//------------------------------------------------------------------------------
64
65#[cfg(any(feature = "turso", feature = "libsql", feature = "rusqlite"))]
66#[cfg(test)]
67mod tests {
68    use crate::common::{Join, JoinType, Number};
69    use crate::values::SQLiteValue;
70    use std::borrow::Cow;
71
72    #[test]
73    fn test_into_sqlite_value_impls() {
74        assert_eq!(
75            SQLiteValue::from("hello"),
76            SQLiteValue::Text(Cow::Borrowed("hello"))
77        );
78        assert_eq!(
79            SQLiteValue::from(String::from("world")),
80            SQLiteValue::Text(Cow::Owned("world".to_string()))
81        );
82        assert_eq!(SQLiteValue::from(42i64), SQLiteValue::Integer(42));
83        assert_eq!(SQLiteValue::from(123i32), SQLiteValue::Integer(123));
84        assert_eq!(SQLiteValue::from(2.5f64), SQLiteValue::Real(2.5));
85        assert_eq!(SQLiteValue::from(true), SQLiteValue::Integer(1));
86        assert_eq!(SQLiteValue::from(false), SQLiteValue::Integer(0));
87        let blob_vec: Vec<u8> = vec![1, 2, 3];
88        assert_eq!(
89            SQLiteValue::from(blob_vec.clone()),
90            SQLiteValue::Blob(Cow::Owned(blob_vec.clone()))
91        );
92        let blob_slice: &[u8] = &[4, 5, 6];
93        assert_eq!(
94            SQLiteValue::from(blob_slice),
95            SQLiteValue::Blob(Cow::Borrowed(blob_slice))
96        );
97        assert_eq!(SQLiteValue::from(Option::<String>::None), SQLiteValue::Null);
98        assert_eq!(
99            SQLiteValue::from(Some("optional")),
100            SQLiteValue::Text(Cow::Borrowed("optional"))
101        );
102    }
103
104    #[test]
105    fn test_number_enum() {
106        let int_num = Number::Integer(42);
107        let real_num = Number::Real(2.5);
108
109        assert_eq!(int_num, Number::from(42i64));
110        assert_eq!(real_num, Number::from(2.5f64));
111        assert_eq!(Number::default(), Number::Integer(0));
112    }
113
114    #[test]
115    fn test_join_type_and_join() {
116        let join = Join::new().inner().natural();
117        assert_eq!(join.join_type, JoinType::Inner);
118        assert!(join.natural);
119        assert!(!join.outer);
120
121        let outer_join = Join::new().left().outer();
122        assert_eq!(outer_join.join_type, JoinType::Left);
123        assert!(outer_join.outer);
124
125        let cross_join = Join::new().cross();
126        assert_eq!(cross_join.join_type, JoinType::Cross);
127    }
128
129    #[test]
130    fn test_join_to_sql() {
131        use drizzle_core::{SQL, ToSQL};
132
133        let inner_join = Join::new().inner();
134        let sql: SQL<SQLiteValue> = inner_join.to_sql();
135        assert_eq!(sql.sql(), "INNER JOIN");
136
137        let natural_left_outer = Join::new().natural().left().outer();
138        let sql: SQL<SQLiteValue> = natural_left_outer.to_sql();
139        assert_eq!(sql.sql(), "NATURAL LEFT OUTER JOIN");
140
141        let cross_join = Join::new().cross();
142        let sql: SQL<SQLiteValue> = cross_join.to_sql();
143        assert_eq!(sql.sql(), "CROSS JOIN");
144    }
145}