fix(structure): load dynamic data type options

This commit is contained in:
t8y2 committed 2026-06-26 15:22:33 +08:00
1 parent 5ffac129e0
commit cdfe576024
24 files changed
+380 -3

No files matched your search

+18 -1
View File
@@ -120,6 +120,7 @@ pub enum AgentMethod {
ListSchemas,
ListTables,
ListObjects,
ListDataTypes,
CompletionAssistantSearchV1,
GetObjectSource,
GetColumns,
@@ -141,7 +142,7 @@ pub enum AgentMethod {
}
impl AgentMethod {
pub const ALL: [Self; 26] = [
pub const ALL: [Self; 27] = [
Self::Handshake,
Self::Connect,
Self::TestConnection,
@@ -150,6 +151,7 @@ impl AgentMethod {
Self::ListSchemas,
Self::ListTables,
Self::ListObjects,
Self::ListDataTypes,
Self::CompletionAssistantSearchV1,
Self::GetObjectSource,
Self::GetTableDdl,
@@ -180,6 +182,7 @@ impl AgentMethod {
Self::ListSchemas => "list_schemas",
Self::ListTables => "list_tables",
Self::ListObjects => "list_objects",
Self::ListDataTypes => "list_data_types",
Self::CompletionAssistantSearchV1 => "completion_assistant_search_v1",
Self::GetObjectSource => "get_object_source",
Self::GetTableDdl => "get_table_ddl",
@@ -616,6 +619,19 @@ impl AgentDriverClient {
.await
}
pub async fn list_data_types<T: DeserializeOwned + Send + 'static>(
&mut self,
database: &str,
timeout_duration: Option<Duration>,
) -> Result<T, String> {
self.call_method_with_timeout(
AgentMethod::ListDataTypes,
serde_json::json!({ "database": database }),
timeout_duration,
)
.await
}
pub async fn completion_assistant_search<T: DeserializeOwned + Send + 'static>(
&mut self,
request: &crate::types::CompletionAssistantRequest,
@@ -1338,6 +1354,7 @@ mod tests {
assert_eq!(AgentMethod::ListSchemas.as_str(), "list_schemas");
assert_eq!(AgentMethod::ListTables.as_str(), "list_tables");
assert_eq!(AgentMethod::ListObjects.as_str(), "list_objects");
assert_eq!(AgentMethod::ListDataTypes.as_str(), "list_data_types");
assert_eq!(AgentMethod::CompletionAssistantSearchV1.as_str(), "completion_assistant_search_v1");
assert_eq!(AgentMethod::GetObjectSource.as_str(), "get_object_source");
assert_eq!(AgentMethod::GetColumns.as_str(), "get_columns");
+50
View File
@@ -627,6 +627,56 @@ async fn list_schema_infos_once(
Ok(schemas.into_iter().map(|name| db::SchemaInfo { name, comment: None }).collect())
}
pub async fn list_data_types_core(
state: &AppState,
connection_id: &str,
database: &str,
) -> Result<Vec<String>, String> {
retry_metadata_connection(state, connection_id, Some(database), || async {
let pool_key = state.get_or_create_pool(connection_id, Some(database)).await?;
let db_config = connection_config(state, connection_id).await;
let connections = state.connections.read().await;
if let Some(PoolKind::ExternalDriver { config, session, .. }) = connections.get(&pool_key) {
let config = config.clone();
let session = session.clone();
drop(connections);
return session
.invoke::<Vec<String>>(
"listDataTypes",
serde_json::json!({ "connection": config.as_ref(), "database": database }),
)
.await
.map(deduplicate_data_type_names);
}
if let Some(client) = extract_pool!(&connections, &pool_key, Agent) {
drop(connections);
let mut client = client.lock().await;
return client
.list_data_types::<Vec<String>>(database, agent_metadata_timeout(db_config.as_ref()))
.await
.map(deduplicate_data_type_names);
}
Ok(Vec::new())
})
.await
}
fn deduplicate_data_type_names(names: Vec<String>) -> Vec<String> {
let mut seen = std::collections::HashSet::new();
let mut result = Vec::new();
for name in names {
let trimmed = name.trim();
if trimmed.is_empty() {
continue;
}
let key = trimmed.to_ascii_lowercase();
if seen.insert(key) {
result.push(trimmed.to_string());
}
}
result
}
async fn list_schemas_once(
state: &AppState,
connection_id: &str,