From 6248a1c5edc0dac481e4f5a8a01a3038c93d2750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Przytu=C5=82a?= Date: Tue, 20 Aug 2024 11:30:10 +0200 Subject: [PATCH] docs: update for new paging API --- docs/source/queries/paged.md | 77 +++++++++++++++++++++++------- docs/source/queries/result.md | 3 +- docs/source/queries/simple.md | 9 ++-- docs/source/queries/usekeyspace.md | 4 +- 4 files changed, 70 insertions(+), 23 deletions(-) diff --git a/docs/source/queries/paged.md b/docs/source/queries/paged.md index cff040d79d..f6f56c4e60 100644 --- a/docs/source/queries/paged.md +++ b/docs/source/queries/paged.md @@ -1,9 +1,10 @@ # Paged query -Sometimes query results might not fit in a single page. Paged queries -allow to receive the whole result page by page. +Sometimes query results might be so big that one prefers not to fetch them all at once, +e.g. to reduce latency and/or memory footprint. +Paged queries allow to receive the whole result page by page, with a configurable page size. -`Session::query_iter` and `Session::execute_iter` take a [simple query](simple.md) or a [prepared query](prepared.md) -and return an `async` iterator over result `Rows`. +`Session::query_iter` and `Session::execute_iter` take a [simple query](simple.md) +or a [prepared query](prepared.md) and return an `async` iterator over result `Rows`. > ***Warning***\ > In case of unprepared variant (`Session::query_iter`) if the values are not empty @@ -79,7 +80,7 @@ On a `Query`: use scylla::query::Query; let mut query: Query = Query::new("SELECT a, b FROM ks.t"); -query.set_page_size(16); +query.set_page_size(16.try_into().unwrap()); let _ = session.query_iter(query, &[]).await?; // ... # Ok(()) @@ -98,7 +99,7 @@ let mut prepared: PreparedStatement = session .prepare("SELECT a, b FROM ks.t") .await?; -prepared.set_page_size(16); +prepared.set_page_size(16.try_into().unwrap()); let _ = session.execute_iter(prepared, &[]).await?; // ... # Ok(()) @@ -117,12 +118,33 @@ On a `Query`: # use std::error::Error; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::query::Query; +use scylla::statement::{PagingState, PagingStateResponse}; +use std::ops::ControlFlow; + +let paged_query = Query::new("SELECT a, b, c FROM ks.t").with_page_size(6.try_into().unwrap()); + +let mut paging_state = PagingState::start(); +loop { + let (res, paging_state_response) = session + .query_single_page(paged_query.clone(), &[], paging_state) + .await?; + + // Do something with `res`. + // ... + + match paging_state_response.into_paging_control_flow() { + ControlFlow::Break(()) => { + // No more pages to be fetched. + break; + } + ControlFlow::Continue(new_paging_state) => { + // Update paging state from the response, so that query + // will be resumed from where it ended the last time. + paging_state = new_paging_state + } + } +} -let paged_query = Query::new("SELECT a, b, c FROM ks.t").with_page_size(6); -let res1 = session.query(paged_query.clone(), &[]).await?; -let res2 = session - .query_single_page(paged_query.clone(), &[], res1.paging_state) - .await?; # Ok(()) # } ``` @@ -139,14 +161,37 @@ On a `PreparedStatement`: # use std::error::Error; # async fn check_only_compiles(session: &Session) -> Result<(), Box> { use scylla::query::Query; +use scylla::statement::{PagingState, PagingStateResponse}; +use std::ops::ControlFlow; let paged_prepared = session - .prepare(Query::new("SELECT a, b, c FROM ks.t").with_page_size(7)) - .await?; -let res1 = session.execute(&paged_prepared, &[]).await?; -let res2 = session - .execute_single_page(&paged_prepared, &[], res1.paging_state) + .prepare(Query::new("SELECT a, b, c FROM ks.t").with_page_size(7.try_into().unwrap())) .await?; + +let mut paging_state = PagingState::start(); +loop { + let (res, paging_state_response) = session + .execute_single_page(&paged_prepared, &[], paging_state) + .await?; + + println!( + "Paging state response from the prepared statement execution: {:#?} ({} rows)", + paging_state_response, + res.rows_num()?, + ); + + match paging_state_response.into_paging_control_flow() { + ControlFlow::Break(()) => { + // No more pages to be fetched. + break; + } + ControlFlow::Continue(new_paging_state) => { + // Update paging state from the response, so that query + // will be resumed from where it ended the last time. + paging_state = new_paging_state + } + } +} # Ok(()) # } ``` diff --git a/docs/source/queries/result.md b/docs/source/queries/result.md index 3663e23726..7eed7fc416 100644 --- a/docs/source/queries/result.md +++ b/docs/source/queries/result.md @@ -1,6 +1,7 @@ # Query result -`Session::query` and `Session::execute` return a `QueryResult` with rows represented as `Option>`. +`Session::query_unpaged`, `Session::query_single_page`, `Session::execute_unpaged` and `Session::execute_single_page` +return a `QueryResult` with rows represented as `Option>`. ### Basic representation `Row` is a basic representation of a received row. It can be used by itself, but it's a bit awkward to use: diff --git a/docs/source/queries/simple.md b/docs/source/queries/simple.md index ca0a4269e2..1eaf9d8be9 100644 --- a/docs/source/queries/simple.md +++ b/docs/source/queries/simple.md @@ -20,7 +20,8 @@ session > By default the query is unpaged and might cause heavy load on the cluster.\ > In such cases set a page size and use [paged query](paged.md) instead.\ > -> When page size is set, `query` will return only the first page of results. +> `query_unpaged` will return all results in one, possibly giant, piece +> (unless a timeout occurs due to high load incurred by the cluster). > ***Warning***\ > If the values are not empty, driver first needs to send a `PREPARE` request @@ -28,7 +29,7 @@ session > performance because 2 round trips will be required instead of 1. ### First argument - the query -As the first argument `Session::query` takes anything implementing `Into`.\ +As the first argument `Session::query_unpaged` takes anything implementing `Into`.\ You can create a query manually to set custom options. For example to change query consistency: ```rust # extern crate scylla; @@ -74,7 +75,7 @@ Here the first `?` will be filled with `2` and the second with `"Some text"`. See [Query values](values.md) for more information about sending values in queries ### Query result -`Session::query` returns `QueryResult` with rows represented as `Option>`.\ +`Session::query_unpaged` returns `QueryResult` with rows represented as `Option>`.\ Each row can be parsed as a tuple of rust types using `rows_typed`: ```rust # extern crate scylla; @@ -92,8 +93,6 @@ while let Some(read_row) = iter.next().transpose()? { # Ok(()) # } ``` -> In cases where page size is set, simple query returns only a single page of results.\ -> To receive all pages use a [paged query](paged.md) instead.\ See [Query result](result.md) for more information about handling query results diff --git a/docs/source/queries/usekeyspace.md b/docs/source/queries/usekeyspace.md index 2879a26275..85c92b1c8a 100644 --- a/docs/source/queries/usekeyspace.md +++ b/docs/source/queries/usekeyspace.md @@ -49,7 +49,8 @@ session The first argument is the keyspace name.\ The second argument states whether this name is case sensitive. -It is also possible to send raw use keyspace query using `Session::query` instead of `Session::use_keyspace` such as: +It is also possible to send raw use keyspace query using `Session::query_*` instead of `Session::use_keyspace` such as: + ```rust # extern crate scylla; # use scylla::Session; @@ -59,6 +60,7 @@ session.query_unpaged("USE my_keyspace", &[]).await?; # Ok(()) # } ``` + This method has a slightly worse latency than `Session::use_keyspace` - there are two roundtrips needed instead of one. Therefore, `Session::use_keyspace` is the preferred method for setting keyspaces.