query.rs
Overview
This file defines core components for implementing cursor-based pagination in data queries. It provides an enumeration for pagination direction and a struct encapsulating pagination parameters typically used in paginated data fetching scenarios. The functionality supports both forward and backward pagination, enabling efficient navigation through large datasets by managing limits, cursors, and page boundaries.
Components
Enum: PaginateDirection
Represents the direction of pagination.
Variants:
Forward: Indicates paginating forward through results.Backward: Indicates paginating backward through results.
Struct: PaginationArgs
Encapsulates the arguments necessary for paginating over a collection of items.
Fields:
first: Option<usize>
Specifies the number of items to fetch starting after a given cursor (forward pagination).after: Option<String>
The cursor after which to start fetching items (forward pagination cursor).last: Option<usize>
Specifies the number of items to fetch ending before a given cursor (backward pagination).before: Option<String>
The cursor before which to end fetching items (backward pagination cursor).
These fields correspond to standard cursor-based pagination parameters, supporting both forward and backward traversal of data.
Methods
get_limit(&self) -> usize
Returns the maximum number of items to fetch based on the pagination arguments.
Logic:
Returns 1 plus the specifiedfirstorlastargument if set. If neither is set, falls back to a default batch size (crate::defaults::QUERY_BATCH_SIZE).Return:
usize— the effective limit on the number of items to retrieve.Usage Example:
let args = PaginationArgs { first: Some(10), after: None, last: None, before: None };
let limit = args.get_limit(); // returns 11
shrink_portion<T>(&self, portion: &mut Vec<T>)
Adjusts the vector of fetched items by removing one item depending on the pagination direction, ensuring the returned portion respects the requested limit.
Parameters:
portion: &mut Vec<T>— mutable reference to a vector of items fetched.
Behavior:
If the length ofportionis greater than or equal to the limit returned byget_limit(), it removes one item:For
Forwardpagination, truncates the last item.For
Backwardpagination, removes the first item.
Purpose:
This method helps in handling the extra item fetched to determine if there are more pages available without returning it to the caller.Usage Example:
let mut items = vec![1, 2, 3, 4];
let args = PaginationArgs { first: Some(3), after: None, last: None, before: None };
args.shrink_portion(&mut items);
// items now contains three elements, one removed to match the limit
get_direction(&self) -> PaginateDirection
Determines the direction of pagination based on which arguments are set.
Logic:
ReturnsBackwardif eitherlastorbeforeis set; otherwise, returnsForward.Return:
PaginateDirection— indicates the effective pagination direction.Usage Example:
let args = PaginationArgs { first: None, after: None, last: Some(5), before: None };
assert_eq!(args.get_direction(), PaginateDirection::Backward);
get_bound_markers(&self, num_nodes: usize) -> (bool, bool)
Determines if there are previous or next pages available given the number of nodes fetched.
Parameters:
num_nodes: usize— number of items fetched.
Returns:
Tuple(has_previous_page, has_next_page)where each is a boolean indicating existence of additional pages.Implementation:
Callshas_previous_pageandhas_next_pageinternally.Usage Example:
let args = PaginationArgs { first: Some(10), after: None, last: None, before: None };
let (prev, next) = args.get_bound_markers(11);
has_next_page(&self, num_nodes: usize) -> bool
Checks if a next page exists based on the current pagination arguments and the number of nodes fetched.
Parameters:
num_nodes: usize— number of items fetched.
Returns:
trueif there is a next page available; otherwise,false.Logic:
Iffirstis set, returnstrueifnum_nodesexceedsfirstor ifbeforecursor is set (sincebeforeimplies backward pagination and potential for more data forward).Usage Example:
let args = PaginationArgs { first: Some(10), after: None, last: None, before: None };
let has_next = args.has_next_page(12); // true
has_previous_page(&self, num_nodes: usize) -> bool
Checks if a previous page exists based on the current pagination arguments and the number of nodes fetched.
Parameters:
num_nodes: usize— number of items fetched.
Returns:
trueif there is a previous page available; otherwise,false.Logic:
Iflastis set, returnstrueifnum_nodesexceedslastor ifaftercursor is set (sinceafterimplies forward pagination and potential for more data backward).Usage Example:
let args = PaginationArgs { first: None, after: Some("cursor".to_string()), last: Some(5), before: None };
let has_prev = args.has_previous_page(7); // true
Implementation Details
The pagination logic follows the Cursor-based Pagination pattern.
Fetching one additional item beyond the requested limit helps determine if more pages exist, which is then adjusted by
shrink_portion.Direction determination is based on the presence of
lastorbefore, signaling backward pagination, or defaulting to forward.Uses optional fields to flexibly support different pagination use cases.
The default batch size fallback (
crate::defaults::QUERY_BATCH_SIZE) ensures reasonable limits when no explicit size is provided.
Interaction with Other System Components
This module is expected to be used wherever paginated queries are performed, such as database queries or API data fetching layers.
It likely interacts with query builders, resolvers, or data access layers that consume
PaginationArgsto apply limit and cursor constraints.The default batch size constant is defined externally in
crate::defaults, linking this file to broader application configuration.Cursor values (
afterandbefore) are strings, implying external encoding/decoding of cursors occurs elsewhere, possibly in Cursor Encoding/Decoding utilities.
Structure Diagram
classDiagram
class PaginationArgs {
+first: Option<usize>
+after: Option<String>
+last: Option<usize>
+before: Option<String>
+get_limit() usize
+shrink_portion(&mut Vec<T>)
+get_direction() PaginateDirection
+get_bound_markers(num_nodes: usize) (bool, bool)
+has_next_page(num_nodes: usize) bool
+has_previous_page(num_nodes: usize) bool
}
class PaginateDirection {
<<enumeration>>
+Forward
+Backward
}
PaginationArgs --> PaginateDirection : uses