sf-query-engine-core is the high-level SOQL/SOSL query execution engine for the SFDCAnomaly desktop application.
It wraps sf-client-core and provides automatic cursor-based pagination, query plan analysis, and structured response types ready for Tauri IPC serialization.
- SOQL Execution: Execute SOQL queries with typed
QueryResponsecontaining pagination metadata (totalSize,done,nextRecordsUrl). - Cursor-Based Pagination: Automatically follows
nextRecordsUrlcursors to fetch all records, bypassing the 2,000-rowOFFSETlimit imposed by Salesforce. - Capped Pagination:
query_all_with_limit()stops accumulating after a specified number of records to prevent runaway memory consumption. - SOSL Search: Execute SOSL search queries with typed
SearchResponse. - Query Plan Analysis: Hit the
/query/?explain=endpoint to retrieve optimizer metadata — index usage, cardinality, leading operation type, and relative cost. - Tauri Ready: All response types derive
SerializeandDeserializefor seamless Tauri IPC serialization.QueryEngineisSend + Sync, so it can be used directly as Tauri managed state without aMutex.
The crate is structured into a single internal module, with the public API accessible from the crate root:
core/engine.rs— TheQueryEnginestruct with all query methods.core/models.rs— Response types (QueryResponse,SearchResponse,QueryExplainResponse).core/error.rs— TheQueryEngineErrorenum.core/constants.rs— Default limits and parameter keys.
Add this crate to your Cargo workspace or dependencies:
[dependencies]
sf-query-engine-core = { path = "path/to/sf-query-engine-core" }
sf-client-core = { path = "path/to/sf-client-core" }use sf_client_core::{SalesforceClient, ClientConfig};
use sf_query_engine_core::{QueryEngine, QueryResponse};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Build the client (token obtained from sf-auth-core)
let config = ClientConfig::builder(
"https://myorg.my.salesforce.com",
"your_access_token",
)
.build()?;
let client = SalesforceClient::new(config)?;
// Create the query engine
let engine = QueryEngine::new(client);
// 1. Execute a SOQL query (single page)
let result = engine.query("SELECT Id, Name FROM Account LIMIT 10").await?;
println!("Found {} accounts", result.total_size);
for record in &result.records {
println!(" {}", record);
}
// 2. Auto-paginate through all results
let all_contacts = engine.query_all("SELECT Id, Email FROM Contact").await?;
println!("Fetched all {} contacts", all_contacts.records.len());
// 3. Capped pagination (max 1000 records)
let capped = engine
.query_all_with_limit("SELECT Id FROM Lead", 1000)
.await?;
println!("Fetched {} leads (done: {})", capped.records.len(), capped.done);
// 4. SOSL search
let search = engine
.search("FIND {Acme} IN ALL FIELDS RETURNING Account(Id, Name)")
.await?;
println!("Search found {} records", search.search_records.len());
// 5. Query plan analysis
let plan = engine
.explain("SELECT Id FROM Account WHERE Name = 'Acme'")
.await?;
for p in &plan.plans {
println!(
"Plan: {} | Cost: {} | Cardinality: {}",
p.leading_operation_type, p.relative_cost, p.cardinality
);
}
Ok(())
}QueryEngine wraps SalesforceClient, which is Clone + Send + Sync (it uses reqwest::Client internally with Arc-based reference counting). This means QueryEngine can be used directly as Tauri managed state without a Mutex:
use sf_query_engine_core::QueryEngine;
#[tauri::command]
async fn execute_soql(
engine: tauri::State<'_, QueryEngine>,
soql: String,
) -> Result<sf_query_engine_core::QueryResponse, String> {
engine.query(&soql).await.map_err(|e| e.to_string())
}This is different from sf-workspace-mgr-core, which requires Mutex wrapping because rusqlite::Connection is !Send.
To run this crate's test suite:
cargo testIntegration tests use mockito to simulate Salesforce REST API responses without requiring a live org connection.