1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
use crate::DocumentCollection; use crate::{QldbResult, QueryBuilder}; use std::convert::TryInto; /// Cursor allows to get all values from a statement page by page. /// /// QLDB returns 200 documents for each page. /// /// You don't need to directly use Cursor in your code. When the /// method [](crate::QueryBuilder::execute) uses Cursor internally /// in order to load all values. /// /// ```rust,no_run /// use qldb::{QldbClient, Cursor}; /// # use std::collections::HashMap; /// # use eyre::Result; /// /// # async fn test() -> Result<()> { /// let client = QldbClient::default("rust-crate-test", 200).await?; /// /// let mut value_to_insert = HashMap::new(); /// // This will insert a documents with a key "test_column" /// // with the value "IonValue::String(test_value)" /// value_to_insert.insert("test_column", "test_value"); /// /// client /// .transaction_within(|client| async move { /// let mut cursor = client /// .query("SEL/CT * FROM TestTable") /// .get_cursor()?; /// /// while let Some(mut values) = cursor.load_more().await? { /// println!("{:?}", values); /// } /// /// Ok(()) /// }) /// .await?; /// # Ok(()) /// # } /// ``` /// #[derive(Debug)] pub struct Cursor { query_builder: QueryBuilder, next_page: Option<String>, is_first_page: bool, } impl Cursor { pub(crate) fn new(query_builder: QueryBuilder) -> Cursor { Cursor { query_builder, next_page: None, is_first_page: true, } } /// It loads the next page from a query. It automatically tracks /// the next_page_token, so you can call this method again and /// again in order to load all pages. /// /// It returns Ok(Some(_)) when QLDB returns documents. /// /// It returns Ok(None) when QLDB doesn't return documents, /// which means that there isn't more pages to query /// /// ```rust,no_run /// # use qldb::{Cursor, QldbResult}; /// /// # async fn test(mut cursor: Cursor) -> QldbResult<()> { /// while let Some(mut values) = cursor.load_more().await? { /// println!("{:?}", values); /// } /// /// # Ok(()) /// # } /// /// ``` pub async fn load_more(&mut self) -> QldbResult<Option<DocumentCollection>> { let (values, next_page_token) = if self.is_first_page { self.query_builder.execute_statement().await? } else if let Some(page) = &self.next_page { self.query_builder.execute_get_page(&page).await? } else { self.is_first_page = false; return Ok(None); }; self.is_first_page = false; self.next_page = next_page_token; Ok(Some(values.try_into()?)) } /// Loads all pages from the cursor and consumes it in the process. pub async fn load_all(mut self) -> QldbResult<DocumentCollection> { let mut result = DocumentCollection::new(vec![]); while let Some(values) = self.load_more().await? { result.extend(values.into_iter()); if self.next_page.is_none() { break; } } Ok(result) } }