Skip to content
This repository was archived by the owner on Jan 7, 2025. It is now read-only.

Commit 7ac3930

Browse files
authored
feat(core): support physical properties in heuristics (#230)
* add physical property builder * support building and passing through physical properties in heuristics (we can change the behavior later, i.e., choose to not passthrough but simply add new nodes to satisfy) * add test cases for heuristics + physical properties --------- Signed-off-by: Alex Chi <[email protected]>
1 parent c77a719 commit 7ac3930

19 files changed

+1191
-221
lines changed

Cargo.lock

+31-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

optd-core/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ serde = { version = "1.0", features = ["derive", "rc"] }
1919
arrow-schema = "47.0.0"
2020
chrono = "0.4"
2121
erased-serde = "0.4"
22+
23+
[dev-dependencies]
24+
pretty_assertions = "1.4.1"

optd-core/src/cascades/memo.rs

+17-150
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file or at
44
// https://opensource.org/licenses/MIT.
55

6-
use std::any::Any;
76
use std::collections::hash_map::Entry;
87
use std::collections::{HashMap, HashSet};
98
use std::sync::Arc;
@@ -14,8 +13,8 @@ use tracing::trace;
1413

1514
use super::optimizer::{ExprId, GroupId, PredId};
1615
use crate::cost::{Cost, Statistics};
16+
use crate::logical_property::{LogicalProperty, LogicalPropertyBuilderAny};
1717
use crate::nodes::{ArcPlanNode, ArcPredNode, NodeType, PlanNode, PlanNodeOrGroup};
18-
use crate::property::PropertyBuilderAny;
1918

2019
pub type ArcMemoPlanNode<T> = Arc<MemoPlanNode<T>>;
2120

@@ -89,7 +88,7 @@ pub struct GroupInfo {
8988
pub struct Group {
9089
pub(crate) group_exprs: HashSet<ExprId>,
9190
pub(crate) info: GroupInfo,
92-
pub(crate) properties: Arc<[Box<dyn Any + Send + Sync + 'static>]>,
91+
pub(crate) properties: Arc<[Box<dyn LogicalProperty>]>,
9392
}
9493

9594
/// Trait for memo table implementations.
@@ -262,7 +261,7 @@ pub struct NaiveMemo<T: NodeType> {
262261

263262
// Internal states.
264263
group_expr_counter: usize,
265-
property_builders: Arc<[Box<dyn PropertyBuilderAny<T>>]>,
264+
property_builders: Arc<[Box<dyn LogicalPropertyBuilderAny<T>>]>,
266265

267266
// Indexes.
268267
expr_node_to_expr_id: HashMap<MemoPlanNode<T>, ExprId>,
@@ -376,7 +375,7 @@ impl<T: NodeType> Memo<T> for NaiveMemo<T> {
376375
}
377376

378377
impl<T: NodeType> NaiveMemo<T> {
379-
pub fn new(property_builders: Arc<[Box<dyn PropertyBuilderAny<T>>]>) -> Self {
378+
pub fn new(property_builders: Arc<[Box<dyn LogicalPropertyBuilderAny<T>>]>) -> Self {
380379
Self {
381380
expr_id_to_group_id: HashMap::new(),
382381
expr_id_to_expr_node: HashMap::new(),
@@ -615,10 +614,7 @@ impl<T: NodeType> NaiveMemo<T> {
615614
(group_id, expr_id)
616615
}
617616

618-
fn infer_properties(
619-
&self,
620-
memo_node: MemoPlanNode<T>,
621-
) -> Vec<Box<dyn Any + 'static + Send + Sync>> {
617+
fn infer_properties(&self, memo_node: MemoPlanNode<T>) -> Vec<Box<dyn LogicalProperty>> {
622618
let child_properties = memo_node
623619
.children
624620
.iter()
@@ -628,7 +624,7 @@ impl<T: NodeType> NaiveMemo<T> {
628624
for (id, builder) in self.property_builders.iter().enumerate() {
629625
let child_properties = child_properties
630626
.iter()
631-
.map(|x| x[id].as_ref() as &dyn std::any::Any)
627+
.map(|x| x[id].as_ref())
632628
.collect::<Vec<_>>();
633629
let child_predicates = memo_node
634630
.predicates
@@ -678,107 +674,15 @@ impl<T: NodeType> NaiveMemo<T> {
678674
}
679675

680676
#[cfg(test)]
681-
mod tests {
682-
677+
pub(crate) mod tests {
683678
use super::*;
684679
use crate::{
685-
nodes::{PredNode, Value},
686-
property::PropertyBuilder,
680+
nodes::Value,
681+
tests::common::{
682+
expr, group, join, list, project, scan, MemoTestRelTyp, TestProp, TestPropertyBuilder,
683+
},
687684
};
688685

689-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
690-
enum MemoTestRelTyp {
691-
Join,
692-
Project,
693-
Scan,
694-
}
695-
696-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
697-
enum MemoTestPredTyp {
698-
List,
699-
Expr,
700-
TableName,
701-
}
702-
703-
impl std::fmt::Display for MemoTestRelTyp {
704-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
705-
write!(f, "{:?}", self)
706-
}
707-
}
708-
709-
impl std::fmt::Display for MemoTestPredTyp {
710-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
711-
write!(f, "{:?}", self)
712-
}
713-
}
714-
715-
impl NodeType for MemoTestRelTyp {
716-
type PredType = MemoTestPredTyp;
717-
718-
fn is_logical(&self) -> bool {
719-
matches!(self, Self::Project | Self::Scan | Self::Join)
720-
}
721-
}
722-
723-
fn join(
724-
left: impl Into<PlanNodeOrGroup<MemoTestRelTyp>>,
725-
right: impl Into<PlanNodeOrGroup<MemoTestRelTyp>>,
726-
cond: ArcPredNode<MemoTestRelTyp>,
727-
) -> ArcPlanNode<MemoTestRelTyp> {
728-
Arc::new(PlanNode {
729-
typ: MemoTestRelTyp::Join,
730-
children: vec![left.into(), right.into()],
731-
predicates: vec![cond],
732-
})
733-
}
734-
735-
fn scan(table: &str) -> ArcPlanNode<MemoTestRelTyp> {
736-
Arc::new(PlanNode {
737-
typ: MemoTestRelTyp::Scan,
738-
children: vec![],
739-
predicates: vec![table_name(table)],
740-
})
741-
}
742-
743-
fn table_name(table: &str) -> ArcPredNode<MemoTestRelTyp> {
744-
Arc::new(PredNode {
745-
typ: MemoTestPredTyp::TableName,
746-
children: vec![],
747-
data: Some(Value::String(table.to_string().into())),
748-
})
749-
}
750-
751-
fn project(
752-
input: impl Into<PlanNodeOrGroup<MemoTestRelTyp>>,
753-
expr_list: ArcPredNode<MemoTestRelTyp>,
754-
) -> ArcPlanNode<MemoTestRelTyp> {
755-
Arc::new(PlanNode {
756-
typ: MemoTestRelTyp::Project,
757-
children: vec![input.into()],
758-
predicates: vec![expr_list],
759-
})
760-
}
761-
762-
fn list(items: Vec<ArcPredNode<MemoTestRelTyp>>) -> ArcPredNode<MemoTestRelTyp> {
763-
Arc::new(PredNode {
764-
typ: MemoTestPredTyp::List,
765-
children: items,
766-
data: None,
767-
})
768-
}
769-
770-
fn expr(data: Value) -> ArcPredNode<MemoTestRelTyp> {
771-
Arc::new(PredNode {
772-
typ: MemoTestPredTyp::Expr,
773-
children: vec![],
774-
data: Some(data),
775-
})
776-
}
777-
778-
fn group(group_id: GroupId) -> PlanNodeOrGroup<MemoTestRelTyp> {
779-
PlanNodeOrGroup::Group(group_id)
780-
}
781-
782686
#[test]
783687
fn add_predicate() {
784688
let mut memo = NaiveMemo::<MemoTestRelTyp>::new(Arc::new([]));
@@ -882,49 +786,8 @@ mod tests {
882786
assert_eq!(memo.get_expr_info(expr1), memo.get_expr_info(expr2));
883787
}
884788

885-
struct TestPropertyBuilder;
886-
887-
#[derive(Clone, Debug)]
888-
struct TestProp(Vec<String>);
889-
impl std::fmt::Display for TestProp {
890-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
891-
write!(f, "{:?}", self.0)
892-
}
893-
}
894-
impl PropertyBuilder<MemoTestRelTyp> for TestPropertyBuilder {
895-
type Prop = TestProp;
896-
fn derive(
897-
&self,
898-
typ: MemoTestRelTyp,
899-
pred: &[ArcPredNode<MemoTestRelTyp>],
900-
children: &[&Self::Prop],
901-
) -> Self::Prop {
902-
match typ {
903-
MemoTestRelTyp::Join => {
904-
let mut a = children[0].0.clone();
905-
let b = children[1].0.clone();
906-
a.extend(b);
907-
TestProp(a)
908-
}
909-
MemoTestRelTyp::Project => {
910-
let preds = &pred[0].children;
911-
TestProp(
912-
preds
913-
.iter()
914-
.map(|x| x.data.as_ref().unwrap().as_i64().to_string())
915-
.collect(),
916-
)
917-
}
918-
MemoTestRelTyp::Scan => TestProp(vec!["scan_col".to_string()]),
919-
}
920-
}
921-
fn property_name(&self) -> &'static str {
922-
"test"
923-
}
924-
}
925-
926789
#[test]
927-
fn logical_property() {
790+
fn derive_logical_property() {
928791
let mut memo = NaiveMemo::new(Arc::new([Box::new(TestPropertyBuilder)]));
929792
let (group_id, _) = memo.add_new_expr(join(
930793
scan("t1"),
@@ -937,7 +800,11 @@ mod tests {
937800
let group = memo.get_group(group_id);
938801
assert_eq!(group.properties.len(), 1);
939802
assert_eq!(
940-
group.properties[0].downcast_ref::<TestProp>().unwrap().0,
803+
group.properties[0]
804+
.as_any()
805+
.downcast_ref::<TestProp>()
806+
.unwrap()
807+
.0,
941808
vec!["scan_col", "1", "2"]
942809
);
943810
}

0 commit comments

Comments
 (0)