mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-23 11:36:21 +00:00
fix: resolve clippy warnings and missing struct fields in tests
This commit is contained in:
@@ -47,6 +47,7 @@ fn provider_supports_function_calling(config: &AiConfig) -> bool {
|
||||
///
|
||||
/// If the provider does not support function calling (e.g., Ollama), automatically
|
||||
/// degrades to a text-only completion with schema context injected into the system prompt.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn run_agent_loop(
|
||||
config: &AiConfig,
|
||||
system_prompt: &str,
|
||||
@@ -300,7 +301,7 @@ async fn stream_with_tools(
|
||||
return Err("Agent loop cancelled".to_string());
|
||||
}
|
||||
|
||||
ai::stream_with_tools(config, request, session_id, &tools, cancelled, on_chunk).await
|
||||
ai::stream_with_tools(config, request, session_id, tools, cancelled, on_chunk).await
|
||||
}
|
||||
|
||||
fn is_context_length_error(error: &str) -> bool {
|
||||
@@ -324,6 +325,7 @@ fn is_context_length_error(error: &str) -> bool {
|
||||
///
|
||||
/// Injects database schema context into the system prompt so the LLM can still
|
||||
/// give informed answers, then performs a single non-streaming completion.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn run_agent_loop_text_only(
|
||||
config: &AiConfig,
|
||||
system_prompt: &str,
|
||||
@@ -453,16 +455,12 @@ fn context_window_for_model(model: &str) -> u32 {
|
||||
if m.contains("gpt-4.1") {
|
||||
return 1_000_000;
|
||||
}
|
||||
if m.contains("claude") {
|
||||
200_000
|
||||
} else if m.contains("o1") || m.starts_with("o3") || m.starts_with("o4") {
|
||||
if m.contains("claude") || m.contains("o1") || m.starts_with("o3") || m.starts_with("o4") {
|
||||
200_000
|
||||
} else if m.contains("gpt-4") {
|
||||
128_000
|
||||
} else if m.contains("gemini") {
|
||||
1_000_000
|
||||
} else if m.contains("deepseek") || m.contains("qwen") {
|
||||
128_000
|
||||
} else {
|
||||
128_000
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ pub fn resolve_model_list_endpoint(config: &AiConfig) -> Result<String, String>
|
||||
.unwrap_or(ep)
|
||||
.trim_end_matches('/');
|
||||
|
||||
let base = ensure_openai_version_prefix(&base);
|
||||
let base = ensure_openai_version_prefix(base);
|
||||
|
||||
Ok(format!("{base}/models"))
|
||||
}
|
||||
@@ -1351,6 +1351,12 @@ pub struct StreamingToolCallAccumulator {
|
||||
ordered_indices: Vec<u32>,
|
||||
}
|
||||
|
||||
impl Default for StreamingToolCallAccumulator {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl StreamingToolCallAccumulator {
|
||||
pub fn new() -> Self {
|
||||
Self { calls: std::collections::HashMap::new(), ordered_indices: Vec::new() }
|
||||
@@ -1417,7 +1423,7 @@ async fn stream_claude_with_tools(
|
||||
if !pending_tool_results.is_empty() {
|
||||
messages.push(json!({
|
||||
"role": "user",
|
||||
"content": pending_tool_results.drain(..).collect::<Vec<_>>()
|
||||
"content": std::mem::take(&mut pending_tool_results)
|
||||
}));
|
||||
}
|
||||
if m.role == "assistant" && !m.tool_calls.is_empty() {
|
||||
@@ -1439,7 +1445,7 @@ async fn stream_claude_with_tools(
|
||||
if !pending_tool_results.is_empty() {
|
||||
messages.push(json!({
|
||||
"role": "user",
|
||||
"content": pending_tool_results.drain(..).collect::<Vec<_>>()
|
||||
"content": std::mem::take(&mut pending_tool_results)
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -1739,7 +1745,7 @@ async fn stream_gemini_with_tools(
|
||||
.tool_call_id
|
||||
.as_deref()
|
||||
.and_then(|s| s.strip_prefix("gemini-tc-"))
|
||||
.and_then(|s| s.rsplitn(2, '-').nth(1))
|
||||
.and_then(|s| s.rsplit_once('-').map(|x| x.0))
|
||||
.unwrap_or("unknown");
|
||||
pending_function_responses.push(json!({
|
||||
"functionResponse": {
|
||||
@@ -1752,7 +1758,7 @@ async fn stream_gemini_with_tools(
|
||||
if !pending_function_responses.is_empty() {
|
||||
contents.push(json!({
|
||||
"role": "user",
|
||||
"parts": pending_function_responses.drain(..).collect::<Vec<_>>()
|
||||
"parts": std::mem::take(&mut pending_function_responses)
|
||||
}));
|
||||
}
|
||||
if m.role == "assistant" && !m.tool_calls.is_empty() {
|
||||
@@ -1774,7 +1780,7 @@ async fn stream_gemini_with_tools(
|
||||
if !pending_function_responses.is_empty() {
|
||||
contents.push(json!({
|
||||
"role": "user",
|
||||
"parts": pending_function_responses.drain(..).collect::<Vec<_>>()
|
||||
"parts": std::mem::take(&mut pending_function_responses)
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -2008,6 +2014,7 @@ mod tests {
|
||||
proxy_enabled: true,
|
||||
proxy_url: "not a proxy url".to_string(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
|
||||
let err = build_ai_http_client(&config, 1).unwrap_err();
|
||||
@@ -2027,6 +2034,7 @@ mod tests {
|
||||
proxy_enabled: true,
|
||||
proxy_url: "127.0.0.1:7890".to_string(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
|
||||
build_ai_http_client(&config, 1).unwrap();
|
||||
@@ -2044,6 +2052,7 @@ mod tests {
|
||||
proxy_enabled: true,
|
||||
proxy_url: "not a proxy url".to_string(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
|
||||
build_ai_http_client(&config, 1).unwrap();
|
||||
@@ -2061,6 +2070,7 @@ mod tests {
|
||||
proxy_enabled: false,
|
||||
proxy_url: String::new(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
@@ -2078,6 +2088,7 @@ mod tests {
|
||||
proxy_enabled: false,
|
||||
proxy_url: String::new(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
|
||||
assert_eq!(resolve_endpoint(&ollama), "http://localhost:11434/v1/chat/completions");
|
||||
@@ -2096,6 +2107,7 @@ mod tests {
|
||||
proxy_enabled: false,
|
||||
proxy_url: String::new(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
assert_eq!(resolve_model_list_endpoint(&openai).unwrap(), "https://api.openai.com/v1/models");
|
||||
|
||||
@@ -2109,6 +2121,7 @@ mod tests {
|
||||
proxy_enabled: false,
|
||||
proxy_url: String::new(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
assert_eq!(resolve_model_list_endpoint(&claude).unwrap(), "https://api.anthropic.com/v1/models");
|
||||
}
|
||||
@@ -2126,6 +2139,7 @@ mod tests {
|
||||
proxy_enabled: false,
|
||||
proxy_url: String::new(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
assert_eq!(resolve_endpoint(&config), "https://api.example.com/v1/chat/completions");
|
||||
assert_eq!(resolve_model_list_endpoint(&config).unwrap(), "https://api.example.com/v1/models");
|
||||
@@ -2178,6 +2192,7 @@ mod tests {
|
||||
proxy_enabled: false,
|
||||
proxy_url: String::new(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
|
||||
let api_key_headers = claude_headers(&config).unwrap();
|
||||
@@ -2233,6 +2248,7 @@ mod tests {
|
||||
proxy_enabled: false,
|
||||
proxy_url: String::new(),
|
||||
enable_thinking: true,
|
||||
context_window: None,
|
||||
};
|
||||
|
||||
assert!(!supports_temperature(&config));
|
||||
|
||||
@@ -523,7 +523,7 @@ static NULL_VALUE: Value = Value::Null;
|
||||
type CompareRowValues = Vec<Value>;
|
||||
type CompareRowMap = HashMap<String, CompareRowValues>;
|
||||
|
||||
fn column_index_map<'a>(columns: &'a [String]) -> HashMap<&'a str, usize> {
|
||||
fn column_index_map(columns: &[String]) -> HashMap<&str, usize> {
|
||||
let mut indexes = HashMap::with_capacity(columns.len());
|
||||
for (index, column) in columns.iter().enumerate() {
|
||||
indexes.insert(column.as_str(), index);
|
||||
@@ -688,7 +688,7 @@ fn generate_data_sync_statements(options: &GenerateDataSyncSqlOptions<'_>) -> Ve
|
||||
.join(", ");
|
||||
format!(
|
||||
"UPDATE {table} SET {assignments} WHERE {};",
|
||||
where_by_key(&row.key_values, &options.key_columns, options.database_type, column_info)
|
||||
where_by_key(&row.key_values, options.key_columns, options.database_type, column_info)
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -699,7 +699,7 @@ fn generate_data_sync_statements(options: &GenerateDataSyncSqlOptions<'_>) -> Ve
|
||||
.map(|row| {
|
||||
format!(
|
||||
"DELETE FROM {table} WHERE {};",
|
||||
where_by_key(&row.key_values, &options.key_columns, options.database_type, column_info)
|
||||
where_by_key(&row.key_values, options.key_columns, options.database_type, column_info)
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -429,10 +429,7 @@ fn elasticsearch_query_from_document_filter(filter: Option<&str>) -> Result<Opti
|
||||
};
|
||||
let value: serde_json::Value = serde_json::from_str(filter).map_err(|e| format!("Invalid filter JSON: {e}"))?;
|
||||
let query = translate_document_filter_value(&value)?;
|
||||
Ok(match query {
|
||||
Some(query) => Some(query),
|
||||
None => None,
|
||||
})
|
||||
Ok(query)
|
||||
}
|
||||
|
||||
fn translate_document_filter_value(value: &serde_json::Value) -> Result<Option<serde_json::Value>, String> {
|
||||
|
||||
@@ -2160,7 +2160,7 @@ mod tests {
|
||||
let escaped = pg_quote_ident(malicious);
|
||||
// Double quotes should be doubled, not breaking out
|
||||
assert_eq!(escaped, r#""public""; DROP TABLE users; --""#);
|
||||
assert!(escaped.matches('"').count() % 2 == 0, "quote count should be even");
|
||||
assert!(escaped.matches('"').count().is_multiple_of(2), "quote count should be even");
|
||||
}
|
||||
|
||||
// --- query_result_row_limit ---
|
||||
@@ -2479,14 +2479,14 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn execute_batch_whitespace_only_is_filtered() {
|
||||
let statements = vec![" ".to_string(), "\t\n".to_string(), "".to_string()];
|
||||
let statements = [" ".to_string(), "\t\n".to_string(), "".to_string()];
|
||||
let combined = statements.iter().map(|s| s.trim()).filter(|s| !s.is_empty()).collect::<Vec<_>>().join(";\n");
|
||||
assert!(combined.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn execute_batch_joins_with_semicolons() {
|
||||
let statements = vec!["SELECT 1".to_string(), "SELECT 2".to_string()];
|
||||
let statements = ["SELECT 1".to_string(), "SELECT 2".to_string()];
|
||||
let combined = statements.iter().map(|s| s.trim()).filter(|s| !s.is_empty()).collect::<Vec<_>>().join(";\n");
|
||||
assert_eq!(combined, "SELECT 1;\nSELECT 2");
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ fn ssh_client_config() -> Config {
|
||||
Config { nodelay: true, keepalive_interval: Some(Duration::from_secs(30)), preferred, ..Default::default() }
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn connect_and_authenticate(
|
||||
ssh_host: &str,
|
||||
ssh_port: u16,
|
||||
|
||||
@@ -109,6 +109,7 @@ pub async fn document_find_documents_core(
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn mongo_find_documents_core(
|
||||
state: &AppState,
|
||||
connection_id: &str,
|
||||
|
||||
@@ -89,6 +89,7 @@ pub async fn redis_scan_keys_batch_core(
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn redis_scan_values_core(
|
||||
state: &AppState,
|
||||
connection_id: &str,
|
||||
|
||||
@@ -1302,7 +1302,7 @@ fn merge_optional_string(target: &mut Option<String>, candidate: Option<String>)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if target.as_ref().map_or(true, |value| value.trim().is_empty()) {
|
||||
if target.as_ref().is_none_or(|value| value.trim().is_empty()) {
|
||||
*target = Some(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1029,6 +1029,7 @@ fn table_comment_sql(table_name: &str, comment: &str, db_type: DatabaseType, sch
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn generate_schema_sync_sql(
|
||||
diffs: &[TableDiff],
|
||||
function_diffs: &[FunctionDiff],
|
||||
@@ -1185,8 +1186,10 @@ pub fn generate_schema_sync_sql(
|
||||
|
||||
if let Some(foreign_keys) = &diff.foreign_keys {
|
||||
for fk in foreign_keys {
|
||||
if (fk.diff_type == "added" || fk.diff_type == "modified") && fk.source.is_some() {
|
||||
lines.push(add_foreign_key_sql(&diff.name, fk.source.as_ref().unwrap(), db_type, schema));
|
||||
if fk.diff_type == "added" || fk.diff_type == "modified" {
|
||||
if let Some(source) = &fk.source {
|
||||
lines.push(add_foreign_key_sql(&diff.name, source, db_type, schema));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,5 +365,5 @@ pub(super) fn build_questdb_table_select_sql(
|
||||
return format!("SELECT {columns_sql} FROM {table}{where_clause}{order_by} LIMIT {limit}");
|
||||
}
|
||||
let upper_bound = offset + limit;
|
||||
return format!("SELECT {columns_sql} FROM {table}{where_clause}{order_by} LIMIT {offset}, {upper_bound}");
|
||||
format!("SELECT {columns_sql} FROM {table}{where_clause}{order_by} LIMIT {offset}, {upper_bound}")
|
||||
}
|
||||
|
||||
@@ -194,9 +194,7 @@ pub(super) fn build_add_column_sql(
|
||||
table_name: &str,
|
||||
) -> Vec<String> {
|
||||
let definition = column_definition(dialect, column);
|
||||
let mut statements = if dialect == StructureDialect::Oracle {
|
||||
vec![format!("ALTER TABLE {table} ADD ({definition});")]
|
||||
} else if dialect == StructureDialect::Informix {
|
||||
let mut statements = if dialect == StructureDialect::Oracle || dialect == StructureDialect::Informix {
|
||||
vec![format!("ALTER TABLE {table} ADD ({definition});")]
|
||||
} else {
|
||||
let add_keyword = if dialect == StructureDialect::SqlServer { "ADD" } else { "ADD COLUMN" };
|
||||
|
||||
@@ -609,7 +609,7 @@ pub fn escape_value_typed(val: &serde_json::Value, db_type: &DatabaseType, colum
|
||||
serde_json::Value::Number(n) => match db_type {
|
||||
DatabaseType::Mysql | DatabaseType::Doris | DatabaseType::StarRocks => {
|
||||
if column_type.is_some_and(is_mysql_bit_type) {
|
||||
format!("b'{}'", n.to_string())
|
||||
format!("b'{}'", n)
|
||||
} else {
|
||||
n.to_string()
|
||||
}
|
||||
|
||||
@@ -216,6 +216,7 @@ mod tests {
|
||||
let state = Arc::new(WebState {
|
||||
app,
|
||||
data_dir: dir.clone(),
|
||||
password_disabled: false,
|
||||
password_hash: RwLock::new(None),
|
||||
sessions: RwLock::new(HashSet::new()),
|
||||
sse_channels: RwLock::new(HashMap::new()),
|
||||
|
||||
@@ -52,6 +52,7 @@ pub async fn ai_cancel_stream(session_id: String) -> Result<bool, String> {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn ai_agent_stream(
|
||||
app: AppHandle,
|
||||
state: State<'_, Arc<AppState>>,
|
||||
|
||||
@@ -41,6 +41,7 @@ pub async fn redis_scan_keys_batch(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn redis_scan_values(
|
||||
state: State<'_, Arc<AppState>>,
|
||||
connection_id: String,
|
||||
|
||||
@@ -6,6 +6,7 @@ pub fn prepare_schema_diff(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn generate_schema_sync_sql(
|
||||
diffs: Vec<dbx_core::schema_diff::TableDiff>,
|
||||
function_diffs: Option<Vec<dbx_core::schema_diff::FunctionDiff>>,
|
||||
|
||||
Reference in New Issue
Block a user