Skip to main content

duckdb/types/
value.rs

1use super::{Decimal, Null, OrderedMap, TimeUnit, Type};
2
3/// Owning [dynamic type value](https://duckdb.org/docs/stable/sql/data_types/overview.html).
4/// Value's type is typically dictated by DuckDB (not by the caller).
5///
6/// Container variants decode child values without DuckDB child logical type
7/// metadata. See the [`crate::types`] compatibility notes for `UHUGEINT`
8/// behavior inside containers.
9///
10/// See [`ValueRef`](crate::types::ValueRef) for a non-owning dynamic type
11/// value.
12#[derive(Clone, Debug, PartialEq)]
13#[non_exhaustive]
14pub enum Value {
15    /// The value is a `NULL` value.
16    Null,
17    /// The value is a boolean.
18    Boolean(bool),
19    /// The value is a signed tiny integer.
20    TinyInt(i8),
21    /// The value is a signed small integer.
22    SmallInt(i16),
23    /// The value is a signed integer.
24    Int(i32),
25    /// The value is a signed big integer.
26    BigInt(i64),
27    /// The value is a signed huge integer.
28    HugeInt(i128),
29    /// The value is an unsigned huge integer.
30    ///
31    /// Top-level `UHUGEINT` result values materialize as this variant. Nested
32    /// `UHUGEINT` values inside lists, structs, maps, arrays, and unions do
33    /// not currently carry DuckDB child logical metadata and cannot recover
34    /// values above `i128::MAX`.
35    UHugeInt(u128),
36    /// The value is a unsigned tiny integer.
37    UTinyInt(u8),
38    /// The value is a unsigned small integer.
39    USmallInt(u16),
40    /// The value is a unsigned integer.
41    UInt(u32),
42    /// The value is a unsigned big integer.
43    UBigInt(u64),
44    /// The value is a f32.
45    Float(f32),
46    /// The value is a f64.
47    Double(f64),
48    /// The value is a DuckDB decimal.
49    ///
50    /// [`Decimal`] stores DuckDB's decimal width, scale, and scaled integer
51    /// payload.
52    Decimal(Decimal),
53    /// The value is a timestamp.
54    Timestamp(TimeUnit, i64),
55    /// The value is a text string.
56    Text(String),
57    /// The value is a blob of data
58    Blob(Vec<u8>),
59    /// The value is a `GEOMETRY`, represented as WKB bytes.
60    ///
61    /// As of the bundled DuckDB version, DuckDB does not expose a dedicated
62    /// geometry bind or appender helper. Binding this variant routes its WKB
63    /// bytes through the BLOB APIs. Use spatial SQL such as `ST_GeomFromWKB(?)`
64    /// when binding WKB bytes into a `GEOMETRY` SQL context. Appender writes
65    /// can stage these bytes in BLOB columns; appending directly to GEOMETRY
66    /// columns is not supported. See [`ValueRef::Geometry`](super::ValueRef::Geometry)
67    /// for borrowed geometry values.
68    Geometry(Vec<u8>),
69    /// The value is a date32
70    ///
71    /// The `i32` represents the number of days since the Unix epoch (1970-01-01).
72    ///
73    /// Enable the `chrono` feature for easy conversion to proper date types like `NaiveDate`.
74    Date32(i32),
75    /// The value is a time64
76    Time64(TimeUnit, i64),
77    /// The value is an interval (month, day, nano)
78    Interval {
79        /// months
80        months: i32,
81        /// days
82        days: i32,
83        /// nanos
84        nanos: i64,
85    },
86    /// The value is a list.
87    List(Vec<Value>),
88    /// The value is an enum
89    Enum(String),
90    /// The value is a struct.
91    Struct(OrderedMap<String, Value>),
92    /// The value is an array.
93    Array(Vec<Value>),
94    /// The value is a map.
95    Map(OrderedMap<Value, Value>),
96    /// The value is a union.
97    Union(Box<Value>),
98}
99
100impl From<Null> for Value {
101    #[inline]
102    fn from(_: Null) -> Self {
103        Self::Null
104    }
105}
106
107impl From<bool> for Value {
108    #[inline]
109    fn from(i: bool) -> Self {
110        Self::Boolean(i)
111    }
112}
113
114impl From<usize> for Value {
115    #[inline]
116    fn from(i: usize) -> Self {
117        Self::UBigInt(i as u64)
118    }
119}
120
121impl From<isize> for Value {
122    #[inline]
123    fn from(i: isize) -> Self {
124        Self::BigInt(i as i64)
125    }
126}
127
128#[cfg(feature = "uuid")]
129impl From<uuid::Uuid> for Value {
130    #[inline]
131    fn from(id: uuid::Uuid) -> Self {
132        Self::Text(id.to_string())
133    }
134}
135
136impl From<i8> for Value {
137    #[inline]
138    fn from(i: i8) -> Self {
139        Self::TinyInt(i)
140    }
141}
142
143impl From<i16> for Value {
144    #[inline]
145    fn from(i: i16) -> Self {
146        Self::SmallInt(i)
147    }
148}
149
150impl From<i32> for Value {
151    #[inline]
152    fn from(i: i32) -> Self {
153        Self::Int(i)
154    }
155}
156
157impl From<i64> for Value {
158    #[inline]
159    fn from(i: i64) -> Self {
160        Self::BigInt(i)
161    }
162}
163
164impl From<u8> for Value {
165    #[inline]
166    fn from(i: u8) -> Self {
167        Self::UTinyInt(i)
168    }
169}
170
171impl From<u16> for Value {
172    #[inline]
173    fn from(i: u16) -> Self {
174        Self::USmallInt(i)
175    }
176}
177
178impl From<u32> for Value {
179    #[inline]
180    fn from(i: u32) -> Self {
181        Self::UInt(i)
182    }
183}
184
185impl From<u64> for Value {
186    #[inline]
187    fn from(i: u64) -> Self {
188        Self::UBigInt(i)
189    }
190}
191
192impl From<i128> for Value {
193    #[inline]
194    fn from(i: i128) -> Self {
195        Self::HugeInt(i)
196    }
197}
198
199impl From<u128> for Value {
200    #[inline]
201    fn from(i: u128) -> Self {
202        Self::UHugeInt(i)
203    }
204}
205
206impl From<Decimal> for Value {
207    #[inline]
208    fn from(decimal: Decimal) -> Self {
209        Self::Decimal(decimal)
210    }
211}
212
213impl From<f32> for Value {
214    #[inline]
215    fn from(f: f32) -> Self {
216        Self::Float(f)
217    }
218}
219
220impl From<f64> for Value {
221    #[inline]
222    fn from(f: f64) -> Self {
223        Self::Double(f)
224    }
225}
226
227impl From<String> for Value {
228    #[inline]
229    fn from(s: String) -> Self {
230        Self::Text(s)
231    }
232}
233
234impl From<Vec<u8>> for Value {
235    #[inline]
236    fn from(v: Vec<u8>) -> Self {
237        Self::Blob(v)
238    }
239}
240
241impl<T> From<Option<T>> for Value
242where
243    T: Into<Self>,
244{
245    #[inline]
246    fn from(v: Option<T>) -> Self {
247        match v {
248            Some(x) => x.into(),
249            None => Self::Null,
250        }
251    }
252}
253
254impl Value {
255    /// Returns DuckDB fundamental datatype.
256    #[inline]
257    pub fn data_type(&self) -> Type {
258        match *self {
259            Self::Null => Type::Null,
260            Self::Boolean(_) => Type::Boolean,
261            Self::TinyInt(_) => Type::TinyInt,
262            Self::SmallInt(_) => Type::SmallInt,
263            Self::Int(_) => Type::Int,
264            Self::BigInt(_) => Type::BigInt,
265            Self::HugeInt(_) => Type::HugeInt,
266            Self::UHugeInt(_) => Type::UHugeInt,
267            Self::UTinyInt(_) => Type::UTinyInt,
268            Self::USmallInt(_) => Type::USmallInt,
269            Self::UInt(_) => Type::UInt,
270            Self::UBigInt(_) => Type::UBigInt,
271            Self::Float(_) => Type::Float,
272            Self::Double(_) => Type::Double,
273            Self::Decimal(_) => Type::Decimal,
274            Self::Timestamp(_, _) => Type::Timestamp,
275            Self::Text(_) => Type::Text,
276            Self::Blob(_) => Type::Blob,
277            Self::Geometry(_) => Type::Geometry,
278            Self::Date32(_) => Type::Date32,
279            Self::Time64(..) => Type::Time64,
280            Self::Interval { .. } => Type::Interval,
281            Self::Union(..) | Self::Struct(..) | Self::List(..) | Self::Array(..) | Self::Map(..) => todo!(),
282            Self::Enum(..) => Type::Enum,
283        }
284    }
285}