Skip to main content

hawdb_core/
access.rs

1// Copyright 2026 Nowledge
2// SPDX-License-Identifier: Apache-2.0
3
4//! Language-neutral graph index access requests shared by planning and storage.
5
6use crate::Value;
7
8/// One equality-index branch in a bounded exact-property union seek.
9#[derive(Debug, Clone, PartialEq)]
10pub struct ExactPropertySeekBranch {
11    pub property: String,
12    pub values: Vec<Value>,
13}
14
15/// Leading equalities followed by one bounded range on an ordered composite index.
16#[derive(Debug, Clone, PartialEq)]
17pub struct CompositeRangeSeek {
18    pub index_properties: Vec<String>,
19    pub equality_prefix: Vec<(String, Value)>,
20    pub range_property: String,
21    pub lower: Option<(Value, bool)>,
22    pub upper: Option<(Value, bool)>,
23}
24
25/// Ordered traversal of complete non-NULL keys, after an exclusive suffix tuple.
26/// Canonical-query planning must prove complete key coverage and comparator compatibility.
27#[derive(Debug, Clone, PartialEq)]
28pub struct CompositeOrderedSeek {
29    pub index_properties: Vec<String>,
30    pub equality_prefix: Vec<(String, Value)>,
31    pub after: Option<Vec<Value>>,
32    pub descending: bool,
33}
34
35/// Candidate source used by a fused scalar node projection.
36///
37/// Keeping the access path beside the required-property set lets storage
38/// decode only fields needed by the residual predicate and output projection,
39/// without giving up an index seek selected earlier by the optimizer.
40#[derive(Debug, Clone, PartialEq)]
41pub enum NodeProjectionAccess {
42    LabelScan,
43    PropertyValues {
44        property: String,
45        values: Vec<Value>,
46    },
47    PropertyUnion {
48        branches: Vec<ExactPropertySeekBranch>,
49    },
50    CompositeEquality {
51        predicates: Vec<(String, Value)>,
52    },
53    CompositeRange {
54        seek: CompositeRangeSeek,
55    },
56    CompositeOrdered {
57        seek: CompositeOrderedSeek,
58    },
59    PropertyRange {
60        property: String,
61        lower: Option<(Value, bool)>,
62        upper: Option<(Value, bool)>,
63    },
64    FullText {
65        property: String,
66        query: String,
67    },
68}
69
70impl NodeProjectionAccess {
71    pub fn is_label_scan(&self) -> bool {
72        matches!(self, Self::LabelScan)
73    }
74
75    pub fn kind_name(&self) -> &'static str {
76        match self {
77            Self::LabelScan => "label_scan",
78            Self::PropertyValues { .. } => "property_values",
79            Self::PropertyUnion { .. } => "property_union",
80            Self::CompositeEquality { .. } => "composite_equality",
81            Self::CompositeRange { .. } => "composite_range",
82            Self::CompositeOrdered { .. } => "composite_ordered",
83            Self::PropertyRange { .. } => "property_range",
84            Self::FullText { .. } => "full_text",
85        }
86    }
87
88    /// Returns the access operator represented inside the fused projection.
89    pub fn physical_operator_name(&self) -> &'static str {
90        match self {
91            Self::LabelScan => "SeqNodeScan",
92            Self::PropertyValues { values, .. } if values.len() == 1 => "IndexNodeSeek",
93            Self::PropertyValues { .. } => "IndexNodeMultiSeek",
94            Self::PropertyUnion { .. } => "IndexNodeUnionSeek",
95            Self::CompositeEquality { .. } => "IndexNodeCompositeSeek",
96            Self::CompositeRange { .. } => "IndexNodeCompositeRangeSeek",
97            Self::CompositeOrdered { .. } => "IndexNodeCompositeOrderedSeek",
98            Self::PropertyRange { .. } => "IndexNodeRangeSeek",
99            Self::FullText { .. } => "IndexNodeTextSeek",
100        }
101    }
102}