pub struct PostgresRepository<T>{ /* private fields */ }Expand description
PostgreSQL repository implementation with JSON-based dynamic queries
Implementations§
Source§impl<T> PostgresRepository<T>
impl<T> PostgresRepository<T>
pub fn new(pool: Pool<Postgres>, table_name: &str) -> PostgresRepository<T>
pub fn pool(&self) -> &Pool<Postgres>
pub fn table_name(&self) -> &str
Sourcepub async fn list_with_filters(
&self,
pagination: PaginationParams,
filters: &HashMap<String, String>,
column_types: &HashMap<String, String>,
search_fields: &[&str],
) -> Result<PaginatedResult<T>, Error>
pub async fn list_with_filters( &self, pagination: PaginationParams, filters: &HashMap<String, String>, column_types: &HashMap<String, String>, search_fields: &[&str], ) -> Result<PaginatedResult<T>, Error>
List entities with pagination and advanced filtering
This method provides comprehensive filtering capabilities similar to Laravel’s Filter Query String.
§Supported Filter Operators
field[eq]=value- Equalfield[notEq]=value- Not equalfield[gt]=value- Greater thanfield[gte]=value- Greater than or equalfield[lt]=value- Less thanfield[lte]=value- Less than or equalfield[like]=value- LIKE (case-sensitive)field[ilike]=value- ILIKE (case-insensitive)field[notlike]=value- NOT LIKEfield[contain]=value- Contains (%value%)field[notcontain]=value- Does not containfield[startwith]=value- Starts with (value%)field[endwith]=value- Ends with (%value)field[in]=val1,val2- IN arrayfield[notin]=val1,val2- NOT IN arrayfield[between]=val1,val2- BETWEENfield[notbetween]=val1,val2- NOT BETWEENfield[isnull]- IS NULLfield[isnotnull]- IS NOT NULL
§Special Parameters
search=value&searchFields=field1,field2- Search in multiple fieldsorderby=fieldororderby[field]=asc- Sort resultslimit=10- Limit resultspage=1- Page number
§Column Type Casting
The column_types HashMap maps field names to their PostgreSQL types for proper casting.
For example, {"status": "user_status"} will cast the status parameter to user_status enum type.
§Example
let mut filters = HashMap::new();
filters.insert("username[contain]".to_string(), "john".to_string());
filters.insert("age[gt]".to_string(), "18".to_string());
let mut column_types = HashMap::new();
column_types.insert("status".to_string(), "user_status".to_string());
let result = repo.list_with_filters(
PaginationParams::new(1, 10),
&filters,
&column_types,
&["username", "email"] // search fields
).await?;Sourcepub async fn list_with_filters_whitelisted(
&self,
pagination: PaginationParams,
filters: &HashMap<String, String>,
column_types: &HashMap<String, String>,
search_fields: &[&str],
allowed_fields: Option<&HashSet<String>>,
) -> Result<PaginatedResult<T>, Error>
pub async fn list_with_filters_whitelisted( &self, pagination: PaginationParams, filters: &HashMap<String, String>, column_types: &HashMap<String, String>, search_fields: &[&str], allowed_fields: Option<&HashSet<String>>, ) -> Result<PaginatedResult<T>, Error>
List entities with pagination, filtering, and field whitelist enforcement
Similar to list_with_filters but accepts an optional set of allowed field names.
When provided, only filter conditions on whitelisted fields are applied;
conditions on unknown fields are silently dropped.
This prevents clients from filtering on internal or sensitive columns
(e.g., password_hash, internal_notes).
§Arguments
pagination- Page and limit parametersfilters- HTTP query parameters (e.g.,field[operator]=value)column_types- PostgreSQL type mappings for enum castingsearch_fields- Fields to search whensearchparameter is presentallowed_fields- Optional whitelist of field names;Noneallows all fields
§Example
let allowed: HashSet<String> = ["username", "email", "status"]
.iter().map(|s| s.to_string()).collect();
let result = repo.list_with_filters_whitelisted(
PaginationParams::new(1, 10),
&filters,
&column_types,
&["username", "email"],
Some(&allowed),
).await?;Source§impl<T> PostgresRepository<T>
impl<T> PostgresRepository<T>
Sourcepub async fn aggregate_with_filters(
&self,
spec: &AggregateSpec,
filters: &HashMap<String, String>,
column_types: &HashMap<String, String>,
search_fields: &[&str],
) -> Result<AggregateResult, Error>
pub async fn aggregate_with_filters( &self, spec: &AggregateSpec, filters: &HashMap<String, String>, column_types: &HashMap<String, String>, search_fields: &[&str], ) -> Result<AggregateResult, Error>
Group and reduce rows in one statement, under the same filters, the same soft-delete convention and the same tenancy fence as the list endpoint.
Groups and the overall total come back from a single GROUPING SETS
query, which is what lets a caller draw a chart and its headline from
one reply, and what keeps the two numbers consistent — a separate total
query could observe a different set of rows.
Trait Implementations§
Source§impl<T> DatabaseOperations<T> for PostgresRepository<T>
impl<T> DatabaseOperations<T> for PostgresRepository<T>
Source§fn create<'life0, 'life1, 'async_trait>(
&'life0 self,
entity: &'life1 T,
) -> Pin<Box<dyn Future<Output = Result<T, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
PostgresRepository<T>: 'async_trait,
fn create<'life0, 'life1, 'async_trait>(
&'life0 self,
entity: &'life1 T,
) -> Pin<Box<dyn Future<Output = Result<T, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
PostgresRepository<T>: 'async_trait,
Source§fn find_by_id<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<T>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
PostgresRepository<T>: 'async_trait,
fn find_by_id<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<T>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
PostgresRepository<T>: 'async_trait,
Source§fn find_all<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<T>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
PostgresRepository<T>: 'async_trait,
fn find_all<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<T>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
PostgresRepository<T>: 'async_trait,
Source§fn update<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
id: &'life1 str,
entity: &'life2 T,
) -> Pin<Box<dyn Future<Output = Result<Option<T>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
PostgresRepository<T>: 'async_trait,
fn update<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
id: &'life1 str,
entity: &'life2 T,
) -> Pin<Box<dyn Future<Output = Result<Option<T>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
PostgresRepository<T>: 'async_trait,
Source§fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
PostgresRepository<T>: 'async_trait,
fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
PostgresRepository<T>: 'async_trait,
Source§fn count<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<u64, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
PostgresRepository<T>: 'async_trait,
fn count<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<u64, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
PostgresRepository<T>: 'async_trait,
Auto Trait Implementations§
impl<T> !RefUnwindSafe for PostgresRepository<T>
impl<T> !UnwindSafe for PostgresRepository<T>
impl<T> Freeze for PostgresRepository<T>where
PhantomData<T>: Freeze,
impl<T> Send for PostgresRepository<T>where
PhantomData<T>: Send,
impl<T> Sync for PostgresRepository<T>where
PhantomData<T>: Sync,
impl<T> Unpin for PostgresRepository<T>where
PhantomData<T>: Unpin,
impl<T> UnsafeUnpin for PostgresRepository<T>where
PhantomData<T>: UnsafeUnpin,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more