Skip to main content

rustbasic_core/sql/
query.rs

1use 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}