Paged query

Sometimes query results might not fit in a single page. Paged queries allow to receive the whole result page by page.

Session::query_iter and Session::execute_iter take a simple query or a prepared query and return an async iterator over result Rows.

Examples

Use query_iter to perform a simple query with paging:


#![allow(unused)]
fn main() {
extern crate scylla;
extern crate futures;
use scylla::Session;
use std::error::Error;
async fn check_only_compiles(session: &Session) -> Result<(), Box<dyn Error>> {
use scylla::IntoTypedRows;
use futures::stream::StreamExt;

let mut rows_stream = session
    .query_iter("SELECT a, b FROM ks.t", &[])
    .await?
    .into_typed::<(i32, i32)>();

while let Some(next_row_res) = rows_stream.next().await {
    let (a, b): (i32, i32) = next_row_res?;
    println!("a, b: {}, {}", a, b);
}
Ok(())
}
}

Use execute_iter to perform a prepared query with paging:


#![allow(unused)]
fn main() {
extern crate scylla;
extern crate futures;
use scylla::Session;
use std::error::Error;
async fn check_only_compiles(session: &Session) -> Result<(), Box<dyn Error>> {
use scylla::IntoTypedRows;
use scylla::prepared_statement::PreparedStatement;
use futures::stream::StreamExt;

let prepared: PreparedStatement = session
    .prepare("SELECT a, b FROM ks.t")
    .await?;

let mut rows_stream = session
    .execute_iter(prepared, &[])
    .await?
    .into_typed::<(i32, i32)>();

while let Some(next_row_res) = rows_stream.next().await {
    let (a, b): (i32, i32) = next_row_res?;
    println!("a, b: {}, {}", a, b);
}
Ok(())
}
}

Query values can be passed to query_iter and execute_iter just like in a simple query

Configuring page size

It's possible to configure the size of a single page.

On a Query:


#![allow(unused)]
fn main() {
extern crate scylla;
use scylla::Session;
use std::error::Error;
async fn check_only_compiles(session: &Session) -> Result<(), Box<dyn Error>> {
use scylla::query::Query;

let mut query: Query = Query::new("SELECT a, b FROM ks.t");
query.set_page_size(16);

let _ = session.query_iter(query, &[]).await?; // ...
Ok(())
}
}

On a PreparedStatement:


#![allow(unused)]
fn main() {
extern crate scylla;
use scylla::Session;
use std::error::Error;
async fn check_only_compiles(session: &Session) -> Result<(), Box<dyn Error>> {
use scylla::prepared_statement::PreparedStatement;

let mut prepared: PreparedStatement = session
    .prepare("SELECT a, b FROM ks.t")
    .await?;

prepared.set_page_size(16);

let _ = session.execute_iter(prepared, &[]).await?; // ...
Ok(())
}
}

Passing the paging state manually

It's possible to fetch a single page from the table, extract the paging state from the result and manually pass it to the next query. That way, the next query will start fetching the results from where the previous one left off.

On a Query:


#![allow(unused)]
fn main() {
extern crate scylla;
use scylla::Session;
use std::error::Error;
async fn check_only_compiles(session: &Session) -> Result<(), Box<dyn Error>> {
use scylla::query::Query;

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_paged(paged_query.clone(), &[], res1.paging_state)
    .await?;
Ok(())
}
}

On a PreparedStatement:


#![allow(unused)]
fn main() {
extern crate scylla;
use scylla::Session;
use std::error::Error;
async fn check_only_compiles(session: &Session) -> Result<(), Box<dyn Error>> {
use scylla::query::Query;

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_paged(&paged_prepared, &[], res1.paging_state)
    .await?;
Ok(())
}
}

Performance

Performance is the same as in non-paged variants.
For the best performance use prepared queries.