@@ -36,23 +36,20 @@ object DefaultOptimizer extends Optimizer {
36
36
// SubQueries are only needed for analysis and can be removed before execution.
37
37
Batch (" Remove SubQueries" , FixedPoint (100 ),
38
38
EliminateSubQueries ) ::
39
- Batch (" Transform Condition" , FixedPoint (100 ),
40
- TransformCondition ) ::
41
- Batch (" Operator Reordering" , FixedPoint (100 ),
39
+ Batch (" Operator Optimizations" , FixedPoint (100 ),
42
40
UnionPushdown ,
43
41
CombineFilters ,
44
42
PushPredicateThroughProject ,
45
- PushPredicateThroughJoin ,
46
43
PushPredicateThroughGenerate ,
47
44
ColumnPruning ,
48
45
ProjectCollapsing ,
49
- CombineLimits ) ::
50
- Batch (" ConstantFolding" , FixedPoint (100 ),
46
+ CombineLimits ,
51
47
NullPropagation ,
52
48
OptimizeIn ,
53
49
ConstantFolding ,
54
50
LikeSimplification ,
55
51
BooleanSimplification ,
52
+ PushPredicateThroughJoin ,
56
53
SimplifyFilters ,
57
54
SimplifyCasts ,
58
55
SimplifyCaseConversionExpressions ) ::
@@ -62,80 +59,6 @@ object DefaultOptimizer extends Optimizer {
62
59
ConvertToLocalRelation ) :: Nil
63
60
}
64
61
65
- /**
66
- * Transform and/or Condition:
67
- * 1. a && a => a
68
- * 2. (a || b) && (a || c) => a || (b && c)
69
- * 3. a || a => a
70
- * 4. (a && b) || (a && c) => a && (b || c)
71
- */
72
- object TransformCondition extends Rule [LogicalPlan ] with PredicateHelper {
73
- def apply (plan : LogicalPlan ): LogicalPlan = plan transform {
74
- case q : LogicalPlan => q transformExpressionsUp {
75
- case and @ And (left, right) => (left, right) match {
76
-
77
- // a && a => a
78
- case (l, r) if l fastEquals r => l
79
- // (a || b) && (a || c) => a || (b && c)
80
- case _ =>
81
- // 1. Split left and right to get the disjunctive predicates,
82
- // i.e. lhsSet = (a, b), rhsSet = (a, c)
83
- // 2. Find the common predict between lhsSet and rhsSet, i.e. common = (a)
84
- // 3. Remove common predict from lhsSet and rhsSet, i.e. ldiff = (b), rdiff = (c)
85
- // 4. Apply the formula, get the optimized predicate: common || (ldiff && rdiff)
86
- val lhsSet = splitDisjunctivePredicates(left).toSet
87
- val rhsSet = splitDisjunctivePredicates(right).toSet
88
- val common = lhsSet.intersect(rhsSet)
89
- if (common.isEmpty) {
90
- // No common factors, return the original predicate
91
- and
92
- } else {
93
- val ldiff = lhsSet.diff(common)
94
- val rdiff = rhsSet.diff(common)
95
- if (ldiff.isEmpty || rdiff.isEmpty) {
96
- // (a || b || c || ...) && (a || b) => (a || b)
97
- common.reduce(Or )
98
- } else {
99
- // (a || b || c || ...) && (a || b || d || ...) =>
100
- // ((c || ...) && (d || ...)) || a || b
101
- (common + And (ldiff.reduce(Or ), rdiff.reduce(Or ))).reduce(Or )
102
- }
103
- }
104
- } // end of And(left, right)
105
-
106
- case or @ Or (left, right) => (left, right) match {
107
-
108
- case (l, r) if l fastEquals r => l
109
- // (a && b) || (a && c) => a && (b || c)
110
- case _ =>
111
- // 1. Split left and right to get the conjunctive predicates,
112
- // i.e. lhsSet = (a, b), rhsSet = (a, c)
113
- // 2. Find the common predict between lhsSet and rhsSet, i.e. common = (a)
114
- // 3. Remove common predict from lhsSet and rhsSet, i.e. ldiff = (b), rdiff = (c)
115
- // 4. Apply the formula, get the optimized predicate: common && (ldiff || rdiff)
116
- val lhsSet = splitConjunctivePredicates(left).toSet
117
- val rhsSet = splitConjunctivePredicates(right).toSet
118
- val common = lhsSet.intersect(rhsSet)
119
- if (common.isEmpty) {
120
- // No common factors, return the original predicate
121
- or
122
- } else {
123
- val ldiff = lhsSet.diff(common)
124
- val rdiff = rhsSet.diff(common)
125
- if (ldiff.isEmpty || rdiff.isEmpty) {
126
- // (a && b) || (a && b && c && ...) => a && b
127
- common.reduce(And )
128
- } else {
129
- // (a && b && c && ...) || (a && b && d && ...) =>
130
- // ((c && ...) || (d && ...)) && a && b
131
- (common + Or (ldiff.reduce(And ), rdiff.reduce(And ))).reduce(And )
132
- }
133
- }
134
- } // end of Or(left, right)
135
- }
136
- }
137
- }
138
-
139
62
/**
140
63
* Pushes operations to either side of a Union.
141
64
*/
@@ -423,7 +346,32 @@ object BooleanSimplification extends Rule[LogicalPlan] with PredicateHelper {
423
346
// l && false => false
424
347
case (_, Literal (false , BooleanType )) => Literal (false )
425
348
// a && a => a
426
- case _ => and
349
+ case (l, r) if l fastEquals r => l
350
+ // (a || b) && (a || c) => a || (b && c)
351
+ case _ =>
352
+ // 1. Split left and right to get the disjunctive predicates,
353
+ // i.e. lhsSet = (a, b), rhsSet = (a, c)
354
+ // 2. Find the common predict between lhsSet and rhsSet, i.e. common = (a)
355
+ // 3. Remove common predict from lhsSet and rhsSet, i.e. ldiff = (b), rdiff = (c)
356
+ // 4. Apply the formula, get the optimized predicate: common || (ldiff && rdiff)
357
+ val lhsSet = splitDisjunctivePredicates(left).toSet
358
+ val rhsSet = splitDisjunctivePredicates(right).toSet
359
+ val common = lhsSet.intersect(rhsSet)
360
+ if (common.isEmpty) {
361
+ // No common factors, return the original predicate
362
+ and
363
+ } else {
364
+ val ldiff = lhsSet.diff(common)
365
+ val rdiff = rhsSet.diff(common)
366
+ if (ldiff.isEmpty || rdiff.isEmpty) {
367
+ // (a || b || c || ...) && (a || b) => (a || b)
368
+ common.reduce(Or )
369
+ } else {
370
+ // (a || b || c || ...) && (a || b || d || ...) =>
371
+ // ((c || ...) && (d || ...)) || a || b
372
+ (common + And (ldiff.reduce(Or ), rdiff.reduce(Or ))).reduce(Or )
373
+ }
374
+ }
427
375
} // end of And(left, right)
428
376
429
377
case or @ Or (left, right) => (left, right) match {
@@ -435,7 +383,33 @@ object BooleanSimplification extends Rule[LogicalPlan] with PredicateHelper {
435
383
case (Literal (false , BooleanType ), r) => r
436
384
// l || false => l
437
385
case (l, Literal (false , BooleanType )) => l
438
- case _ => or
386
+ // a || b = a
387
+ case (l, r) if l fastEquals r => l
388
+ // (a && b) || (a && c) => a && (b || c)
389
+ case _ =>
390
+ // 1. Split left and right to get the conjunctive predicates,
391
+ // i.e. lhsSet = (a, b), rhsSet = (a, c)
392
+ // 2. Find the common predict between lhsSet and rhsSet, i.e. common = (a)
393
+ // 3. Remove common predict from lhsSet and rhsSet, i.e. ldiff = (b), rdiff = (c)
394
+ // 4. Apply the formula, get the optimized predicate: common && (ldiff || rdiff)
395
+ val lhsSet = splitConjunctivePredicates(left).toSet
396
+ val rhsSet = splitConjunctivePredicates(right).toSet
397
+ val common = lhsSet.intersect(rhsSet)
398
+ if (common.isEmpty) {
399
+ // No common factors, return the original predicate
400
+ or
401
+ } else {
402
+ val ldiff = lhsSet.diff(common)
403
+ val rdiff = rhsSet.diff(common)
404
+ if (ldiff.isEmpty || rdiff.isEmpty) {
405
+ // (a && b) || (a && b && c && ...) => a && b
406
+ common.reduce(And )
407
+ } else {
408
+ // (a && b && c && ...) || (a && b && d && ...) =>
409
+ // ((c && ...) || (d && ...)) && a && b
410
+ (common + Or (ldiff.reduce(And ), rdiff.reduce(And ))).reduce(And )
411
+ }
412
+ }
439
413
} // end of Or(left, right)
440
414
441
415
case not @ Not (exp) => exp match {
0 commit comments