From 72b60e8a7de403e5d28e593d1da905d8b23cabfd Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Sat, 29 Feb 2020 12:17:36 -0800 Subject: [PATCH] remove the DB type parameter from HasCursor and push to an associated type; remove Cursor::first --- sqlx-core/src/cursor.rs | 22 +++++----- sqlx-core/src/database.rs | 11 +++-- sqlx-core/src/executor.rs | 10 +---- sqlx-core/src/pool/executor.rs | 18 ++++----- sqlx-core/src/postgres/connection.rs | 7 ++-- sqlx-core/src/postgres/cursor.rs | 60 ++-------------------------- sqlx-core/src/postgres/database.rs | 4 +- sqlx-core/src/query.rs | 26 +----------- sqlx-core/src/transaction.rs | 7 +--- 9 files changed, 38 insertions(+), 127 deletions(-) diff --git a/sqlx-core/src/cursor.rs b/sqlx-core/src/cursor.rs index 1bf88002..bb72c424 100644 --- a/sqlx-core/src/cursor.rs +++ b/sqlx-core/src/cursor.rs @@ -16,32 +16,28 @@ use crate::{Connect, Pool, Row}; /// Initially the `Cursor` is positioned before the first row. The `next` method moves the cursor /// to the next row, and because it returns `None` when there are no more rows, it can be used /// in a `while` loop to iterate through all returned rows. -pub trait Cursor<'c, 'q, DB> +pub trait Cursor<'c, 'q> where Self: Send, - DB: Database, // `.await`-ing a cursor will return the affected rows from the query Self: Future>, { + type Database: Database; + #[doc(hidden)] - fn from_pool(pool: &Pool, query: E) -> Self + fn from_pool(pool: &Pool<::Connection>, query: E) -> Self where Self: Sized, - E: Execute<'q, DB>; + E: Execute<'q, Self::Database>; #[doc(hidden)] fn from_connection(conn: C, query: E) -> Self where Self: Sized, - DB::Connection: Connect, - C: Into>, - E: Execute<'q, DB>; - - #[doc(hidden)] - fn first(self) -> BoxFuture<'c, crate::Result>::Row>>> - where - 'q: 'c; + ::Connection: Connect, + C: Into::Connection>>, + E: Execute<'q, Self::Database>; /// Fetch the next row in the result. Returns `None` if there are no more rows. - fn next(&mut self) -> BoxFuture::Row>>>; + fn next(&mut self) -> BoxFuture::Row>>>; } diff --git a/sqlx-core/src/database.rs b/sqlx-core/src/database.rs index b86b4e66..e8c274ee 100644 --- a/sqlx-core/src/database.rs +++ b/sqlx-core/src/database.rs @@ -15,7 +15,7 @@ where Self: Sized + 'static, Self: for<'a> HasRow<'a, Database = Self>, Self: for<'a> HasRawValue<'a>, - Self: for<'c, 'q> HasCursor<'c, 'q, Self>, + Self: for<'c, 'q> HasCursor<'c, 'q, Database = Self>, { /// The concrete `Connection` implementation for this database. type Connection: Connection; @@ -34,11 +34,10 @@ pub trait HasRawValue<'a> { type RawValue; } -pub trait HasCursor<'c, 'q, DB> -where - DB: Database, -{ - type Cursor: Cursor<'c, 'q, DB>; +pub trait HasCursor<'c, 'q> { + type Database: Database; + + type Cursor: Cursor<'c, 'q, Database = Self::Database>; } pub trait HasRow<'a> { diff --git a/sqlx-core/src/executor.rs b/sqlx-core/src/executor.rs index 98c96497..b6d8912e 100644 --- a/sqlx-core/src/executor.rs +++ b/sqlx-core/src/executor.rs @@ -22,18 +22,12 @@ where type Database: Database; /// Executes a query that may or may not return a result set. - fn execute<'q, E>( - self, - query: E, - ) -> >::Cursor + fn execute<'q, E>(self, query: E) -> >::Cursor where E: Execute<'q, Self::Database>; #[doc(hidden)] - fn execute_by_ref<'b, E>( - &mut self, - query: E, - ) -> >::Cursor + fn execute_by_ref<'b, E>(&mut self, query: E) -> >::Cursor where E: Execute<'b, Self::Database>; } diff --git a/sqlx-core/src/pool/executor.rs b/sqlx-core/src/pool/executor.rs index b70fd7de..0a4a3956 100644 --- a/sqlx-core/src/pool/executor.rs +++ b/sqlx-core/src/pool/executor.rs @@ -19,12 +19,12 @@ impl<'p, C, DB> Executor<'p> for &'p Pool where C: Connect, DB: Database, - DB: for<'c, 'q> HasCursor<'c, 'q, DB>, + DB: for<'c, 'q> HasCursor<'c, 'q, Database = DB>, for<'con> &'con mut C: Executor<'con>, { type Database = DB; - fn execute<'q, E>(self, query: E) -> >::Cursor + fn execute<'q, E>(self, query: E) -> >::Cursor where E: Execute<'q, DB>, { @@ -36,7 +36,7 @@ where fn execute_by_ref<'q, 'e, E>( &'e mut self, query: E, - ) -> >::Cursor + ) -> >::Cursor where E: Execute<'q, DB>, { @@ -48,12 +48,12 @@ impl<'c, C, DB> Executor<'c> for &'c mut PoolConnection where C: Connect, DB: Database, - DB: for<'c2, 'q> HasCursor<'c2, 'q, DB>, + DB: for<'c2, 'q> HasCursor<'c2, 'q, Database = DB>, for<'con> &'con mut C: Executor<'con>, { type Database = C::Database; - fn execute<'q, E>(self, query: E) -> >::Cursor + fn execute<'q, E>(self, query: E) -> >::Cursor where E: Execute<'q, Self::Database>, { @@ -65,7 +65,7 @@ where fn execute_by_ref<'q, 'e, E>( &'e mut self, query: E, - ) -> >::Cursor + ) -> >::Cursor where E: Execute<'q, Self::Database>, { @@ -77,11 +77,11 @@ impl Executor<'static> for PoolConnection where C: Connect, DB: Database, - DB: for<'c, 'q> HasCursor<'c, 'q, DB>, + DB: for<'c, 'q> HasCursor<'c, 'q, Database = DB>, { type Database = DB; - fn execute<'q, E>(self, query: E) -> >::Cursor + fn execute<'q, E>(self, query: E) -> >::Cursor where E: Execute<'q, Self::Database>, { @@ -90,7 +90,7 @@ where #[doc(hidden)] #[inline] - fn execute_by_ref<'q, 'e, E>(&'e mut self, query: E) -> >::Cursor + fn execute_by_ref<'q, 'e, E>(&'e mut self, query: E) -> >::Cursor where E: Execute<'q, Self::Database>, { diff --git a/sqlx-core/src/postgres/connection.rs b/sqlx-core/src/postgres/connection.rs index 8e796596..25f9e534 100644 --- a/sqlx-core/src/postgres/connection.rs +++ b/sqlx-core/src/postgres/connection.rs @@ -87,8 +87,9 @@ pub struct PgConnection { pub(super) next_statement_id: u32, pub(super) is_ready: bool, - // TODO: Think of a better way to do this, better name perhaps? - pub(super) data_row_values_buf: Vec>>, + // Work buffer for the value ranges of the current row + // This is used as the backing memory for each Row's value indexes + pub(super) current_row_values: Vec>>, } // https://www.postgresql.org/docs/12/protocol-flow.html#id-1.10.5.7.3 @@ -234,7 +235,7 @@ impl PgConnection { Ok(Self { stream, - data_row_values_buf: Vec::new(), + current_row_values: Vec::with_capacity(10), next_statement_id: 1, is_ready: true, }) diff --git a/sqlx-core/src/postgres/cursor.rs b/sqlx-core/src/postgres/cursor.rs index fa3dfe5b..ff5c878b 100644 --- a/sqlx-core/src/postgres/cursor.rs +++ b/sqlx-core/src/postgres/cursor.rs @@ -32,7 +32,9 @@ pub struct PgCursor<'c, 'q> { state: State<'c, 'q>, } -impl<'c, 'q> Cursor<'c, 'q, Postgres> for PgCursor<'c, 'q> { +impl<'c, 'q> Cursor<'c, 'q> for PgCursor<'c, 'q> { + type Database = Postgres; + #[doc(hidden)] fn from_pool(pool: &Pool, query: E) -> Self where @@ -64,14 +66,6 @@ impl<'c, 'q> Cursor<'c, 'q, Postgres> for PgCursor<'c, 'q> { } } - #[doc(hidden)] - fn first(self) -> BoxFuture<'c, crate::Result>>> - where - 'q: 'c, - { - Box::pin(first(self)) - } - fn next(&mut self) -> BoxFuture>>> { Box::pin(next(self)) } @@ -266,51 +260,3 @@ async fn next<'a, 'c: 'a, 'q: 'a>( Ok(None) } - -async fn first<'c, 'q>(mut cursor: PgCursor<'c, 'q>) -> crate::Result>> { - let mut conn = cursor.source.resolve().await?; - - match cursor.state { - State::Query(q, ref mut arguments) => { - // write out the query to the connection - write(&mut conn, q, arguments.take()).await?; - } - - State::NextRow => { - // just grab the next row as the first - } - - State::Resolve(_) | State::AffectedRows(_) => { - panic!("`PgCursor` must not be used after being polled"); - } - } - - loop { - match conn.stream.read().await? { - Message::ParseComplete | Message::BindComplete => { - // ignore x_complete messages - } - - Message::CommandComplete => { - // no more rows - break; - } - - Message::DataRow => { - let data = DataRow::read(&mut conn)?; - - return Ok(Some(PgRow { - connection: conn, - columns: Arc::default(), - data, - })); - } - - message => { - return Err(protocol_err!("first: unexpected message: {:?}", message).into()); - } - } - } - - Ok(None) -} diff --git a/sqlx-core/src/postgres/database.rs b/sqlx-core/src/postgres/database.rs index ed07cd52..a3e409d1 100644 --- a/sqlx-core/src/postgres/database.rs +++ b/sqlx-core/src/postgres/database.rs @@ -20,7 +20,9 @@ impl<'a> HasRow<'a> for Postgres { type Row = super::PgRow<'a>; } -impl<'s, 'q> HasCursor<'s, 'q, Postgres> for Postgres { +impl<'s, 'q> HasCursor<'s, 'q> for Postgres { + type Database = Postgres; + type Cursor = super::PgCursor<'s, 'q>; } diff --git a/sqlx-core/src/query.rs b/sqlx-core/src/query.rs index c8fe37a8..54745af5 100644 --- a/sqlx-core/src/query.rs +++ b/sqlx-core/src/query.rs @@ -121,36 +121,12 @@ where executor.execute(self).await } - pub fn fetch<'e, E>(self, executor: E) -> >::Cursor + pub fn fetch<'e, E>(self, executor: E) -> >::Cursor where E: Executor<'e, Database = DB>, { executor.execute(self) } - - pub async fn fetch_optional<'e, E>( - self, - executor: E, - ) -> crate::Result>::Row>> - where - E: Executor<'e, Database = DB>, - 'q: 'e, - { - executor.execute(self).first().await - } - - pub async fn fetch_one<'e, E>(self, executor: E) -> crate::Result<>::Row> - where - E: Executor<'e, Database = DB>, - 'q: 'e, - { - self.fetch_optional(executor) - .and_then(|row| match row { - Some(row) => ready(Ok(row)), - None => ready(Err(crate::Error::NotFound)), - }) - .await - } } impl<'q, DB, F> Map<'q, DB, F> diff --git a/sqlx-core/src/transaction.rs b/sqlx-core/src/transaction.rs index ac01bb4c..006b4d38 100644 --- a/sqlx-core/src/transaction.rs +++ b/sqlx-core/src/transaction.rs @@ -136,10 +136,7 @@ where { type Database = ::Database; - fn execute<'q, E>( - self, - query: E, - ) -> <::Database as HasCursor<'c, 'q, DB>>::Cursor + fn execute<'q, E>(self, query: E) -> <::Database as HasCursor<'c, 'q>>::Cursor where E: Execute<'q, Self::Database>, { @@ -150,7 +147,7 @@ where fn execute_by_ref<'q, 'e, E>( &'e mut self, query: E, - ) -> >::Cursor + ) -> >::Cursor where E: Execute<'q, Self::Database>, {