fire_postgres/query/
mod.rs

1use crate::table::column::{ColumnData, ColumnKind, ColumnType};
2
3use std::borrow::Cow;
4use std::fmt;
5
6#[cfg(feature = "connect")]
7use tokio_postgres::types::ToSql;
8
9pub mod update;
10pub mod whr;
11pub use update::UpdateParams;
12
13pub type SqlStr = Cow<'static, str>;
14
15// find query
16// select query
17// insert query
18// delete query
19// update query
20
21#[derive(Debug, Clone)]
22enum SqlBuilderType {
23	NoSpace(SqlStr),
24	SpaceAfter(SqlStr),
25	SpaceBefore(SqlStr),
26	Space(SqlStr),
27	Param,
28}
29
30#[derive(Debug, Clone)]
31pub struct SqlBuilder {
32	data: Vec<SqlBuilderType>,
33}
34
35impl SqlBuilder {
36	pub fn new() -> Self {
37		Self { data: vec![] }
38	}
39
40	pub fn from_sql_str(sql: impl Into<SqlStr>) -> Self {
41		Self {
42			data: vec![SqlBuilderType::SpaceAfter(sql.into())],
43		}
44	}
45
46	pub fn no_space(&mut self, s: impl Into<SqlStr>) {
47		self.data.push(SqlBuilderType::NoSpace(s.into()));
48	}
49
50	pub fn space_after(&mut self, s: impl Into<SqlStr>) {
51		self.data.push(SqlBuilderType::SpaceAfter(s.into()));
52	}
53
54	pub fn space_before(&mut self, s: impl Into<SqlStr>) {
55		self.data.push(SqlBuilderType::SpaceBefore(s.into()));
56	}
57
58	pub fn space(&mut self, s: impl Into<SqlStr>) {
59		self.data.push(SqlBuilderType::Space(s.into()));
60	}
61
62	pub fn param(&mut self) {
63		self.data.push(SqlBuilderType::Param);
64	}
65
66	pub fn prepend(&mut self, mut sql: SqlBuilder) {
67		sql.data.append(&mut self.data);
68		self.data = sql.data;
69	}
70
71	pub fn append(&mut self, mut sql: SqlBuilder) {
72		self.data.append(&mut sql.data);
73	}
74
75	pub fn is_empty(&self) -> bool {
76		self.data.is_empty()
77	}
78}
79
80impl fmt::Display for SqlBuilder {
81	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82		let mut c = 0;
83		for d in &self.data {
84			match d {
85				SqlBuilderType::NoSpace(s) => {
86					f.write_str(s)?;
87				}
88				SqlBuilderType::SpaceAfter(s) => {
89					write!(f, "{} ", s)?;
90				}
91				SqlBuilderType::SpaceBefore(s) => {
92					write!(f, " {}", s)?;
93				}
94				SqlBuilderType::Space(s) => {
95					write!(f, " {} ", s)?;
96				}
97				SqlBuilderType::Param => {
98					c += 1;
99					write!(f, "${}", c)?;
100				}
101			}
102		}
103
104		Ok(())
105	}
106}
107
108#[derive(Debug, Clone)]
109pub struct Query<'a> {
110	pub sql: SqlBuilder,
111	pub params: Vec<Param<'a>>,
112}
113
114impl<'a> Query<'a> {
115	pub fn new(sql: SqlBuilder, params: Vec<Param<'a>>) -> Self {
116		Self { sql, params }
117	}
118
119	pub fn from_sql_str(sql: impl Into<SqlStr>) -> Self {
120		Self {
121			sql: SqlBuilder::from_sql_str(sql),
122			params: vec![],
123		}
124	}
125
126	pub fn prepend(&mut self, sql: SqlBuilder, mut params: Vec<Param<'a>>) {
127		self.sql.prepend(sql);
128		params.append(&mut self.params);
129		self.params = params;
130	}
131
132	pub fn append(&mut self, mut query: Query<'a>) {
133		self.sql.append(query.sql);
134		self.params.append(&mut query.params);
135	}
136
137	pub fn append_raw(&mut self, sql: SqlBuilder, mut params: Vec<Param<'a>>) {
138		self.sql.append(sql);
139		self.params.append(&mut params);
140	}
141
142	pub fn sql(&self) -> &SqlBuilder {
143		&self.sql
144	}
145
146	pub fn params(&self) -> &[Param] {
147		self.params.as_slice()
148	}
149
150	pub fn is_empty(&self) -> bool {
151		self.sql.is_empty() && self.params.is_empty()
152	}
153
154	pub fn params_data(&self) -> Vec<&ColumnData> {
155		let mut v = Vec::with_capacity(self.params.len());
156		for param in &self.params {
157			v.push(param.data());
158		}
159		v
160	}
161
162	#[cfg(feature = "connect")]
163	pub fn to_sql_params(&self) -> Vec<&(dyn ToSql + Sync)> {
164		let mut v = Vec::with_capacity(self.params.len());
165		for param in &self.params {
166			v.push(param.data() as &(dyn ToSql + Sync));
167		}
168		v
169	}
170}
171
172#[derive(Debug, Clone, PartialEq)]
173pub struct Param<'a> {
174	pub name: &'static str,
175	pub kind: ColumnKind,
176	pub data: ColumnData<'a>,
177}
178
179impl<'a> Param<'a> {
180	pub fn new<T>(name: &'static str, data: &'a T) -> Self
181	where
182		T: ColumnType,
183	{
184		let kind = T::column_kind();
185		Self {
186			name,
187			kind,
188			data: data.to_data(),
189		}
190	}
191
192	pub fn data(&self) -> &ColumnData {
193		&self.data
194	}
195
196	#[inline(always)]
197	pub fn maybe_null(&self) -> bool {
198		matches!(self.kind, ColumnKind::Option(_))
199	}
200}
201
202/*
203find
204- eq
205- ne
206- gt
207- gte
208- lt
209- lte
210- in
211- nin
212
213- and
214- or
215- not
216- nor
217*/