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_key_store;
|
||||
pub mod user_role;
|
||||
mod utils;
|
||||
|
||||
@ -4,7 +4,7 @@ use async_bb8_diesel::AsyncRunQueryDsl;
|
||||
use diesel::{
|
||||
associations::HasTable,
|
||||
debug_query,
|
||||
dsl::{Find, Limit},
|
||||
dsl::{Find, IsNotNull, Limit},
|
||||
helper_types::{Filter, IntoBoxed},
|
||||
insertable::CanInsertInSingleQuery,
|
||||
pg::{Pg, PgConnection},
|
||||
@ -17,12 +17,12 @@ use diesel::{
|
||||
LoadQuery, RunQueryDsl,
|
||||
},
|
||||
result::Error as DieselError,
|
||||
Expression, Insertable, QueryDsl, QuerySource, Table,
|
||||
Expression, ExpressionMethods, Insertable, QueryDsl, QuerySource, Table,
|
||||
};
|
||||
use error_stack::{report, ResultExt};
|
||||
use router_env::logger;
|
||||
|
||||
use crate::{errors, PgPooledConn, StorageResult};
|
||||
use crate::{errors, query::utils::GetPrimaryKey, PgPooledConn, StorageResult};
|
||||
|
||||
pub mod db_metrics {
|
||||
#[derive(Debug)]
|
||||
@ -401,7 +401,7 @@ where
|
||||
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,
|
||||
predicate: P,
|
||||
limit: Option<i64>,
|
||||
@ -409,8 +409,9 @@ pub async fn generic_filter<T, P, O, R>(
|
||||
order: Option<O>,
|
||||
) -> StorageResult<Vec<R>>
|
||||
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>>
|
||||
+ FilterDsl<IsNotNull<T::PK>, Output = IntoBoxed<'static, T, Pg>>
|
||||
+ LimitDsl<Output = IntoBoxed<'static, T, Pg>>
|
||||
+ OffsetDsl<Output = IntoBoxed<'static, T, Pg>>
|
||||
+ OrderDsl<O, Output = IntoBoxed<'static, T, Pg>>
|
||||
@ -421,8 +422,9 @@ where
|
||||
R: Send + 'static,
|
||||
{
|
||||
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 {
|
||||
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