mirror of
https://github.com/launchbadge/sqlx
synced 2024-11-10 14:34:19 +00:00
query refactors
This commit is contained in:
parent
acca40c88e
commit
193e79569a
16 changed files with 172 additions and 162 deletions
|
@ -41,36 +41,33 @@ where
|
|||
{
|
||||
type Backend = DB;
|
||||
|
||||
fn execute<'e, 'q: 'e, I: 'e>(
|
||||
fn execute<'e, 'q: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
{
|
||||
params: <DB as Backend>::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<u64>> {
|
||||
self.live.execute(query, params)
|
||||
}
|
||||
|
||||
fn fetch<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: <DB as Backend>::QueryParameters,
|
||||
) -> BoxStream<'e, crate::Result<T>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
self.live.fetch(query, params)
|
||||
}
|
||||
|
||||
fn fetch_optional<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch_optional<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: <DB as Backend>::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<Option<T>>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
|
||||
T: FromRow<Self::Backend> + Send,
|
||||
{
|
||||
self.live.fetch_optional(query, params)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Types and traits related to serializing values for the database.
|
||||
use crate::{backend::Backend, types::HasSqlType};
|
||||
|
||||
use std::mem;
|
||||
|
||||
/// Annotates the result of [Encode] to differentiate between an empty value and a null value.
|
||||
pub enum IsNull {
|
||||
/// The value was null (and no data was written to the buffer).
|
||||
|
@ -26,6 +28,11 @@ pub trait Encode<DB: Backend> {
|
|||
/// The return value indicates if this value should be represented as `NULL`.
|
||||
/// If this is the case, implementations **must not** write anything to `out`.
|
||||
fn encode(&self, buf: &mut Vec<u8>) -> IsNull;
|
||||
|
||||
/// Calculate the number of bytes this type will use when encoded.
|
||||
fn size_hint(&self) -> usize {
|
||||
mem::size_of_val(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// [Encode] is implemented for `Option<T>` where `T` implements `Encode`. An `Option<T>`
|
||||
|
@ -43,6 +50,10 @@ where
|
|||
IsNull::Yes
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
if self.is_some() { mem::size_of::<T>() } else { 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, DB> Encode<DB> for &'_ T
|
||||
|
@ -54,4 +65,8 @@ where
|
|||
fn encode(&self, buf: &mut Vec<u8>) -> IsNull {
|
||||
(*self).encode(buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
(*self).size_hint()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,57 +16,51 @@ pub trait Executor: Send {
|
|||
Box::pin(
|
||||
self.execute(
|
||||
"SELECT 1",
|
||||
<Self::Backend as Backend>::QueryParameters::new(),
|
||||
Default::default(),
|
||||
)
|
||||
.map_ok(|_| ()),
|
||||
)
|
||||
}
|
||||
|
||||
fn execute<'e, 'q: 'e, I: 'e>(
|
||||
fn execute<'e, 'q: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send;
|
||||
params: <Self::Backend as Backend>::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<u64>>;
|
||||
|
||||
fn fetch<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: <Self::Backend as Backend>::QueryParameters,
|
||||
) -> BoxStream<'e, crate::Result<T>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send + Unpin;
|
||||
|
||||
fn fetch_all<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch_all<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: <Self::Backend as Backend>::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<Vec<T>>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
Box::pin(self.fetch(query, params).try_collect())
|
||||
}
|
||||
|
||||
fn fetch_optional<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch_optional<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: <Self::Backend as Backend>::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<Option<T>>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send;
|
||||
|
||||
fn fetch_one<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch_one<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: <Self::Backend as Backend>::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<T>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send,
|
||||
{
|
||||
let fut = self.fetch_optional(query, params);
|
||||
|
|
|
@ -248,7 +248,7 @@ impl MariaDb {
|
|||
self.write(ComStmtExecute {
|
||||
statement_id,
|
||||
params: ¶ms.params,
|
||||
null: ¶ms.null,
|
||||
null: ¶ms.null_bitmap,
|
||||
flags: StmtExecFlag::NO_CURSOR,
|
||||
param_types: ¶ms.param_types,
|
||||
});
|
||||
|
|
|
@ -19,14 +19,11 @@ use futures_core::{future::BoxFuture, stream::BoxStream};
|
|||
impl Executor for MariaDb {
|
||||
type Backend = Self;
|
||||
|
||||
fn execute<'e, 'q: 'e, I: 'e>(
|
||||
fn execute<'e, 'q: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
{
|
||||
params: MariaDbQueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<u64>> {
|
||||
let params = params.into_params();
|
||||
|
||||
Box::pin(async move {
|
||||
|
@ -67,13 +64,12 @@ impl Executor for MariaDb {
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch<'e, 'q: 'e, I: 'e, O: 'e, T: 'e>(
|
||||
fn fetch<'e, 'q: 'e, O: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: MariaDbQueryParameters,
|
||||
) -> BoxStream<'e, crate::Result<T>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend, O> + Send + Unpin,
|
||||
{
|
||||
let params = params.into_params();
|
||||
|
@ -108,13 +104,12 @@ impl Executor for MariaDb {
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch_optional<'e, 'q: 'e, I: 'e, O: 'e, T: 'e>(
|
||||
fn fetch_optional<'e, 'q: 'e, O: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: MariaDbQueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<Option<T>>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend, O> + Send,
|
||||
{
|
||||
let params = params.into_params();
|
||||
|
|
|
@ -6,21 +6,25 @@ use crate::{
|
|||
types::HasSqlType,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MariaDbQueryParameters {
|
||||
pub(crate) param_types: Vec<MariaDbTypeMetadata>,
|
||||
pub(crate) params: Vec<u8>,
|
||||
pub(crate) null: Vec<u8>,
|
||||
pub(crate) null_bitmap: Vec<u8>,
|
||||
}
|
||||
|
||||
impl QueryParameters for MariaDbQueryParameters {
|
||||
type Backend = MariaDb;
|
||||
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
param_types: Vec::with_capacity(4),
|
||||
params: Vec::with_capacity(32),
|
||||
null: vec![0],
|
||||
}
|
||||
fn reserve(&mut self, binds: usize, bytes: usize) {
|
||||
self.param_types.reserve(binds);
|
||||
self.params.reserve(bytes);
|
||||
|
||||
// ensure we have enough bytes in the bitmap to hold at least `binds` extra bits
|
||||
// the second `& 7` gives us 0 spare bits when param_types.len() is a multiple of 8
|
||||
let spare_bits = (8 - (self.param_types.len()) & 7) & 7;
|
||||
// ensure that if there are no spare bits left, `binds = 1` reserves another byte
|
||||
self.null_bitmap.reserve( (binds + 7 - spare_bits) / 8);
|
||||
}
|
||||
|
||||
fn bind<T>(&mut self, value: T)
|
||||
|
@ -33,9 +37,10 @@ impl QueryParameters for MariaDbQueryParameters {
|
|||
let index = self.param_types.len();
|
||||
|
||||
self.param_types.push(metadata);
|
||||
self.null_bitmap.resize(index / 8, 0);
|
||||
|
||||
if let IsNull::Yes = value.encode(&mut self.params) {
|
||||
self.null[index / 8] = self.null[index / 8] & (1 << index % 8);
|
||||
self.null_bitmap[index / 8] &= (1 << index % 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use crate::{backend::Backend, encode::Encode, types::HasSqlType};
|
||||
|
||||
pub trait QueryParameters: Send {
|
||||
pub trait QueryParameters: Default + Send {
|
||||
type Backend: Backend;
|
||||
|
||||
fn new() -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
fn reserve(&mut self, binds: usize, bytes: usize);
|
||||
|
||||
fn bind<T>(&mut self, value: T)
|
||||
where
|
||||
|
@ -29,8 +27,12 @@ macro_rules! impl_into_query_parameters {
|
|||
$($T: crate::encode::Encode<$B>,)+
|
||||
{
|
||||
fn into_params(self) -> <$B as crate::backend::Backend>::QueryParameters {
|
||||
let mut params = <<$B as crate::backend::Backend>::QueryParameters
|
||||
as crate::params::QueryParameters>::new();
|
||||
let mut params = <$B as crate::backend::Backend>::QueryParameters::default();
|
||||
|
||||
let binds = 0 $(+ { $idx; 1 } )+;
|
||||
let bytes = 0 $(+ crate::encode::Encode::size_hint(&self.$idx))+;
|
||||
|
||||
params.reserve(binds, bytes);
|
||||
|
||||
$(crate::params::QueryParameters::bind(&mut params, self.$idx);)+
|
||||
|
||||
|
@ -57,8 +59,7 @@ macro_rules! impl_into_query_parameters_for_backend {
|
|||
{
|
||||
#[inline]
|
||||
fn into_params(self) -> <$B as crate::backend::Backend>::QueryParameters {
|
||||
<<$B as crate::backend::Backend>::QueryParameters
|
||||
as crate::params::QueryParameters>::new()
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,24 +11,20 @@ where
|
|||
{
|
||||
type Backend = DB;
|
||||
|
||||
fn execute<'e, 'q: 'e, I: 'e>(
|
||||
fn execute<'e, 'q: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
{
|
||||
params: DB::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<u64>> {
|
||||
Box::pin(async move { <&Pool<DB> as Executor>::execute(&mut &*self, query, params).await })
|
||||
}
|
||||
|
||||
fn fetch<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: DB::QueryParameters,
|
||||
) -> BoxStream<'e, crate::Result<T>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
Box::pin(async_stream::try_stream! {
|
||||
|
@ -41,13 +37,12 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch_optional<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch_optional<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: DB::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<Option<T>>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send,
|
||||
{
|
||||
Box::pin(async move {
|
||||
|
@ -69,24 +64,20 @@ where
|
|||
{
|
||||
type Backend = DB;
|
||||
|
||||
fn execute<'e, 'q: 'e, I: 'e>(
|
||||
fn execute<'e, 'q: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
{
|
||||
params: DB::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<u64>> {
|
||||
Box::pin(async move { self.0.acquire().await?.execute(query, params).await })
|
||||
}
|
||||
|
||||
fn fetch<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: DB::QueryParameters,
|
||||
) -> BoxStream<'e, crate::Result<T>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
Box::pin(async_stream::try_stream! {
|
||||
|
@ -99,13 +90,12 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch_optional<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch_optional<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: DB::QueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<Option<T>>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send,
|
||||
{
|
||||
Box::pin(async move { self.0.acquire().await?.fetch_optional(query, params).await })
|
||||
|
|
|
@ -8,21 +8,17 @@ use crate::{
|
|||
url::Url,
|
||||
};
|
||||
use futures_core::{future::BoxFuture, stream::BoxStream};
|
||||
use crate::postgres::query::PostgresQueryParameters;
|
||||
|
||||
impl Executor for Postgres {
|
||||
type Backend = Self;
|
||||
|
||||
fn execute<'e, 'q: 'e, I: 'e>(
|
||||
fn execute<'e, 'q: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
{
|
||||
params: PostgresQueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<u64>> {
|
||||
Box::pin(async move {
|
||||
let params = params.into_params();
|
||||
|
||||
self.parse("", query, ¶ms);
|
||||
self.bind("", "", ¶ms);
|
||||
self.execute("", 1);
|
||||
|
@ -40,17 +36,14 @@ impl Executor for Postgres {
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: PostgresQueryParameters,
|
||||
) -> BoxStream<'e, crate::Result<T>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
let params = params.into_params();
|
||||
|
||||
self.parse("", query, ¶ms);
|
||||
self.bind("", "", ¶ms);
|
||||
self.execute("", 0);
|
||||
|
@ -66,18 +59,15 @@ impl Executor for Postgres {
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch_optional<'e, 'q: 'e, I: 'e, T: 'e>(
|
||||
fn fetch_optional<'e, 'q: 'e, T: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
params: I,
|
||||
params: PostgresQueryParameters,
|
||||
) -> BoxFuture<'e, crate::Result<Option<T>>>
|
||||
where
|
||||
I: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send,
|
||||
{
|
||||
Box::pin(async move {
|
||||
let params = params.into_params();
|
||||
|
||||
self.parse("", query, ¶ms);
|
||||
self.bind("", "", ¶ms);
|
||||
self.execute("", 2);
|
||||
|
@ -104,7 +94,7 @@ impl Executor for Postgres {
|
|||
query: &'q str,
|
||||
) -> BoxFuture<'e, crate::Result<Describe<Self::Backend>>> {
|
||||
Box::pin(async move {
|
||||
self.parse("", query, &QueryParameters::new());
|
||||
self.parse("", query, &Default::default());
|
||||
self.describe("");
|
||||
self.sync().await?;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
|||
};
|
||||
use byteorder::{BigEndian, ByteOrder, NetworkEndian};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PostgresQueryParameters {
|
||||
// OIDs of the bind parameters
|
||||
pub(super) types: Vec<u32>,
|
||||
|
@ -17,13 +18,9 @@ pub struct PostgresQueryParameters {
|
|||
impl QueryParameters for PostgresQueryParameters {
|
||||
type Backend = Postgres;
|
||||
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
// Estimates for average number of bind parameters were
|
||||
// chosen from sampling from internal projects
|
||||
types: Vec::with_capacity(4),
|
||||
buf: Vec::with_capacity(32),
|
||||
}
|
||||
fn reserve(&mut self, binds: usize, bytes: usize) {
|
||||
self.types.reserve(binds);
|
||||
self.buf.reserve(bytes);
|
||||
}
|
||||
|
||||
fn bind<T>(&mut self, value: T)
|
||||
|
|
|
@ -31,6 +31,10 @@ impl Encode<Postgres> for Vec<u8> {
|
|||
fn encode(&self, buf: &mut Vec<u8>) -> IsNull {
|
||||
<[u8] as Encode<Postgres>>::encode(self, buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode<Postgres> for Vec<u8> {
|
||||
|
|
|
@ -38,6 +38,10 @@ impl Encode<Postgres> for String {
|
|||
fn encode(&self, buf: &mut Vec<u8>) -> IsNull {
|
||||
<str as Encode<Postgres>>::encode(self.as_str(), buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode<Postgres> for String {
|
||||
|
|
|
@ -1,84 +1,68 @@
|
|||
use crate::{
|
||||
backend::Backend,
|
||||
encode::Encode,
|
||||
error::Error,
|
||||
executor::Executor,
|
||||
params::{IntoQueryParameters, QueryParameters},
|
||||
row::FromRow,
|
||||
types::HasSqlType,
|
||||
Row,
|
||||
};
|
||||
use crate::{backend::Backend, encode::Encode, error::Error, executor::Executor, params::{IntoQueryParameters, QueryParameters}, row::FromRow, types::HasSqlType, Row, Decode};
|
||||
use bitflags::_core::marker::PhantomData;
|
||||
use futures_core::{future::BoxFuture, stream::BoxStream};
|
||||
|
||||
pub struct Query<'q, DB, I = <DB as Backend>::QueryParameters, O = <DB as Backend>::Row>
|
||||
pub struct Query<'q, DB, P = <DB as Backend>::QueryParameters, R = <DB as Backend>::Row>
|
||||
where
|
||||
DB: Backend,
|
||||
{
|
||||
#[doc(hidden)]
|
||||
pub query: &'q str,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub input: I,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub output: PhantomData<O>,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub backend: PhantomData<DB>,
|
||||
query: &'q str,
|
||||
params: P,
|
||||
record: PhantomData<R>,
|
||||
backend: PhantomData<DB>,
|
||||
}
|
||||
|
||||
impl<'q, DB, I: 'q, O: 'q> Query<'q, DB, I, O>
|
||||
impl<'q, DB, P: 'q, R: 'q> Query<'q, DB, P, R>
|
||||
where
|
||||
DB: Backend,
|
||||
DB::QueryParameters: 'q,
|
||||
I: IntoQueryParameters<DB> + Send,
|
||||
O: FromRow<DB> + Send + Unpin,
|
||||
P: IntoQueryParameters<DB> + Send,
|
||||
R: FromRow<DB> + Send + Unpin,
|
||||
{
|
||||
#[inline]
|
||||
pub fn execute<E>(self, executor: &'q mut E) -> BoxFuture<'q, crate::Result<u64>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
{
|
||||
executor.execute(self.query, self.input)
|
||||
executor.execute(self.query, self.params.into_params())
|
||||
}
|
||||
|
||||
pub fn fetch<E>(self, executor: &'q mut E) -> BoxStream<'q, crate::Result<O>>
|
||||
pub fn fetch<E>(self, executor: &'q mut E) -> BoxStream<'q, crate::Result<R>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
{
|
||||
executor.fetch(self.query, self.input)
|
||||
executor.fetch(self.query, self.params.into_params())
|
||||
}
|
||||
|
||||
pub fn fetch_all<E>(self, executor: &'q mut E) -> BoxFuture<'q, crate::Result<Vec<O>>>
|
||||
pub fn fetch_all<E>(self, executor: &'q mut E) -> BoxFuture<'q, crate::Result<Vec<R>>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
{
|
||||
executor.fetch_all(self.query, self.input)
|
||||
executor.fetch_all(self.query, self.params.into_params())
|
||||
}
|
||||
|
||||
pub fn fetch_optional<E>(self, executor: &'q mut E) -> BoxFuture<'q, crate::Result<Option<O>>>
|
||||
pub fn fetch_optional<E>(self, executor: &'q mut E) -> BoxFuture<'q, crate::Result<Option<R>>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
{
|
||||
executor.fetch_optional(self.query, self.input)
|
||||
executor.fetch_optional(self.query, self.params.into_params())
|
||||
}
|
||||
|
||||
pub fn fetch_one<E>(self, executor: &'q mut E) -> BoxFuture<'q, crate::Result<O>>
|
||||
pub fn fetch_one<E>(self, executor: &'q mut E) -> BoxFuture<'q, crate::Result<R>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
{
|
||||
executor.fetch_one(self.query, self.input)
|
||||
executor.fetch_one(self.query, self.params.into_params())
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> Query<'_, DB>
|
||||
impl<'q, DB> Query<'q, DB>
|
||||
where
|
||||
DB: Backend,
|
||||
{
|
||||
/// Bind a value for use with this SQL query.
|
||||
///
|
||||
/// # Safety
|
||||
/// # Logic Safety
|
||||
///
|
||||
/// This function should be used with care, as SQLx cannot validate
|
||||
/// that the value is of the right type nor can it validate that you have
|
||||
|
@ -88,17 +72,47 @@ where
|
|||
DB: HasSqlType<T>,
|
||||
T: Encode<DB>,
|
||||
{
|
||||
self.input.bind(value);
|
||||
self.params.bind(value);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'q, DB, I, O> Query<'q, DB, I, O> where DB: Backend {
|
||||
pub fn with_output_type<O_>(self) -> Query<'q, DB, I, O_> {
|
||||
/// Bind all query parameters at once.
|
||||
///
|
||||
/// If any parameters were previously bound with `.bind()` they are discarded.
|
||||
///
|
||||
/// # Logic Safety
|
||||
///
|
||||
/// This function should be used with care, as SQLx cannot validate
|
||||
/// that the value is of the right type nor can it validate that you have
|
||||
/// passed the correct number of parameters.
|
||||
pub fn bind_all<I>(self, values: I) -> Query<'q, DB, I> where I: IntoQueryParameters<DB> {
|
||||
Query {
|
||||
query: self.query,
|
||||
input: self.input,
|
||||
output: PhantomData,
|
||||
params: values,
|
||||
record: PhantomData,
|
||||
backend: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
//noinspection RsSelfConvention
|
||||
impl<'q, DB, I, R> Query<'q, DB, I, R> where DB: Backend {
|
||||
|
||||
/// Change the expected output type of the query to a single scalar value.
|
||||
pub fn as_scalar<R_>(self) -> Query<'q, DB, I, R_> where R_: Decode<DB> {
|
||||
Query {
|
||||
query: self.query,
|
||||
params: self.params,
|
||||
record: PhantomData,
|
||||
backend: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Change the expected output of the query to a new type implementing `FromRow`.
|
||||
pub fn as_record<R_>(self) -> Query<'q, DB, I, R_> where R_: FromRow<DB> {
|
||||
Query {
|
||||
query: self.query,
|
||||
params: self.params,
|
||||
record: PhantomData,
|
||||
backend: PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -112,8 +126,8 @@ where
|
|||
{
|
||||
Query {
|
||||
query,
|
||||
input: DB::QueryParameters::new(),
|
||||
output: PhantomData,
|
||||
params: Default::default(),
|
||||
record: PhantomData,
|
||||
backend: PhantomData,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,13 @@ macro_rules! impl_from_row {
|
|||
};
|
||||
}
|
||||
|
||||
/// Scalar conversions for rows
|
||||
impl<T, DB> FromRow<DB> for T where DB: Backend + HasSqlType<T>, T: Decode<DB> {
|
||||
fn from_row(row: <DB as Backend>::Row) -> Self {
|
||||
row.get(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! impl_from_row_for_backend {
|
||||
($B:ident, $row:ident) => {
|
||||
|
|
|
@ -132,12 +132,9 @@ pub async fn process_sql<DB: BackendExt>(
|
|||
|
||||
#params
|
||||
|
||||
sqlx::Query::<#backend_path, _, (#record_type)> {
|
||||
query: #query,
|
||||
input: params,
|
||||
output: ::core::marker::PhantomData,
|
||||
backend: ::core::marker::PhantomData,
|
||||
}
|
||||
sqlx::query::<#backend_path>(#query)
|
||||
.bind_all(params)
|
||||
.as_record::<#record_type>()
|
||||
}})
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,12 @@ async fn postgres_query() -> sqlx::Result<()> {
|
|||
sqlx::Connection::<sqlx::Postgres>::open(&dotenv::var("DATABASE_URL").unwrap()).await?;
|
||||
|
||||
let uuid: Uuid = "256ba9c8-0048-11ea-b0f0-8f04859d047e".parse().unwrap();
|
||||
let account = sqlx::query!("SELECT * from accounts where id != $1", uuid)
|
||||
let account_id = sqlx::query!("SELECT id from accounts where id != $1", uuid)
|
||||
.as_scalar::<Uuid>()
|
||||
.fetch_one(&mut conn)
|
||||
.await?;
|
||||
|
||||
println!("account ID: {:?}", account.id);
|
||||
println!("account name: {}", account.name);
|
||||
println!("account ID: {:?}", account_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue