risingwave_frontend/optimizer/rule/
mod.rs1use std::convert::Infallible;
18use std::ops::FromResidual;
19
20use thiserror_ext::AsReport;
21
22use super::PlanRef;
23use crate::error::RwError;
24
25pub enum ApplyResult<T> {
27 Ok(T),
29 NotApplicable,
32 Err(RwError),
35}
36
37impl<T> ApplyResult<T> {
38 pub fn unwrap(self) -> T {
40 match self {
41 ApplyResult::Ok(plan) => plan,
42 ApplyResult::NotApplicable => panic!("unwrap ApplyResult::NotApplicable"),
43 ApplyResult::Err(e) => panic!("unwrap ApplyResult::Err, error: {:?}", e.as_report()),
44 }
45 }
46}
47
48impl<T> FromResidual<Option<Infallible>> for ApplyResult<T> {
50 fn from_residual(residual: Option<Infallible>) -> Self {
51 match residual {
52 Some(i) => match i {},
53 None => Self::NotApplicable,
54 }
55 }
56}
57
58impl<T, E> FromResidual<Result<Infallible, E>> for ApplyResult<T>
60where
61 E: Into<RwError>,
62{
63 fn from_residual(residual: Result<Infallible, E>) -> Self {
64 match residual {
65 Ok(i) => match i {},
66 Err(e) => Self::Err(e.into()),
67 }
68 }
69}
70
71trait InfallibleRule<C: ConventionMarker>: Send + Sync + Description {
75 fn apply(&self, plan: PlanRef<C>) -> Option<PlanRef<C>>;
80}
81
82use InfallibleRule as Rule;
83
84pub trait FallibleRule<C: ConventionMarker>: Send + Sync + Description {
89 fn apply(&self, plan: PlanRef<C>) -> ApplyResult<PlanRef<C>>;
96}
97
98impl<C: ConventionMarker, R> FallibleRule<C> for R
99where
100 R: InfallibleRule<C>,
101{
102 fn apply(&self, plan: PlanRef<C>) -> ApplyResult<PlanRef<C>> {
103 match InfallibleRule::apply(self, plan) {
104 Some(plan) => ApplyResult::Ok(plan),
105 None => ApplyResult::NotApplicable,
106 }
107 }
108}
109
110pub trait Description {
111 fn description(&self) -> &str;
112}
113
114pub(super) type BoxedRule<C> = Box<dyn FallibleRule<C>>;
115
116mod correlated_expr_rewriter;
117mod logical_filter_expression_simplify_rule;
118pub use logical_filter_expression_simplify_rule::*;
119mod mv_selection_rule;
120pub use mv_selection_rule::*;
121mod over_window_merge_rule;
122pub use over_window_merge_rule::*;
123mod project_join_merge_rule;
124pub use project_join_merge_rule::*;
125mod project_eliminate_rule;
126pub use project_eliminate_rule::*;
127mod project_merge_rule;
128pub use project_merge_rule::*;
129mod project_top_n_transpose_rule;
130pub use project_top_n_transpose_rule::*;
131mod top_n_project_transpose_rule;
132pub use top_n_project_transpose_rule::*;
133mod pull_up_correlated_predicate_rule;
134pub use pull_up_correlated_predicate_rule::*;
135mod pull_up_correlated_project_value_rule;
136pub use pull_up_correlated_project_value_rule::*;
137mod index_delta_join_rule;
138pub use index_delta_join_rule::*;
139mod left_deep_tree_join_ordering_rule;
140pub use left_deep_tree_join_ordering_rule::*;
141mod apply_agg_transpose_rule;
142pub use apply_agg_transpose_rule::*;
143mod apply_filter_transpose_rule;
144pub use apply_filter_transpose_rule::*;
145mod apply_project_transpose_rule;
146pub use apply_project_transpose_rule::*;
147mod apply_eliminate_rule;
148pub use apply_eliminate_rule::*;
149mod translate_apply_rule;
150pub use translate_apply_rule::*;
151mod merge_multijoin_rule;
152pub use merge_multijoin_rule::*;
153mod max_one_row_eliminate_rule;
154pub use max_one_row_eliminate_rule::*;
155mod apply_join_transpose_rule;
156pub use apply_join_transpose_rule::*;
157mod apply_to_join_rule;
158pub use apply_to_join_rule::*;
159mod distinct_agg_rule;
160pub use distinct_agg_rule::*;
161mod index_selection_rule;
162pub use index_selection_rule::*;
163mod push_calculation_of_join_rule;
164pub use push_calculation_of_join_rule::*;
165mod join_commute_rule;
166mod over_window_to_agg_and_join_rule;
167pub use over_window_to_agg_and_join_rule::*;
168mod over_window_split_rule;
169pub use over_window_split_rule::*;
170mod over_window_to_topn_rule;
171pub use join_commute_rule::*;
172pub use over_window_to_topn_rule::*;
173mod union_to_distinct_rule;
174pub use union_to_distinct_rule::*;
175mod agg_project_merge_rule;
176pub use agg_project_merge_rule::*;
177mod union_merge_rule;
178pub use union_merge_rule::*;
179mod dag_to_tree_rule;
180pub use dag_to_tree_rule::*;
181mod apply_share_eliminate_rule;
182pub use apply_share_eliminate_rule::*;
183mod top_n_on_index_rule;
184pub use top_n_on_index_rule::*;
185mod stream;
186pub use stream::bushy_tree_join_ordering_rule::*;
187pub use stream::filter_with_now_to_join_rule::*;
188pub use stream::generate_series_with_now_rule::*;
189pub use stream::separate_consecutive_join_rule::*;
190pub use stream::split_now_and_rule::*;
191pub use stream::split_now_or_rule::*;
192pub use stream::stream_project_merge_rule::*;
193mod trivial_project_to_values_rule;
194pub use trivial_project_to_values_rule::*;
195mod union_input_values_merge_rule;
196pub use union_input_values_merge_rule::*;
197mod rewrite_like_expr_rule;
198pub use rewrite_like_expr_rule::*;
199mod min_max_on_index_rule;
200pub use min_max_on_index_rule::*;
201mod always_false_filter_rule;
202pub use always_false_filter_rule::*;
203mod join_project_transpose_rule;
204pub use join_project_transpose_rule::*;
205mod limit_push_down_rule;
206pub use limit_push_down_rule::*;
207mod pull_up_hop_rule;
208pub use pull_up_hop_rule::*;
209mod apply_offset_rewriter;
210use apply_offset_rewriter::ApplyOffsetRewriter;
211mod intersect_to_semi_join_rule;
212pub use intersect_to_semi_join_rule::*;
213mod except_to_anti_join_rule;
214pub use except_to_anti_join_rule::*;
215mod intersect_merge_rule;
216pub use intersect_merge_rule::*;
217mod except_merge_rule;
218pub use except_merge_rule::*;
219mod apply_union_transpose_rule;
220pub use apply_union_transpose_rule::*;
221mod apply_dedup_transpose_rule;
222pub use apply_dedup_transpose_rule::*;
223mod project_join_separate_rule;
224pub use project_join_separate_rule::*;
225mod grouping_sets_to_expand_rule;
226pub use grouping_sets_to_expand_rule::*;
227mod apply_project_set_transpose_rule;
228pub use apply_project_set_transpose_rule::*;
229mod apply_table_function_to_project_set_rule;
230pub use apply_table_function_to_project_set_rule::*;
231mod cross_join_eliminate_rule;
232pub use cross_join_eliminate_rule::*;
233mod table_function_to_project_set_rule;
234
235pub use table_function_to_project_set_rule::*;
236mod apply_topn_transpose_rule;
237pub use apply_topn_transpose_rule::*;
238mod apply_limit_transpose_rule;
239pub use apply_limit_transpose_rule::*;
240mod batch;
241pub use batch::batch_project_merge_rule::*;
242mod common_sub_expr_extract_rule;
243pub use common_sub_expr_extract_rule::*;
244mod apply_over_window_transpose_rule;
245pub use apply_over_window_transpose_rule::*;
246mod apply_expand_transpose_rule;
247pub use apply_expand_transpose_rule::*;
248mod expand_to_project_rule;
249pub use expand_to_project_rule::*;
250mod agg_group_by_simplify_rule;
251pub use agg_group_by_simplify_rule::*;
252mod apply_hop_window_transpose_rule;
253pub use apply_hop_window_transpose_rule::*;
254mod agg_call_merge_rule;
255pub use agg_call_merge_rule::*;
256mod unify_first_last_value_rule;
257pub use unify_first_last_value_rule::*;
258mod empty_agg_remove_rule;
259pub use empty_agg_remove_rule::*;
260mod add_logstore_rule;
261mod correlated_topn_to_vector_search;
262mod iceberg_count_star_rule;
263mod iceberg_intermediate_scan_rule;
264mod pull_up_correlated_predicate_agg_rule;
265mod source_to_iceberg_intermediate_scan_rule;
266mod source_to_kafka_scan_rule;
267mod table_function_to_file_scan_rule;
268mod table_function_to_internal_backfill_progress;
269mod table_function_to_internal_get_channel_delta_stats;
270mod table_function_to_internal_source_backfill_progress;
271mod table_function_to_mysql_query_rule;
272mod table_function_to_postgres_query_rule;
273mod top_n_to_vector_search_rule;
274mod values_extract_project_rule;
275pub use add_logstore_rule::*;
276pub use batch::batch_push_limit_to_scan_rule::*;
277pub use correlated_topn_to_vector_search::*;
278pub use iceberg_count_star_rule::IcebergCountStarRule;
279pub use iceberg_intermediate_scan_rule::*;
280pub use pull_up_correlated_predicate_agg_rule::*;
281pub use source_to_iceberg_intermediate_scan_rule::*;
282pub use source_to_kafka_scan_rule::*;
283pub use table_function_to_file_scan_rule::*;
284pub use table_function_to_internal_backfill_progress::*;
285pub use table_function_to_internal_get_channel_delta_stats::*;
286pub use table_function_to_internal_source_backfill_progress::*;
287pub use table_function_to_mysql_query_rule::*;
288pub use table_function_to_postgres_query_rule::*;
289pub use top_n_to_vector_search_rule::*;
290pub use values_extract_project_rule::*;
291
292use crate::optimizer::plan_node::ConventionMarker;
293
294#[macro_export]
295macro_rules! for_all_rules {
296 ($macro:ident) => {
297 $macro! {
298 { ApplyAggTransposeRule }
299 , { ApplyFilterTransposeRule }
300 , { ApplyProjectTransposeRule }
301 , { ApplyProjectSetTransposeRule }
302 , { ApplyTableFunctionToProjectSetRule }
303 , { ApplyEliminateRule }
304 , { ApplyJoinTransposeRule }
305 , { ApplyShareEliminateRule }
306 , { ApplyToJoinRule }
307 , { MaxOneRowEliminateRule }
308 , { DistinctAggRule }
309 , { IndexDeltaJoinRule }
310 , { MergeMultiJoinRule }
311 , { ProjectEliminateRule }
312 , { ProjectJoinMergeRule }
313 , { ProjectMergeRule }
314 , { PullUpCorrelatedPredicateRule }
315 , { PullUpCorrelatedProjectValueRule }
316 , { LeftDeepTreeJoinOrderingRule }
317 , { TranslateApplyRule }
318 , { PushCalculationOfJoinRule }
319 , { IndexSelectionRule }
320 , { OverWindowToTopNRule }
321 , { OverWindowToAggAndJoinRule }
322 , { OverWindowSplitRule }
323 , { OverWindowMergeRule }
324 , { JoinCommuteRule }
325 , { UnionToDistinctRule }
326 , { AggProjectMergeRule }
327 , { UnionMergeRule }
328 , { DagToTreeRule }
329 , { SplitNowAndRule }
330 , { SplitNowOrRule }
331 , { FilterWithNowToJoinRule }
332 , { GenerateSeriesWithNowRule }
333 , { ProjectTopNTransposeRule }
334 , { TopNProjectTransposeRule }
335 , { TopNOnIndexRule }
336 , { TrivialProjectToValuesRule }
337 , { UnionInputValuesMergeRule }
338 , { RewriteLikeExprRule }
339 , { MinMaxOnIndexRule }
340 , { AlwaysFalseFilterRule }
341 , { BushyTreeJoinOrderingRule }
342 , { StreamProjectMergeRule }
343 , { SeparateConsecutiveJoinRule }
344 , { LogicalFilterExpressionSimplifyRule }
345 , { JoinProjectTransposeRule }
346 , { LimitPushDownRule }
347 , { PullUpHopRule }
348 , { IntersectToSemiJoinRule }
349 , { ExceptToAntiJoinRule }
350 , { IntersectMergeRule }
351 , { ExceptMergeRule }
352 , { ApplyUnionTransposeRule }
353 , { ApplyDedupTransposeRule }
354 , { ProjectJoinSeparateRule }
355 , { GroupingSetsToExpandRule }
356 , { CrossJoinEliminateRule }
357 , { ApplyTopNTransposeRule }
358 , { TableFunctionToProjectSetRule }
359 , { TableFunctionToFileScanRule }
360 , { TableFunctionToPostgresQueryRule }
361 , { TableFunctionToMySqlQueryRule }
362 , { TableFunctionToInternalBackfillProgressRule }
363 , { TableFunctionToInternalGetChannelDeltaStatsRule }
364 , { TableFunctionToInternalSourceBackfillProgressRule }
365 , { ApplyLimitTransposeRule }
366 , { CommonSubExprExtractRule }
367 , { BatchProjectMergeRule }
368 , { ApplyOverWindowTransposeRule }
369 , { ApplyExpandTransposeRule }
370 , { ExpandToProjectRule }
371 , { AggGroupBySimplifyRule }
372 , { ApplyHopWindowTransposeRule }
373 , { AggCallMergeRule }
374 , { UnifyFirstLastValueRule }
375 , { ValuesExtractProjectRule }
376 , { BatchPushLimitToScanRule }
377 , { PullUpCorrelatedPredicateAggRule }
378 , { SourceToKafkaScanRule }
379 , { SourceToIcebergIntermediateScanRule }
380 , { IcebergCountStarRule}
381 , { IcebergIntermediateScanRule }
382 , { AddLogstoreRule }
383 , { EmptyAggRemoveRule }
384 , { TopNToVectorSearchRule }
385 , { CorrelatedTopNToVectorSearchRule }
386 , { MvSelectionRule }
387 }
388 };
389}
390
391macro_rules! impl_description {
392 ($( { $name:ident }),*) => {
393 paste::paste!{
394 $(impl Description for [<$name>] {
395 fn description(&self) -> &str {
396 stringify!([<$name>])
397 }
398 })*
399 }
400 }
401}
402
403for_all_rules! {impl_description}
404
405mod prelude {
406 pub(super) use crate::optimizer::plan_node::{Logical, LogicalPlanRef as PlanRef};
407 pub(super) use crate::optimizer::rule::Rule;
408
409 pub(super) type BoxedRule = crate::optimizer::rule::BoxedRule<Logical>;
410}