From 3724eea08e62beb323a6abf256b9805746c04665 Mon Sep 17 00:00:00 2001 From: Tsubasa SEKIGUCHI Date: Sun, 8 Feb 2026 05:14:25 +0000 Subject: [PATCH 1/3] =?UTF-8?q?GetStationsByLineGroupIdList=20RPC=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- stationapi/proto | 2 +- .../domain/repository/station_repository.rs | 19 +++ .../src/infrastructure/station_repository.rs | 114 ++++++++++++++++++ .../src/presentation/controller/grpc.rs | 31 ++++- stationapi/src/use_case/interactor/query.rs | 33 +++++ stationapi/src/use_case/traits/query.rs | 5 + 6 files changed, 202 insertions(+), 2 deletions(-) diff --git a/stationapi/proto b/stationapi/proto index b0508057..6f5474ca 160000 --- a/stationapi/proto +++ b/stationapi/proto @@ -1 +1 @@ -Subproject commit b050805770f4063d509b3acb5016f9464dc96417 +Subproject commit 6f5474cabcdb637bab5ce9417c578417fbb5f055 diff --git a/stationapi/src/domain/repository/station_repository.rs b/stationapi/src/domain/repository/station_repository.rs index 9bb53d82..94a447a6 100644 --- a/stationapi/src/domain/repository/station_repository.rs +++ b/stationapi/src/domain/repository/station_repository.rs @@ -39,6 +39,10 @@ pub trait StationRepository: Send + Sync + 'static { transport_type: Option, ) -> Result, DomainError>; async fn get_by_line_group_id(&self, line_group_id: u32) -> Result, DomainError>; + async fn get_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + ) -> Result, DomainError>; async fn get_route_stops( &self, from_station_id: u32, @@ -219,6 +223,21 @@ mod tests { Ok(result) } + async fn get_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + ) -> Result, DomainError> { + let result: Vec = self + .stations + .values() + .filter(|station| { + line_group_ids.contains(&(station.line_group_cd.unwrap_or(0) as u32)) + }) + .cloned() + .collect(); + Ok(result) + } + async fn get_route_stops( &self, from_station_id: u32, diff --git a/stationapi/src/infrastructure/station_repository.rs b/stationapi/src/infrastructure/station_repository.rs index 0e111e88..d1615b68 100644 --- a/stationapi/src/infrastructure/station_repository.rs +++ b/stationapi/src/infrastructure/station_repository.rs @@ -272,6 +272,14 @@ impl StationRepository for MyStationRepository { InternalStationRepository::get_by_line_group_id(line_group_id, &mut conn).await } + async fn get_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + ) -> Result, DomainError> { + let mut conn = self.pool.acquire().await?; + InternalStationRepository::get_by_line_group_id_vec(line_group_ids, &mut conn).await + } + async fn get_route_stops( &self, from_station_id: u32, @@ -1343,6 +1351,112 @@ impl InternalStationRepository { Ok(stations) } + async fn get_by_line_group_id_vec( + line_group_ids: &[u32], + conn: &mut PgConnection, + ) -> Result, DomainError> { + if line_group_ids.is_empty() { + return Ok(vec![]); + } + + let params = (1..=line_group_ids.len()) + .map(|i| format!("${i}")) + .collect::>() + .join(", "); + + let order_case = line_group_ids + .iter() + .enumerate() + .map(|(i, _)| format!("WHEN ${} THEN {}", i + 1 + line_group_ids.len(), i)) + .collect::>() + .join(" "); + + let query_str = format!( + r#"SELECT + s.station_cd, + s.station_g_cd, + s.station_name, + s.station_name_k, + s.station_name_r, + s.station_name_rn, + s.station_name_zh, + s.station_name_ko, + s.station_number1, + s.station_number2, + s.station_number3, + s.station_number4, + s.three_letter_code, + s.line_cd, + s.pref_cd, + s.post, + s.address, + s.lon, + s.lat, + s.open_ymd, + s.close_ymd, + s.e_status, + s.e_sort, + COALESCE(NULLIF(COALESCE(a.line_name, l.line_name), ''), NULL) AS line_name, + COALESCE(NULLIF(COALESCE(a.line_name_k, l.line_name_k), ''), NULL) AS line_name_k, + COALESCE(NULLIF(COALESCE(a.line_name_h, l.line_name_h), ''), NULL) AS line_name_h, + COALESCE(NULLIF(COALESCE(a.line_name_r, l.line_name_r), ''), NULL) AS line_name_r, + COALESCE(NULLIF(COALESCE(a.line_name_zh, l.line_name_zh), ''), NULL) AS line_name_zh, + COALESCE(NULLIF(COALESCE(a.line_name_ko, l.line_name_ko), ''), NULL) AS line_name_ko, + COALESCE(NULLIF(COALESCE(a.line_color_c, l.line_color_c), ''), NULL) AS line_color_c, + l.company_cd, + l.line_type, + l.line_symbol1, + l.line_symbol2, + l.line_symbol3, + l.line_symbol4, + l.line_symbol1_color, + l.line_symbol2_color, + l.line_symbol3_color, + l.line_symbol4_color, + l.line_symbol1_shape, + l.line_symbol2_shape, + l.line_symbol3_shape, + l.line_symbol4_shape, + COALESCE(l.average_distance, 0.0)::DOUBLE PRECISION AS average_distance, + sst.id AS sst_id, + sst.type_cd, + sst.line_group_cd, + sst.pass, + t.id AS type_id, + t.type_name, + t.type_name_k, + t.type_name_r, + t.type_name_zh, + t.type_name_ko, + t.color, + t.direction, + t.kind, + s.transport_type + FROM stations AS s + JOIN lines AS l ON l.line_cd = s.line_cd AND l.e_status = 0 + JOIN station_station_types AS sst ON sst.line_group_cd IN ( {params} ) AND sst.station_cd = s.station_cd + JOIN types AS t ON t.type_cd = sst.type_cd + LEFT JOIN line_aliases AS la ON la.station_cd = s.station_cd + LEFT JOIN aliases AS a ON a.id = la.alias_cd + WHERE + s.e_status = 0 + ORDER BY CASE sst.line_group_cd {order_case} END, sst.id"# + ); + + let mut query = sqlx::query_as::<_, StationRow>(&query_str); + for id in line_group_ids { + query = query.bind(*id as i32); + } + for id in line_group_ids { + query = query.bind(*id as i32); + } + + let rows = query.fetch_all(conn).await?; + let stations: Vec = rows.into_iter().map(|row| row.into()).collect(); + + Ok(stations) + } + async fn get_route_stops( from_station_id: u32, to_station_id: u32, diff --git a/stationapi/src/presentation/controller/grpc.rs b/stationapi/src/presentation/controller/grpc.rs index 6716fc0c..846d5f86 100644 --- a/stationapi/src/presentation/controller/grpc.rs +++ b/stationapi/src/presentation/controller/grpc.rs @@ -9,7 +9,8 @@ use crate::{ station_api_server::StationApi, GetConnectedStationsRequest, GetLineByIdListRequest, GetLineByIdRequest, GetLinesByNameRequest, GetRouteRequest, GetStationByCoordinatesRequest, GetStationByGroupIdRequest, GetStationByIdListRequest, GetStationByIdRequest, - GetStationByLineIdListRequest, GetStationByLineIdRequest, GetStationsByLineGroupIdRequest, + GetStationByLineIdListRequest, GetStationByLineIdRequest, + GetStationsByLineGroupIdListRequest, GetStationsByLineGroupIdRequest, GetStationsByNameRequest, GetTrainTypesByStationIdRequest, MultipleLineResponse, MultipleStationResponse, MultipleTrainTypeResponse, Route, RouteMinimalResponse, RouteResponse, RouteTypeResponse, SingleLineResponse, SingleStationResponse, @@ -231,6 +232,26 @@ impl StationApi for MyApi { } } + async fn get_stations_by_line_group_id_list( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> { + let request_ref = request.get_ref(); + let line_group_ids = &request_ref.line_group_ids; + let transport_type = convert_transport_type(request_ref.transport_type); + + match self + .query_use_case + .get_stations_by_line_group_id_vec(line_group_ids, transport_type) + .await + { + Ok(stations) => Ok(Response::new(MultipleStationResponse { + stations: stations.into_iter().map(|station| station.into()).collect(), + })), + Err(err) => Err(PresentationalError::from(err).into()), + } + } + async fn get_train_types_by_station_id( &self, request: tonic::Request, @@ -765,6 +786,14 @@ mod tests { Ok(vec![]) } + async fn get_stations_by_line_group_id_vec( + &self, + _line_group_ids: &[u32], + _transport_type: TransportTypeFilter, + ) -> Result, UseCaseError> { + Ok(vec![]) + } + async fn get_train_types_by_station_id( &self, _station_id: u32, diff --git a/stationapi/src/use_case/interactor/query.rs b/stationapi/src/use_case/interactor/query.rs index 3f57c6bf..f3d48acc 100644 --- a/stationapi/src/use_case/interactor/query.rs +++ b/stationapi/src/use_case/interactor/query.rs @@ -389,6 +389,27 @@ where Ok(stations) } + async fn get_stations_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + transport_type: TransportTypeFilter, + ) -> Result, UseCaseError> { + let stations = self + .station_repository + .get_by_line_group_id_vec(line_group_ids) + .await?; + + let stations: Vec = stations + .into_iter() + .filter(|s| matches_transport_filter(s.transport_type, transport_type)) + .collect(); + + let stations = self + .update_station_vec_with_attributes(stations, None, transport_type) + .await?; + + Ok(stations) + } fn get_station_numbers(&self, station: &Station) -> Vec { let line_symbols_raw = [ &station.line_symbol1, @@ -1370,6 +1391,12 @@ mod tests { async fn get_by_line_group_id(&self, _: u32) -> Result, DomainError> { Ok(vec![]) } + async fn get_by_line_group_id_vec( + &self, + _: &[u32], + ) -> Result, DomainError> { + Ok(vec![]) + } async fn get_route_stops( &self, _: u32, @@ -1762,6 +1789,12 @@ mod tests { async fn get_by_line_group_id(&self, _: u32) -> Result, DomainError> { Ok(vec![]) } + async fn get_by_line_group_id_vec( + &self, + _: &[u32], + ) -> Result, DomainError> { + Ok(vec![]) + } async fn get_route_stops( &self, _: u32, diff --git a/stationapi/src/use_case/traits/query.rs b/stationapi/src/use_case/traits/query.rs index 13c313c0..d134c7d4 100644 --- a/stationapi/src/use_case/traits/query.rs +++ b/stationapi/src/use_case/traits/query.rs @@ -82,6 +82,11 @@ pub trait QueryUseCase: Send + Sync + 'static { line_group_id: u32, transport_type: TransportTypeFilter, ) -> Result, UseCaseError>; + async fn get_stations_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + transport_type: TransportTypeFilter, + ) -> Result, UseCaseError>; async fn get_train_types_by_station_id( &self, station_id: u32, From 3ed762ee69b176b42ffd944e042fb934d8491b54 Mon Sep 17 00:00:00 2001 From: Tsubasa SEKIGUCHI Date: Sun, 8 Feb 2026 05:20:23 +0000 Subject: [PATCH 2/3] submodule update --- stationapi/proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stationapi/proto b/stationapi/proto index 6f5474ca..7eede39e 160000 --- a/stationapi/proto +++ b/stationapi/proto @@ -1 +1 @@ -Subproject commit 6f5474cabcdb637bab5ce9417c578417fbb5f055 +Subproject commit 7eede39eb74fac9cde5e3ed0535cc1aff8b95580 From 05b0e7d8a8a57e93c3ab9ed22b96acac8c506adc Mon Sep 17 00:00:00 2001 From: Tsubasa SEKIGUCHI Date: Sun, 8 Feb 2026 05:26:40 +0000 Subject: [PATCH 3/3] =?UTF-8?q?Mock=E3=81=AEget=5Fby=5Fline=5Fgroup=5Fid?= =?UTF-8?q?=5Fvec=E3=81=A7None=E3=81=8C=E3=83=9E=E3=83=83=E3=83=81?= =?UTF-8?q?=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- stationapi/src/domain/repository/station_repository.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stationapi/src/domain/repository/station_repository.rs b/stationapi/src/domain/repository/station_repository.rs index 94a447a6..151c24a3 100644 --- a/stationapi/src/domain/repository/station_repository.rs +++ b/stationapi/src/domain/repository/station_repository.rs @@ -231,7 +231,10 @@ mod tests { .stations .values() .filter(|station| { - line_group_ids.contains(&(station.line_group_cd.unwrap_or(0) as u32)) + station + .line_group_cd + .map(|v| line_group_ids.contains(&(v as u32))) + .unwrap_or(false) }) .cloned() .collect();