optimization on the client steel scripts + fixed proto comments

This commit is contained in:
Priec
2026-07-17 22:46:57 +02:00
parent c1c77ad378
commit d5bce6378a
12 changed files with 253 additions and 51 deletions

Binary file not shown.

View File

@@ -55,7 +55,7 @@ pub struct ExecuteAnalyticsQueryRequest {
/// Exactly one read-only SELECT query. Table and column names are public aliases.
#[prost(string, tag = "2")]
pub sql: ::prost::alloc::string::String,
/// Optional result cap. Zero uses the server default; the server maximum still applies.
/// Result cap. Zero uses the server default; the server maximum still applies.
#[prost(uint32, tag = "3")]
pub max_rows: u32,
}

View File

@@ -7,7 +7,7 @@ pub struct Search2Request {
pub table_name: ::prost::alloc::string::String,
#[prost(message, repeated, tag = "3")]
pub column_filters: ::prost::alloc::vec::Vec<ColumnFilter>,
/// Optional fallback text search
/// Fallback text search
#[prost(string, optional, tag = "4")]
pub text_query: ::core::option::Option<::prost::alloc::string::String>,
#[prost(int32, optional, tag = "5")]

View File

@@ -193,7 +193,7 @@ pub struct CopyProfileResponse {
pub struct GetColumnAliasRenameHistoryRequest {
#[prost(string, tag = "1")]
pub profile_name: ::prost::alloc::string::String,
/// Optional filter. When omitted, returns all tables in the profile.
/// Filter. When omitted, returns all tables in the profile.
#[prost(int64, optional, tag = "2")]
pub table_definition_id: ::core::option::Option<i64>,
}

View File

@@ -33,8 +33,10 @@ pub struct PostTableScriptRequest {
/// @sum(table.column), @min(table.column), @max(table.column),
/// @count(table.column), @count_distinct(table.column),
/// @any(table.boolean), @all(table.boolean),
/// @count_rows(table), @exists(table)
/// The related table must be a direct child or share exactly one parent.
/// @count_rows(table via anchor), @exists(table via anchor)
/// Every related aggregate requires the `via anchor` clause. The related
/// table must be reachable through that anchor by an unambiguous FK path;
/// the path may span multiple FK hops.
/// * Raw SQL access is not supported; steel_query_sql is rejected
///
/// Math operations:
@@ -82,74 +84,135 @@ pub struct GetTableScriptsRequest {
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetTableScriptsResponse {
/// Scripts and dependency allowlists used to configure the client Steel runtime.
#[prost(message, repeated, tag = "1")]
pub scripts: ::prost::alloc::vec::Vec<StoredTableScript>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct StoredTableScript {
/// Persistent script identifier.
#[prost(int64, tag = "1")]
pub id: i64,
/// Display-name key of the current-table field populated by this script.
#[prost(string, tag = "2")]
pub target_column: ::prost::alloc::string::String,
/// Logical type used by the client to validate and convert the result.
#[prost(string, tag = "3")]
pub target_column_type: ::prost::alloc::string::String,
/// Validated and transformed Steel expression executed by the client for
/// immediate feedback and by the server for authoritative persistence.
#[prost(string, tag = "4")]
pub script: ::prost::alloc::string::String,
#[prost(string, tag = "5")]
pub description: ::prost::alloc::string::String,
/// Complete allowlist of data inputs that may be exposed to this script.
#[prost(message, repeated, tag = "6")]
pub dependencies: ::prost::alloc::vec::Vec<ScriptDependency>,
/// Whether changes to dependency rows trigger authoritative server propagation.
#[prost(bool, tag = "7")]
pub recompute_on_dependency_change: bool,
}
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ScriptDependency {
/// Logical table name referenced by the script.
#[prost(string, tag = "1")]
pub target_table: ::prost::alloc::string::String,
/// Normalized dependency kind, such as column_access or related_aggregate.
#[prost(string, tag = "2")]
pub dependency_type: ::prost::alloc::string::String,
/// Logical column name. Empty for aggregates that operate on rows only.
#[prost(string, tag = "3")]
pub column: ::prost::alloc::string::String,
/// Deprecated legacy field. Raw SQL dependencies are no longer produced.
#[prost(string, tag = "4")]
pub query_fragment: ::prost::alloc::string::String,
/// Aggregate operation name, such as sum, count_rows, or exists; empty for
/// column_access dependencies.
#[prost(string, tag = "5")]
pub operation: ::prost::alloc::string::String,
/// Relationship table used to match the owner row to the related collection.
#[prost(string, tag = "6")]
pub via_table: ::prost::alloc::string::String,
}
/// Identifies the active form row whose external Steel inputs must be hydrated.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetScriptDependencyValuesRequest {
pub struct HydrateScriptDependenciesRequest {
/// Required profile/database schema containing the scripted table.
#[prost(string, tag = "1")]
pub profile_name: ::prost::alloc::string::String,
/// Required logical name of the table owning the scripts.
#[prost(string, tag = "2")]
pub table_name: ::prost::alloc::string::String,
/// Persisted owner-row ID, or zero for a new unsaved row.
#[prost(int64, tag = "3")]
pub row_id: i64,
/// Complete current client form snapshot keyed by logical column name.
/// It contains unsaved current-table values and related foreign keys such as
/// "customer_id". The server uses it to resolve related rows and new-row
/// aggregate semantics; it is not an arbitrary dependency request.
#[prost(map = "string, string", tag = "4")]
pub row_data: ::std::collections::HashMap<
::prost::alloc::string::String,
::prost::alloc::string::String,
>,
}
/// One declared cross-table column input for the client Steel context.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct ScriptDependencyValue {
pub struct HydratedColumnValue {
/// Logical related-table name used by steel_get_column.
#[prost(string, tag = "1")]
pub operation: ::prost::alloc::string::String,
#[prost(string, tag = "2")]
pub target_table: ::prost::alloc::string::String,
/// Related row from which the value was loaded.
#[prost(int64, tag = "2")]
pub row_id: i64,
/// Logical column name used by steel_get_column.
#[prost(string, tag = "3")]
pub column: ::prost::alloc::string::String,
/// String-encoded database value. An empty string represents NULL/empty input.
#[prost(string, tag = "4")]
pub value: ::prost::alloc::string::String,
/// Logical database type used to create a typed client ScriptValue.
#[prost(string, tag = "5")]
pub field_type: ::prost::alloc::string::String,
/// Related table's base currency for MONEY values; otherwise empty.
#[prost(string, tag = "6")]
pub base_currency: ::prost::alloc::string::String,
}
/// One declared related-collection aggregate input for the client Steel context.
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
pub struct HydratedAggregateValue {
/// Normalized aggregate operation: sum, min, max, count, count_distinct,
/// any, all, count_rows, or exists.
#[prost(string, tag = "1")]
pub operation: ::prost::alloc::string::String,
/// Logical table whose related rows were aggregated.
#[prost(string, tag = "2")]
pub target_table: ::prost::alloc::string::String,
/// Logical aggregated column; empty for count_rows and exists.
#[prost(string, tag = "3")]
pub column: ::prost::alloc::string::String,
/// Relationship anchor used to distinguish aggregate dependency paths.
#[prost(string, tag = "4")]
pub via_table: ::prost::alloc::string::String,
/// String-encoded aggregate result.
#[prost(string, tag = "5")]
pub value: ::prost::alloc::string::String,
/// Logical source-column type; empty for row-only aggregates.
#[prost(string, tag = "6")]
pub field_type: ::prost::alloc::string::String,
/// Aggregate table's base currency for MONEY values; otherwise empty.
#[prost(string, tag = "7")]
pub base_currency: ::prost::alloc::string::String,
}
/// Complete external dependency snapshot for client-side Steel execution.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetScriptDependencyValuesResponse {
pub struct HydrateScriptDependenciesResponse {
/// Exact related-column inputs declared by stored scripts.
#[prost(message, repeated, tag = "1")]
pub values: ::prost::alloc::vec::Vec<ScriptDependencyValue>,
pub columns: ::prost::alloc::vec::Vec<HydratedColumnValue>,
/// Exact related aggregate inputs declared by stored scripts.
#[prost(message, repeated, tag = "2")]
pub aggregates: ::prost::alloc::vec::Vec<HydratedAggregateValue>,
}
/// Generated client implementations.
pub mod table_script_client {
@@ -162,7 +225,8 @@ pub mod table_script_client {
)]
use tonic::codegen::*;
use tonic::codegen::http::Uri;
/// Manages column-computation scripts for user-defined tables.
/// Manages column-computation scripts for user-defined tables and supplies the
/// dependency data used by the client-side Steel runtime.
/// Each script belongs to a single table (table_definition_id) and populates
/// exactly one target column in that table. The server:
///
@@ -174,7 +238,16 @@ pub mod table_script_client {
/// * Analyzes dependencies and prevents cycles across the schema
/// * Transforms the script to decimal-safe math (steel_decimal)
/// * Upserts into table_scripts and records dependencies in script_dependencies
/// The whole operation is transactional.
/// * Hydrates external column and aggregate inputs requested by the client
///
/// The client fetches stored scripts and their declared dependencies, builds a
/// restricted Steel context, and executes scripts for immediate form feedback.
/// Current-table values come from the client's active row snapshot. External
/// values must come from HydrateScriptDependencies; the client must not query
/// arbitrary database data from inside the Steel VM.
///
/// Server-side persistence remains authoritative and recalculates affected rows.
/// Script creation and update are transactional.
#[derive(Debug, Clone)]
pub struct TableScriptClient<T> {
inner: tonic::client::Grpc<T>,
@@ -310,6 +383,12 @@ pub mod table_script_client {
/// * Returns the stored, transformed script from table_scripts
/// * Includes normalized dependency metadata from script_dependencies
/// * Returns an empty scripts list when the table has no scripts
///
/// Client use:
///
/// * Registers each client-evaluable script with the computed-field runtime
/// * Uses dependencies as the allowlist for values exposed to the Steel VM
/// * Uses target_column_type to validate and convert the script result
pub async fn get_table_scripts(
&mut self,
request: impl tonic::IntoRequest<super::GetTableScriptsRequest>,
@@ -339,11 +418,24 @@ pub mod table_script_client {
);
self.inner.unary(req, path, codec).await
}
pub async fn get_script_dependency_values(
/// Build the external data snapshot needed to execute a table's scripts in
/// the client-side Steel runtime.
///
/// The server derives the required inputs from stored script_dependencies;
/// callers do not choose arbitrary tables or columns. Direct related-column
/// reads are grouped by related row, while related aggregates are evaluated
/// through the analytics runtime. Returned values include logical type and
/// currency metadata so the client can create correctly typed ScriptValues.
///
/// Current-table column values are intentionally not returned. The client
/// supplies those directly from row_data so unsaved edits participate in
/// immediate calculations. The response replaces the client's previous
/// script dependency cache as one complete hydration snapshot.
pub async fn hydrate_script_dependencies(
&mut self,
request: impl tonic::IntoRequest<super::GetScriptDependencyValuesRequest>,
request: impl tonic::IntoRequest<super::HydrateScriptDependenciesRequest>,
) -> std::result::Result<
tonic::Response<super::GetScriptDependencyValuesResponse>,
tonic::Response<super::HydrateScriptDependenciesResponse>,
tonic::Status,
> {
self.inner
@@ -356,14 +448,14 @@ pub mod table_script_client {
})?;
let codec = tonic_prost::ProstCodec::default();
let path = http::uri::PathAndQuery::from_static(
"/komp_ac.table_script.TableScript/GetScriptDependencyValues",
"/komp_ac.table_script.TableScript/HydrateScriptDependencies",
);
let mut req = request.into_request();
req.extensions_mut()
.insert(
GrpcMethod::new(
"komp_ac.table_script.TableScript",
"GetScriptDependencyValues",
"HydrateScriptDependencies",
),
);
self.inner.unary(req, path, codec).await
@@ -416,6 +508,12 @@ pub mod table_script_server {
/// * Returns the stored, transformed script from table_scripts
/// * Includes normalized dependency metadata from script_dependencies
/// * Returns an empty scripts list when the table has no scripts
///
/// Client use:
///
/// * Registers each client-evaluable script with the computed-field runtime
/// * Uses dependencies as the allowlist for values exposed to the Steel VM
/// * Uses target_column_type to validate and convert the script result
async fn get_table_scripts(
&self,
request: tonic::Request<super::GetTableScriptsRequest>,
@@ -423,15 +521,29 @@ pub mod table_script_server {
tonic::Response<super::GetTableScriptsResponse>,
tonic::Status,
>;
async fn get_script_dependency_values(
/// Build the external data snapshot needed to execute a table's scripts in
/// the client-side Steel runtime.
///
/// The server derives the required inputs from stored script_dependencies;
/// callers do not choose arbitrary tables or columns. Direct related-column
/// reads are grouped by related row, while related aggregates are evaluated
/// through the analytics runtime. Returned values include logical type and
/// currency metadata so the client can create correctly typed ScriptValues.
///
/// Current-table column values are intentionally not returned. The client
/// supplies those directly from row_data so unsaved edits participate in
/// immediate calculations. The response replaces the client's previous
/// script dependency cache as one complete hydration snapshot.
async fn hydrate_script_dependencies(
&self,
request: tonic::Request<super::GetScriptDependencyValuesRequest>,
request: tonic::Request<super::HydrateScriptDependenciesRequest>,
) -> std::result::Result<
tonic::Response<super::GetScriptDependencyValuesResponse>,
tonic::Response<super::HydrateScriptDependenciesResponse>,
tonic::Status,
>;
}
/// Manages column-computation scripts for user-defined tables.
/// Manages column-computation scripts for user-defined tables and supplies the
/// dependency data used by the client-side Steel runtime.
/// Each script belongs to a single table (table_definition_id) and populates
/// exactly one target column in that table. The server:
///
@@ -443,7 +555,16 @@ pub mod table_script_server {
/// * Analyzes dependencies and prevents cycles across the schema
/// * Transforms the script to decimal-safe math (steel_decimal)
/// * Upserts into table_scripts and records dependencies in script_dependencies
/// The whole operation is transactional.
/// * Hydrates external column and aggregate inputs requested by the client
///
/// The client fetches stored scripts and their declared dependencies, builds a
/// restricted Steel context, and executes scripts for immediate form feedback.
/// Current-table values come from the client's active row snapshot. External
/// values must come from HydrateScriptDependencies; the client must not query
/// arbitrary database data from inside the Steel VM.
///
/// Server-side persistence remains authoritative and recalculates affected rows.
/// Script creation and update are transactional.
#[derive(Debug)]
pub struct TableScriptServer<T> {
inner: Arc<T>,
@@ -610,15 +731,15 @@ pub mod table_script_server {
};
Box::pin(fut)
}
"/komp_ac.table_script.TableScript/GetScriptDependencyValues" => {
"/komp_ac.table_script.TableScript/HydrateScriptDependencies" => {
#[allow(non_camel_case_types)]
struct GetScriptDependencyValuesSvc<T: TableScript>(pub Arc<T>);
struct HydrateScriptDependenciesSvc<T: TableScript>(pub Arc<T>);
impl<
T: TableScript,
> tonic::server::UnaryService<
super::GetScriptDependencyValuesRequest,
> for GetScriptDependencyValuesSvc<T> {
type Response = super::GetScriptDependencyValuesResponse;
super::HydrateScriptDependenciesRequest,
> for HydrateScriptDependenciesSvc<T> {
type Response = super::HydrateScriptDependenciesResponse;
type Future = BoxFuture<
tonic::Response<Self::Response>,
tonic::Status,
@@ -626,12 +747,12 @@ pub mod table_script_server {
fn call(
&mut self,
request: tonic::Request<
super::GetScriptDependencyValuesRequest,
super::HydrateScriptDependenciesRequest,
>,
) -> Self::Future {
let inner = Arc::clone(&self.0);
let fut = async move {
<T as TableScript>::get_script_dependency_values(
<T as TableScript>::hydrate_script_dependencies(
&inner,
request,
)
@@ -646,7 +767,7 @@ pub mod table_script_server {
let max_encoding_message_size = self.max_encoding_message_size;
let inner = self.inner.clone();
let fut = async move {
let method = GetScriptDependencyValuesSvc(inner);
let method = HydrateScriptDependenciesSvc(inner);
let codec = tonic_prost::ProstCodec::default();
let mut grpc = tonic::server::Grpc::new(codec)
.apply_compression_config(