Skip to main content

Value

Enum Value 

Source
#[non_exhaustive]
pub enum Value {
Show 26 variants Null, Boolean(bool), TinyInt(i8), SmallInt(i16), Integer(i32), BigInt(i64), HugeInt(i128), UTinyInt(u8), USmallInt(u16), UInteger(u32), UBigInt(u64), UHugeInt(u128), Float(f32), Double(f64), Decimal { unscaled: i128, width: u8, scale: u8, }, Varchar(String), Blob(Vec<u8>), Date(i32), Time(i64), TimeTz(i64), Timestamp(i64), TimestampTz(i64), Interval { months: i32, days: i32, micros: i64, }, List { element: LogicalType, values: Vec<Value>, }, Struct(Vec<(String, Value)>), Map { key: Box<LogicalType>, value: Box<LogicalType>, entries: Vec<(Value, Value)>, },
}
Expand description

A single SQL value.

PartialEq here is Rust equality and not SQL equality. Two nulls compare equal and two NaNs compare equal, both of which SQL disagrees with. That is the right behaviour for a test assertion and the wrong behaviour for a WHERE clause, and the WHERE clause gets its comparison from the kernels rather than from here.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Null

NULL, of no particular type.

§

Boolean(bool)

BOOLEAN.

§

TinyInt(i8)

TINYINT.

§

SmallInt(i16)

SMALLINT.

§

Integer(i32)

INTEGER.

§

BigInt(i64)

BIGINT.

§

HugeInt(i128)

HUGEINT.

§

UTinyInt(u8)

UTINYINT.

§

USmallInt(u16)

USMALLINT.

§

UInteger(u32)

UINTEGER.

§

UBigInt(u64)

UBIGINT.

§

UHugeInt(u128)

UHUGEINT.

§

Float(f32)

FLOAT.

§

Double(f64)

DOUBLE.

§

Decimal

DECIMAL(width, scale), carrying the unscaled integer.

Fields

§unscaled: i128

The unscaled value, so 12.34 at scale 2 is 1234.

§width: u8

Total digits.

§scale: u8

Digits right of the point.

§

Varchar(String)

VARCHAR.

§

Blob(Vec<u8>)

BLOB.

§

Date(i32)

DATE, days since 1970-01-01.

§

Time(i64)

TIME, microseconds since midnight.

§

TimeTz(i64)

TIME WITH TIME ZONE, microseconds since midnight UTC.

An arm of its own rather than a Value::Time under a type that says the zone, because the plan holds a constant’s type and its value in two places and checks that the two agree, and because printing one is not printing the other: a zoned time carries the offset after it.

§

Timestamp(i64)

TIMESTAMP, microseconds since 1970-01-01 00:00:00.

§

TimestampTz(i64)

TIMESTAMP WITH TIME ZONE, microseconds since 1970-01-01 00:00:00 UTC.

The same instant a Value::Timestamp holds, and what makes it a different value is what a reader is entitled to conclude from it. A TIMESTAMP is a wall clock reading with no zone behind it and this is a point in time, so the one thing this arm knows that the other does not is which moment it is.

§

Interval

INTERVAL, the months, days and microseconds triple.

Three fields rather than one duration because interval arithmetic with months is not associative with days, and DuckDB’s specific behaviour is what tests assert on. A month is not 30 days and this representation is what refuses to pretend otherwise.

Fields

§months: i32

Whole months.

§days: i32

Whole days.

§micros: i64

Microseconds.

§

List

A list, carrying its element type so that an empty list still knows what it is empty of.

Fields

§element: LogicalType

The element type.

§values: Vec<Value>

The elements.

§

Struct(Vec<(String, Value)>)

A struct, in field order.

§

Map

A map, in insertion order, carrying both of its types so that an empty map still knows what it is empty of.

Pairs rather than a struct per entry, even though that is how a map is stored underneath and how DuckDB stores one. A Value is what a result is read out as and what a test asserts on, and an assertion about a map should read as an assertion about a map rather than about a list of two field structs. The vector is where the other shape lives, and it is the shape that matters for the bytes.

Order is kept rather than sorted. DuckDB prints a map in the order it was built in and nothing here is entitled to decide that the keys wanted sorting.

The two types are boxed and the list’s one is not, which looks inconsistent and is not. A LogicalType is 32 bytes and this enum is 64, so a list fits its type and its values in an arm with room to spare while two types and a vector would need 96 and every BOOLEAN in the system would get 32 bytes wider to pay for it. LogicalType::Map boxes them for the same reason, so the boxes here are the ones it already has rather than new ones.

Fields

§key: Box<LogicalType>

The key type.

§value: Box<LogicalType>

The value type.

§entries: Vec<(Value, Value)>

The entries, in order.

Implementations§

Source§

impl Value

Source

pub fn map( key: LogicalType, value: LogicalType, entries: Vec<(Self, Self)>, ) -> Self

A map of these entries, keyed and valued by these types.

Here because Value::Map holds its two types boxed and a caller should not have to say so. Every other arm of this enum is built as a literal and this one would be too if it were not for the boxes.

Source

pub fn footprint(&self) -> usize

How many bytes this value takes, counting what it owns on the heap.

What the memory limit charges for a value held in a buffer. It is the enum itself plus the string, the blob, the list or the struct behind it, and it counts capacity rather than length, because capacity is what was taken from the allocator and a string built by pushing bytes usually has more of it than it needs.

The enum is as wide as its widest arm whatever is in it, so a BOOLEAN costs the same as a HUGEINT here. That is not a rounding error, it is the layout: a row of booleans held as values really does cost that.

Source

pub fn is_null(&self) -> bool

Whether this is NULL.

Source

pub fn logical_type(&self) -> LogicalType

The type of this value.

Source

pub fn as_i64(&self) -> Option<i64>

The value as an i64, for the integer types that fit in one.

Used by the planner for the places where a literal has to be a small integer, LIMIT and OFFSET being the obvious ones. Returns None rather than saturating, because a LIMIT that silently became i64::MAX is worse than an error.

Source

pub fn as_bool(&self) -> Option<bool>

The value as a bool, for a BOOLEAN and nothing else.

Source

pub fn as_str(&self) -> Option<&str>

The value as a string slice, for a VARCHAR and nothing else.

Source§

impl Value

Source

pub fn to_string_at_offset(&self, offset_seconds: i32) -> String

Formats a value in a session offset rather than the UTC fallback used by std::fmt::Display.

Trait Implementations§

Source§

impl Clone for Value

Source§

fn clone(&self) -> Value

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Value

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Value

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Value

Source§

fn eq(&self, other: &Value) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Value

Auto Trait Implementations§

§

impl Freeze for Value

§

impl RefUnwindSafe for Value

§

impl Send for Value

§

impl Sync for Value

§

impl Unpin for Value

§

impl UnsafeUnpin for Value

§

impl UnwindSafe for Value

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.