@@ -23,56 +23,115 @@ namespace FlowtideDotNet.Core.Optimizer.FilterPushdown
23
23
/// </summary>
24
24
internal class JoinFilterPushdownVisitor : OptimizerBaseVisitor
25
25
{
26
+ private static void TestPushdownNotNull ( JoinRelation joinRelation , Expression expression , List < Expression > leftPushdowns , List < Expression > rightPushdowns )
27
+ {
28
+ if ( ( joinRelation . Type == JoinType . Inner || joinRelation . Type == JoinType . Left || joinRelation . Type == JoinType . Right ) &&
29
+ MergeJoinFindVisitor . Check ( joinRelation , expression , out var leftKey , out var rightKey ) )
30
+ {
31
+ if ( joinRelation . Type == JoinType . Inner || joinRelation . Type == JoinType . Right )
32
+ {
33
+ if ( leftKey . ReferenceSegment is StructReferenceSegment leftStruct )
34
+ {
35
+ leftPushdowns . Add ( new ScalarFunction ( )
36
+ {
37
+ Arguments = new List < Expression > ( )
38
+ {
39
+ new DirectFieldReference ( )
40
+ {
41
+ ReferenceSegment = new StructReferenceSegment ( )
42
+ {
43
+ Field = leftStruct . Field ,
44
+ Child = leftStruct . Child
45
+ }
46
+ }
47
+ } ,
48
+ ExtensionUri = FunctionsComparison . Uri ,
49
+ ExtensionName = FunctionsComparison . IsNotNull
50
+ } ) ;
51
+ }
52
+ }
53
+
54
+ if ( joinRelation . Type == JoinType . Inner || joinRelation . Type == JoinType . Left )
55
+ {
56
+ if ( rightKey . ReferenceSegment is StructReferenceSegment rightStruct )
57
+ {
58
+ rightPushdowns . Add ( new ScalarFunction ( )
59
+ {
60
+ Arguments = new List < Expression > ( )
61
+ {
62
+ new DirectFieldReference ( )
63
+ {
64
+ ReferenceSegment = new StructReferenceSegment ( )
65
+ {
66
+ Field = rightStruct . Field ,
67
+ Child = rightStruct . Child
68
+ }
69
+ }
70
+ } ,
71
+ ExtensionUri = FunctionsComparison . Uri ,
72
+ ExtensionName = FunctionsComparison . IsNotNull
73
+ } ) ;
74
+ }
75
+ }
76
+ }
77
+ }
78
+
26
79
public override Relation VisitJoinRelation ( JoinRelation joinRelation , object state )
27
80
{
28
81
// Check root expression
29
82
var visitor = new JoinExpressionVisitor ( joinRelation . Left . OutputLength ) ;
30
83
visitor . Visit ( joinRelation . Expression ! , state ) ;
84
+
85
+ List < Expression > leftPushdowns = new List < Expression > ( ) ;
86
+ List < Expression > rightPushdowns = new List < Expression > ( ) ;
87
+
88
+ if ( joinRelation . Expression != null )
89
+ {
90
+ TestPushdownNotNull ( joinRelation , joinRelation . Expression , leftPushdowns , rightPushdowns ) ;
91
+
92
+ if ( joinRelation . Expression is ScalarFunction scalarFunc &&
93
+ scalarFunc . ExtensionUri == FunctionsBoolean . Uri && scalarFunc . ExtensionName == FunctionsBoolean . And )
94
+ {
95
+ for ( int i = 0 ; i < scalarFunc . Arguments . Count ; i ++ )
96
+ {
97
+ TestPushdownNotNull ( joinRelation , scalarFunc . Arguments [ i ] , leftPushdowns , rightPushdowns ) ;
98
+ }
99
+ }
100
+ }
101
+
31
102
if ( ! visitor . unknownCase )
32
103
{
33
104
// Only fields from left is used
34
105
if ( visitor . fieldInLeft && ! visitor . fieldInRight && joinRelation . Type == JoinType . Inner )
35
106
{
36
- joinRelation . Left = new FilterRelation ( )
37
- {
38
- Condition = joinRelation . Expression ! ,
39
- Input = joinRelation . Left
40
- } ;
41
- joinRelation . Expression = new BoolLiteral ( ) { Value = true } ;
107
+ leftPushdowns . Add ( new BoolLiteral ( ) { Value = true } ) ;
42
108
}
43
109
// Only field in right is used
44
110
else if ( ! visitor . fieldInLeft && visitor . fieldInRight && joinRelation . Type == JoinType . Inner )
45
111
{
46
- joinRelation . Right = new FilterRelation ( )
47
- {
48
- Condition = joinRelation . Expression ! ,
49
- Input = joinRelation . Right
50
- } ;
51
- joinRelation . Expression = new BoolLiteral ( ) { Value = true } ;
112
+ rightPushdowns . Add ( new BoolLiteral ( ) { Value = true } ) ;
52
113
}
53
114
}
54
115
55
116
if ( joinRelation . Expression is ScalarFunction andFunctionScalar &&
56
117
andFunctionScalar . ExtensionUri == FunctionsBoolean . Uri &&
57
118
andFunctionScalar . ExtensionName == FunctionsBoolean . And )
58
119
{
59
- List < Expression > leftPushDown = new List < Expression > ( ) ;
60
- List < Expression > rightPushDown = new List < Expression > ( ) ;
61
120
for ( int i = 0 ; i < andFunctionScalar . Arguments . Count ; i ++ )
62
121
{
63
122
var expr = andFunctionScalar . Arguments [ i ] ;
64
123
var andVisitor = new JoinExpressionVisitor ( joinRelation . Left . OutputLength ) ;
65
124
andVisitor . Visit ( expr , state ) ;
66
125
if ( andVisitor . fieldInLeft && ! andVisitor . fieldInRight && joinRelation . Type == JoinType . Inner )
67
126
{
68
- leftPushDown . Add ( expr ) ;
127
+ leftPushdowns . Add ( expr ) ;
69
128
andFunctionScalar . Arguments . RemoveAt ( i ) ;
70
129
i -- ;
71
130
}
72
131
// Only field in right is used
73
132
else if ( ! andVisitor . fieldInLeft && andVisitor . fieldInRight && joinRelation . Type == JoinType . Inner )
74
133
{
75
- rightPushDown . Add ( expr ) ;
134
+ rightPushdowns . Add ( expr ) ;
76
135
andFunctionScalar . Arguments . RemoveAt ( i ) ;
77
136
i -- ;
78
137
}
@@ -85,64 +144,65 @@ public override Relation VisitJoinRelation(JoinRelation joinRelation, object sta
85
144
joinRelation . Expression = new BoolLiteral ( ) { Value = true } ;
86
145
}
87
146
}
88
- if ( leftPushDown . Count > 0 )
89
- {
147
+ }
90
148
91
- if ( leftPushDown . Count == 1 )
92
- {
93
- joinRelation . Left = new FilterRelation ( )
94
- {
95
- Condition = leftPushDown [ 0 ] ,
96
- Input = joinRelation . Left
97
- } ;
98
- }
99
- else
149
+ if ( leftPushdowns . Count > 0 )
150
+ {
151
+
152
+ if ( leftPushdowns . Count == 1 )
153
+ {
154
+ joinRelation . Left = new FilterRelation ( )
100
155
{
101
- joinRelation . Left = new FilterRelation ( )
102
- {
103
- Condition = new ScalarFunction ( ) { ExtensionUri = FunctionsBoolean . Uri , ExtensionName = FunctionsBoolean . And , Arguments = leftPushDown } ,
104
- Input = joinRelation . Left
105
- } ;
106
- }
156
+ Condition = leftPushdowns [ 0 ] ,
157
+ Input = joinRelation . Left
158
+ } ;
107
159
}
108
- if ( rightPushDown . Count > 0 )
160
+ else
109
161
{
110
- // Find used fields
111
- var usageVisitor = new ExpressionFieldUsageVisitor ( joinRelation . Left . OutputLength ) ;
112
- foreach ( var expr in rightPushDown )
162
+ joinRelation . Left = new FilterRelation ( )
113
163
{
114
- usageVisitor . Visit ( expr , default ) ;
115
- }
116
- var rightUsageFields = usageVisitor . UsedFieldsRight . Distinct ( ) . ToList ( ) ;
164
+ Condition = new ScalarFunction ( ) { ExtensionUri = FunctionsBoolean . Uri , ExtensionName = FunctionsBoolean . And , Arguments = leftPushdowns } ,
165
+ Input = joinRelation . Left
166
+ } ;
167
+ }
168
+ }
169
+ if ( rightPushdowns . Count > 0 )
170
+ {
171
+ // Find used fields
172
+ var usageVisitor = new ExpressionFieldUsageVisitor ( joinRelation . Left . OutputLength ) ;
173
+ foreach ( var expr in rightPushdowns )
174
+ {
175
+ usageVisitor . Visit ( expr , default ) ;
176
+ }
177
+ var rightUsageFields = usageVisitor . UsedFieldsRight . Distinct ( ) . ToList ( ) ;
117
178
118
- // Build lookup table from old to new field id
119
- Dictionary < int , int > oldToNew = new Dictionary < int , int > ( ) ;
120
- foreach ( var usedField in rightUsageFields )
121
- {
122
- oldToNew . Add ( usedField , usedField - joinRelation . Left . OutputLength ) ;
123
- }
124
- // Replace old ids with the new ids
125
- var replaceVisitor = new ExpressionFieldReplaceVisitor ( oldToNew ) ;
126
- foreach ( var expr in rightPushDown )
127
- {
128
- replaceVisitor . Visit ( expr , default ) ;
129
- }
130
- if ( rightPushDown . Count == 1 )
179
+ // Build lookup table from old to new field id
180
+ Dictionary < int , int > oldToNew = new Dictionary < int , int > ( ) ;
181
+ foreach ( var usedField in rightUsageFields )
182
+ {
183
+ oldToNew . Add ( usedField , usedField - joinRelation . Left . OutputLength ) ;
184
+ }
185
+ // Replace old ids with the new ids
186
+ var replaceVisitor = new ExpressionFieldReplaceVisitor ( oldToNew ) ;
187
+ foreach ( var expr in rightPushdowns )
188
+ {
189
+ replaceVisitor . Visit ( expr , default ) ;
190
+ }
191
+ if ( rightPushdowns . Count == 1 )
192
+ {
193
+ joinRelation . Right = new FilterRelation ( )
131
194
{
132
- joinRelation . Right = new FilterRelation ( )
133
- {
134
- Condition = rightPushDown [ 0 ] ,
135
- Input = joinRelation . Right
136
- } ;
137
- }
138
- else
195
+ Condition = rightPushdowns [ 0 ] ,
196
+ Input = joinRelation . Right
197
+ } ;
198
+ }
199
+ else
200
+ {
201
+ joinRelation . Right = new FilterRelation ( )
139
202
{
140
- joinRelation . Right = new FilterRelation ( )
141
- {
142
- Condition = new ScalarFunction ( ) { ExtensionUri = FunctionsBoolean . Uri , ExtensionName = FunctionsBoolean . And , Arguments = rightPushDown } ,
143
- Input = joinRelation . Right
144
- } ;
145
- }
203
+ Condition = new ScalarFunction ( ) { ExtensionUri = FunctionsBoolean . Uri , ExtensionName = FunctionsBoolean . And , Arguments = rightPushdowns } ,
204
+ Input = joinRelation . Right
205
+ } ;
146
206
}
147
207
}
148
208
0 commit comments