pub struct RewriteDisjunctivePredicate;
Expand description
Optimizer pass that rewrites predicates of the form
(A = B AND <expr1>) OR (A = B AND <expr2>) OR ... (A = B AND <exprN>)
Into
(A = B) AND (<expr1> OR <expr2> OR ... <exprN> )
Predicates connected by OR
typically not able to be broken down
and distributed as well as those connected by AND
.
The idea is to rewrite predicates into good_predicate1 AND good_predicate2 AND ...
where good_predicate
means the
predicate has special support in the execution engine.
Equality join predicates (e.g. col1 = col2
), or single column
expressions (e.g. col = 5
) are examples of predicates with
special support.
§TPCH Q19
This optimization is admittedly somewhat of a niche usecase. It’s main use is that it appears in TPCH Q19 and is required to avoid a CROSS JOIN.
Specifically, Q19 has a WHERE clause that looks like
where
(
p_partkey = l_partkey
and p_brand = ‘[BRAND1]’
and p_container in ( ‘SM CASE’, ‘SM BOX’, ‘SM PACK’, ‘SM PKG’)
and l_quantity >= [QUANTITY1] and l_quantity <= [QUANTITY1] + 10
and p_size between 1 and 5
and l_shipmode in (‘AIR’, ‘AIR REG’)
and l_shipinstruct = ‘DELIVER IN PERSON’
)
or
(
p_partkey = l_partkey
and p_brand = ‘[BRAND2]’
and p_container in (‘MED BAG’, ‘MED BOX’, ‘MED PKG’, ‘MED PACK’)
and l_quantity >= [QUANTITY2] and l_quantity <= [QUANTITY2] + 10
and p_size between 1 and 10
and l_shipmode in (‘AIR’, ‘AIR REG’)
and l_shipinstruct = ‘DELIVER IN PERSON’
)
or
(
p_partkey = l_partkey
and p_brand = ‘[BRAND3]’
and p_container in ( ‘LG CASE’, ‘LG BOX’, ‘LG PACK’, ‘LG PKG’)
and l_quantity >= [QUANTITY3] and l_quantity <= [QUANTITY3] + 10
and p_size between 1 and 15
and l_shipmode in (‘AIR’, ‘AIR REG’)
and l_shipinstruct = ‘DELIVER IN PERSON’
)
)
Naively planning this query will result in a CROSS join with that
single large OR filter. However, rewriting it using the rewrite in
this pass results in a proper join predicate, p_partkey = l_partkey
:
where
p_partkey = l_partkey
and l_shipmode in (‘AIR’, ‘AIR REG’)
and l_shipinstruct = ‘DELIVER IN PERSON’
and (
(
and p_brand = ‘[BRAND1]’
and p_container in ( ‘SM CASE’, ‘SM BOX’, ‘SM PACK’, ‘SM PKG’)
and l_quantity >= [QUANTITY1] and l_quantity <= [QUANTITY1] + 10
and p_size between 1 and 5
)
or
(
and p_brand = ‘[BRAND2]’
and p_container in (‘MED BAG’, ‘MED BOX’, ‘MED PKG’, ‘MED PACK’)
and l_quantity >= [QUANTITY2] and l_quantity <= [QUANTITY2] + 10
and p_size between 1 and 10
)
or
(
and p_brand = ‘[BRAND3]’
and p_container in ( ‘LG CASE’, ‘LG BOX’, ‘LG PACK’, ‘LG PKG’)
and l_quantity >= [QUANTITY3] and l_quantity <= [QUANTITY3] + 10
and p_size between 1 and 15
)
)
Implementations§
Trait Implementations§
source§impl Default for RewriteDisjunctivePredicate
impl Default for RewriteDisjunctivePredicate
source§fn default() -> RewriteDisjunctivePredicate
fn default() -> RewriteDisjunctivePredicate
source§impl OptimizerRule for RewriteDisjunctivePredicate
impl OptimizerRule for RewriteDisjunctivePredicate
source§fn apply_order(&self) -> Option<ApplyOrder>
fn apply_order(&self) -> Option<ApplyOrder>
ApplyOrder
for details. Read moresource§fn supports_rewrite(&self) -> bool
fn supports_rewrite(&self) -> bool
source§fn rewrite(
&self,
plan: LogicalPlan,
_config: &dyn OptimizerConfig,
) -> Result<Transformed<LogicalPlan>>
fn rewrite( &self, plan: LogicalPlan, _config: &dyn OptimizerConfig, ) -> Result<Transformed<LogicalPlan>>
plan
to an optimized form, returning Transformed::yes
if the plan was rewritten and Transformed::no
if it was not. Read moresource§fn try_optimize(
&self,
_plan: &LogicalPlan,
_config: &dyn OptimizerConfig,
) -> Result<Option<LogicalPlan>>
fn try_optimize( &self, _plan: &LogicalPlan, _config: &dyn OptimizerConfig, ) -> Result<Option<LogicalPlan>>
plan
to an optimized form, returning None if the plan
cannot be optimized by this rule. Read moreAuto Trait Implementations§
impl Freeze for RewriteDisjunctivePredicate
impl RefUnwindSafe for RewriteDisjunctivePredicate
impl Send for RewriteDisjunctivePredicate
impl Sync for RewriteDisjunctivePredicate
impl Unpin for RewriteDisjunctivePredicate
impl UnwindSafe for RewriteDisjunctivePredicate
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more