Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Execution and plans

Inspect Graph IR and generated SQL, choose a read policy, and understand execution statistics.

Managed read policies

GraphEngine defaults to ReadMode::Hybrid. It lowers Graph IR to a DataFusion relational DAG, executes eligible SQL regions in DuckDB, and schedules native kernels through DataFusion. To require a complete SQL read, set ReadMode::SqlOnly:

use orchiddb::engine::ReadMode;

graph.set_read_mode(ReadMode::SqlOnly);
let result = graph.cypher(
    "MATCH (p:Person) RETURN p.name"
).await?;

SqlOnly applies to managed-storage reads. Mapped execution currently uses the shared DAG path regardless of this setting; it lowers source reads to SQL islands and schedules remaining operators through DataFusion. RDF dataset queries use the same mapped execution path.

Inspect Graph IR

The legacy core CLI’s --explain flag parses and plans a query, then prints Graph IR:

cargo run --features duckdb --bin orchiddb -- --explain --query \
  "MATCH (p:Person)-[:KNOWS]->(friend) RETURN p.name, friend.name"

Use this to inspect scans, expansions, filters, and projections. Explain mode does not execute the query or open a database.

From Rust, build a plan through the language frontend and format it:

use orchiddb::language::cypher;

let parsed = cypher::parse_query(
    "MATCH (p:Person) RETURN p.name"
).map_err(|error| error.to_string())?;
let plan = cypher::CypherPlanner::new().plan(&parsed)
    .map_err(|error| error.to_string())?;
println!("{}", orchiddb::ir::explain(&plan));

Inspect generated SQL

For SQL inspection without execution, use compiler::compile or compile_json and inspect CompiledSql.sql and logical_plan. The existing MappedGraphEngine compatibility facade also offers explain_cypher (the following snippet uses that facade):

let sql = graph.explain_cypher(
    "MATCH (p:Person)-[:ORDERED]->(o:Order) \
     WHERE o.total > 100.0 RETURN p.name, o.total"
).await?;
println!("{sql}");

Graph property names resolve to the physical columns in your mapping. Use this output when reviewing source joins, filters, and query-backed definitions.

Execution metadata

GraphEngine query results identify their backend for managed or mapped storage:

BackendExecution
ExecutionBackend::DuckDbThe query’s execution used DuckDB.
ExecutionBackend::HybridDuckDB SQL regions and DataFusion operators were combined.
ExecutionBackend::DataFusionThe relational DAG executed through DataFusion.

ExecStats records datafusion_ops, islands, island_rows, sql_queries, native_source_queries, native_source_rows, and cost. It also exposes logical_plan, physical_plan, constraint_proofs, layout_selections, and representation_selections. The latter records the chosen derived or materialized input, candidate costs, and decision reasons. Use fully_pushed_down() to inspect whether all recorded query operators were delegated to SQL. Backend labels alone do not establish that.

Logical plans show selected physical tables and collection Unnest operators. Layout estimates describe parent-table bytes/files; they are not measured I/O or expanded collection cardinalities. SQL island rows are intermediate rows; use the result batch for the number of returned rows.

For RDF, sparql_dataset returns these statistics in QueryResult.stats. sparql_query decodes typed terms and does not return the stats wrapper. sparql_sql(query, dataset) produces SQL without executing the query.

SQL timeout

use std::time::Duration;
graph.set_sql_timeout(Duration::from_secs(10));

This setting applies to individual DuckDB queries and setup work. Treat the SQL timeout as one part of your application’s overall request budget.

Planner and executor boundaries

Language planners produce GraphPlan values. RelBackend handles relational lowering; SQL preparation turns the lowered plan into a dialect-specific program. SqlExecutor supplies the SQL execution boundary. Managed execution compiles to a DataFusion relational DAG with explicit DuckDB regions and native kernels.

Graph IR is retained for planning and inspection. It has no standalone recursive interpreter, and execution errors do not trigger an interpreter fallback. SPARQL SERVICE, including SERVICE SILENT, is unsupported; no remote SPARQL HTTP calls are made.

Use the engine APIs for application workflows. Use these lower-level types when integrating a custom planner or execution target. See the Rust API for the module map.