mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
feat: add primary key not null query to generic filter function (#7785)
This commit is contained in:
@ -44,3 +44,4 @@ pub mod user;
|
|||||||
pub mod user_authentication_method;
|
pub mod user_authentication_method;
|
||||||
pub mod user_key_store;
|
pub mod user_key_store;
|
||||||
pub mod user_role;
|
pub mod user_role;
|
||||||
|
mod utils;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use async_bb8_diesel::AsyncRunQueryDsl;
|
|||||||
use diesel::{
|
use diesel::{
|
||||||
associations::HasTable,
|
associations::HasTable,
|
||||||
debug_query,
|
debug_query,
|
||||||
dsl::{Find, Limit},
|
dsl::{Find, IsNotNull, Limit},
|
||||||
helper_types::{Filter, IntoBoxed},
|
helper_types::{Filter, IntoBoxed},
|
||||||
insertable::CanInsertInSingleQuery,
|
insertable::CanInsertInSingleQuery,
|
||||||
pg::{Pg, PgConnection},
|
pg::{Pg, PgConnection},
|
||||||
@ -17,12 +17,12 @@ use diesel::{
|
|||||||
LoadQuery, RunQueryDsl,
|
LoadQuery, RunQueryDsl,
|
||||||
},
|
},
|
||||||
result::Error as DieselError,
|
result::Error as DieselError,
|
||||||
Expression, Insertable, QueryDsl, QuerySource, Table,
|
Expression, ExpressionMethods, Insertable, QueryDsl, QuerySource, Table,
|
||||||
};
|
};
|
||||||
use error_stack::{report, ResultExt};
|
use error_stack::{report, ResultExt};
|
||||||
use router_env::logger;
|
use router_env::logger;
|
||||||
|
|
||||||
use crate::{errors, PgPooledConn, StorageResult};
|
use crate::{errors, query::utils::GetPrimaryKey, PgPooledConn, StorageResult};
|
||||||
|
|
||||||
pub mod db_metrics {
|
pub mod db_metrics {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -401,7 +401,7 @@ where
|
|||||||
to_optional(generic_find_one_core::<T, _, _>(conn, predicate).await)
|
to_optional(generic_find_one_core::<T, _, _>(conn, predicate).await)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn generic_filter<T, P, O, R>(
|
pub(super) async fn generic_filter<T, P, O, R>(
|
||||||
conn: &PgPooledConn,
|
conn: &PgPooledConn,
|
||||||
predicate: P,
|
predicate: P,
|
||||||
limit: Option<i64>,
|
limit: Option<i64>,
|
||||||
@ -409,8 +409,9 @@ pub async fn generic_filter<T, P, O, R>(
|
|||||||
order: Option<O>,
|
order: Option<O>,
|
||||||
) -> StorageResult<Vec<R>>
|
) -> StorageResult<Vec<R>>
|
||||||
where
|
where
|
||||||
T: HasTable<Table = T> + Table + BoxedDsl<'static, Pg> + 'static,
|
T: HasTable<Table = T> + Table + BoxedDsl<'static, Pg> + GetPrimaryKey + 'static,
|
||||||
IntoBoxed<'static, T, Pg>: FilterDsl<P, Output = IntoBoxed<'static, T, Pg>>
|
IntoBoxed<'static, T, Pg>: FilterDsl<P, Output = IntoBoxed<'static, T, Pg>>
|
||||||
|
+ FilterDsl<IsNotNull<T::PK>, Output = IntoBoxed<'static, T, Pg>>
|
||||||
+ LimitDsl<Output = IntoBoxed<'static, T, Pg>>
|
+ LimitDsl<Output = IntoBoxed<'static, T, Pg>>
|
||||||
+ OffsetDsl<Output = IntoBoxed<'static, T, Pg>>
|
+ OffsetDsl<Output = IntoBoxed<'static, T, Pg>>
|
||||||
+ OrderDsl<O, Output = IntoBoxed<'static, T, Pg>>
|
+ OrderDsl<O, Output = IntoBoxed<'static, T, Pg>>
|
||||||
@ -421,8 +422,9 @@ where
|
|||||||
R: Send + 'static,
|
R: Send + 'static,
|
||||||
{
|
{
|
||||||
let mut query = T::table().into_boxed();
|
let mut query = T::table().into_boxed();
|
||||||
query = query.filter(predicate);
|
query = query
|
||||||
|
.filter(predicate)
|
||||||
|
.filter(T::table().get_primary_key().is_not_null());
|
||||||
if let Some(limit) = limit {
|
if let Some(limit) = limit {
|
||||||
query = query.limit(limit);
|
query = query.limit(limit);
|
||||||
}
|
}
|
||||||
|
|||||||
144
crates/diesel_models/src/query/utils.rs
Normal file
144
crates/diesel_models/src/query/utils.rs
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
use diesel;
|
||||||
|
|
||||||
|
use crate::{schema, schema_v2};
|
||||||
|
|
||||||
|
/// This trait will return a single column as primary key even in case of composite primary key.
|
||||||
|
///
|
||||||
|
/// In case of composite key, it will return the column that is used as local unique.
|
||||||
|
pub(super) trait GetPrimaryKey: diesel::Table {
|
||||||
|
type PK: diesel::ExpressionMethods;
|
||||||
|
fn get_primary_key(&self) -> Self::PK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This trait must be implemented for all composite keys.
|
||||||
|
pub(super) trait CompositeKey {
|
||||||
|
type UK;
|
||||||
|
/// It will return the local unique key of the composite key.
|
||||||
|
///
|
||||||
|
/// If `(attempt_id, merchant_id)` is the composite key for `payment_attempt` table, then it will return `attempt_id`.
|
||||||
|
fn get_local_unique_key(&self) -> Self::UK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// implementation of `CompositeKey` trait for all the composite keys must be done here.
|
||||||
|
mod composite_key {
|
||||||
|
use super::{schema, schema_v2, CompositeKey};
|
||||||
|
impl CompositeKey for <schema::payment_attempt::table as diesel::Table>::PrimaryKey {
|
||||||
|
type UK = schema::payment_attempt::dsl::attempt_id;
|
||||||
|
fn get_local_unique_key(&self) -> Self::UK {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl CompositeKey for <schema::refund::table as diesel::Table>::PrimaryKey {
|
||||||
|
type UK = schema::refund::dsl::refund_id;
|
||||||
|
fn get_local_unique_key(&self) -> Self::UK {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl CompositeKey for <schema::customers::table as diesel::Table>::PrimaryKey {
|
||||||
|
type UK = schema::customers::dsl::customer_id;
|
||||||
|
fn get_local_unique_key(&self) -> Self::UK {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl CompositeKey for <schema::blocklist::table as diesel::Table>::PrimaryKey {
|
||||||
|
type UK = schema::blocklist::dsl::fingerprint_id;
|
||||||
|
fn get_local_unique_key(&self) -> Self::UK {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl CompositeKey for <schema::incremental_authorization::table as diesel::Table>::PrimaryKey {
|
||||||
|
type UK = schema::incremental_authorization::dsl::authorization_id;
|
||||||
|
fn get_local_unique_key(&self) -> Self::UK {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl CompositeKey for <schema_v2::incremental_authorization::table as diesel::Table>::PrimaryKey {
|
||||||
|
type UK = schema_v2::incremental_authorization::dsl::authorization_id;
|
||||||
|
fn get_local_unique_key(&self) -> Self::UK {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl CompositeKey for <schema_v2::blocklist::table as diesel::Table>::PrimaryKey {
|
||||||
|
type UK = schema_v2::blocklist::dsl::fingerprint_id;
|
||||||
|
fn get_local_unique_key(&self) -> Self::UK {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This macro will implement the `GetPrimaryKey` trait for all the tables with single primary key.
|
||||||
|
macro_rules! impl_get_primary_key {
|
||||||
|
($($table:ty),*) => {
|
||||||
|
$(
|
||||||
|
impl GetPrimaryKey for $table
|
||||||
|
{
|
||||||
|
type PK = <$table as diesel::Table>::PrimaryKey;
|
||||||
|
fn get_primary_key(&self) -> Self::PK {
|
||||||
|
<Self as diesel::Table>::primary_key(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
impl_get_primary_key!(
|
||||||
|
// v1 tables
|
||||||
|
schema::dashboard_metadata::table,
|
||||||
|
schema::merchant_connector_account::table,
|
||||||
|
schema::merchant_key_store::table,
|
||||||
|
schema::payment_methods::table,
|
||||||
|
schema::user_authentication_methods::table,
|
||||||
|
schema::user_key_store::table,
|
||||||
|
schema::users::table,
|
||||||
|
schema::api_keys::table,
|
||||||
|
schema::captures::table,
|
||||||
|
schema::business_profile::table,
|
||||||
|
schema::mandate::dsl::mandate,
|
||||||
|
schema::dispute::table,
|
||||||
|
schema::events::table,
|
||||||
|
schema::merchant_account::table,
|
||||||
|
schema::process_tracker::table,
|
||||||
|
// v2 tables
|
||||||
|
schema_v2::dashboard_metadata::table,
|
||||||
|
schema_v2::merchant_connector_account::table,
|
||||||
|
schema_v2::merchant_key_store::table,
|
||||||
|
schema_v2::payment_methods::table,
|
||||||
|
schema_v2::user_authentication_methods::table,
|
||||||
|
schema_v2::user_key_store::table,
|
||||||
|
schema_v2::users::table,
|
||||||
|
schema_v2::api_keys::table,
|
||||||
|
schema_v2::captures::table,
|
||||||
|
schema_v2::business_profile::table,
|
||||||
|
schema_v2::mandate::table,
|
||||||
|
schema_v2::dispute::table,
|
||||||
|
schema_v2::events::table,
|
||||||
|
schema_v2::merchant_account::table,
|
||||||
|
schema_v2::process_tracker::table,
|
||||||
|
schema_v2::refund::table,
|
||||||
|
schema_v2::customers::table,
|
||||||
|
schema_v2::payment_attempt::table
|
||||||
|
);
|
||||||
|
|
||||||
|
/// This macro will implement the `GetPrimaryKey` trait for all the tables with composite key.
|
||||||
|
macro_rules! impl_get_primary_key_for_composite {
|
||||||
|
($($table:ty),*) => {
|
||||||
|
$(
|
||||||
|
impl GetPrimaryKey for $table
|
||||||
|
{
|
||||||
|
type PK = <<$table as diesel::Table>::PrimaryKey as CompositeKey>::UK;
|
||||||
|
fn get_primary_key(&self) -> Self::PK {
|
||||||
|
<Self as diesel::Table>::primary_key(self).get_local_unique_key()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_get_primary_key_for_composite!(
|
||||||
|
schema::payment_attempt::table,
|
||||||
|
schema::refund::table,
|
||||||
|
schema::customers::table,
|
||||||
|
schema::blocklist::table,
|
||||||
|
schema::incremental_authorization::table,
|
||||||
|
schema_v2::incremental_authorization::table,
|
||||||
|
schema_v2::blocklist::table
|
||||||
|
);
|
||||||
Reference in New Issue
Block a user