1pub use self::{
6 from_sql::{FromSql, FromSqlError, FromSqlResult},
7 ordered_map::OrderedMap,
8 string::DuckString,
9 to_sql::{ToSql, ToSqlOutput},
10 value::Value,
11 value_ref::{EnumType, ListType, TimeUnit, ValueRef},
12};
13
14use arrow::datatypes::DataType;
15use std::fmt;
16
17#[cfg(feature = "chrono")]
18mod chrono;
19mod from_sql;
20#[cfg(feature = "serde_json")]
21mod serde_json;
22mod to_sql;
23#[cfg(feature = "url")]
24mod url;
25mod value;
26mod value_ref;
27
28mod ordered_map;
29mod string;
30
31#[derive(Copy, Clone)]
44pub struct Null;
45
46#[derive(Clone, Debug, PartialEq, Eq)]
49pub enum Type {
50 Null,
52 Boolean,
54 TinyInt,
56 SmallInt,
58 Int,
60 BigInt,
62 HugeInt,
64 UTinyInt,
66 USmallInt,
68 UInt,
70 UBigInt,
72 Float,
74 Double,
76 Decimal,
78 Timestamp,
80 Text,
82 Blob,
84 Date32,
86 Time64,
88 Interval,
90 List(Box<Type>),
92 Enum,
94 Struct(Vec<(String, Type)>),
96 Map(Box<Type>, Box<Type>),
98 Array(Box<Type>, u32),
100 Union,
102 Any,
104}
105
106impl From<&DataType> for Type {
107 fn from(value: &DataType) -> Self {
108 match value {
109 DataType::Null => Self::Null,
110 DataType::Boolean => Self::Boolean,
111 DataType::Int8 => Self::TinyInt,
112 DataType::Int16 => Self::SmallInt,
113 DataType::Int32 => Self::Int,
114 DataType::Int64 => Self::BigInt,
115 DataType::UInt8 => Self::UTinyInt,
116 DataType::UInt16 => Self::USmallInt,
117 DataType::UInt32 => Self::UInt,
118 DataType::UInt64 => Self::UBigInt,
119 DataType::Float32 => Self::Float, DataType::Float64 => Self::Double, DataType::Timestamp(_, _) => Self::Timestamp,
123 DataType::Date32 => Self::Date32,
124 DataType::Time64(_) => Self::Time64,
127 DataType::Binary => Self::Blob,
130 DataType::FixedSizeBinary(_) => Self::Blob,
131 DataType::LargeUtf8 | DataType::Utf8 => Self::Text,
133 DataType::List(inner) => Self::List(Box::new(Self::from(inner.data_type()))),
134 DataType::FixedSizeList(field, size) => {
135 Self::Array(Box::new(Self::from(field.data_type())), (*size).try_into().unwrap())
136 }
137 DataType::Struct(inner) => {
139 let capacity = inner.len();
140 let mut struct_vec = Vec::with_capacity(capacity);
141 struct_vec.extend(inner.iter().map(|f| (f.name().to_owned(), Self::from(f.data_type()))));
142 Self::Struct(struct_vec)
143 }
144 DataType::LargeList(inner) => Self::List(Box::new(Self::from(inner.data_type()))),
145 DataType::Union(_, _) => Self::Union,
146 DataType::Decimal128(..) => Self::Decimal,
147 DataType::Decimal256(..) => Self::Decimal,
148 DataType::Map(field, ..) => {
149 let data_type = field.data_type();
150 match data_type {
151 DataType::Struct(fields) => Self::Map(
152 Box::new(Self::from(fields[0].data_type())),
153 Box::new(Self::from(fields[1].data_type())),
154 ),
155 _ => unreachable!(),
156 }
157 }
158 res => unimplemented!("{}", res),
159 }
160 }
161}
162
163impl fmt::Display for Type {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 match *self {
166 Self::Null => f.pad("Null"),
167 Self::Boolean => f.pad("Boolean"),
168 Self::TinyInt => f.pad("TinyInt"),
169 Self::SmallInt => f.pad("SmallInt"),
170 Self::Int => f.pad("Int"),
171 Self::BigInt => f.pad("BigInt"),
172 Self::HugeInt => f.pad("HugeInt"),
173 Self::UTinyInt => f.pad("UTinyInt"),
174 Self::USmallInt => f.pad("USmallInt"),
175 Self::UInt => f.pad("UInt"),
176 Self::UBigInt => f.pad("UBigInt"),
177 Self::Float => f.pad("Float"),
178 Self::Double => f.pad("Double"),
179 Self::Decimal => f.pad("Decimal"),
180 Self::Timestamp => f.pad("Timestamp"),
181 Self::Text => f.pad("Text"),
182 Self::Blob => f.pad("Blob"),
183 Self::Date32 => f.pad("Date32"),
184 Self::Time64 => f.pad("Time64"),
185 Self::Interval => f.pad("Interval"),
186 Self::Struct(..) => f.pad("Struct"),
187 Self::List(..) => f.pad("List"),
188 Self::Enum => f.pad("Enum"),
189 Self::Map(..) => f.pad("Map"),
190 Self::Array(..) => f.pad("Array"),
191 Self::Union => f.pad("Union"),
192 Self::Any => f.pad("Any"),
193 }
194 }
195}
196
197#[cfg(test)]
198mod test {
199 use super::Value;
200 use crate::{Connection, Result};
201
202 fn checked_memory_handle() -> Result<Connection> {
203 let db = Connection::open_in_memory()?;
204 db.execute_batch("CREATE TABLE foo (b BLOB, t TEXT, i INTEGER, f FLOAT, n BLOB)")?;
205 Ok(db)
206 }
207
208 #[test]
209 fn test_blob() -> Result<()> {
210 let db = checked_memory_handle()?;
211
212 let v1234 = vec![1u8, 2, 3, 4];
213 db.execute("INSERT INTO foo(b) VALUES (?)", [&v1234])?;
214
215 let v: Vec<u8> = db.query_row("SELECT b FROM foo", [], |r| r.get(0))?;
216 assert_eq!(v, v1234);
217 Ok(())
218 }
219
220 #[test]
221 fn test_empty_blob() -> Result<()> {
222 let db = checked_memory_handle()?;
223
224 let empty = vec![];
225 db.execute("INSERT INTO foo(b) VALUES (?)", [&empty])?;
226
227 let v: Vec<u8> = db.query_row("SELECT b FROM foo", [], |r| r.get(0))?;
228 assert_eq!(v, empty);
229 Ok(())
230 }
231
232 #[test]
233 fn test_str() -> Result<()> {
234 let db = checked_memory_handle()?;
235
236 let s = "hello, world!";
237 db.execute("INSERT INTO foo(t) VALUES (?)", [&s])?;
238
239 let from: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
240 assert_eq!(from, s);
241 Ok(())
242 }
243
244 #[test]
245 fn test_string() -> Result<()> {
246 let db = checked_memory_handle()?;
247
248 let s = "hello, world!";
249 let result = db.execute("INSERT INTO foo(t) VALUES (?)", [s.to_owned()]);
250 if result.is_err() {
251 panic!("exe error: {}", result.unwrap_err())
252 }
253
254 let from: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?;
255 assert_eq!(from, s);
256 Ok(())
257 }
258
259 #[test]
260 fn test_value() -> Result<()> {
261 let db = checked_memory_handle()?;
262
263 db.execute("INSERT INTO foo(i) VALUES (?)", [Value::BigInt(10)])?;
264
265 assert_eq!(10i64, db.query_row::<i64, _, _>("SELECT i FROM foo", [], |r| r.get(0))?);
266 Ok(())
267 }
268
269 #[test]
270 fn test_option() -> Result<()> {
271 let db = checked_memory_handle()?;
272
273 let s = "hello, world!";
274 let b = Some(vec![1u8, 2, 3, 4]);
275
276 db.execute("INSERT INTO foo(t) VALUES (?)", [&s])?;
277 db.execute("INSERT INTO foo(b) VALUES (?)", [&b])?;
278
279 let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC")?;
280 let mut rows = stmt.query([])?;
281
282 {
283 let row1 = rows.next()?.unwrap();
284 let s1: Option<String> = row1.get_unwrap(0);
285 let b1: Option<Vec<u8>> = row1.get_unwrap(1);
286 assert_eq!(s, s1.unwrap());
287 assert!(b1.is_none());
288 }
289
290 {
291 let row2 = rows.next()?.unwrap();
292 let s2: Option<String> = row2.get_unwrap(0);
293 let b2: Option<Vec<u8>> = row2.get_unwrap(1);
294 assert!(s2.is_none());
295 assert_eq!(b, b2);
296 }
297 Ok(())
298 }
299
300 #[test]
301 fn test_dynamic_type() -> Result<()> {
302 use super::Value;
303 let db = checked_memory_handle()?;
304
305 db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)", [])?;
306
307 let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo")?;
308 let mut rows = stmt.query([])?;
309 let row = rows.next()?.unwrap();
310 assert_eq!(Value::Blob(vec![120, 48, 49, 48, 50]), row.get::<_, Value>(0)?);
313 assert_eq!(Value::Text(String::from("text")), row.get::<_, Value>(1)?);
314 assert_eq!(Value::Int(1), row.get::<_, Value>(2)?);
315 match row.get::<_, Value>(3)? {
316 Value::Float(val) => assert!((1.5 - val).abs() < f32::EPSILON),
317 x => panic!("Invalid Value {x:?}"),
318 }
319 assert_eq!(Value::Null, row.get::<_, Value>(4)?);
320 Ok(())
321 }
322}