From 59a21845927984b2a98264f6377ee0d36f312254 Mon Sep 17 00:00:00 2001 From: filipriec Date: Wed, 5 Mar 2025 10:10:20 +0100 Subject: [PATCH] working get count endpoint --- common/proto/tables_data.proto | 7 ++ common/src/proto/descriptor.bin | Bin 16856 -> 17242 bytes common/src/proto/multieko2.tables_data.rs | 89 ++++++++++++++++++ .../server/services/tables_data_service.rs | 13 ++- .../src/tables_data/docs/get_data_count.txt | 5 + server/src/tables_data/handlers.rs | 2 + .../handlers/get_table_data_count.rs | 61 ++++++++++++ 7 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 server/src/tables_data/docs/get_data_count.txt create mode 100644 server/src/tables_data/handlers/get_table_data_count.rs diff --git a/common/proto/tables_data.proto b/common/proto/tables_data.proto index ae314aa..2cfb0b7 100644 --- a/common/proto/tables_data.proto +++ b/common/proto/tables_data.proto @@ -9,6 +9,8 @@ service TablesData { rpc PutTableData (PutTableDataRequest) returns (PutTableDataResponse); rpc DeleteTableData (DeleteTableDataRequest) returns (DeleteTableDataResponse); rpc GetTableData(GetTableDataRequest) returns (GetTableDataResponse); + rpc GetTableDataCount(GetTableDataCountRequest) returns (multieko2.common.CountResponse); + } message PostTableDataRequest { @@ -55,3 +57,8 @@ message GetTableDataRequest { message GetTableDataResponse { map data = 1; } + +message GetTableDataCountRequest { + string profile_name = 1; + string table_name = 2; +} diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 2bcaa002d23a258e5a8d60d00a89d2e9173df634..d99a613a7120e37ac9c952d644d9b2c040313fb6 100644 GIT binary patch delta 1678 zcmZXU&uSA<6vpq|xtZKf+9tVaW~S{VsZAqITAI=%(wHV)D2U=p1QFe|keyinr0ZD- z?n_=k&<7B@)kknIg5cU$5W(-D{y0*`15am$Uh|{rm3GM|FKQ{NjXW>X-jZG2QuxK{#I-EiYTiqv`9* z>D$@-SN?|o;OnaI8Rdx6`IFH@XJ!6r^gAi|$`euU~!>=Fm6e1kc1#dq%%TdX{nk~f_kNBopp$nWyCQDy7EHj zP;9A^#ULvOAYA1E7zAlT_F95PSy9Ys5*M1g*tiH0!E&&bfETJ2b(#6smJUb9{4PF|EQh8~v zQQP8X+BIcu^U1l?b(41nfQ=^a41~lc?+k=;P2QO+6U27-Vb^xO!(D?Y#!CZ1x05bS zxzu$_+P??^o@;T}Ajn$U*sej4wW@*LnKEiu?5FPOPqwS;i5-U``)ytt0QK5z1BA>r zFAaoxZQhxpr#ied0A!tojNEs4XNW=8;hkaL#@&+vIZPA?x;?fJf^JWjt$o@IXsv4P z=ZrcKhpGJ>vJP~^y3djOE)O4oa$O!i2#H-DJ_zNy7(QJvK1D|&xs}%Qkaol;>`}cQ zPXmB@J#Gtx#2!xrgnB)mhDXl(JPiP3{e_IC(dTI(23g-u1O0n6jsc%A0J;HB0|ecG zPZ$K<04GfL^F|$u+o}6JvX1!_^W=WWpCbS+d&ma{LgJ7w8|0eA9r9^wqfW$WT2CYG zL~q&YYN|I@v0VrN_QopxPl1p)E~Iw|g1zxZ`W?{Ze4^4X9{{q+LPpb=6zCgS$teV( Pn?&p9-m5nkvy0w8s4s8w delta 1412 zcmX|>O>PrG5QV3!+v9Nu|D^4i#J`Dc6x%39u^q)h$_WrlPQZ>;5Mn<_NbFHAf|P9z zg5U;hH~>Q8)yx|&KUKXqudB-b`PKaRV!r>qmS6qHf7jof-9FjJKd+vQfBm`X-nz&H+e}9O$U7HF6l_Zd{+X{S)RdBn(Aa9E6|l{tbLFftu?w;Er+h1olqyicI1pTiIu7k2y~sSiXxD8#uFqKXM*cSCuMqd z?G03aJ4WSV}+;iCpwKIHI45Pu}?A}|2D5#xiP8zsJ~K{sl)m=ZAN&O|JBHsBUu}z5&y!Hqpqr;zadIxWi|9qUGu)rONG8QJoTguJ zX8_nO7z2dH1$PF5-Qu*LQ-|7;OLIm1faC2ElJXp1g}c Ke7yg3zxxl~sY^!y diff --git a/common/src/proto/multieko2.tables_data.rs b/common/src/proto/multieko2.tables_data.rs index 8dc41ac..38a5ce4 100644 --- a/common/src/proto/multieko2.tables_data.rs +++ b/common/src/proto/multieko2.tables_data.rs @@ -74,6 +74,13 @@ pub struct GetTableDataResponse { ::prost::alloc::string::String, >, } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTableDataCountRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub table_name: ::prost::alloc::string::String, +} /// Generated client implementations. pub mod tables_data_client { #![allow( @@ -272,6 +279,35 @@ pub mod tables_data_client { ); self.inner.unary(req, path, codec).await } + pub async fn get_table_data_count( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/multieko2.tables_data.TablesData/GetTableDataCount", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "multieko2.tables_data.TablesData", + "GetTableDataCount", + ), + ); + self.inner.unary(req, path, codec).await + } } } /// Generated server implementations. @@ -315,6 +351,13 @@ pub mod tables_data_server { tonic::Response, tonic::Status, >; + async fn get_table_data_count( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; } #[derive(Debug)] pub struct TablesDataServer { @@ -572,6 +615,52 @@ pub mod tables_data_server { }; Box::pin(fut) } + "/multieko2.tables_data.TablesData/GetTableDataCount" => { + #[allow(non_camel_case_types)] + struct GetTableDataCountSvc(pub Arc); + impl< + T: TablesData, + > tonic::server::UnaryService + for GetTableDataCountSvc { + type Response = super::super::common::CountResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_table_data_count(&inner, request) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetTableDataCountSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => { Box::pin(async move { let mut response = http::Response::new(empty_body()); diff --git a/server/src/server/services/tables_data_service.rs b/server/src/server/services/tables_data_service.rs index d631867..c3a93ea 100644 --- a/server/src/server/services/tables_data_service.rs +++ b/server/src/server/services/tables_data_service.rs @@ -1,13 +1,15 @@ // src/server/services/tables_data_service.rs use tonic::{Request, Response, Status}; use common::proto::multieko2::tables_data::tables_data_server::TablesData; +use common::proto::multieko2::common::CountResponse; use common::proto::multieko2::tables_data::{ PostTableDataRequest, PostTableDataResponse, PutTableDataRequest, PutTableDataResponse, DeleteTableDataRequest, DeleteTableDataResponse, GetTableDataRequest, GetTableDataResponse, + GetTableDataCountRequest, }; -use crate::tables_data::handlers::{post_table_data, put_table_data, delete_table_data, get_table_data,}; +use crate::tables_data::handlers::{post_table_data, put_table_data, delete_table_data, get_table_data, get_table_data_count}; use sqlx::PgPool; #[derive(Debug)] @@ -53,4 +55,13 @@ impl TablesData for TablesDataService { let response = get_table_data(&self.db_pool, request).await?; Ok(Response::new(response)) } + + async fn get_table_data_count( + &self, + request: Request, + ) -> Result, Status> { + let request = request.into_inner(); + let response = get_table_data_count(&self.db_pool, request).await?; + Ok(Response::new(response)) + } } diff --git a/server/src/tables_data/docs/get_data_count.txt b/server/src/tables_data/docs/get_data_count.txt new file mode 100644 index 0000000..aee7b1d --- /dev/null +++ b/server/src/tables_data/docs/get_data_count.txt @@ -0,0 +1,5 @@ +grpcurl -plaintext -d '{"profile_name": "default", "table_name": "2025_adresar"}' localhost:50051 multieko2.tables_data.TablesData/GetTableDataCount + +{ + "count": "1" +} diff --git a/server/src/tables_data/handlers.rs b/server/src/tables_data/handlers.rs index c3d6385..6237ec3 100644 --- a/server/src/tables_data/handlers.rs +++ b/server/src/tables_data/handlers.rs @@ -3,8 +3,10 @@ pub mod post_table_data; pub mod put_table_data; pub mod delete_table_data; pub mod get_table_data; +pub mod get_table_data_count; pub use post_table_data::post_table_data; pub use put_table_data::put_table_data; pub use delete_table_data::delete_table_data; pub use get_table_data::get_table_data; +pub use get_table_data_count::get_table_data_count; diff --git a/server/src/tables_data/handlers/get_table_data_count.rs b/server/src/tables_data/handlers/get_table_data_count.rs new file mode 100644 index 0000000..d4f729d --- /dev/null +++ b/server/src/tables_data/handlers/get_table_data_count.rs @@ -0,0 +1,61 @@ +// src/tables_data/handlers/get_table_data_count.rs +use tonic::Status; +use sqlx::PgPool; +use common::proto::multieko2::common::{CountResponse, Empty}; +use common::proto::multieko2::tables_data::GetTableDataCountRequest; + +pub async fn get_table_data_count( + db_pool: &PgPool, + request: GetTableDataCountRequest, +) -> Result { + let profile_name = request.profile_name; + let table_name = request.table_name; + + // Lookup profile + let profile = sqlx::query!( + "SELECT id FROM profiles WHERE name = $1", + profile_name + ) + .fetch_optional(db_pool) + .await + .map_err(|e| Status::internal(format!("Profile lookup error: {}", e)))?; + + let profile_id = profile.ok_or_else(|| Status::not_found("Profile not found"))?.id; + + // Verify table exists and belongs to profile + let table_exists = sqlx::query!( + r#"SELECT EXISTS( + SELECT 1 FROM table_definitions + WHERE profile_id = $1 AND table_name = $2 + )"#, + profile_id, + table_name + ) + .fetch_one(db_pool) + .await + .map_err(|e| Status::internal(format!("Table verification error: {}", e)))? + .exists + .unwrap_or(false); + + if !table_exists { + return Err(Status::not_found("Table not found")); + } + + // Get count of non-deleted records + let query = format!( + r#" + SELECT COUNT(*) AS count + FROM "{}" + WHERE deleted = FALSE + "#, + table_name + ); + + let count: i64 = sqlx::query_scalar::<_, Option>(&query) + .fetch_one(db_pool) + .await + .map_err(|e| Status::internal(format!("Count query failed: {}", e)))? + .unwrap_or(0); + + Ok(CountResponse { count }) +}