use crate::optimizer::heuristic::context::RewriteContext;
use crate::optimizer::heuristic::pattern::Pattern;
use crate::optimizer::heuristic::result::{RewriteResult, TransformResult};
use crate::optimizer::heuristic::rule::{EliminationRule, RewriteRule};
use crate::planning::plan::core::nodes::base::plan_node_traits::SingleInputNode;
use crate::planning::plan::PlanNodeEnum;
#[derive(Debug)]
pub struct DedupEliminationRule;
impl DedupEliminationRule {
pub fn new() -> Self {
Self
}
fn child_guarantees_uniqueness(&self, child: &PlanNodeEnum) -> bool {
if child.is_index_scan() {
return true;
}
match child {
PlanNodeEnum::GetVertices(_) => true,
PlanNodeEnum::GetEdges(_) => true,
PlanNodeEnum::ScanVertices(node) => {
node.limit() == Some(1)
}
PlanNodeEnum::ScanEdges(node) => node.limit() == Some(1),
PlanNodeEnum::Start(_) => true,
_ => false,
}
}
}
impl Default for DedupEliminationRule {
fn default() -> Self {
Self::new()
}
}
impl RewriteRule for DedupEliminationRule {
fn name(&self) -> &'static str {
"DedupEliminationRule"
}
fn pattern(&self) -> Pattern {
Pattern::new_with_name("Dedup")
}
fn apply(
&self,
_ctx: &mut RewriteContext,
node: &PlanNodeEnum,
) -> RewriteResult<Option<TransformResult>> {
let dedup_node = match node {
PlanNodeEnum::Dedup(n) => n,
_ => return Ok(None),
};
let input = dedup_node.input();
if !self.child_guarantees_uniqueness(input) {
return Ok(None);
}
let mut result = TransformResult::new();
result.erase_curr = true;
result.add_new_node(input.clone());
Ok(Some(result))
}
}
impl EliminationRule for DedupEliminationRule {
fn can_eliminate(&self, node: &PlanNodeEnum) -> bool {
match node {
PlanNodeEnum::Dedup(n) => {
let input = n.input();
self.child_guarantees_uniqueness(input)
}
_ => false,
}
}
fn eliminate(
&self,
ctx: &mut RewriteContext,
node: &PlanNodeEnum,
) -> RewriteResult<Option<TransformResult>> {
self.apply(ctx, node)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::optimizer::heuristic::rule::RewriteRule;
#[test]
fn test_dedup_elimination_rule_name() {
let rule = DedupEliminationRule::new();
assert_eq!(rule.name(), "DedupEliminationRule");
}
#[test]
fn test_dedup_elimination_rule_pattern() {
let rule = DedupEliminationRule::new();
let pattern = rule.pattern();
assert!(pattern.node.is_some());
}
#[test]
fn test_child_guarantees_uniqueness() {
let rule = DedupEliminationRule::new();
let start_node =
crate::planning::plan::core::nodes::control_flow::start_node::StartNode::new();
assert!(rule.child_guarantees_uniqueness(&PlanNodeEnum::Start(start_node)));
}
}