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, savepoints,
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, LocyConfig, LocyError, Row, SavepointId};
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 Row-based format internally.
26#[async_trait(?Send)]
27pub trait DerivedFactSource: Send + Sync {
28    /// Look up all facts for a rule. Returns Row-based results.
29    fn lookup_derived(&self, rule_name: &str) -> Result<Vec<Row>, 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<Row>` 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(?Send)]
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<Row>, 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<Row>, 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    /// Begin a savepoint for transactional rollback.
83    async fn begin_savepoint(&self) -> Result<SavepointId, LocyError>;
84
85    /// Rollback to a previously created savepoint.
86    async fn rollback_savepoint(&self, id: SavepointId) -> Result<(), LocyError>;
87
88    /// Re-evaluate all strata in the current (possibly mutated) state.
89    ///
90    /// Used by ASSUME and ABDUCE `validate_modification` to check hypothetical states.
91    /// Returns the row-based `RowStore` after convergence.
92    async fn re_evaluate_strata(
93        &self,
94        program: &CompiledProgram,
95        config: &LocyConfig,
96    ) -> Result<RowStore, LocyError>;
97}