From 7912c532d3185accad68ba8d8df1e9c632277d2f Mon Sep 17 00:00:00 2001 From: Ahmad Baalbaky Date: Fri, 9 Jan 2026 11:32:08 +0100 Subject: [PATCH 1/4] fix: rename SQL function to remove style of names * Rename `rm_mp_style` to `unstyled` * Make it remove link tags Refs: #112. --- crates/graphql-api/src/objects/root.rs | 6 ++-- .../graphql-api/src/utils/records_filter.rs | 6 ++-- crates/migration/src/lib.rs | 2 ++ .../m20260109_101455_refactor_rm_mp_style.rs | 33 +++++++++++++++++++ .../create_function_rm_mp_style.sql | 5 +++ .../create_function_unstyled.sql | 5 +++ .../func_management.rs | 2 ++ crates/player-map-ranking/src/lib.rs | 4 +-- 8 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs create mode 100644 crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_rm_mp_style.sql create mode 100644 crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_unstyled.sql create mode 100644 crates/migration/src/m20260109_101455_refactor_rm_mp_style/func_management.rs diff --git a/crates/graphql-api/src/objects/root.rs b/crates/graphql-api/src/objects/root.rs index cf08b74..13abe6a 100644 --- a/crates/graphql-api/src/objects/root.rs +++ b/crates/graphql-api/src/objects/root.rs @@ -597,7 +597,7 @@ where }; let mut query = players::Entity::find().expr_as( - Func::cust("rm_mp_style").arg(Expr::col((players::Entity, players::Column::Name))), + Func::cust("unstyled").arg(Expr::col((players::Entity, players::Column::Name))), "unstyled_player_name", ); let query = SelectStatement::new() @@ -708,7 +708,7 @@ where }; let mut query = maps::Entity::find().expr_as( - Func::cust("rm_mp_style").arg(Expr::col((maps::Entity, maps::Column::Name))), + Func::cust("unstyled").arg(Expr::col((maps::Entity, maps::Column::Name))), "unstyled_map_name", ); let query = SelectStatement::new() @@ -733,7 +733,7 @@ where }) .apply_if(filter.player_name, |query, name| { query.and_where( - Func::cust("rm_mp_style") + Func::cust("unstyled") .arg(Expr::col(("author", players::Column::Name))) .like(format!("%{name}%")), ); diff --git a/crates/graphql-api/src/utils/records_filter.rs b/crates/graphql-api/src/utils/records_filter.rs index 0be647c..e9d88b2 100644 --- a/crates/graphql-api/src/utils/records_filter.rs +++ b/crates/graphql-api/src/utils/records_filter.rs @@ -99,7 +99,7 @@ where // Apply player name filter if let Some(name) = &filter.player_name { query = query.filter( - Func::cust("rm_mp_style") + Func::cust("unstyled") .arg(Expr::col(("p", players::Column::Name))) .like(format!("%{name}%")), ); @@ -115,7 +115,7 @@ where // Apply map name filter if let Some(name) = &filter.map_name { query = query.filter( - Func::cust("rm_mp_style") + Func::cust("unstyled") .arg(Expr::col(("m", maps::Column::Name))) .like(format!("%{name}%")), ); @@ -131,7 +131,7 @@ where // Apply player name filter if let Some(name) = &filter.player_name { query = query.filter( - Func::cust("rm_mp_style") + Func::cust("unstyled") .arg(Expr::col(("p2", players::Column::Name))) .like(format!("%{name}%")), ); diff --git a/crates/migration/src/lib.rs b/crates/migration/src/lib.rs index 3d9e721..5a34787 100644 --- a/crates/migration/src/lib.rs +++ b/crates/migration/src/lib.rs @@ -9,6 +9,7 @@ mod m20250918_222203_add_event_edition_maps_disability; mod m20251002_100827_add_rm_mp_style_func; mod m20251004_214656_add_maps_medal_times; mod m20260103_142202_players_maps_score; +mod m20260109_101455_refactor_rm_mp_style; use sea_orm_migration::prelude::*; @@ -31,6 +32,7 @@ impl MigratorTrait for Migrator { Box::new(m20251002_100827_add_rm_mp_style_func::Migration), Box::new(m20251004_214656_add_maps_medal_times::Migration), Box::new(m20260103_142202_players_maps_score::Migration), + Box::new(m20260109_101455_refactor_rm_mp_style::Migration), ] } } diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs b/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs new file mode 100644 index 0000000..e7a2e05 --- /dev/null +++ b/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs @@ -0,0 +1,33 @@ +mod func_management; + +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared("drop function rm_mp_style") + .await?; + manager + .get_connection() + .execute_unprepared(func_management::CREATE_FUNCTION_UNSTYLED) + .await?; + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .get_connection() + .execute_unprepared("drop function unstyled") + .await?; + manager + .get_connection() + .execute_unprepared(func_management::CREATE_FUNCTION_RM_MP_STYLE) + .await?; + Ok(()) + } +} diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_rm_mp_style.sql b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_rm_mp_style.sql new file mode 100644 index 0000000..a7564a9 --- /dev/null +++ b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_rm_mp_style.sql @@ -0,0 +1,5 @@ +create or replace function rm_mp_style(in login text) returns text collate 'utf8mb4_unicode_ci' +begin + return replace(regexp_replace(login, '\\$([wWnNoOiItTsSgGzZ<>]|[aAbBcCdDeEfF0-9]([aAbBcCdDeEfF0-9]{2})?)', ''), + '$$', '$'); +end; diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_unstyled.sql b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_unstyled.sql new file mode 100644 index 0000000..d777104 --- /dev/null +++ b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_unstyled.sql @@ -0,0 +1,5 @@ +create or replace function unstyled(in login text) returns text collate 'utf8mb4_unicode_ci' +begin + return replace(regexp_replace(login, '\\$(([wWnNoOiItTsSgGzZ<>]|([lL](\\[.*\\])?))|[aAbBcCdDeEfF0-9]([aAbBcCdDeEfF0-9]{2})?)', ''), + '$$', '$'); +end; diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/func_management.rs b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/func_management.rs new file mode 100644 index 0000000..633899b --- /dev/null +++ b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/func_management.rs @@ -0,0 +1,2 @@ +pub const CREATE_FUNCTION_RM_MP_STYLE: &str = include_str!("./create_function_rm_mp_style.sql"); +pub const CREATE_FUNCTION_UNSTYLED: &str = include_str!("./create_function_unstyled.sql"); diff --git a/crates/player-map-ranking/src/lib.rs b/crates/player-map-ranking/src/lib.rs index b2590a6..7403a9d 100644 --- a/crates/player-map-ranking/src/lib.rs +++ b/crates/player-map-ranking/src/lib.rs @@ -92,7 +92,7 @@ pub async fn compute_scores( ) -> anyhow::Result { let mut maps = maps::Entity::find() .expr_as( - Func::cust("rm_mp_style").arg(Expr::col((maps::Entity, maps::Column::Name))), + Func::cust("unstyled").arg(Expr::col((maps::Entity, maps::Column::Name))), "unstyled_name", ) .into_model::() @@ -105,7 +105,7 @@ pub async fn compute_scores( let mut players = players::Entity::find() .expr_as( - Func::cust("rm_mp_style").arg(Expr::col((players::Entity, players::Column::Name))), + Func::cust("unstyled").arg(Expr::col((players::Entity, players::Column::Name))), "unstyled_name", ) .into_model::() From 7c482d864ef48d185f286c1097a7d548ef96de4a Mon Sep 17 00:00:00 2001 From: Ahmad Baalbaky Date: Fri, 9 Jan 2026 12:58:06 +0100 Subject: [PATCH 2/4] feat: `unstyled` function in the entity crate * Rename back `unstyled` SQL function to `rm_mp_style`. * Use new `unstyled` function in entity everywhere needed. Refs: #112. --- crates/entity/src/functions.rs | 8 ++++++++ crates/entity/src/lib.rs | 1 + crates/graphql-api/src/objects/root.rs | 15 +++++++-------- crates/graphql-api/src/utils/records_filter.rs | 16 +++++----------- .../src/m20260109_101455_refactor_rm_mp_style.rs | 4 ++-- ...d.sql => create_new_function_rm_mp_style.sql} | 2 +- ...e.sql => create_old_function_rm_mp_style.sql} | 0 .../func_management.rs | 6 ++++-- crates/player-map-ranking/src/lib.rs | 14 +++----------- 9 files changed, 31 insertions(+), 35 deletions(-) create mode 100644 crates/entity/src/functions.rs rename crates/migration/src/m20260109_101455_refactor_rm_mp_style/{create_function_unstyled.sql => create_new_function_rm_mp_style.sql} (64%) rename crates/migration/src/m20260109_101455_refactor_rm_mp_style/{create_function_rm_mp_style.sql => create_old_function_rm_mp_style.sql} (100%) diff --git a/crates/entity/src/functions.rs b/crates/entity/src/functions.rs new file mode 100644 index 0000000..f15599e --- /dev/null +++ b/crates/entity/src/functions.rs @@ -0,0 +1,8 @@ +use sea_orm::{ + IntoSimpleExpr, + sea_query::{Func, SimpleExpr}, +}; + +pub fn unstyled(v: impl IntoSimpleExpr) -> SimpleExpr { + Func::cust("rm_mp_style").arg(v.into_simple_expr()).into() +} diff --git a/crates/entity/src/lib.rs b/crates/entity/src/lib.rs index a7e44ce..1b1b25d 100644 --- a/crates/entity/src/lib.rs +++ b/crates/entity/src/lib.rs @@ -1,6 +1,7 @@ mod entities; pub use entities::*; +pub mod functions; pub mod types; pub mod current_bans; diff --git a/crates/graphql-api/src/objects/root.rs b/crates/graphql-api/src/objects/root.rs index 13abe6a..573d1a5 100644 --- a/crates/graphql-api/src/objects/root.rs +++ b/crates/graphql-api/src/objects/root.rs @@ -3,7 +3,9 @@ use async_graphql::{ connection::{self, CursorType}, }; use deadpool_redis::redis::{AsyncCommands, ToRedisArgs}; -use entity::{event as event_entity, event_edition, global_records, maps, players, records}; +use entity::{ + event as event_entity, event_edition, functions, global_records, maps, players, records, +}; use records_lib::{ Database, RedisConnection, RedisPool, must, opt_event::OptEvent, @@ -597,7 +599,7 @@ where }; let mut query = players::Entity::find().expr_as( - Func::cust("unstyled").arg(Expr::col((players::Entity, players::Column::Name))), + functions::unstyled(players::Column::Name), "unstyled_player_name", ); let query = SelectStatement::new() @@ -707,10 +709,8 @@ where }, }; - let mut query = maps::Entity::find().expr_as( - Func::cust("unstyled").arg(Expr::col((maps::Entity, maps::Column::Name))), - "unstyled_map_name", - ); + let mut query = + maps::Entity::find().expr_as(functions::unstyled(maps::Column::Name), "unstyled_map_name"); let query = SelectStatement::new() .column(Asterisk) .from_subquery(QuerySelect::query(&mut query).take(), "map") @@ -733,8 +733,7 @@ where }) .apply_if(filter.player_name, |query, name| { query.and_where( - Func::cust("unstyled") - .arg(Expr::col(("author", players::Column::Name))) + functions::unstyled(Expr::col(("author", players::Column::Name))) .like(format!("%{name}%")), ); }); diff --git a/crates/graphql-api/src/utils/records_filter.rs b/crates/graphql-api/src/utils/records_filter.rs index e9d88b2..f17b519 100644 --- a/crates/graphql-api/src/utils/records_filter.rs +++ b/crates/graphql-api/src/utils/records_filter.rs @@ -1,9 +1,7 @@ -use entity::{global_event_records, global_records, maps, players, records}; +use entity::{functions, global_event_records, global_records, maps, players, records}; use sea_orm::{ ColumnTrait, EntityTrait, JoinType, QueryFilter as _, QuerySelect as _, RelationDef, - RelationTrait as _, Select, - prelude::Expr, - sea_query::{ExprTrait as _, Func}, + RelationTrait as _, Select, prelude::Expr, }; use crate::objects::records_filter::RecordsFilter; @@ -99,8 +97,7 @@ where // Apply player name filter if let Some(name) = &filter.player_name { query = query.filter( - Func::cust("unstyled") - .arg(Expr::col(("p", players::Column::Name))) + functions::unstyled(Expr::col(("p", players::Column::Name))) .like(format!("%{name}%")), ); } @@ -115,9 +112,7 @@ where // Apply map name filter if let Some(name) = &filter.map_name { query = query.filter( - Func::cust("unstyled") - .arg(Expr::col(("m", maps::Column::Name))) - .like(format!("%{name}%")), + functions::unstyled(Expr::col(("m", maps::Column::Name))).like(format!("%{name}%")), ); } @@ -131,8 +126,7 @@ where // Apply player name filter if let Some(name) = &filter.player_name { query = query.filter( - Func::cust("unstyled") - .arg(Expr::col(("p2", players::Column::Name))) + functions::unstyled(Expr::col(("p2", players::Column::Name))) .like(format!("%{name}%")), ); } diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs b/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs index e7a2e05..e8390e1 100644 --- a/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs +++ b/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs @@ -14,7 +14,7 @@ impl MigrationTrait for Migration { .await?; manager .get_connection() - .execute_unprepared(func_management::CREATE_FUNCTION_UNSTYLED) + .execute_unprepared(func_management::CREATE_NEW_FUNCTION_RM_MP_STYLE) .await?; Ok(()) } @@ -26,7 +26,7 @@ impl MigrationTrait for Migration { .await?; manager .get_connection() - .execute_unprepared(func_management::CREATE_FUNCTION_RM_MP_STYLE) + .execute_unprepared(func_management::CREATE_OLD_FUNCTION_RM_MP_STYLE) .await?; Ok(()) } diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_unstyled.sql b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_new_function_rm_mp_style.sql similarity index 64% rename from crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_unstyled.sql rename to crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_new_function_rm_mp_style.sql index d777104..690f14d 100644 --- a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_unstyled.sql +++ b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_new_function_rm_mp_style.sql @@ -1,4 +1,4 @@ -create or replace function unstyled(in login text) returns text collate 'utf8mb4_unicode_ci' +create or replace function rm_mp_style(in login text) returns text collate 'utf8mb4_unicode_ci' begin return replace(regexp_replace(login, '\\$(([wWnNoOiItTsSgGzZ<>]|([lL](\\[.*\\])?))|[aAbBcCdDeEfF0-9]([aAbBcCdDeEfF0-9]{2})?)', ''), '$$', '$'); diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_rm_mp_style.sql b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_old_function_rm_mp_style.sql similarity index 100% rename from crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_function_rm_mp_style.sql rename to crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_old_function_rm_mp_style.sql diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/func_management.rs b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/func_management.rs index 633899b..16d2a8b 100644 --- a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/func_management.rs +++ b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/func_management.rs @@ -1,2 +1,4 @@ -pub const CREATE_FUNCTION_RM_MP_STYLE: &str = include_str!("./create_function_rm_mp_style.sql"); -pub const CREATE_FUNCTION_UNSTYLED: &str = include_str!("./create_function_unstyled.sql"); +pub const CREATE_OLD_FUNCTION_RM_MP_STYLE: &str = + include_str!("./create_old_function_rm_mp_style.sql"); +pub const CREATE_NEW_FUNCTION_RM_MP_STYLE: &str = + include_str!("./create_new_function_rm_mp_style.sql"); diff --git a/crates/player-map-ranking/src/lib.rs b/crates/player-map-ranking/src/lib.rs index 7403a9d..0b502fb 100644 --- a/crates/player-map-ranking/src/lib.rs +++ b/crates/player-map-ranking/src/lib.rs @@ -1,12 +1,10 @@ use std::{collections::HashMap, hash::Hash}; use anyhow::Context as _; -use entity::{global_records, maps, players}; +use entity::{functions, global_records, maps, players}; use sea_orm::{ ColumnTrait as _, ConnectionTrait, EntityTrait as _, QueryFilter as _, QueryOrder, QuerySelect, QueryTrait, - prelude::Expr, - sea_query::Func, sqlx::types::chrono::{DateTime, Utc}, }; @@ -91,10 +89,7 @@ pub async fn compute_scores( from: Option>, ) -> anyhow::Result { let mut maps = maps::Entity::find() - .expr_as( - Func::cust("unstyled").arg(Expr::col((maps::Entity, maps::Column::Name))), - "unstyled_name", - ) + .expr_as(functions::unstyled(maps::Column::Name), "unstyled_name") .into_model::() .all(conn) .await @@ -104,10 +99,7 @@ pub async fn compute_scores( .collect::>(); let mut players = players::Entity::find() - .expr_as( - Func::cust("unstyled").arg(Expr::col((players::Entity, players::Column::Name))), - "unstyled_name", - ) + .expr_as(functions::unstyled(players::Column::Name), "unstyled_name") .into_model::() .all(conn) .await From f5ac70b7d2b9a299d965a041df3758d5ec4a684d Mon Sep 17 00:00:00 2001 From: Ahmad <39441506+ahmadbky@users.noreply.github.com> Date: Sat, 10 Jan 2026 00:26:05 +0100 Subject: [PATCH 3/4] Update crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_new_function_rm_mp_style.sql Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../create_new_function_rm_mp_style.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_new_function_rm_mp_style.sql b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_new_function_rm_mp_style.sql index 690f14d..4a616ea 100644 --- a/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_new_function_rm_mp_style.sql +++ b/crates/migration/src/m20260109_101455_refactor_rm_mp_style/create_new_function_rm_mp_style.sql @@ -1,5 +1,5 @@ create or replace function rm_mp_style(in login text) returns text collate 'utf8mb4_unicode_ci' begin - return replace(regexp_replace(login, '\\$(([wWnNoOiItTsSgGzZ<>]|([lL](\\[.*\\])?))|[aAbBcCdDeEfF0-9]([aAbBcCdDeEfF0-9]{2})?)', ''), + return replace(regexp_replace(login, '\\$(([wWnNoOiItTsSgGzZ<>]|([lL](\\[.*?\\])?))|[aAbBcCdDeEfF0-9]([aAbBcCdDeEfF0-9]{2})?)', ''), '$$', '$'); end; From 8027f9a07242fe9aebf8cffe1e1470685813e1ef Mon Sep 17 00:00:00 2001 From: Ahmad Baalbaky Date: Sat, 10 Jan 2026 00:26:28 +0100 Subject: [PATCH 4/4] fix: wrong function dropped in migration down Refs: #112. --- crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs b/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs index e8390e1..f96cc6d 100644 --- a/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs +++ b/crates/migration/src/m20260109_101455_refactor_rm_mp_style.rs @@ -22,7 +22,7 @@ impl MigrationTrait for Migration { async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { manager .get_connection() - .execute_unprepared("drop function unstyled") + .execute_unprepared("drop function rm_mp_style") .await?; manager .get_connection()