rustbasic_core/sql/
query.rs1use std::marker::PhantomData;
2use serde_json::Value;
3use super::error::Error;
4use super::any::{AnyQueryResult, Executor};
5use super::row::AnyRow;
6
7pub struct Query<'q, DB = super::any::Any, Args = super::any::AnyArguments<'q>> {
8 pub sql: &'q str,
9 pub arguments: Vec<Value>,
10 pub _marker: PhantomData<(DB, Args)>,
11}
12
13impl<'q, DB: super::any::Database, Args> Query<'q, DB, Args> {
14 pub fn bind<T>(mut self, value: T) -> Self
15 where
16 T: IntoBindValue,
17 {
18 self.arguments.push(value.into_bind_value());
19 self
20 }
21
22 pub async fn execute<E>(self, executor: E) -> Result<AnyQueryResult, Error>
23 where
24 E: Executor<Database = DB>,
25 {
26 executor.execute(self.sql, &self.arguments).await
27 }
28
29 pub async fn fetch_all<E>(self, executor: E) -> Result<Vec<AnyRow>, Error>
30 where
31 E: Executor<Database = DB>,
32 {
33 executor.fetch_all(self.sql, &self.arguments).await
34 }
35
36 pub async fn fetch_optional<E>(self, executor: E) -> Result<Option<AnyRow>, Error>
37 where
38 E: Executor<Database = DB>,
39 {
40 executor.fetch_optional(self.sql, &self.arguments).await
41 }
42
43 pub async fn fetch_one<E>(self, executor: E) -> Result<AnyRow, Error>
44 where
45 E: Executor<Database = DB>,
46 {
47 executor.fetch_one(self.sql, &self.arguments).await
48 }
49}
50
51pub fn query<'q, DB>(sql: &'q str) -> Query<'q, DB, super::any::AnyArguments<'q>> {
52 Query {
53 sql,
54 arguments: Vec::new(),
55 _marker: PhantomData,
56 }
57}
58
59pub trait IntoBindValue {
60 fn into_bind_value(self) -> Value;
61}
62
63impl IntoBindValue for Value {
64 fn into_bind_value(self) -> Value {
65 self
66 }
67}
68
69impl IntoBindValue for &Value {
70 fn into_bind_value(self) -> Value {
71 self.clone()
72 }
73}
74
75impl IntoBindValue for &str {
76 fn into_bind_value(self) -> Value {
77 Value::String(self.to_string())
78 }
79}
80
81impl IntoBindValue for String {
82 fn into_bind_value(self) -> Value {
83 Value::String(self)
84 }
85}
86
87impl IntoBindValue for &String {
88 fn into_bind_value(self) -> Value {
89 Value::String(self.clone())
90 }
91}
92
93impl IntoBindValue for i64 {
94 fn into_bind_value(self) -> Value {
95 Value::Number(serde_json::Number::from(self))
96 }
97}
98
99impl IntoBindValue for i32 {
100 fn into_bind_value(self) -> Value {
101 Value::Number(serde_json::Number::from(self))
102 }
103}
104
105impl IntoBindValue for u64 {
106 fn into_bind_value(self) -> Value {
107 Value::Number(serde_json::Number::from(self))
108 }
109}
110
111impl IntoBindValue for f64 {
112 fn into_bind_value(self) -> Value {
113 if let Some(n) = serde_json::Number::from_f64(self) {
114 Value::Number(n)
115 } else {
116 Value::Null
117 }
118 }
119}
120
121impl IntoBindValue for bool {
122 fn into_bind_value(self) -> Value {
123 Value::Bool(self)
124 }
125}
126
127impl<T: IntoBindValue> IntoBindValue for Option<T> {
128 fn into_bind_value(self) -> Value {
129 match self {
130 Some(v) => v.into_bind_value(),
131 None => Value::Null,
132 }
133 }
134}