table structure docs are made
This commit is contained in:
@@ -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 script’s 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 script’s 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 script’s result (type-aware).
|
||||
// - If X is not included here but the update would cause the script’s 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user