drizzle_core/sql/
owned.rs

1use crate::prelude::*;
2use crate::{OwnedParam, SQL, SQLChunk, SQLColumnInfo, SQLParam, SQLTableInfo, ToSQL, Token};
3use smallvec::SmallVec;
4
5/// Owned version of SQLChunk with 'static lifetime
6#[derive(Debug, Clone)]
7pub enum OwnedSQLChunk<V: SQLParam> {
8    Token(Token),
9    Ident(String),
10    Raw(String),
11    Param(OwnedParam<V>),
12    Table(&'static dyn SQLTableInfo),
13    Column(&'static dyn SQLColumnInfo),
14    Alias {
15        inner: Box<OwnedSQLChunk<V>>,
16        alias: String,
17    },
18}
19
20impl<V: SQLParam> OwnedSQLChunk<V> {
21    /// Creates a token chunk.
22    #[inline]
23    pub const fn token(t: Token) -> Self {
24        Self::Token(t)
25    }
26
27    /// Creates a table chunk.
28    #[inline]
29    pub const fn table(table: &'static dyn SQLTableInfo) -> Self {
30        Self::Table(table)
31    }
32
33    /// Creates a column chunk.
34    #[inline]
35    pub const fn column(column: &'static dyn SQLColumnInfo) -> Self {
36        Self::Column(column)
37    }
38
39    /// Creates a quoted identifier from a runtime string.
40    #[inline]
41    pub fn ident(name: impl Into<String>) -> Self {
42        Self::Ident(name.into())
43    }
44
45    /// Creates raw SQL text from a runtime string.
46    #[inline]
47    pub fn raw(text: impl Into<String>) -> Self {
48        Self::Raw(text.into())
49    }
50
51    /// Creates a parameter chunk with owned value.
52    #[inline]
53    pub fn param(value: OwnedParam<V>) -> Self {
54        Self::Param(value)
55    }
56
57    /// Creates an alias chunk wrapping any OwnedSQLChunk.
58    #[inline]
59    pub fn alias(inner: OwnedSQLChunk<V>, alias: impl Into<String>) -> Self {
60        Self::Alias {
61            inner: Box::new(inner),
62            alias: alias.into(),
63        }
64    }
65}
66
67impl<'a, V: SQLParam> From<SQLChunk<'a, V>> for OwnedSQLChunk<V> {
68    fn from(value: SQLChunk<'a, V>) -> Self {
69        match value {
70            SQLChunk::Token(token) => Self::Token(token),
71            SQLChunk::Ident(cow) => Self::Ident(cow.into_owned()),
72            SQLChunk::Raw(cow) => Self::Raw(cow.into_owned()),
73            SQLChunk::Param(param) => Self::Param(param.into()),
74            SQLChunk::Table(table) => Self::Table(table),
75            SQLChunk::Column(column) => Self::Column(column),
76            SQLChunk::Alias { inner, alias } => Self::Alias {
77                inner: Box::new((*inner).into()),
78                alias: alias.into_owned(),
79            },
80        }
81    }
82}
83
84impl<V: SQLParam> From<OwnedSQLChunk<V>> for SQLChunk<'static, V> {
85    fn from(value: OwnedSQLChunk<V>) -> Self {
86        match value {
87            OwnedSQLChunk::Token(token) => SQLChunk::Token(token),
88            OwnedSQLChunk::Ident(s) => SQLChunk::Ident(Cow::Owned(s)),
89            OwnedSQLChunk::Raw(s) => SQLChunk::Raw(Cow::Owned(s)),
90            OwnedSQLChunk::Param(param) => SQLChunk::Param(param.into()),
91            OwnedSQLChunk::Table(table) => SQLChunk::Table(table),
92            OwnedSQLChunk::Column(column) => SQLChunk::Column(column),
93            OwnedSQLChunk::Alias { inner, alias } => SQLChunk::Alias {
94                inner: Box::new((*inner).into()),
95                alias: Cow::Owned(alias),
96            },
97        }
98    }
99}
100
101/// Owned version of SQL with 'static lifetime
102#[derive(Debug, Clone)]
103pub struct OwnedSQL<V: SQLParam> {
104    pub chunks: SmallVec<[OwnedSQLChunk<V>; 8]>,
105}
106
107impl<V: SQLParam> Default for OwnedSQL<V> {
108    fn default() -> Self {
109        Self {
110            chunks: SmallVec::new(),
111        }
112    }
113}
114
115impl<'a, V: SQLParam> From<SQL<'a, V>> for OwnedSQL<V> {
116    fn from(value: SQL<'a, V>) -> Self {
117        Self {
118            chunks: value.chunks.into_iter().map(Into::into).collect(),
119        }
120    }
121}
122
123impl<V: SQLParam> OwnedSQL<V> {
124    /// Creates an empty SQL fragment with const-friendly initialization.
125    #[inline]
126    pub const fn empty() -> Self {
127        Self {
128            chunks: SmallVec::new_const(),
129        }
130    }
131
132    /// Creates an empty SQL fragment with pre-allocated chunk capacity.
133    #[inline]
134    pub fn with_capacity_chunks(capacity: usize) -> Self {
135        Self {
136            chunks: SmallVec::with_capacity(capacity),
137        }
138    }
139
140    /// Convert to SQL with 'static lifetime
141    pub fn to_sql(&self) -> SQL<'static, V> {
142        SQL {
143            chunks: self.chunks.iter().cloned().map(Into::into).collect(),
144        }
145    }
146
147    /// Convert into SQL with 'static lifetime (consuming)
148    pub fn into_sql(self) -> SQL<'static, V> {
149        SQL {
150            chunks: self.chunks.into_iter().map(Into::into).collect(),
151        }
152    }
153}
154
155impl<V: SQLParam> ToSQL<'static, V> for OwnedSQL<V> {
156    fn to_sql(&self) -> SQL<'static, V> {
157        OwnedSQL::to_sql(self)
158    }
159}