Skip to main content

drizzle_core/sql/
owned.rs

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