1use std::collections::HashMap;
2use std::time::Duration;
3
4use uni_common::Value;
5
6pub type Row = HashMap<String, Value>;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub struct SavepointId(pub u64);
12
13#[derive(Debug, Clone)]
15pub struct LocyResult {
16 pub derived: HashMap<String, Vec<Row>>,
18 pub stats: LocyStats,
20 pub command_results: Vec<CommandResult>,
22}
23
24#[derive(Debug, Clone)]
26pub enum CommandResult {
27 Query(Vec<Row>),
28 Assume(Vec<Row>),
29 Explain(DerivationNode),
30 Abduce(AbductionResult),
31 Derive { affected: usize },
32 Cypher(Vec<Row>),
33}
34
35#[derive(Debug, Clone)]
37pub struct DerivationNode {
38 pub rule: String,
39 pub clause_index: usize,
40 pub priority: Option<i64>,
41 pub bindings: HashMap<String, Value>,
42 pub along_values: HashMap<String, Value>,
43 pub children: Vec<DerivationNode>,
44 pub graph_fact: Option<String>,
45}
46
47#[derive(Debug, Clone)]
49pub struct AbductionResult {
50 pub modifications: Vec<ValidatedModification>,
51}
52
53#[derive(Debug, Clone)]
55pub struct ValidatedModification {
56 pub modification: Modification,
57 pub validated: bool,
58 pub cost: f64,
59}
60
61#[derive(Debug, Clone)]
63pub enum Modification {
64 RemoveEdge {
65 source_var: String,
66 target_var: String,
67 edge_var: String,
68 edge_type: String,
69 match_properties: HashMap<String, Value>,
70 },
71 ChangeProperty {
72 element_var: String,
73 property: String,
74 old_value: Box<Value>,
75 new_value: Box<Value>,
76 },
77 AddEdge {
78 source_var: String,
79 target_var: String,
80 edge_type: String,
81 properties: HashMap<String, Value>,
82 },
83}
84
85#[derive(Debug, Clone, Default)]
87pub struct LocyStats {
88 pub strata_evaluated: usize,
89 pub total_iterations: usize,
90 pub derived_nodes: usize,
91 pub derived_edges: usize,
92 pub evaluation_time: Duration,
93 pub queries_executed: usize,
94 pub mutations_executed: usize,
95 pub peak_memory_bytes: usize,
97}
98
99impl LocyResult {
100 pub fn derived_facts(&self, rule: &str) -> Option<&Vec<Row>> {
102 self.derived.get(rule)
103 }
104
105 pub fn rows(&self) -> Option<&Vec<Row>> {
107 self.command_results.iter().find_map(|cr| cr.as_query())
108 }
109
110 pub fn columns(&self) -> Option<Vec<String>> {
112 self.rows()
113 .and_then(|rows| rows.first().map(|row| row.keys().cloned().collect()))
114 }
115
116 pub fn stats(&self) -> &LocyStats {
118 &self.stats
119 }
120
121 pub fn iterations(&self) -> usize {
123 self.stats.total_iterations
124 }
125}
126
127impl CommandResult {
128 pub fn as_explain(&self) -> Option<&DerivationNode> {
130 match self {
131 CommandResult::Explain(node) => Some(node),
132 _ => None,
133 }
134 }
135
136 pub fn as_query(&self) -> Option<&Vec<Row>> {
138 match self {
139 CommandResult::Query(rows) => Some(rows),
140 _ => None,
141 }
142 }
143
144 pub fn as_abduce(&self) -> Option<&AbductionResult> {
146 match self {
147 CommandResult::Abduce(result) => Some(result),
148 _ => None,
149 }
150 }
151}