1use std::collections::HashMap;
2use std::time::Duration;
3
4use uni_common::Value;
5
6use crate::types::{RuntimeWarning, RuntimeWarningCode};
7
8pub type Row = HashMap<String, Value>;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub struct SavepointId(pub u64);
14
15#[derive(Debug, Clone)]
17pub struct LocyResult {
18 pub derived: HashMap<String, Vec<Row>>,
20 pub stats: LocyStats,
22 pub command_results: Vec<CommandResult>,
24 pub warnings: Vec<RuntimeWarning>,
26 pub approximate_groups: HashMap<String, Vec<String>>,
29}
30
31#[derive(Debug, Clone)]
33pub enum CommandResult {
34 Query(Vec<Row>),
35 Assume(Vec<Row>),
36 Explain(DerivationNode),
37 Abduce(AbductionResult),
38 Derive { affected: usize },
39 Cypher(Vec<Row>),
40}
41
42#[derive(Debug, Clone)]
44pub struct DerivationNode {
45 pub rule: String,
46 pub clause_index: usize,
47 pub priority: Option<i64>,
48 pub bindings: HashMap<String, Value>,
49 pub along_values: HashMap<String, Value>,
50 pub children: Vec<DerivationNode>,
51 pub graph_fact: Option<String>,
52 pub approximate: bool,
55 pub proof_probability: Option<f64>,
58}
59
60#[derive(Debug, Clone)]
62pub struct AbductionResult {
63 pub modifications: Vec<ValidatedModification>,
64}
65
66#[derive(Debug, Clone)]
68pub struct ValidatedModification {
69 pub modification: Modification,
70 pub validated: bool,
71 pub cost: f64,
72}
73
74#[derive(Debug, Clone)]
76pub enum Modification {
77 RemoveEdge {
78 source_var: String,
79 target_var: String,
80 edge_var: String,
81 edge_type: String,
82 match_properties: HashMap<String, Value>,
83 },
84 ChangeProperty {
85 element_var: String,
86 property: String,
87 old_value: Box<Value>,
88 new_value: Box<Value>,
89 },
90 AddEdge {
91 source_var: String,
92 target_var: String,
93 edge_type: String,
94 properties: HashMap<String, Value>,
95 },
96}
97
98#[derive(Debug, Clone, Default)]
100pub struct LocyStats {
101 pub strata_evaluated: usize,
102 pub total_iterations: usize,
103 pub derived_nodes: usize,
104 pub derived_edges: usize,
105 pub evaluation_time: Duration,
106 pub queries_executed: usize,
107 pub mutations_executed: usize,
108 pub peak_memory_bytes: usize,
110}
111
112impl LocyResult {
113 pub fn derived_facts(&self, rule: &str) -> Option<&Vec<Row>> {
115 self.derived.get(rule)
116 }
117
118 pub fn rows(&self) -> Option<&Vec<Row>> {
120 self.command_results.iter().find_map(|cr| cr.as_query())
121 }
122
123 pub fn columns(&self) -> Option<Vec<String>> {
125 self.rows()
126 .and_then(|rows| rows.first().map(|row| row.keys().cloned().collect()))
127 }
128
129 pub fn stats(&self) -> &LocyStats {
131 &self.stats
132 }
133
134 pub fn iterations(&self) -> usize {
136 self.stats.total_iterations
137 }
138
139 pub fn warnings(&self) -> &[RuntimeWarning] {
141 &self.warnings
142 }
143
144 pub fn has_warning(&self, code: &RuntimeWarningCode) -> bool {
146 self.warnings.iter().any(|w| w.code == *code)
147 }
148}
149
150impl CommandResult {
151 pub fn as_explain(&self) -> Option<&DerivationNode> {
153 match self {
154 CommandResult::Explain(node) => Some(node),
155 _ => None,
156 }
157 }
158
159 pub fn as_query(&self) -> Option<&Vec<Row>> {
161 match self {
162 CommandResult::Query(rows) => Some(rows),
163 _ => None,
164 }
165 }
166
167 pub fn as_abduce(&self) -> Option<&AbductionResult> {
169 match self {
170 CommandResult::Abduce(result) => Some(result),
171 _ => None,
172 }
173 }
174}