From 070defe72b1ac4e2e721cafa351afd47656e7f85 Mon Sep 17 00:00:00 2001 From: Filipriec Date: Thu, 27 Aug 2026 22:44:44 +0200 Subject: [PATCH] we get dynamic position of the data for billions of rows of data now --- .gitignore | 1 + client | 2 +- common/proto/tables_data.proto | 37 ++++++++++- common/src/proto/descriptor.bin | Bin 194456 -> 196843 bytes common/src/proto/komp_ac.tables_data.rs | 68 +++++++++++++++++++- server | 2 +- web/src/pages/import_export/export/logic.rs | 6 +- 7 files changed, 109 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index e9e86ec1..28eb681b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ mutants*/ testing/ run_bins/ result +corporate_erp/ diff --git a/client b/client index 74ebcab6..bcd298b3 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 74ebcab618be649ce9ceb2c7fb2e56fbc891428c +Subproject commit bcd298b3f1a9930e71f3c65caa3fa4a1361737f5 diff --git a/common/proto/tables_data.proto b/common/proto/tables_data.proto index edad66df..a71f3881 100644 --- a/common/proto/tables_data.proto +++ b/common/proto/tables_data.proto @@ -418,6 +418,10 @@ message GetTableDataResponse { // Active journal containing this row's automatic accounting line, when the // table is ACCOUNTING-enabled and the row has been posted. optional int64 journal_id = 6; + + // Present when the row was loaded through a form-navigation RPC. The row and + // its numbering bounds come from the same server operation. + RowNavigation navigation = 7; } // Count non-deleted rows. @@ -433,13 +437,34 @@ message GetTableDataCountRequest { message GetLastTableDataRequest { string profile_name = 1; string table_name = 2; + RowNavigationMode navigation_mode = 3; +} + +// Controls how an unfiltered form numbers rows. +enum RowNavigationMode { + // Actual database row id / highest visible row id. Deleted ids leave gaps. + ROW_NAVIGATION_MODE_ID = 0; + // Ordinal position / exact visible-row count. Deleted rows are omitted. + ROW_NAVIGATION_MODE_POSITION = 1; +} + +// Complete numbering state returned with a navigated row. +message RowNavigation { + RowNavigationMode mode = 1; + // Actual row id in ID mode; 1-based ordinal in POSITION mode. For an empty + // table this is the first new-row slot (1). + uint64 current = 2; + // Highest visible id in ID mode; exact visible-row count in POSITION mode. + uint64 total = 3; } message GetLastTableDataResponse { - // Zero when the table has no visible rows. + // Zero when the table has no visible rows. Retained as row identity; clients + // should use navigation for display bounds. int64 last_id = 1; // Absent when last_id is zero. GetTableDataResponse row = 2; + RowNavigation navigation = 3; } enum RowIdDirection { @@ -452,11 +477,15 @@ message GetAdjacentTableDataRequest { string table_name = 2; int64 anchor_id = 3; RowIdDirection direction = 4; + RowNavigationMode navigation_mode = 5; + // Current ordinal position when navigation_mode is POSITION. Ignored in ID mode. + uint64 anchor_position = 6; } message GetAdjacentTableDataResponse { // Absent when no visible row exists in the requested direction. GetTableDataResponse row = 1; + RowNavigation navigation = 2; } // Fetch by ordinal position among non-deleted rows (1-based). @@ -467,6 +496,10 @@ message GetTableDataByPositionRequest { // Required. Table name within the profile. string table_name = 2; - // Required. 1-based position by id ascending among rows with deleted = FALSE. + // Set this or record_id, never both. This is the 1-based position by id + // ascending among rows with deleted = FALSE. int32 position = 3; + // Direct row lookup that also returns its ID or ordinal navigation bounds. + int64 record_id = 4; + RowNavigationMode navigation_mode = 5; } diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index bdf7cb640342622a010a9486e7f075adc4d55e91..e408177920e0ceb95d69ef942e0ca6fff5493a36 100644 GIT binary patch delta 3604 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 chJ~8v>t8RBs*X^#Bf1E_d?f?J) diff --git a/common/src/proto/komp_ac.tables_data.rs b/common/src/proto/komp_ac.tables_data.rs index d259b25c..cc3e2b70 100644 --- a/common/src/proto/komp_ac.tables_data.rs +++ b/common/src/proto/komp_ac.tables_data.rs @@ -376,6 +376,10 @@ pub struct GetTableDataResponse { /// table is ACCOUNTING-enabled and the row has been posted. #[prost(int64, optional, tag = "6")] pub journal_id: ::core::option::Option, + /// Present when the row was loaded through a form-navigation RPC. The row and + /// its numbering bounds come from the same server operation. + #[prost(message, optional, tag = "7")] + pub navigation: ::core::option::Option, } /// Count non-deleted rows. #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] @@ -394,15 +398,33 @@ pub struct GetLastTableDataRequest { pub profile_name: ::prost::alloc::string::String, #[prost(string, tag = "2")] pub table_name: ::prost::alloc::string::String, + #[prost(enumeration = "RowNavigationMode", tag = "3")] + pub navigation_mode: i32, +} +/// Complete numbering state returned with a navigated row. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RowNavigation { + #[prost(enumeration = "RowNavigationMode", tag = "1")] + pub mode: i32, + /// Actual row id in ID mode; 1-based ordinal in POSITION mode. For an empty + /// table this is the first new-row slot (1). + #[prost(uint64, tag = "2")] + pub current: u64, + /// Highest visible id in ID mode; exact visible-row count in POSITION mode. + #[prost(uint64, tag = "3")] + pub total: u64, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetLastTableDataResponse { - /// Zero when the table has no visible rows. + /// Zero when the table has no visible rows. Retained as row identity; clients + /// should use navigation for display bounds. #[prost(int64, tag = "1")] pub last_id: i64, /// Absent when last_id is zero. #[prost(message, optional, tag = "2")] pub row: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub navigation: ::core::option::Option, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct GetAdjacentTableDataRequest { @@ -414,12 +436,19 @@ pub struct GetAdjacentTableDataRequest { pub anchor_id: i64, #[prost(enumeration = "RowIdDirection", tag = "4")] pub direction: i32, + #[prost(enumeration = "RowNavigationMode", tag = "5")] + pub navigation_mode: i32, + /// Current ordinal position when navigation_mode is POSITION. Ignored in ID mode. + #[prost(uint64, tag = "6")] + pub anchor_position: u64, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetAdjacentTableDataResponse { /// Absent when no visible row exists in the requested direction. #[prost(message, optional, tag = "1")] pub row: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub navigation: ::core::option::Option, } /// Fetch by ordinal position among non-deleted rows (1-based). #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] @@ -430,9 +459,15 @@ pub struct GetTableDataByPositionRequest { /// Required. Table name within the profile. #[prost(string, tag = "2")] pub table_name: ::prost::alloc::string::String, - /// Required. 1-based position by id ascending among rows with deleted = FALSE. + /// Set this or record_id, never both. This is the 1-based position by id + /// ascending among rows with deleted = FALSE. #[prost(int32, tag = "3")] pub position: i32, + /// Direct row lookup that also returns its ID or ordinal navigation bounds. + #[prost(int64, tag = "4")] + pub record_id: i64, + #[prost(enumeration = "RowNavigationMode", tag = "5")] + pub navigation_mode: i32, } /// A link resolved exactly as the source row stored it, together with the /// target row's current state. The physical companion version column remains @@ -474,6 +509,35 @@ impl ResolvedTableLinkStatus { } } } +/// Controls how an unfiltered form numbers rows. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum RowNavigationMode { + /// Actual database row id / highest visible row id. Deleted ids leave gaps. + Id = 0, + /// Ordinal position / exact visible-row count. Deleted rows are omitted. + Position = 1, +} +impl RowNavigationMode { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Id => "ROW_NAVIGATION_MODE_ID", + Self::Position => "ROW_NAVIGATION_MODE_POSITION", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ROW_NAVIGATION_MODE_ID" => Some(Self::Id), + "ROW_NAVIGATION_MODE_POSITION" => Some(Self::Position), + _ => None, + } + } +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum RowIdDirection { diff --git a/server b/server index 32cab246..c958eb0f 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit 32cab246fa68c29eae7759bdde7cfd567b24c6f5 +Subproject commit c958eb0f17080b86c97d487974ecba46467eaa71 diff --git a/web/src/pages/import_export/export/logic.rs b/web/src/pages/import_export/export/logic.rs index c39f65df..f864857e 100644 --- a/web/src/pages/import_export/export/logic.rs +++ b/web/src/pages/import_export/export/logic.rs @@ -11,7 +11,9 @@ use crate::{ AppState, definitions::{ table_structure::GetTableStructureRequest, - tables_data::{GetTableDataByPositionRequest, GetTableDataCountRequest}, + tables_data::{ + GetTableDataByPositionRequest, GetTableDataCountRequest, RowNavigationMode, + }, }, {i18n::Locale, tr}, services::{authenticated_request, reject_cross_site}, @@ -156,6 +158,8 @@ pub(crate) async fn export_csv( profile_name: profile_name.clone(), table_name: table.name.clone(), position: position as i32, + record_id: 0, + navigation_mode: RowNavigationMode::Position as i32, }; let mut data = state.tables_data.clone(); let response = match data.get_table_data_by_position(match authenticated_request(&headers, request) {