feat: add primary key not null query to generic filter function (#7785)

This commit is contained in:
Hrithikesh
2025-04-17 10:34:46 +05:30
committed by GitHub
parent 0607baa083
commit 8738f19067
3 changed files with 154 additions and 7 deletions

View File

@ -44,3 +44,4 @@ pub mod user;
pub mod user_authentication_method;
pub mod user_key_store;
pub mod user_role;
mod utils;

View File

@ -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);
}

View 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
);