1 use std::marker::PhantomData; 2 3 use backend::Backend; 4 use connection::Connection; 5 use deserialize::QueryableByName; 6 use query_builder::{AstPass, QueryFragment, QueryId}; 7 use query_dsl::{LoadQuery, RunQueryDsl}; 8 use result::QueryResult; 9 use serialize::ToSql; 10 use sql_types::HasSqlType; 11 12 #[derive(Debug, Clone)] 13 #[must_use = "Queries are only executed when calling `load`, `get_result` or similar."] 14 /// The return value of `sql_query`. 15 /// 16 /// Unlike most queries in Diesel, `SqlQuery` loads its data by column name, 17 /// rather than by index. This means that you cannot deserialize this query into 18 /// a tuple, and any structs used must implement `QueryableByName`. 19 /// 20 /// See [`sql_query`](../fn.sql_query.html) for examples. 21 pub struct SqlQuery { 22 query: String, 23 } 24 25 impl SqlQuery { new(query: String) -> Self26 pub(crate) fn new(query: String) -> Self { 27 SqlQuery { query } 28 } 29 30 /// Bind a value for use with this SQL query. 31 /// 32 /// # Safety 33 /// 34 /// This function should be used with care, as Diesel cannot validate that 35 /// the value is of the right type nor can it validate that you have passed 36 /// the correct number of parameters. 37 /// 38 /// # Example 39 /// 40 /// ``` 41 /// # #[macro_use] extern crate diesel; 42 /// # include!("../doctest_setup.rs"); 43 /// # 44 /// # use schema::users; 45 /// # 46 /// # #[derive(QueryableByName, Debug, PartialEq)] 47 /// # #[table_name="users"] 48 /// # struct User { 49 /// # id: i32, 50 /// # name: String, 51 /// # } 52 /// # 53 /// # fn main() { 54 /// # use diesel::sql_query; 55 /// # use diesel::sql_types::{Integer, Text}; 56 /// # 57 /// # let connection = establish_connection(); 58 /// # diesel::insert_into(users::table) 59 /// # .values(users::name.eq("Jim")) 60 /// # .execute(&connection).unwrap(); 61 /// # #[cfg(feature = "postgres")] 62 /// # let users = sql_query("SELECT * FROM users WHERE id > $1 AND name != $2"); 63 /// # #[cfg(not(feature = "postgres"))] 64 /// let users = sql_query("SELECT * FROM users WHERE id > ? AND name <> ?") 65 /// # ; 66 /// # let users = users 67 /// .bind::<Integer, _>(1) 68 /// .bind::<Text, _>("Tess") 69 /// .get_results(&connection); 70 /// let expected_users = vec![ 71 /// User { id: 3, name: "Jim".into() }, 72 /// ]; 73 /// assert_eq!(Ok(expected_users), users); 74 /// # } 75 /// ``` bind<ST, Value>(self, value: Value) -> UncheckedBind<Self, Value, ST>76 pub fn bind<ST, Value>(self, value: Value) -> UncheckedBind<Self, Value, ST> { 77 UncheckedBind::new(self, value) 78 } 79 } 80 81 impl<DB> QueryFragment<DB> for SqlQuery 82 where 83 DB: Backend, 84 { walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()>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 92 impl QueryId for SqlQuery { 93 type QueryId = (); 94 95 const HAS_STATIC_QUERY_ID: bool = false; 96 } 97 98 impl<Conn, T> LoadQuery<Conn, T> for SqlQuery 99 where 100 Conn: Connection, 101 T: QueryableByName<Conn::Backend>, 102 { internal_load(self, conn: &Conn) -> QueryResult<Vec<T>>103 fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> { 104 conn.query_by_name(&self) 105 } 106 } 107 108 impl<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."] 112 pub struct UncheckedBind<Query, Value, ST> { 113 query: Query, 114 value: Value, 115 _marker: PhantomData<ST>, 116 } 117 118 impl<Query, Value, ST> UncheckedBind<Query, Value, ST> { new(query: Query, value: Value) -> Self119 pub fn new(query: Query, value: Value) -> Self { 120 UncheckedBind { 121 query, 122 value, 123 _marker: PhantomData, 124 } 125 } 126 bind<ST2, Value2>(self, value: Value2) -> UncheckedBind<Self, Value2, ST2>127 pub fn bind<ST2, Value2>(self, value: Value2) -> UncheckedBind<Self, Value2, ST2> { 128 UncheckedBind::new(self, value) 129 } 130 } 131 132 impl<Query, Value, ST> QueryId for UncheckedBind<Query, Value, ST> 133 where 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 142 impl<Query, Value, ST, DB> QueryFragment<DB> for UncheckedBind<Query, Value, ST> 143 where 144 DB: Backend + HasSqlType<ST>, 145 Query: QueryFragment<DB>, 146 Value: ToSql<ST, DB>, 147 { walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()>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 155 impl<Conn, Query, Value, ST, T> LoadQuery<Conn, T> for UncheckedBind<Query, Value, ST> 156 where 157 Conn: Connection, 158 T: QueryableByName<Conn::Backend>, 159 Self: QueryFragment<Conn::Backend> + QueryId, 160 { internal_load(self, conn: &Conn) -> QueryResult<Vec<T>>161 fn internal_load(self, conn: &Conn) -> QueryResult<Vec<T>> { 162 conn.query_by_name(&self) 163 } 164 } 165 166 impl<Conn, Query, Value, ST> RunQueryDsl<Conn> for UncheckedBind<Query, Value, ST> {} 167