diesel/query_builder/
sql_query.rs1use std::marker::PhantomData;
2
3use backend::Backend;
4use connection::Connection;
5use deserialize::QueryableByName;
6use query_builder::{AstPass, QueryFragment, QueryId};
7use query_dsl::{LoadQuery, RunQueryDsl};
8use result::QueryResult;
9use serialize::ToSql;
10use sql_types::HasSqlType;
11
12#[derive(Debug, Clone)]
13#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
14pub struct SqlQuery {
22 query: String,
23}
24
25impl SqlQuery {
26 pub(crate) fn new(query: String) -> Self {
27 SqlQuery { query }
28 }
29
30 pub fn bind<ST, Value>(self, value: Value) -> UncheckedBind<Self, Value, ST> {
77 UncheckedBind::new(self, value)
78 }
79}
80
81impl<DB> QueryFragment<DB> for SqlQuery
82where
83 DB: Backend,
84{
85 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
86 out.unsafe_to_cache_prepared();
87 out.push_sql(&self.query);
88 Ok(())
89 }
90}
91
92impl QueryId for SqlQuery {
93 type QueryId = ();
94
95 const HAS_STATIC_QUERY_ID: bool = false;
96}
97
98impl<Conn, T> LoadQuery<Conn, T> for SqlQuery
99where
100 Conn: Connection,
101 T: QueryableByName<Conn::Backend>,
102{
103 fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
104 conn.query_by_name(&self)
105 }
106}
107
108impl<Conn> RunQueryDsl<Conn> for SqlQuery {}
109
110#[derive(Debug, Clone, Copy)]
111#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
112pub struct UncheckedBind<Query, Value, ST> {
113 query: Query,
114 value: Value,
115 _marker: PhantomData<ST>,
116}
117
118impl<Query, Value, ST> UncheckedBind<Query, Value, ST> {
119 pub fn new(query: Query, value: Value) -> Self {
120 UncheckedBind {
121 query,
122 value,
123 _marker: PhantomData,
124 }
125 }
126
127 pub fn bind<ST2, Value2>(self, value: Value2) -> UncheckedBind<Self, Value2, ST2> {
128 UncheckedBind::new(self, value)
129 }
130}
131
132impl<Query, Value, ST> QueryId for UncheckedBind<Query, Value, ST>
133where
134 Query: QueryId,
135 ST: QueryId,
136{
137 type QueryId = UncheckedBind<Query::QueryId, (), ST::QueryId>;
138
139 const HAS_STATIC_QUERY_ID: bool = Query::HAS_STATIC_QUERY_ID && ST::HAS_STATIC_QUERY_ID;
140}
141
142impl<Query, Value, ST, DB> QueryFragment<DB> for UncheckedBind<Query, Value, ST>
143where
144 DB: Backend + HasSqlType<ST>,
145 Query: QueryFragment<DB>,
146 Value: ToSql<ST, DB>,
147{
148 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
149 self.query.walk_ast(out.reborrow())?;
150 out.push_bind_param_value_only(&self.value)?;
151 Ok(())
152 }
153}
154
155impl<Conn, Query, Value, ST, T> LoadQuery<Conn, T> for UncheckedBind<Query, Value, ST>
156where
157 Conn: Connection,
158 T: QueryableByName<Conn::Backend>,
159 Self: QueryFragment<Conn::Backend> + QueryId,
160{
161 fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> {
162 conn.query_by_name(&self)
163 }
164}
165
166impl<Conn, Query, Value, ST> RunQueryDsl<Conn> for UncheckedBind<Query, Value, ST> {}