vibesql_types/sql_value/
mod.rs

1//! SQL Value runtime representation
2
3mod comparison;
4mod display;
5mod hash;
6
7use crate::{
8    temporal::{Date, Interval, IntervalField, Time, Timestamp},
9    DataType,
10};
11
12/// String type for SQL values using ArcStr with small string optimization (SSO).
13/// Strings ≤22 bytes are stored inline without heap allocation.
14pub type StringValue = arcstr::ArcStr;
15
16/// SQL Values - runtime representation of data
17///
18/// Represents actual values in SQL, including NULL.
19///
20/// String types use `StringValue` (ArcStr) which provides O(1) cloning.
21/// Strings ≤22 bytes are stored inline (small string optimization) avoiding heap allocation.
22#[derive(Debug, Clone)]
23pub enum SqlValue {
24    Integer(i64),
25    Smallint(i16),
26    Bigint(i64),
27    Unsigned(u64), // 64-bit unsigned integer (MySQL compatibility)
28    Numeric(f64),  // f64 for performance (was: String)
29
30    Float(f32),
31    Real(f64),  // SQLite REAL is 8-byte IEEE float (same as f64)
32    Double(f64),
33
34    Character(StringValue),
35    Varchar(StringValue),
36
37    Boolean(bool),
38
39    // Date/Time types with proper structured representation
40    Date(Date),
41    Time(Time),
42    Timestamp(Timestamp),
43
44    // Interval type
45    Interval(Interval),
46
47    // Vector type (for AI/ML workloads)
48    Vector(Vec<f32>),
49
50    // Binary/blob type
51    Blob(Vec<u8>),
52
53    Null,
54}
55
56impl SqlValue {
57    /// Check if this value is NULL
58    pub fn is_null(&self) -> bool {
59        matches!(self, SqlValue::Null)
60    }
61
62    /// Get the type name as a string (for error messages)
63    pub fn type_name(&self) -> &'static str {
64        match self {
65            SqlValue::Integer(_) => "INTEGER",
66            SqlValue::Smallint(_) => "SMALLINT",
67            SqlValue::Bigint(_) => "BIGINT",
68            SqlValue::Unsigned(_) => "UNSIGNED",
69            SqlValue::Numeric(_) => "NUMERIC",
70            SqlValue::Float(_) => "FLOAT",
71            SqlValue::Real(_) => "REAL",
72            SqlValue::Double(_) => "DOUBLE PRECISION",
73            SqlValue::Character(_) => "CHAR",
74            SqlValue::Varchar(_) => "VARCHAR",
75            SqlValue::Boolean(_) => "BOOLEAN",
76            SqlValue::Date(_) => "DATE",
77            SqlValue::Time(_) => "TIME",
78            SqlValue::Timestamp(_) => "TIMESTAMP",
79            SqlValue::Interval(_) => "INTERVAL",
80            SqlValue::Vector(_) => "VECTOR",
81            SqlValue::Blob(_) => "BLOB",
82            SqlValue::Null => "NULL",
83        }
84    }
85
86    /// Get the data type of this value
87    pub fn get_type(&self) -> DataType {
88        match self {
89            SqlValue::Integer(_) => DataType::Integer,
90            SqlValue::Smallint(_) => DataType::Smallint,
91            SqlValue::Bigint(_) => DataType::Bigint,
92            SqlValue::Unsigned(_) => DataType::Unsigned,
93            SqlValue::Numeric(_) => DataType::Numeric { precision: 38, scale: 0 }, // Default
94            SqlValue::Float(_) => DataType::Float { precision: 53 }, // Default to double precision
95            SqlValue::Real(_) => DataType::Real,
96            SqlValue::Double(_) => DataType::DoublePrecision,
97            SqlValue::Character(s) => DataType::Character { length: s.len() }, /* Arc<str> has */
98            // len()
99            SqlValue::Varchar(_) => DataType::Varchar { max_length: None }, /* Unknown/unlimited */
100            // length
101            SqlValue::Boolean(_) => DataType::Boolean,
102            SqlValue::Date(_) => DataType::Date,
103            SqlValue::Time(_) => DataType::Time { with_timezone: false },
104            SqlValue::Timestamp(_) => DataType::Timestamp { with_timezone: false },
105            SqlValue::Interval(_) => DataType::Interval {
106                start_field: IntervalField::Day, /* Default - actual type lost in string
107                                                  * representation */
108                end_field: None,
109            },
110            SqlValue::Vector(v) => DataType::Vector { dimensions: v.len() as u32 },
111            SqlValue::Blob(_) => DataType::BinaryLargeObject,
112            SqlValue::Null => DataType::Null,
113        }
114    }
115
116    /// Estimate the memory size of this value in bytes
117    ///
118    /// Used for memory limit tracking during query execution.
119    /// Provides a reasonable approximation including heap allocations.
120    pub fn estimated_size_bytes(&self) -> usize {
121        use std::mem::size_of;
122
123        // Base size of the enum (24 bytes for largest variant discriminant + data)
124        let base_size = size_of::<SqlValue>();
125
126        // Add heap allocation size for variable-length types
127        match self {
128            SqlValue::Character(s) | SqlValue::Varchar(s) => {
129                // StringValue: base + string length
130                // Note: ArcStr strings ≤22 bytes use SSO (no heap)
131                // but we still count the string length for accounting purposes
132                base_size + s.len()
133            }
134            SqlValue::Interval(i) => {
135                // Interval stores a String internally
136                base_size + i.to_string().len()
137            }
138            SqlValue::Vector(v) => {
139                // Vector: base + heap capacity (each f32 is 4 bytes)
140                base_size + (v.capacity() * std::mem::size_of::<f32>())
141            }
142            SqlValue::Blob(b) => {
143                // Blob: base + heap capacity
144                base_size + b.capacity()
145            }
146            // Fixed-size types: just the enum size
147            SqlValue::Integer(_)
148            | SqlValue::Smallint(_)
149            | SqlValue::Bigint(_)
150            | SqlValue::Unsigned(_)
151            | SqlValue::Numeric(_)
152            | SqlValue::Float(_)
153            | SqlValue::Real(_)
154            | SqlValue::Double(_)
155            | SqlValue::Boolean(_)
156            | SqlValue::Date(_)
157            | SqlValue::Time(_)
158            | SqlValue::Timestamp(_)
159            | SqlValue::Null => base_size,
160        }
161    }
162}