Skip to main content

sqlx_paginated/paginated_query_as/models/
query_params.rs

1use crate::paginated_query_as::internal::{
2    deserialize_filter_map, QueryDateRangeParams, QueryPaginationParams, QuerySearchParams,
3    QuerySortParams,
4};
5use crate::paginated_query_as::models::QueryFilterCondition;
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::marker::PhantomData;
9
10/// Flattened query parameters suitable for deserializing from HTTP query strings.
11///
12/// This struct is designed to work with web frameworks' query string deserializers.
13/// All fields are optional to allow partial parameter specification.
14///
15/// # Filter Syntax
16///
17/// Supports both simple equality and advanced operator syntax:
18/// - Simple: `field=value` → Equal operator
19/// - With operator: `field[op]=value` → Specified operator
20///
21/// # Examples
22///
23/// ```rust
24/// use sqlx_paginated::FlatQueryParams;
25/// use serde::Deserialize;
26///
27/// // Simple equality filters:
28/// // ?status=active&role=admin
29///
30/// // Advanced operator filters:
31/// // ?price[gt]=10&stock[lte]=100&status[ne]=deleted
32/// // ?role[in]=admin,moderator&deleted_at[is_null]=
33///
34/// // With Actix-web:
35/// // async fn handler(Query(params): Query<FlatQueryParams>) { ... }
36///
37/// // With Axum:
38/// // async fn handler(Query(params): Query<FlatQueryParams>) { ... }
39/// ```
40#[derive(Serialize, Deserialize, Debug, Clone, Default)]
41pub struct FlatQueryParams {
42    /// Pagination parameters (page, page_size)
43    #[serde(flatten)]
44    pub pagination: Option<QueryPaginationParams>,
45
46    /// Sort parameters (sort_column, sort_direction)
47    #[serde(flatten)]
48    pub sort: Option<QuerySortParams>,
49
50    /// Search parameters (search, search_columns)
51    #[serde(flatten)]
52    pub search: Option<QuerySearchParams>,
53
54    /// Date range parameters (date_column, date_after, date_before)
55    #[serde(flatten)]
56    pub date_range: Option<QueryDateRangeParams>,
57
58    /// Filter conditions with operators
59    ///
60    /// Supports operator syntax in query strings:
61    /// - `field=value` → Equality
62    /// - `field[gt]=value` → Greater than
63    /// - `field[in]=val1,val2` → In list
64    /// - `field[is_null]=` → Is null
65    ///
66    /// See `QueryFilterOperator` for all supported operators.
67    #[serde(flatten, deserialize_with = "deserialize_filter_map")]
68    pub filters: Option<HashMap<String, QueryFilterCondition>>,
69}
70
71/// Complete query parameters with all configuration options.
72///
73/// This is the main parameter structure used throughout the library.
74/// It contains all pagination, sorting, filtering, and search configuration.
75///
76/// # Type Parameters
77///
78/// * `'q` - Lifetime for query parameter references
79/// * `T` - The model type being queried
80///
81/// # Examples
82///
83/// ```rust
84/// use sqlx_paginated::{QueryParams, QueryParamsBuilder, QuerySortDirection};
85/// use serde::Serialize;
86///
87/// #[derive(Serialize, Default)]
88/// struct User {
89///     name: String,
90///     email: String,
91/// }
92///
93/// let params = QueryParamsBuilder::<User>::new()
94///     .with_pagination(1, 20)
95///     .with_sort("name", QuerySortDirection::Ascending)
96///     .with_search("john", vec!["name", "email"])
97///     .build();
98/// ```
99#[derive(Default, Clone)]
100pub struct QueryParams<'q, T> {
101    /// Pagination configuration (page, page_size)
102    pub pagination: QueryPaginationParams,
103
104    /// Sort configuration (column, direction)
105    pub sort: QuerySortParams,
106
107    /// Search configuration (term, columns)
108    pub search: QuerySearchParams,
109
110    /// Date range filtering configuration
111    pub date_range: QueryDateRangeParams,
112
113    /// Filter conditions with operators
114    pub filters: HashMap<String, QueryFilterCondition>,
115
116    /// Legacy simple filters (backward compatibility)
117    ///
118    /// Deprecated: Use `filters` with QueryFilterCondition instead
119    #[deprecated(
120        since = "0.3.0",
121        note = "Use filters with QueryFilterCondition instead"
122    )]
123    pub simple_filters: HashMap<String, Option<String>>,
124
125    /// Phantom data to hold the type parameter
126    pub(crate) _phantom: PhantomData<&'q T>,
127}
128
129impl<'q, T> From<FlatQueryParams> for QueryParams<'q, T> {
130    fn from(params: FlatQueryParams) -> Self {
131        let filters = params.filters.unwrap_or_default();
132
133        // Build simple_filters for backward compatibility (deprecated)
134        #[allow(deprecated)]
135        let simple_filters = filters
136            .iter()
137            .map(|(k, v)| (k.clone(), v.value.clone()))
138            .collect();
139
140        QueryParams {
141            pagination: params.pagination.unwrap_or_default(),
142            sort: params.sort.unwrap_or_default(),
143            search: params.search.unwrap_or_default(),
144            date_range: params.date_range.unwrap_or_default(),
145            filters,
146            #[allow(deprecated)]
147            simple_filters,
148            _phantom: PhantomData::<&'q T>,
149        }
150    }
151}