table structure docs are made

This commit is contained in:
Priec
2025-10-26 22:02:44 +01:00
parent bb75b70341
commit 339d06ce7e
12 changed files with 855 additions and 54 deletions

View File

@@ -5,67 +5,220 @@ package komp_ac.tables_data;
import "common.proto";
import "google/protobuf/struct.proto";
// Read and write row data for user-defined tables inside profiles (schemas).
// Operations are performed against the physical PostgreSQL table that
// corresponds to the logical table definition and are scoped by profile
// (schema). Deletions are soft (set deleted = true). Typed binding and
// script-based validation are enforced consistently.
service TablesData {
rpc PostTableData (PostTableDataRequest) returns (PostTableDataResponse);
rpc PutTableData (PutTableDataRequest) returns (PutTableDataResponse);
rpc DeleteTableData (DeleteTableDataRequest) returns (DeleteTableDataResponse);
// Insert a new row into a table with strict type binding and script validation.
//
// Behavior:
// - Validates that profile (schema) exists and table is defined for it
// - Validates provided columns exist (user-defined or allowed system/FK columns)
// - For columns targeted by scripts in this table, the client MUST provide the
// value, and it MUST equal the scripts calculated value (compared type-safely)
// - Binds values with correct SQL types, rejects invalid formats/ranges
// - Inserts the row and returns the new id; queues search indexing (best effort)
// - If the physical table is missing but the definition exists, returns INTERNAL
rpc PostTableData(PostTableDataRequest) returns (PostTableDataResponse);
// Update existing row data with strict type binding and script validation.
//
// Behavior:
// - Validates profile and table, and that the record exists
// - If request data is empty, returns success without changing the row
// - For columns targeted by scripts:
// • If included in update, provided value must equal the script result
// • If not included, update must not cause the script result to differ
// from the current stored value; otherwise FAILED_PRECONDITION is returned
// - Binds values with correct SQL types; rejects invalid formats/ranges
// - Updates the row and returns the id; queues search indexing (best effort)
rpc PutTableData(PutTableDataRequest) returns (PutTableDataResponse);
// Soft-delete a single record (sets deleted = true) if it exists and is not already deleted.
//
// Behavior:
// - Validates profile and table definition
// - Updates only rows with deleted = false
// - success = true means a row was actually changed; false means nothing to delete
// - If the physical table is missing but the definition exists, returns INTERNAL
rpc DeleteTableData(DeleteTableDataRequest) returns (DeleteTableDataResponse);
// Fetch a single non-deleted row by id as textified values.
//
// 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
// named "<linked_table>_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
rpc GetTableData(GetTableDataRequest) returns (GetTableDataResponse);
// Count non-deleted rows in a table.
//
// Behavior:
// - Validates profile and table definition
// - Returns komp_ac.common.CountResponse.count with rows where deleted = FALSE
// - If the physical table is missing but the definition exists, returns INTERNAL
rpc GetTableDataCount(GetTableDataCountRequest) returns (komp_ac.common.CountResponse);
// Fetch the N-th non-deleted row by id order (1-based), then return its full data.
//
// Behavior:
// - position is 1-based (position = 1 → first row by id ASC with deleted = FALSE)
// - Returns NOT_FOUND if position is out of bounds
// - Otherwise identical to GetTableData for the selected id
rpc GetTableDataByPosition(GetTableDataByPositionRequest) returns (GetTableDataResponse);
}
// Insert a new row.
message PostTableDataRequest {
// Required. Profile (PostgreSQL schema) name that owns the table.
// Must exist in the schemas table.
string profile_name = 1;
// Required. Logical table (definition) name within the profile.
// Must exist in table_definitions for the given profile.
string table_name = 2;
// Required. Key-value data for columns to insert.
//
// Allowed keys:
// - User-defined columns from the table definition
// - System/FK columns:
// • "deleted" (BOOLEAN), optional; default FALSE if not provided
// • "<linked_table>_id" (BIGINT) for each table link
//
// Type expectations by SQL type:
// - TEXT: string value; empty string is treated as NULL
// - BOOLEAN: bool value
// - TIMESTAMPTZ: ISO 8601/RFC 3339 string (parsed to TIMESTAMPTZ)
// - INTEGER: number with no fractional part and within i32 range
// - BIGINT: number with no fractional part and within i64 range
// - NUMERIC(p,s): string representation only; empty string becomes NULL
// (numbers for NUMERIC are rejected to avoid precision loss)
//
// Script validation rules:
// - If a script exists for a target column, that column MUST be present here,
// and its provided value MUST equal the scripts computed value (type-aware
// comparison, e.g., decimals are compared numerically).
//
// Notes:
// - Unknown/invalid column names are rejected
// - Some application-specific validations may apply (e.g., max length for
// certain fields like "telefon")
map<string, google.protobuf.Value> data = 3;
}
// Insert response.
message PostTableDataResponse {
// True if the insert succeeded.
bool success = 1;
// Human-readable message.
string message = 2;
// The id of the inserted row.
int64 inserted_id = 3;
}
// Update an existing row.
message PutTableDataRequest {
// Required. Profile (schema) name.
string profile_name = 1;
// Required. Table name within the profile.
string table_name = 2;
// Required. Id of the row to update.
int64 id = 3;
// Required. Columns to update (same typing rules as PostTableDataRequest.data).
//
// Special script rules:
// - If a script targets column X and X is included here, the value for X must
// equal the scripts result (type-aware).
// - If X is not included here but the update would cause the scripts result
// to change compared to the current stored value, the update is rejected with
// FAILED_PRECONDITION, instructing the caller to include X explicitly.
//
// Passing an empty map results in a no-op success response.
map<string, google.protobuf.Value> data = 4;
}
// Update response.
message PutTableDataResponse {
// True if the update succeeded (or no-op on empty data).
bool success = 1;
// Human-readable message.
string message = 2;
// The id of the updated row.
int64 updated_id = 3;
}
// Soft-delete a single row.
message DeleteTableDataRequest {
// Required. Profile (schema) name.
string profile_name = 1;
// Required. Table name within the profile.
string table_name = 2;
// Required. Row id to soft-delete.
int64 record_id = 3;
}
// Soft-delete response.
message DeleteTableDataResponse {
// True if a row was marked deleted (id existed and was not already deleted).
bool success = 1;
}
// Fetch a single non-deleted row by id.
message GetTableDataRequest {
// Required. Profile (schema) name.
string profile_name = 1;
// Required. Table name within the profile.
string table_name = 2;
// Required. Id of the row to fetch.
int64 id = 3;
}
// Row payload: all columns returned as strings.
message GetTableDataResponse {
// Map of column_name → stringified value for:
// - id, deleted
// - all user-defined columns from the table definition
// - FK columns named "<linked_table>_id" for each table link
//
// All values are returned as TEXT via col::TEXT and COALESCEed to empty string
// (NULL becomes ""). The row is returned only if deleted = FALSE.
map<string, string> data = 1;
}
// Count non-deleted rows.
message GetTableDataCountRequest {
string profile_name = 1;
string table_name = 2;
// Required. Profile (schema) name.
string profile_name = 1;
// Required. Table name within the profile.
string table_name = 2;
}
// Fetch by ordinal position among non-deleted rows (1-based).
message GetTableDataByPositionRequest {
// Required. Profile (schema) name.
string profile_name = 1;
// Required. Table name within the profile.
string table_name = 2;
// Required. 1-based position by id ascending among rows with deleted = FALSE.
int32 position = 3;
}