diff --git a/client b/client index 5ad6b46..d0bd9dc 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 5ad6b46ffef55ca36f8789cd3b20a9552387f541 +Subproject commit d0bd9dce45c71ea7590a77b7b3d7d456161eae7b diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index 2d3ecd2..4306755 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -57,7 +57,7 @@ message PostTableDefinitionRequest { // Table name to create inside the target profile. // Must be lowercase, alphanumeric with underscores, // start with a letter, and be <= 63 chars. - // Forbidden names: "id", "deleted", "created_at", or ending in "_id". + // Forbidden names: "id", "deleted", "created_at", "row_revision", or ending in "_id". string table_name = 1; // List of links (foreign keys) to existing tables in the same profile. @@ -69,7 +69,7 @@ message PostTableDefinitionRequest { // List of column names to be indexed (must match existing user-defined columns). // Indexes can target only user-defined columns; system columns ("id", "deleted", - // "created_at") and automatically generated foreign key ("*_id") columns already + // "created_at", "row_revision") and automatically generated foreign key ("*_id") columns already // have indexes. Requests trying to index those columns are rejected. repeated string indexes = 4; @@ -114,7 +114,7 @@ enum MoneyRounding { message ColumnDefinition { // Column name that follows the same validation rules as table_name. // Must be lowercase, start with a letter, no uppercase characters, - // and cannot be "id", "deleted", "created_at", or end with "_id". + // and cannot be "id", "deleted", "created_at", "row_revision", or end with "_id". string name = 1; // Logical column type. Supported values (case-insensitive): diff --git a/common/proto/table_script.proto b/common/proto/table_script.proto index 6dc01ff..5713890 100644 --- a/common/proto/table_script.proto +++ b/common/proto/table_script.proto @@ -56,7 +56,7 @@ message PostTableScriptRequest { // Required. The target column in the target table that this script computes. // Must be an existing user-defined column in that table (not a system column). - // System columns are reserved: "id", "deleted", "created_at". + // System columns are reserved: "id", "deleted", "created_at", "row_revision". // The column's data type must NOT be one of the prohibited target types: // BIGINT, DATE, TIMESTAMPTZ // Note: BOOLEAN targets are allowed (values are converted to Steel #true/#false). diff --git a/common/proto/table_structure.proto b/common/proto/table_structure.proto index dd03a78..d4a4d84 100644 --- a/common/proto/table_structure.proto +++ b/common/proto/table_structure.proto @@ -45,7 +45,7 @@ message GetTableStructureResponse { // Response with the ordered list of columns (by ordinal position) for one table. message TableStructureResponse { // Columns of the physical table, including system columns (id, deleted, - // created_at), user-defined columns, and any foreign-key columns such as + // created_at, row_revision), user-defined columns, and any foreign-key columns such as // "_id". May be empty if the physical table is missing. repeated TableColumn columns = 1; } diff --git a/common/proto/tables_data.proto b/common/proto/tables_data.proto index f8a3fce..4d37972 100644 --- a/common/proto/tables_data.proto +++ b/common/proto/tables_data.proto @@ -61,7 +61,7 @@ service TablesData { // Behavior: // - Validates profile and table definition // - Returns all columns as strings (COALESCE(col::TEXT, '') AS col) - // including: id, deleted, all user-defined columns, and FK columns + // including: id, deleted, row_revision, all user-defined columns, and FK columns // named "_id" for each table link // - Fails with NOT_FOUND if record does not exist or is soft-deleted // - If the physical table is missing but the definition exists, returns INTERNAL @@ -210,6 +210,7 @@ message PutTableDataResponse { message RecomputedRow { string table_name = 1; int64 row_id = 2; + int64 row_revision = 3; } // Soft-delete a single row. diff --git a/common/src/grpc_error.rs b/common/src/grpc_error.rs index f1ffc7a..b43f69d 100644 --- a/common/src/grpc_error.rs +++ b/common/src/grpc_error.rs @@ -1,5 +1,6 @@ pub const ERROR_REASON_METADATA_KEY: &str = "komp-ac-error-reason"; -pub const EXPECTED_ROW_METADATA_KEY: &str = "komp-ac-expected-row-bin"; +pub const EXPECTED_ROW_REVISION_METADATA_KEY: &str = "komp-ac-expected-row-revision"; +pub const ROW_REVISION_METADATA_KEY: &str = "komp-ac-row-revision"; pub const COMPUTED_VALUE_MISMATCH_REASON: &str = "computed-value-mismatch"; pub const ROW_STALE_REASON: &str = "row-stale"; pub const ROW_ID_CONFLICT_REASON: &str = "row-id-conflict"; diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index fbd4fe3..0ee5c07 100644 Binary files a/common/src/proto/descriptor.bin and b/common/src/proto/descriptor.bin differ diff --git a/common/src/proto/komp_ac.table_definition.rs b/common/src/proto/komp_ac.table_definition.rs index a1b09bd..0835ab8 100644 --- a/common/src/proto/komp_ac.table_definition.rs +++ b/common/src/proto/komp_ac.table_definition.rs @@ -21,7 +21,7 @@ pub struct PostTableDefinitionRequest { /// Table name to create inside the target profile. /// Must be lowercase, alphanumeric with underscores, /// start with a letter, and be \<= 63 chars. - /// Forbidden names: "id", "deleted", "created_at", or ending in "\_id". + /// Forbidden names: "id", "deleted", "created_at", "row_revision", or ending in "\_id". #[prost(string, tag = "1")] pub table_name: ::prost::alloc::string::String, /// List of links (foreign keys) to existing tables in the same profile. @@ -33,7 +33,7 @@ pub struct PostTableDefinitionRequest { pub columns: ::prost::alloc::vec::Vec, /// List of column names to be indexed (must match existing user-defined columns). /// Indexes can target only user-defined columns; system columns ("id", "deleted", - /// "created_at") and automatically generated foreign key ("\*\_id") columns already + /// "created_at", "row_revision") and automatically generated foreign key ("\*\_id") columns already /// have indexes. Requests trying to index those columns are rejected. #[prost(string, repeated, tag = "4")] pub indexes: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, @@ -76,7 +76,7 @@ pub struct AddTableColumnsRequest { pub struct ColumnDefinition { /// Column name that follows the same validation rules as table_name. /// Must be lowercase, start with a letter, no uppercase characters, - /// and cannot be "id", "deleted", "created_at", or end with "\_id". + /// and cannot be "id", "deleted", "created_at", "row_revision", or end with "\_id". #[prost(string, tag = "1")] pub name: ::prost::alloc::string::String, /// Logical column type. Supported values (case-insensitive): diff --git a/common/src/proto/komp_ac.table_script.rs b/common/src/proto/komp_ac.table_script.rs index e7a0596..2f06491 100644 --- a/common/src/proto/komp_ac.table_script.rs +++ b/common/src/proto/komp_ac.table_script.rs @@ -10,7 +10,7 @@ pub struct PostTableScriptRequest { pub table_definition_id: i64, /// Required. The target column in the target table that this script computes. /// Must be an existing user-defined column in that table (not a system column). - /// System columns are reserved: "id", "deleted", "created_at". + /// System columns are reserved: "id", "deleted", "created_at", "row_revision". /// The column's data type must NOT be one of the prohibited target types: /// BIGINT, DATE, TIMESTAMPTZ /// Note: BOOLEAN targets are allowed (values are converted to Steel #true/#false). diff --git a/common/src/proto/komp_ac.table_structure.rs b/common/src/proto/komp_ac.table_structure.rs index de44aaf..41cdcbb 100644 --- a/common/src/proto/komp_ac.table_structure.rs +++ b/common/src/proto/komp_ac.table_structure.rs @@ -25,7 +25,7 @@ pub struct GetTableStructureResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct TableStructureResponse { /// Columns of the physical table, including system columns (id, deleted, - /// created_at), user-defined columns, and any foreign-key columns such as + /// created_at, row_revision), user-defined columns, and any foreign-key columns such as /// "\\_id". May be empty if the physical table is missing. #[prost(message, repeated, tag = "1")] pub columns: ::prost::alloc::vec::Vec, diff --git a/common/src/proto/komp_ac.tables_data.rs b/common/src/proto/komp_ac.tables_data.rs index e874947..34f764f 100644 --- a/common/src/proto/komp_ac.tables_data.rs +++ b/common/src/proto/komp_ac.tables_data.rs @@ -149,6 +149,8 @@ pub struct RecomputedRow { pub table_name: ::prost::alloc::string::String, #[prost(int64, tag = "2")] pub row_id: i64, + #[prost(int64, tag = "3")] + pub row_revision: i64, } /// Soft-delete a single row. #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] @@ -482,7 +484,7 @@ pub mod tables_data_client { /// /// * Validates profile and table definition /// * Returns all columns as strings (COALESCE(col::TEXT, '') AS col) - /// including: id, deleted, all user-defined columns, and FK columns + /// including: id, deleted, row_revision, all user-defined columns, and FK columns /// named "\\_id" for each table link /// * Fails with NOT_FOUND if record does not exist or is soft-deleted /// * If the physical table is missing but the definition exists, returns INTERNAL @@ -674,7 +676,7 @@ pub mod tables_data_server { /// /// * Validates profile and table definition /// * Returns all columns as strings (COALESCE(col::TEXT, '') AS col) - /// including: id, deleted, all user-defined columns, and FK columns + /// including: id, deleted, row_revision, all user-defined columns, and FK columns /// named "\\_id" for each table link /// * Fails with NOT_FOUND if record does not exist or is soft-deleted /// * If the physical table is missing but the definition exists, returns INTERNAL diff --git a/server b/server index c5a374a..3fef1db 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit c5a374ac1a58b6a8b366b59012ff79d31364e308 +Subproject commit 3fef1dbed56512f336626b10979efa6f7d97ab11