mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-09-28 21:42:06 +00:00
Add sqlx::Row
- Rename the existing trait to an internal RawRow trait - Row is used for selecting a dyn and deferring pulling its values out till later - FromSqlRow -> FromRow
This commit is contained in:
parent
1b92fe733b
commit
b14d3da2ee
@ -1,4 +1,4 @@
|
||||
use sqlx::{Pool, Postgres};
|
||||
use sqlx::{Row, Pool, Postgres};
|
||||
use std::env;
|
||||
use tide::error::ResultExt;
|
||||
use tide::http::StatusCode;
|
||||
@ -19,6 +19,8 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
app.at("/v1/user").get(get_all_users).post(create_user);
|
||||
|
||||
app.at("/v1/user/latest").get(get_newest_user);
|
||||
|
||||
app.serve(("localhost", 8080))?;
|
||||
|
||||
Ok(())
|
||||
@ -51,6 +53,25 @@ async fn get_all_users(cx: Context<Pool<Postgres>>) -> EndpointResult {
|
||||
Ok(response::json(users))
|
||||
}
|
||||
|
||||
async fn get_newest_user(cx: Context<Pool<Postgres>>) -> EndpointResult {
|
||||
let mut pool = cx.state();
|
||||
|
||||
// This is an example of getting back a dyn row that we ...
|
||||
let row: Row<Postgres> = sqlx::query(
|
||||
r#"
|
||||
SELECT id
|
||||
FROM users
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
"#)
|
||||
.fetch_one(&mut pool)
|
||||
.await
|
||||
.server_err()?;
|
||||
|
||||
// ... can later ask its values by index
|
||||
Ok(response::json(vec![row.get::<i32>(0)]))
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct CreateUserRequest {
|
||||
name: String,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::describe::Describe;
|
||||
use crate::{query::QueryParameters, row::Row, types::HasTypeMetadata};
|
||||
use crate::{query::QueryParameters, row::RawRow, types::HasTypeMetadata};
|
||||
use async_trait::async_trait;
|
||||
use futures_core::stream::BoxStream;
|
||||
|
||||
@ -17,7 +17,7 @@ pub trait Backend: HasTypeMetadata + Send + Sync + Sized {
|
||||
type QueryParameters: QueryParameters<Backend = Self>;
|
||||
|
||||
/// The concrete `Row` implementation for this backend.
|
||||
type Row: Row<Backend = Self>;
|
||||
type Row: RawRow<Backend = Self>;
|
||||
|
||||
/// The identifier for tables; in Postgres this is an `oid` while
|
||||
/// in MariaDB/MySQL this is the qualified name of the table.
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{query::IntoQueryParameters, Backend, Executor, FromSqlRow};
|
||||
use crate::{query::IntoQueryParameters, Backend, Executor, FromRow};
|
||||
use futures_core::{future::BoxFuture, stream::BoxStream};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@ -16,7 +16,7 @@ impl<DB, P, O> CompiledSql<P, O, DB>
|
||||
where
|
||||
DB: Backend,
|
||||
P: IntoQueryParameters<DB> + Send,
|
||||
O: FromSqlRow<DB> + Send + Unpin,
|
||||
O: FromRow<DB> + Send + Unpin,
|
||||
{
|
||||
#[inline]
|
||||
pub fn execute<'e, E: 'e>(self, executor: &'e mut E) -> BoxFuture<'e, crate::Result<u64>>
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
executor::Executor,
|
||||
pool::{Live, SharedPool},
|
||||
query::IntoQueryParameters,
|
||||
row::FromSqlRow,
|
||||
row::FromRow,
|
||||
};
|
||||
use futures_core::{future::BoxFuture, stream::BoxStream};
|
||||
use futures_util::stream::StreamExt;
|
||||
@ -70,7 +70,7 @@ where
|
||||
) -> BoxStream<'c, Result<T, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend> + Send + Unpin,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
Box::pin(async_stream::try_stream! {
|
||||
let mut s = self.live.fetch(query, params.into_params());
|
||||
@ -88,7 +88,7 @@ where
|
||||
) -> BoxFuture<'c, Result<Option<T>, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend>,
|
||||
T: FromRow<Self::Backend>,
|
||||
{
|
||||
Box::pin(async move {
|
||||
let row = self
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{backend::Backend, error::Error, query::IntoQueryParameters, row::FromSqlRow};
|
||||
use crate::{backend::Backend, error::Error, query::IntoQueryParameters, row::FromRow};
|
||||
use futures_core::{future::BoxFuture, stream::BoxStream};
|
||||
use futures_util::TryStreamExt;
|
||||
|
||||
@ -20,7 +20,7 @@ pub trait Executor: Send {
|
||||
) -> BoxStream<'c, Result<T, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend> + Send + Unpin;
|
||||
T: FromRow<Self::Backend> + Send + Unpin;
|
||||
|
||||
fn fetch_all<'c, 'q: 'c, T: 'c, A: 'c>(
|
||||
&'c mut self,
|
||||
@ -29,7 +29,7 @@ pub trait Executor: Send {
|
||||
) -> BoxFuture<'c, Result<Vec<T>, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend> + Send + Unpin,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
Box::pin(self.fetch(query, params).try_collect())
|
||||
}
|
||||
@ -41,7 +41,7 @@ pub trait Executor: Send {
|
||||
) -> BoxFuture<'c, Result<Option<T>, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend> + Send;
|
||||
T: FromRow<Self::Backend> + Send;
|
||||
|
||||
fn fetch_one<'c, 'q: 'c, T: 'c, A: 'c>(
|
||||
&'c mut self,
|
||||
@ -50,7 +50,7 @@ pub trait Executor: Send {
|
||||
) -> BoxFuture<'c, Result<T, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send,
|
||||
{
|
||||
let fut = self.fetch_optional(query, params);
|
||||
Box::pin(async move { fut.await?.ok_or(Error::NotFound) })
|
||||
|
@ -42,7 +42,7 @@ pub use self::{
|
||||
error::{Error, Result},
|
||||
executor::Executor,
|
||||
pool::Pool,
|
||||
row::{FromSqlRow, Row},
|
||||
row::{FromRow, Row},
|
||||
sql::{query, SqlQuery},
|
||||
types::HasSqlType,
|
||||
};
|
||||
|
@ -84,5 +84,5 @@ impl Backend for MariaDb {
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_sql_row_tuples_for_backend!(MariaDb);
|
||||
impl_from_row_for_backend!(MariaDb);
|
||||
impl_into_query_parameters_for_backend!(MariaDb);
|
||||
|
@ -1,18 +1,11 @@
|
||||
use crate::{
|
||||
mariadb::{protocol::ResultRow, MariaDb},
|
||||
row::Row,
|
||||
};
|
||||
use crate::mariadb::{protocol::ResultRow, MariaDb};
|
||||
use crate::row::RawRow;
|
||||
|
||||
pub struct MariaDbRow(pub(super) ResultRow);
|
||||
|
||||
impl Row for MariaDbRow {
|
||||
impl RawRow for MariaDbRow {
|
||||
type Backend = MariaDb;
|
||||
|
||||
#[inline]
|
||||
fn is_empty(&self) -> bool {
|
||||
self.0.values.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
self.0.values.len()
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
backend::Backend, connection::Connection, error::Error, executor::Executor,
|
||||
query::IntoQueryParameters, row::FromSqlRow,
|
||||
query::IntoQueryParameters, row::FromRow,
|
||||
};
|
||||
use futures_channel::oneshot;
|
||||
use futures_core::{future::BoxFuture, stream::BoxStream};
|
||||
@ -258,7 +258,7 @@ where
|
||||
) -> BoxStream<'c, Result<T, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend> + Send + Unpin,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
Box::pin(async_stream::try_stream! {
|
||||
let mut self_ = &*self;
|
||||
@ -279,7 +279,7 @@ where
|
||||
) -> BoxFuture<'c, Result<Option<T>, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send,
|
||||
{
|
||||
Box::pin(async move {
|
||||
<&Pool<DB> as Executor>::fetch_optional(&mut &*self, query, params).await
|
||||
@ -315,7 +315,7 @@ where
|
||||
) -> BoxStream<'c, Result<T, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend> + Send + Unpin,
|
||||
T: FromRow<Self::Backend> + Send + Unpin,
|
||||
{
|
||||
Box::pin(async_stream::try_stream! {
|
||||
let mut live = self.0.acquire().await?;
|
||||
@ -334,7 +334,7 @@ where
|
||||
) -> BoxFuture<'c, Result<Option<T>, Error>>
|
||||
where
|
||||
A: IntoQueryParameters<Self::Backend> + Send,
|
||||
T: FromSqlRow<Self::Backend> + Send,
|
||||
T: FromRow<Self::Backend> + Send,
|
||||
{
|
||||
Box::pin(async move {
|
||||
let mut live = self.0.acquire().await?;
|
||||
|
@ -146,5 +146,5 @@ impl Backend for Postgres {
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_sql_row_tuples_for_backend!(Postgres);
|
||||
impl_from_row_for_backend!(Postgres);
|
||||
impl_into_query_parameters_for_backend!(Postgres);
|
||||
|
@ -1,17 +1,12 @@
|
||||
use super::{protocol::DataRow, Postgres};
|
||||
use crate::row::Row;
|
||||
use crate::row::RawRow;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PostgresRow(pub(crate) DataRow);
|
||||
|
||||
impl Row for PostgresRow {
|
||||
impl RawRow for PostgresRow {
|
||||
type Backend = Postgres;
|
||||
|
||||
#[inline]
|
||||
fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
|
@ -1,58 +1,73 @@
|
||||
use crate::{backend::Backend, decode::Decode, types::HasSqlType};
|
||||
|
||||
pub trait Row: Send {
|
||||
pub trait RawRow: Send {
|
||||
type Backend: Backend;
|
||||
|
||||
fn is_empty(&self) -> bool;
|
||||
|
||||
fn len(&self) -> usize;
|
||||
|
||||
fn get_raw(&self, index: usize) -> Option<&[u8]>;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get<T>(&self, index: usize) -> T
|
||||
pub struct Row<DB>(pub(crate) DB::Row)
|
||||
where
|
||||
DB: Backend;
|
||||
|
||||
impl<DB> Row<DB>
|
||||
where
|
||||
DB: Backend,
|
||||
{
|
||||
pub fn get<T>(&self, index: usize) -> T
|
||||
where
|
||||
Self::Backend: HasSqlType<T>,
|
||||
T: Decode<Self::Backend>,
|
||||
DB: HasSqlType<T>,
|
||||
T: Decode<DB>,
|
||||
{
|
||||
T::decode(self.get_raw(index))
|
||||
T::decode(self.0.get_raw(index))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FromSqlRow<DB: Backend> {
|
||||
fn from_row<R: Row<Backend = DB>>(row: R) -> Self;
|
||||
pub trait FromRow<DB: Backend> {
|
||||
fn from_row(row: DB::Row) -> Self;
|
||||
}
|
||||
|
||||
impl<T, DB> FromSqlRow<DB> for T
|
||||
impl<T, DB> FromRow<DB> for T
|
||||
where
|
||||
DB: Backend + HasSqlType<T>,
|
||||
T: Decode<DB>,
|
||||
{
|
||||
#[inline]
|
||||
fn from_row<R: Row<Backend = DB>>(row: R) -> Self {
|
||||
row.get::<T>(0)
|
||||
fn from_row(row: DB::Row) -> Self {
|
||||
T::decode(row.get_raw(0))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! impl_from_sql_row_tuple {
|
||||
($B:ident: $( ($idx:tt) -> $T:ident );+;) => {
|
||||
impl<$($T,)+> crate::row::FromSqlRow<$B> for ($($T,)+)
|
||||
impl<$($T,)+> crate::row::FromRow<$B> for ($($T,)+)
|
||||
where
|
||||
$($B: crate::types::HasSqlType<$T>,)+
|
||||
$($T: crate::decode::Decode<$B>,)+
|
||||
{
|
||||
#[inline]
|
||||
fn from_row<R: crate::row::Row<Backend = $B>>(row: R) -> Self {
|
||||
($(row.get($idx),)+)
|
||||
fn from_row(row: <$B as crate::Backend>::Row) -> Self {
|
||||
use crate::row::RawRow;
|
||||
|
||||
($($T::decode(row.get_raw($idx)),)+)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! impl_from_sql_row_tuples_for_backend {
|
||||
macro_rules! impl_from_row_for_backend {
|
||||
($B:ident) => {
|
||||
impl crate::row::FromRow<$B> for crate::row::Row<$B> where $B: crate::Backend {
|
||||
#[inline]
|
||||
fn from_row(row: <$B as crate::Backend>::Row) -> Self {
|
||||
Self(row)
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_sql_row_tuple!($B:
|
||||
(0) -> T1;
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
backend::Backend, encode::Encode, error::Error, executor::Executor, query::QueryParameters,
|
||||
row::FromSqlRow, types::HasSqlType,
|
||||
row::FromRow, types::HasSqlType,
|
||||
};
|
||||
use futures_core::{future::BoxFuture, stream::BoxStream};
|
||||
|
||||
@ -43,7 +43,7 @@ where
|
||||
pub fn fetch<E, T: 'q>(self, executor: &'q mut E) -> BoxStream<'q, Result<T, Error>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
T: FromSqlRow<DB> + Send + Unpin,
|
||||
T: FromRow<DB> + Send + Unpin,
|
||||
DB::QueryParameters: 'q,
|
||||
{
|
||||
executor.fetch(self.query, self.params)
|
||||
@ -52,7 +52,7 @@ where
|
||||
pub fn fetch_all<E, T: 'q>(self, executor: &'q mut E) -> BoxFuture<'q, Result<Vec<T>, Error>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
T: FromSqlRow<DB> + Send + Unpin,
|
||||
T: FromRow<DB> + Send + Unpin,
|
||||
DB::QueryParameters: 'q,
|
||||
{
|
||||
executor.fetch_all(self.query, self.params)
|
||||
@ -64,7 +64,7 @@ where
|
||||
) -> BoxFuture<'q, Result<Option<T>, Error>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
T: FromSqlRow<DB> + Send,
|
||||
T: FromRow<DB> + Send,
|
||||
DB::QueryParameters: 'q,
|
||||
{
|
||||
executor.fetch_optional(self.query, self.params)
|
||||
@ -73,7 +73,7 @@ where
|
||||
pub fn fetch_one<E, T: 'q>(self, executor: &'q mut E) -> BoxFuture<'q, Result<T, Error>>
|
||||
where
|
||||
E: Executor<Backend = DB>,
|
||||
T: FromSqlRow<DB> + Send + Unpin,
|
||||
T: FromRow<DB> + Send + Unpin,
|
||||
DB::QueryParameters: 'q,
|
||||
{
|
||||
executor.fetch_one(self.query, self.params)
|
||||
|
Loading…
x
Reference in New Issue
Block a user