@@ -131,6 +131,128 @@ impl WrapperRules {
131131 "?ungrouped_scan_out" ,
132132 ) ,
133133 ) ,
134+ // This rule would introduce new representations:
135+ // replacers from node on top of this node would be able to run with enabled push to Cube.
136+ // However, those representation are not valid on their own, they are necessary
137+ // for flattening to work.
138+ // So, they will be disallowed to pullup by nontrivial pullup rules.
139+ // Also note that trivial pullup rules are allowed to pullup without additional checks,
140+ // because it checks that `from` is not WrappedSelect, so push=true in input can be valid
141+ // There's no equivalent for non-trivial pullup, because it has WrappedSelect in `from`,
142+ // so there's no way to use push to Cube even after flattening
143+ transforming_rewrite(
144+ "wrapper-pull-up-to-cube-scan-non-wrapped-select-with-push" ,
145+ cube_scan_wrapper(
146+ wrapped_select(
147+ "?select_type" ,
148+ wrapper_pullup_replacer(
149+ "?projection_expr" ,
150+ "?alias_to_cube" ,
151+ "?push_to_cube" ,
152+ "?ungrouped_scan" ,
153+ "?in_projection" ,
154+ "?cube_members" ,
155+ ) ,
156+ wrapper_pullup_replacer(
157+ "?subqueries" ,
158+ "?alias_to_cube" ,
159+ "?push_to_cube" ,
160+ "?ungrouped_scan" ,
161+ "?in_projection" ,
162+ "?cube_members" ,
163+ ) ,
164+ wrapper_pullup_replacer(
165+ "?group_expr" ,
166+ "?alias_to_cube" ,
167+ "?push_to_cube" ,
168+ "?ungrouped_scan" ,
169+ "?in_projection" ,
170+ "?cube_members" ,
171+ ) ,
172+ wrapper_pullup_replacer(
173+ "?aggr_expr" ,
174+ "?alias_to_cube" ,
175+ "?push_to_cube" ,
176+ "?ungrouped_scan" ,
177+ "?in_projection" ,
178+ "?cube_members" ,
179+ ) ,
180+ wrapper_pullup_replacer(
181+ "?window_expr" ,
182+ "?alias_to_cube" ,
183+ "?push_to_cube" ,
184+ "?ungrouped_scan" ,
185+ "?in_projection" ,
186+ "?cube_members" ,
187+ ) ,
188+ wrapper_pullup_replacer(
189+ "?cube_scan_input" ,
190+ "?alias_to_cube" ,
191+ "?push_to_cube" ,
192+ "?ungrouped_scan" ,
193+ "?in_projection" ,
194+ "?cube_members" ,
195+ ) ,
196+ wrapped_select_joins_empty_tail( ) ,
197+ wrapper_pullup_replacer(
198+ "?filter_expr" ,
199+ "?alias_to_cube" ,
200+ "?push_to_cube" ,
201+ "?ungrouped_scan" ,
202+ "?in_projection" ,
203+ "?cube_members" ,
204+ ) ,
205+ wrapped_select_having_expr_empty_tail( ) ,
206+ "WrappedSelectLimit:None" ,
207+ "WrappedSelectOffset:None" ,
208+ wrapper_pullup_replacer(
209+ "?order_expr" ,
210+ "?alias_to_cube" ,
211+ "?push_to_cube" ,
212+ "?ungrouped_scan" ,
213+ "?in_projection" ,
214+ "?cube_members" ,
215+ ) ,
216+ "?select_alias" ,
217+ "?select_distinct" ,
218+ "WrappedSelectPushToCube:true" ,
219+ "WrappedSelectUngroupedScan:true" ,
220+ ) ,
221+ "CubeScanWrapperFinalized:false" ,
222+ ) ,
223+ cube_scan_wrapper(
224+ wrapper_pullup_replacer(
225+ wrapped_select(
226+ "?select_type" ,
227+ "?projection_expr" ,
228+ "?subqueries" ,
229+ "?group_expr" ,
230+ "?aggr_expr" ,
231+ "?window_expr" ,
232+ "?cube_scan_input" ,
233+ wrapped_select_joins_empty_tail( ) ,
234+ "?filter_expr" ,
235+ wrapped_select_having_expr_empty_tail( ) ,
236+ "WrappedSelectLimit:None" ,
237+ "WrappedSelectOffset:None" ,
238+ "?order_expr" ,
239+ "?select_alias" ,
240+ "?select_distinct" ,
241+ "WrappedSelectPushToCube:true" ,
242+ "WrappedSelectUngroupedScan:true" ,
243+ ) ,
244+ "?alias_to_cube" ,
245+ // This would allow next LP node on top of this to use push even when from=WrappedSelect(from=CubeScan)
246+ // Wrapper like that would be incorrect, so they will be disallowed by pullup rules for WrappedSelect(from=WrappedSelect) case
247+ "WrapperPullupReplacerPushToCube:true" ,
248+ "WrapperPullupReplacerUngroupedScan:true" ,
249+ "?in_projection" ,
250+ "?cube_members" ,
251+ ) ,
252+ "CubeScanWrapperFinalized:false" ,
253+ ) ,
254+ self . transform_pull_up_wrapper_select_for_push( "?cube_scan_input" ) ,
255+ ) ,
134256 transforming_rewrite(
135257 "wrapper-pull-up-to-cube-scan-non-trivial-wrapped-select" ,
136258 cube_scan_wrapper(
@@ -324,6 +446,20 @@ impl WrapperRules {
324446 }
325447 }
326448
449+ fn transform_pull_up_wrapper_select_for_push (
450+ & self ,
451+ cube_scan_input_var : & ' static str ,
452+ ) -> impl Fn ( & mut CubeEGraph , & mut Subst ) -> bool {
453+ let cube_scan_input_var = var ! ( cube_scan_input_var) ;
454+ move |egraph, subst| {
455+ for _ in var_list_iter ! ( egraph[ subst[ cube_scan_input_var] ] , WrappedSelect ) . cloned ( ) {
456+ return false ;
457+ }
458+
459+ true
460+ }
461+ }
462+
327463 fn transform_pull_up_non_trivial_wrapper_select (
328464 & self ,
329465 select_type_var : & ' static str ,
0 commit comments