11//! Definition of logical expressions / relations in the Cascades query optimization framework.
22//!
3- //! FIXME: All fields are placeholders, and group IDs are just represented as i32 for now.
4- //! FIXME: Representation needs to know how to "rewrite" child group IDs to whatever a fingerprint
5- //! will need.
3+ //! FIXME: All fields are placeholders.
64//!
7- //! TODO figure out if each relation should be in a different submodule.
5+ //! TODO Remove dead code.
6+ //! TODO Figure out if each relation should be in a different submodule.
87//! TODO This entire file is a WIP.
98
10- use crate :: entities:: * ;
9+ #![ allow( dead_code) ]
10+
11+ use crate :: { entities:: * , memo:: GroupId } ;
12+ use fxhash:: hash;
1113use serde:: { Deserialize , Serialize } ;
1214
13- #[ derive( Clone , Debug ) ]
15+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
1416pub enum LogicalExpression {
1517 Scan ( Scan ) ,
1618 Filter ( Filter ) ,
1719 Join ( Join ) ,
1820}
1921
20- #[ derive( Serialize , Deserialize , Clone , Debug ) ]
22+ /// FIXME: Figure out how to make everything unsigned instead of signed.
23+ impl LogicalExpression {
24+ pub fn kind ( & self ) -> i16 {
25+ match self {
26+ LogicalExpression :: Scan ( _) => 0 ,
27+ LogicalExpression :: Filter ( _) => 1 ,
28+ LogicalExpression :: Join ( _) => 2 ,
29+ }
30+ }
31+
32+ /// Definitions of custom fingerprinting strategies for each kind of logical expression.
33+ pub fn fingerprint ( & self ) -> i64 {
34+ self . fingerprint_with_rewrite ( & [ ] )
35+ }
36+
37+ /// Calculates the fingerprint of a given expression, but replaces all of the children group IDs
38+ /// with a new group ID if it is listed in the input `rewrites` list.
39+ ///
40+ /// TODO Allow each expression to implement a trait that does this.
41+ pub fn fingerprint_with_rewrite ( & self , rewrites : & [ ( GroupId , GroupId ) ] ) -> i64 {
42+ // Closure that rewrites a group ID if needed.
43+ let rewrite = |x : GroupId | {
44+ if rewrites. is_empty ( ) {
45+ return x;
46+ }
47+
48+ if let Some ( i) = rewrites. iter ( ) . position ( |( curr, _new) | & x == curr) {
49+ assert_eq ! ( rewrites[ i] . 0 , x) ;
50+ rewrites[ i] . 1
51+ } else {
52+ x
53+ }
54+ } ;
55+
56+ let kind = self . kind ( ) as u16 as usize ;
57+ let hash = match self {
58+ LogicalExpression :: Scan ( scan) => hash ( scan. table_schema . as_str ( ) ) ,
59+ LogicalExpression :: Filter ( filter) => {
60+ hash ( & rewrite ( filter. child ) . 0 ) ^ hash ( filter. expression . as_str ( ) )
61+ }
62+ LogicalExpression :: Join ( join) => {
63+ hash ( & rewrite ( join. left ) . 0 )
64+ ^ hash ( & rewrite ( join. right ) . 0 )
65+ ^ hash ( join. expression . as_str ( ) )
66+ }
67+ } ;
68+
69+ // Mask out the bottom 16 bits of `hash` and replace them with `kind`.
70+ ( ( hash & !0xFFFF ) | kind) as i64
71+ }
72+ }
73+
74+ #[ derive( Serialize , Deserialize , Clone , Debug , PartialEq , Eq ) ]
2175pub struct Scan {
2276 table_schema : String ,
2377}
2478
25- #[ derive( Serialize , Deserialize , Clone , Debug ) ]
79+ #[ derive( Serialize , Deserialize , Clone , Debug , PartialEq , Eq ) ]
2680pub struct Filter {
27- child : i32 ,
81+ child : GroupId ,
2882 expression : String ,
2983}
3084
31- #[ derive( Serialize , Deserialize , Clone , Debug ) ]
85+ #[ derive( Serialize , Deserialize , Clone , Debug , PartialEq , Eq ) ]
3286pub struct Join {
33- left : i32 ,
34- right : i32 ,
87+ left : GroupId ,
88+ right : GroupId ,
3589 expression : String ,
3690}
3791
@@ -71,17 +125,18 @@ impl From<LogicalExpression> for logical_expression::Model {
71125 }
72126 }
73127
128+ let kind = value. kind ( ) ;
74129 match value {
75130 LogicalExpression :: Scan ( scan) => create_logical_expression (
76- 0 ,
131+ kind ,
77132 serde_json:: to_value ( scan) . expect ( "unable to serialize logical `Scan`" ) ,
78133 ) ,
79134 LogicalExpression :: Filter ( filter) => create_logical_expression (
80- 1 ,
135+ kind ,
81136 serde_json:: to_value ( filter) . expect ( "unable to serialize logical `Filter`" ) ,
82137 ) ,
83138 LogicalExpression :: Join ( join) => create_logical_expression (
84- 2 ,
139+ kind ,
85140 serde_json:: to_value ( join) . expect ( "unable to serialize logical `Join`" ) ,
86141 ) ,
87142 }
@@ -94,24 +149,28 @@ pub use build::*;
94149#[ cfg( test) ]
95150mod build {
96151 use super :: * ;
97- use crate :: expression:: Expression ;
152+ use crate :: expression:: LogicalExpression ;
98153
99- pub fn scan ( table_schema : String ) -> Expression {
100- Expression :: Logical ( LogicalExpression :: Scan ( Scan { table_schema } ) )
154+ pub fn scan ( table_schema : String ) -> LogicalExpression {
155+ LogicalExpression :: Scan ( Scan { table_schema } )
101156 }
102157
103- pub fn filter ( child_group : i32 , expression : String ) -> Expression {
104- Expression :: Logical ( LogicalExpression :: Filter ( Filter {
158+ pub fn filter ( child_group : GroupId , expression : String ) -> LogicalExpression {
159+ LogicalExpression :: Filter ( Filter {
105160 child : child_group,
106161 expression,
107- } ) )
162+ } )
108163 }
109164
110- pub fn join ( left_group : i32 , right_group : i32 , expression : String ) -> Expression {
111- Expression :: Logical ( LogicalExpression :: Join ( Join {
165+ pub fn join (
166+ left_group : GroupId ,
167+ right_group : GroupId ,
168+ expression : String ,
169+ ) -> LogicalExpression {
170+ LogicalExpression :: Join ( Join {
112171 left : left_group,
113172 right : right_group,
114173 expression,
115- } ) )
174+ } )
116175 }
117176}
0 commit comments