mod choose;
mod exec;
mod lexical;
mod prune;
#[cfg(any(test, feature = "test-support"))]
mod receipt;
pub use choose::{ALLOW_LIST_ROWS_THRESHOLD, choose_scan_branch};
pub use exec::{FilteredSearchError, FilteredSearchOutcome};
pub(crate) use lexical::search_lexical_filtered_refs_controlled;
pub use lexical::{
LEXICAL_ALLOW_LIST_DIVISOR, LexicalBranch, LexicalFilterError, LexicalSearchOutcome,
search_lexical_filtered,
};
pub use prune::{PlanError, segment_may_match, validate_predicate};
#[cfg(any(test, feature = "test-support"))]
pub(crate) use receipt::MetadataQueryContext;
#[cfg(any(test, feature = "test-support"))]
#[doc(hidden)]
pub use receipt::{
MetadataControllerError, MetadataExecutionReceipt, MetadataFeatureDetail,
MetadataFeatureReceipt, MetadataTestArm, MetadataTestController,
};
use crate::ingest::RowSource;
use crate::meta::Predicate;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SegmentBranch {
Pruned,
ExactAllowList,
MaskedScan,
FilteredGraph,
GraphExactFallback,
Graph,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SegmentTier {
ActiveScan,
SealedScan,
SealedGraph,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum FilterMode {
None,
Pre,
InTraversal,
Post,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PlanFallback {
None,
VisitedBudget,
EfWidened,
CandidateShortfall,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ExplicitScanTier {
Exact,
Scan,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ScanReason {
BelowGraphThreshold {
rows: u32,
min_rows: u32,
},
GraphPending,
ActiveSegment,
FullMaterialization,
WideningCap {
ef: usize,
rows: usize,
},
ExplicitTier(ExplicitScanTier),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(usize)]
pub enum ScanReasonCounter {
BelowGraphThreshold = 0,
GraphPending = 1,
ActiveSegment = 2,
FullMaterialization = 3,
WideningCap = 4,
ExplicitExact = 5,
ExplicitScan = 6,
}
impl ScanReasonCounter {
#[must_use]
pub const fn index(self) -> usize {
self as usize
}
}
pub const SCAN_REASON_COUNTER_COUNT: usize = 7;
impl ScanReason {
pub(crate) const fn counter(self) -> ScanReasonCounter {
match self {
Self::BelowGraphThreshold { .. } => ScanReasonCounter::BelowGraphThreshold,
Self::GraphPending => ScanReasonCounter::GraphPending,
Self::ActiveSegment => ScanReasonCounter::ActiveSegment,
Self::FullMaterialization => ScanReasonCounter::FullMaterialization,
Self::WideningCap { .. } => ScanReasonCounter::WideningCap,
Self::ExplicitTier(ExplicitScanTier::Exact) => ScanReasonCounter::ExplicitExact,
Self::ExplicitTier(ExplicitScanTier::Scan) => ScanReasonCounter::ExplicitScan,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum PlanNode {
Scan {
source: RowSource,
branch: SegmentBranch,
},
Lexical {
allow_list_driven: bool,
},
Graph {
source: RowSource,
fallback: Option<Box<PlanNode>>,
},
BitmapIntersect {
predicate: Predicate,
input: Box<PlanNode>,
},
Fusion {
inputs: Vec<PlanNode>,
},
}
#[derive(Clone, Debug, PartialEq)]
pub struct SegmentPlan {
pub source: RowSource,
pub tier: SegmentTier,
pub branch: SegmentBranch,
pub filter_mode: FilterMode,
pub filter_cardinality: u64,
pub approximate: bool,
pub fallback: PlanFallback,
pub scan_reason: Option<ScanReason>,
pub ef_requested: Option<usize>,
pub ef_effective: Option<usize>,
pub graph_profile: Option<crate::graph::search::GraphSearchProfile>,
pub node: PlanNode,
}
impl SegmentPlan {
pub(crate) fn unfiltered_scan(
source: RowSource,
tier: SegmentTier,
cardinality: u64,
scan_reason: ScanReason,
) -> Self {
let branch = SegmentBranch::MaskedScan;
Self {
source,
tier,
branch,
filter_mode: FilterMode::None,
filter_cardinality: cardinality,
approximate: false,
fallback: PlanFallback::None,
scan_reason: Some(scan_reason),
ef_requested: None,
ef_effective: None,
graph_profile: None,
node: PlanNode::Scan { source, branch },
}
}
pub(crate) fn unfiltered_graph(
source: RowSource,
cardinality: u64,
ef_requested: Option<usize>,
ef_effective: usize,
graph_profile: crate::graph::search::GraphSearchProfile,
) -> Self {
Self {
source,
tier: SegmentTier::SealedGraph,
branch: SegmentBranch::Graph,
filter_mode: FilterMode::None,
filter_cardinality: cardinality,
approximate: true,
fallback: PlanFallback::None,
scan_reason: None,
ef_requested,
ef_effective: Some(ef_effective),
graph_profile: Some(graph_profile),
node: PlanNode::Graph {
source,
fallback: None,
},
}
}
pub(crate) fn unfiltered_pruned(source: RowSource, cardinality: u64) -> Self {
Self {
source,
tier: SegmentTier::SealedGraph,
branch: SegmentBranch::Pruned,
filter_mode: FilterMode::None,
filter_cardinality: cardinality,
approximate: false,
fallback: PlanFallback::None,
scan_reason: None,
ef_requested: None,
ef_effective: None,
graph_profile: None,
node: PlanNode::Scan {
source,
branch: SegmentBranch::Pruned,
},
}
}
pub(crate) fn exact(
source: RowSource,
tier: SegmentTier,
branch: SegmentBranch,
cardinality: u64,
scan_reason: Option<ScanReason>,
) -> Self {
Self {
source,
tier,
branch,
filter_mode: FilterMode::Pre,
filter_cardinality: cardinality,
approximate: false,
fallback: PlanFallback::None,
scan_reason,
ef_requested: None,
ef_effective: None,
graph_profile: None,
node: PlanNode::Scan { source, branch },
}
}
pub(crate) fn filtered_graph(
source: RowSource,
cardinality: u64,
ef_requested: Option<usize>,
ef_effective: usize,
branch: SegmentBranch,
fallback: PlanFallback,
graph_profile: crate::graph::search::GraphSearchProfile,
) -> Self {
let (node, filter_mode, approximate) = match branch {
SegmentBranch::FilteredGraph => (
PlanNode::Graph {
source,
fallback: None,
},
FilterMode::InTraversal,
true,
),
SegmentBranch::GraphExactFallback => (
PlanNode::Graph {
source,
fallback: Some(Box::new(PlanNode::Scan {
source,
branch: SegmentBranch::ExactAllowList,
})),
},
FilterMode::Pre,
false,
),
_ => (PlanNode::Scan { source, branch }, FilterMode::Pre, false),
};
Self {
source,
tier: SegmentTier::SealedGraph,
branch,
filter_mode,
filter_cardinality: cardinality,
approximate,
fallback,
scan_reason: None,
ef_requested,
ef_effective: Some(ef_effective),
graph_profile: Some(graph_profile),
node,
}
}
pub(crate) fn with_predicate(mut self, predicate: &Predicate) -> Self {
self.node = PlanNode::BitmapIntersect {
predicate: predicate.clone(),
input: Box::new(self.node),
};
self
}
}