|
1 | | -//! Traits dealing with DuckDB data types. |
2 | | -//! |
3 | | -//! DuckDB uses a [dynamic type system](https://www.sqlite.org/datatype3.html). Implementations of |
4 | | -//! the [`ToSql`] and [`FromSql`] traits are provided for the basic types that |
5 | | -//! DuckDB provides methods for: |
6 | | -//! |
7 | | -//! * Strings (`String` and `&str`) |
8 | | -//! * Blobs (`Vec<u8>` and `&[u8]`) |
9 | | -//! * Numbers |
10 | | -//! |
11 | | -//! The number situation is a little complicated due to the fact that all |
12 | | -//! numbers in DuckDB are stored as `INTEGER` (`i64`) or `REAL` (`f64`). |
13 | | -//! |
14 | | -//! [`ToSql`] and [`FromSql`] are implemented for all primitive number types. |
15 | | -//! [`FromSql`] has different behaviour depending on the SQL and Rust types, and |
16 | | -//! the value. |
17 | | -//! |
18 | | -//! * `INTEGER` to integer: returns an |
19 | | -//! [`Error::IntegralValueOutOfRange`](crate::Error::IntegralValueOutOfRange) |
20 | | -//! error if the value does not fit in the Rust type. |
21 | | -//! * `REAL` to integer: always returns an |
22 | | -//! [`Error::InvalidColumnType`](crate::Error::InvalidColumnType) error. |
23 | | -//! * `INTEGER` to float: casts using `as` operator. Never fails. |
24 | | -//! * `REAL` to float: casts using `as` operator. Never fails. |
25 | | -//! |
26 | | -//! [`ToSql`] always succeeds except when storing a `u64` or `usize` value that |
27 | | -//! cannot fit in an `INTEGER` (`i64`). Also note that DuckDB ignores column |
28 | | -//! types, so if you store an `i64` in a column with type `REAL` it will be |
29 | | -//! stored as an `INTEGER`, not a `REAL`. |
30 | | -//! |
31 | | -//! If the `time` feature is enabled, implementations are |
32 | | -//! provided for `time::OffsetDateTime` that use the RFC 3339 date/time format, |
33 | | -//! `"%Y-%m-%dT%H:%M:%S.%fZ"`, to store time values as strings. These values |
34 | | -//! can be parsed by SQLite's builtin |
35 | | -//! [datetime](https://www.sqlite.org/lang_datefunc.html) functions. If you |
36 | | -//! want different storage for datetimes, you can use a newtype. |
37 | | -#![cfg_attr( |
38 | | - feature = "time", |
39 | | - doc = r##" |
40 | | -For example, to store datetimes as `i64`s counting the number of seconds since |
41 | | -the Unix epoch: |
42 | | -
|
43 | | -``` |
44 | | -use duckdb::types::{FromSql, FromSqlResult, ToSql, ToSqlOutput, ValueRef}; |
45 | | -use duckdb::Result; |
46 | | -
|
47 | | -pub struct DateTimeSql(pub time::OffsetDateTime); |
48 | | -
|
49 | | -impl FromSql for DateTimeSql { |
50 | | - fn column_result(value: ValueRef) -> FromSqlResult<Self> { |
51 | | - i64::column_result(value).map(|as_i64| { |
52 | | - DateTimeSql(time::OffsetDateTime::from_unix_timestamp(as_i64)) |
53 | | - }) |
54 | | - } |
55 | | -} |
56 | | -
|
57 | | -impl ToSql for DateTimeSql { |
58 | | - fn to_sql(&self) -> Result<ToSqlOutput> { |
59 | | - Ok(self.0.timestamp().into()) |
60 | | - } |
61 | | -} |
62 | | -``` |
63 | | -
|
64 | | -"## |
65 | | -)] |
66 | 1 | //! [`ToSql`] and [`FromSql`] are also implemented for `Option<T>` where `T` |
67 | 2 | //! implements [`ToSql`] or [`FromSql`] for the cases where you want to know if |
68 | 3 | //! a value was NULL (which gets translated to `None`). |
@@ -395,10 +330,6 @@ mod test { |
395 | 330 | assert!(is_invalid_column_type(row.get::<_, i64>(0).err().unwrap())); |
396 | 331 | assert!(is_invalid_column_type(row.get::<_, c_double>(0).err().unwrap())); |
397 | 332 | assert!(is_invalid_column_type(row.get::<_, String>(0).err().unwrap())); |
398 | | - #[cfg(feature = "time")] |
399 | | - assert!(is_invalid_column_type( |
400 | | - row.get::<_, time::OffsetDateTime>(0).err().unwrap() |
401 | | - )); |
402 | 333 | assert!(is_invalid_column_type(row.get::<_, Option<c_int>>(0).err().unwrap())); |
403 | 334 |
|
404 | 335 | // 1 is actually a text (String) |
@@ -426,10 +357,6 @@ mod test { |
426 | 357 | assert!(is_invalid_column_type(row.get::<_, c_double>(4).err().unwrap())); |
427 | 358 | assert!(is_invalid_column_type(row.get::<_, String>(4).err().unwrap())); |
428 | 359 | assert!(is_invalid_column_type(row.get::<_, Vec<u8>>(4).err().unwrap())); |
429 | | - #[cfg(feature = "time")] |
430 | | - assert!(is_invalid_column_type( |
431 | | - row.get::<_, time::OffsetDateTime>(4).err().unwrap() |
432 | | - )); |
433 | 360 | Ok(()) |
434 | 361 | } |
435 | 362 |
|
|
0 commit comments