Skip to main content

uni_query/query/df_graph/
locy_traits.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2024-2026 Dragonscale Team
3
4//! Traits for native Locy command dispatch.
5//!
6//! `DerivedFactSource` provides read-only access to derived facts and the graph,
7//! replacing `CypherExecutor` for read operations in the native path.
8//!
9//! `LocyExecutionContext` extends it with write operations (mutations, L0 fork/restore,
10//! and strata re-evaluation) needed by ASSUME, DERIVE, and ABDUCE.
11
12use std::collections::HashMap;
13
14use arrow_array::RecordBatch;
15use async_trait::async_trait;
16use uni_common::Value;
17use uni_cypher::ast::{Expr, Pattern, Query};
18use uni_locy::{CompiledProgram, FactRow, LocyConfig, LocyError};
19
20use super::locy_delta::RowStore;
21
22/// Read-only access to derived facts and graph data.
23///
24/// Replaces `CypherExecutor` for read operations in the native command dispatch path.
25/// `lookup_derived` converts RecordBatch-based native facts to `FactRow` format internally.
26#[async_trait]
27pub trait DerivedFactSource: Send + Sync {
28    /// Look up all facts for a rule. Returns `FactRow`-based results.
29    fn lookup_derived(&self, rule_name: &str) -> Result<Vec<FactRow>, LocyError>;
30
31    /// Look up all facts for a rule as raw RecordBatches (zero-copy from native store).
32    ///
33    /// Default implementation returns an error. Override in native adapters to read
34    /// directly from `DerivedStore` without converting to rows.
35    fn lookup_derived_batches(&self, _rule_name: &str) -> Result<Vec<RecordBatch>, LocyError> {
36        Err(LocyError::EvaluationError {
37            message: "lookup_derived_batches not implemented for this adapter".into(),
38        })
39    }
40
41    /// Execute a graph MATCH query with optional WHERE conditions.
42    ///
43    /// Returns raw `RecordBatch`es so the native path stays columnar.
44    /// Callers that need `Vec<FactRow>` must convert via `record_batches_to_locy_rows`.
45    ///
46    /// Used by SLG clause resolution, EXPLAIN re-execution, and delta resolution.
47    /// AST construction happens inside the adapter via `build_match_return_query`.
48    async fn execute_pattern(
49        &self,
50        pattern: &Pattern,
51        where_conditions: &[Expr],
52    ) -> Result<Vec<RecordBatch>, LocyError>;
53}
54
55/// DB operations needed by ASSUME, DERIVE, and ABDUCE.
56///
57/// Extends `DerivedFactSource` with write operations.
58#[async_trait]
59pub trait LocyExecutionContext: DerivedFactSource {
60    /// Look up facts enriched with full node objects (for VID-based stores).
61    ///
62    /// Default implementation delegates to `lookup_derived()` (no enrichment needed
63    /// for the orchestrator path which already returns full `Value::Node` objects).
64    /// Override in native adapters to replace UInt64 VID values with full nodes so
65    /// that commands like DERIVE can access node properties.
66    async fn lookup_derived_enriched(&self, rule_name: &str) -> Result<Vec<FactRow>, LocyError> {
67        self.lookup_derived(rule_name)
68    }
69
70    /// Execute a pre-compiled Cypher read query (e.g. from a `CompiledCommand::Cypher`).
71    ///
72    /// Used by ASSUME/ABDUCE body dispatch where a Query AST is already available.
73    async fn execute_cypher_read(&self, ast: Query) -> Result<Vec<FactRow>, LocyError>;
74
75    /// Execute a mutation (CREATE/MERGE/DELETE), returning affected row count.
76    async fn execute_mutation(
77        &self,
78        ast: Query,
79        params: HashMap<String, Value>,
80    ) -> Result<usize, LocyError>;
81
82    /// Fork the current Locy L0 buffer for hypothetical reasoning.
83    ///
84    /// Saves the current L0 state and replaces it with a clone.
85    /// Mutations after fork are isolated to the clone.
86    /// Call `restore_l0()` to undo all hypothetical changes.
87    async fn fork_l0(&self) -> Result<(), LocyError>;
88
89    /// Restore the Locy L0 buffer to its state before the last `fork_l0()`.
90    ///
91    /// Discards all mutations made since the fork.
92    async fn restore_l0(&self) -> Result<(), LocyError>;
93
94    /// Re-evaluate all strata in the current (possibly mutated) state.
95    ///
96    /// Used by ASSUME and ABDUCE `validate_modification` to check hypothetical states.
97    /// Returns the row-based `RowStore` after convergence.
98    async fn re_evaluate_strata(
99        &self,
100        program: &CompiledProgram,
101        config: &LocyConfig,
102    ) -> Result<RowStore, LocyError>;
103}