diff --git a/common/proto/table_structure.proto b/common/proto/table_structure.proto index 15861a2c..8d44b06e 100644 --- a/common/proto/table_structure.proto +++ b/common/proto/table_structure.proto @@ -23,6 +23,12 @@ service TableStructureService { // - Returns an error if any validated table has no visible columns in // information_schema (e.g., physical table missing) rpc GetTableStructure(GetTableStructureRequest) returns (GetTableStructureResponse); + + // Describes the public values accepted by staged table-data import. Unlike + // GetTableStructure, this is an input contract: it includes logical types, + // omission/null behavior, stable identities and link targets. + rpc GetTableImportDescriptor(GetTableImportDescriptorRequest) + returns (GetTableImportDescriptorResponse); } // Request identifying the profile (schema) and tables to inspect. @@ -91,3 +97,52 @@ message TableColumn { // Stable public identity of a managed user column. Zero for system columns. int64 column_id = 10; } + +message GetTableImportDescriptorRequest { + string profile_name = 1; + string table_name = 2; +} + +enum ImportValueKind { + IMPORT_VALUE_KIND_UNSPECIFIED = 0; + IMPORT_VALUE_KIND_NULL = 1; + IMPORT_VALUE_KIND_STRING = 2; + IMPORT_VALUE_KIND_BOOLEAN = 3; + IMPORT_VALUE_KIND_NUMBER = 4; + IMPORT_VALUE_KIND_INTEGER_STRING = 5; + IMPORT_VALUE_KIND_LINK_DISPLAY = 6; +} + +message ImportLinkDescriptor { + int64 target_table_id = 1; + string target_profile_name = 2; + string target_table_name = 3; + repeated string target_row_display_columns = 4; +} + +message ImportFieldDescriptor { + // Stable identity of a managed user column. System columns have zero here + // and are identified by their server-owned name. + int64 column_id = 1; + string name = 2; + string logical_type = 3; + string storage_type = 4; + bool writable = 5; + bool required = 6; + bool may_omit = 7; + bool accepts_null = 8; + bool system = 9; + bool generated = 10; + string generated_from = 11; + optional ImportLinkDescriptor link = 12; + repeated ImportValueKind accepted_value_kinds = 13; +} + +message GetTableImportDescriptorResponse { + string requested_profile_name = 1; + string storage_profile_name = 2; + string table_name = 3; + int64 table_id = 4; + int64 table_revision = 5; + repeated ImportFieldDescriptor fields = 6; +} diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index e4081779..8a984bf5 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_structure.rs b/common/src/proto/komp_ac.table_structure.rs index 1da7b7a9..4a02457a 100644 --- a/common/src/proto/komp_ac.table_structure.rs +++ b/common/src/proto/komp_ac.table_structure.rs @@ -74,6 +74,113 @@ pub struct TableColumn { #[prost(int64, tag = "10")] pub column_id: i64, } +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetTableImportDescriptorRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub table_name: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ImportLinkDescriptor { + #[prost(int64, tag = "1")] + pub target_table_id: i64, + #[prost(string, tag = "2")] + pub target_profile_name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub target_table_name: ::prost::alloc::string::String, + #[prost(string, repeated, tag = "4")] + pub target_row_display_columns: ::prost::alloc::vec::Vec< + ::prost::alloc::string::String, + >, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ImportFieldDescriptor { + /// Stable identity of a managed user column. System columns have zero here + /// and are identified by their server-owned name. + #[prost(int64, tag = "1")] + pub column_id: i64, + #[prost(string, tag = "2")] + pub name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub logical_type: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub storage_type: ::prost::alloc::string::String, + #[prost(bool, tag = "5")] + pub writable: bool, + #[prost(bool, tag = "6")] + pub required: bool, + #[prost(bool, tag = "7")] + pub may_omit: bool, + #[prost(bool, tag = "8")] + pub accepts_null: bool, + #[prost(bool, tag = "9")] + pub system: bool, + #[prost(bool, tag = "10")] + pub generated: bool, + #[prost(string, tag = "11")] + pub generated_from: ::prost::alloc::string::String, + #[prost(message, optional, tag = "12")] + pub link: ::core::option::Option, + #[prost(enumeration = "ImportValueKind", repeated, tag = "13")] + pub accepted_value_kinds: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTableImportDescriptorResponse { + #[prost(string, tag = "1")] + pub requested_profile_name: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub storage_profile_name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub table_name: ::prost::alloc::string::String, + #[prost(int64, tag = "4")] + pub table_id: i64, + #[prost(int64, tag = "5")] + pub table_revision: i64, + #[prost(message, repeated, tag = "6")] + pub fields: ::prost::alloc::vec::Vec, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ImportValueKind { + Unspecified = 0, + Null = 1, + String = 2, + Boolean = 3, + Number = 4, + IntegerString = 5, + LinkDisplay = 6, +} +impl ImportValueKind { + /// 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::Unspecified => "IMPORT_VALUE_KIND_UNSPECIFIED", + Self::Null => "IMPORT_VALUE_KIND_NULL", + Self::String => "IMPORT_VALUE_KIND_STRING", + Self::Boolean => "IMPORT_VALUE_KIND_BOOLEAN", + Self::Number => "IMPORT_VALUE_KIND_NUMBER", + Self::IntegerString => "IMPORT_VALUE_KIND_INTEGER_STRING", + Self::LinkDisplay => "IMPORT_VALUE_KIND_LINK_DISPLAY", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "IMPORT_VALUE_KIND_UNSPECIFIED" => Some(Self::Unspecified), + "IMPORT_VALUE_KIND_NULL" => Some(Self::Null), + "IMPORT_VALUE_KIND_STRING" => Some(Self::String), + "IMPORT_VALUE_KIND_BOOLEAN" => Some(Self::Boolean), + "IMPORT_VALUE_KIND_NUMBER" => Some(Self::Number), + "IMPORT_VALUE_KIND_INTEGER_STRING" => Some(Self::IntegerString), + "IMPORT_VALUE_KIND_LINK_DISPLAY" => Some(Self::LinkDisplay), + _ => None, + } + } +} /// Generated client implementations. pub mod table_structure_service_client { #![allow( @@ -213,6 +320,38 @@ pub mod table_structure_service_client { ); self.inner.unary(req, path, codec).await } + /// Describes the public values accepted by staged table-data import. Unlike + /// GetTableStructure, this is an input contract: it includes logical types, + /// omission/null behavior, stable identities and link targets. + pub async fn get_table_import_descriptor( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.table_structure.TableStructureService/GetTableImportDescriptor", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.table_structure.TableStructureService", + "GetTableImportDescriptor", + ), + ); + self.inner.unary(req, path, codec).await + } } } /// Generated server implementations. @@ -246,6 +385,16 @@ pub mod table_structure_service_server { tonic::Response, tonic::Status, >; + /// Describes the public values accepted by staged table-data import. Unlike + /// GetTableStructure, this is an input contract: it includes logical types, + /// omission/null behavior, stable identities and link targets. + async fn get_table_import_descriptor( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; } /// Introspects the physical PostgreSQL tables for one or more logical tables /// (defined in table_definitions) and returns their column structures. @@ -381,6 +530,59 @@ pub mod table_structure_service_server { }; Box::pin(fut) } + "/komp_ac.table_structure.TableStructureService/GetTableImportDescriptor" => { + #[allow(non_camel_case_types)] + struct GetTableImportDescriptorSvc( + pub Arc, + ); + impl< + T: TableStructureService, + > tonic::server::UnaryService + for GetTableImportDescriptorSvc { + type Response = super::GetTableImportDescriptorResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::GetTableImportDescriptorRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_table_import_descriptor( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetTableImportDescriptorSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => { Box::pin(async move { let mut response = http::Response::new( diff --git a/server b/server index c958eb0f..e4392276 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit c958eb0f17080b86c97d487974ecba46467eaa71 +Subproject commit e4392276bcdf31be965f638e84eb8cde746d6cdb