1use educe::Educe;
16
17use super::generic::GenericPlanNode;
18use super::*;
19use crate::optimizer::property::{Distribution, StreamKind, WatermarkColumns};
20
21#[derive(Clone, Debug, PartialEq, Eq, Hash)]
23pub struct NoExtra;
24
25mod physical_common {
28 use super::*;
29
30 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
32 pub struct PhysicalCommonExtra {
33 pub dist: Distribution,
36 }
37
38 pub trait GetPhysicalCommon {
41 fn physical(&self) -> &PhysicalCommonExtra;
42 fn physical_mut(&mut self) -> &mut PhysicalCommonExtra;
43 }
44}
45
46use physical_common::*;
47
48#[derive(Clone, Debug, PartialEq, Eq, Hash)]
50pub struct StreamExtra {
51 physical: PhysicalCommonExtra,
53
54 stream_kind: StreamKind,
56
57 emit_on_window_close: bool,
59 watermark_columns: WatermarkColumns,
62 columns_monotonicity: MonotonicityMap,
64}
65
66impl GetPhysicalCommon for StreamExtra {
67 fn physical(&self) -> &PhysicalCommonExtra {
68 &self.physical
69 }
70
71 fn physical_mut(&mut self) -> &mut PhysicalCommonExtra {
72 &mut self.physical
73 }
74}
75
76#[derive(Clone, Debug, PartialEq, Eq, Hash)]
78pub struct BatchExtra {
79 physical: PhysicalCommonExtra,
81
82 orders: Vec<Order>,
96}
97
98impl GetPhysicalCommon for BatchExtra {
99 fn physical(&self) -> &PhysicalCommonExtra {
100 &self.physical
101 }
102
103 fn physical_mut(&mut self) -> &mut PhysicalCommonExtra {
104 &mut self.physical
105 }
106}
107
108#[derive(Educe)]
121#[educe(PartialEq, Eq, Hash, Clone, Debug)]
122pub struct PlanBase<C: ConventionMarker> {
123 #[educe(PartialEq(ignore), Hash(ignore))]
125 id: PlanNodeId,
126 #[educe(PartialEq(ignore), Hash(ignore))]
127 ctx: OptimizerContextRef,
128
129 schema: Schema,
130 stream_key: Option<Vec<usize>>,
135 functional_dependency: FunctionalDependencySet,
136
137 extra: C::Extra,
139}
140
141impl<C: ConventionMarker> generic::GenericPlanRef for PlanBase<C> {
142 fn id(&self) -> PlanNodeId {
143 self.id
144 }
145
146 fn schema(&self) -> &Schema {
147 &self.schema
148 }
149
150 fn stream_key(&self) -> Option<&[usize]> {
151 self.stream_key.as_deref()
152 }
153
154 fn ctx(&self) -> OptimizerContextRef {
155 self.ctx.clone()
156 }
157
158 fn functional_dependency(&self) -> &FunctionalDependencySet {
159 &self.functional_dependency
160 }
161}
162
163impl<C: ConventionMarker> generic::PhysicalPlanRef for PlanBase<C>
164where
165 C::Extra: GetPhysicalCommon,
166{
167 fn distribution(&self) -> &Distribution {
168 &self.extra.physical().dist
169 }
170}
171
172impl stream::StreamPlanNodeMetadata for PlanBase<Stream> {
173 fn stream_kind(&self) -> StreamKind {
174 self.extra.stream_kind
175 }
176
177 fn emit_on_window_close(&self) -> bool {
178 self.extra.emit_on_window_close
179 }
180
181 fn watermark_columns(&self) -> &WatermarkColumns {
182 &self.extra.watermark_columns
183 }
184
185 fn columns_monotonicity(&self) -> &MonotonicityMap {
186 &self.extra.columns_monotonicity
187 }
188}
189
190impl batch::BatchPlanNodeMetadata for PlanBase<Batch> {
191 fn order(&self) -> &Order {
192 self.extra
193 .orders
194 .first()
195 .expect("batch plan node should always have at least one order")
196 }
197
198 fn orders(&self) -> Vec<Order> {
199 self.extra.orders.clone()
200 }
201}
202
203impl<C: ConventionMarker> PlanBase<C> {
204 pub fn clone_with_new_plan_id(&self) -> Self {
205 let mut new = self.clone();
206 new.id = self.ctx().next_plan_node_id();
207 new
208 }
209}
210
211impl PlanBase<Logical> {
212 pub fn new_logical(
213 ctx: OptimizerContextRef,
214 schema: Schema,
215 stream_key: Option<Vec<usize>>,
216 functional_dependency: FunctionalDependencySet,
217 ) -> Self {
218 let id = ctx.next_plan_node_id();
219 Self::new_logical_with_id(ctx, id, schema, stream_key, functional_dependency)
220 }
221
222 fn new_logical_with_id(
223 ctx: OptimizerContextRef,
224 id: PlanNodeId,
225 schema: Schema,
226 stream_key: Option<Vec<usize>>,
227 functional_dependency: FunctionalDependencySet,
228 ) -> Self {
229 Self {
230 id,
231 ctx,
232 schema,
233 stream_key,
234 functional_dependency,
235 extra: NoExtra,
236 }
237 }
238
239 pub fn new_logical_with_core(core: &impl GenericPlanNode) -> Self {
240 Self::new_logical(
241 core.ctx(),
242 core.schema(),
243 core.stream_key(),
244 core.functional_dependency(),
245 )
246 }
247
248 pub fn new_logical_share(core: &generic::Share<LogicalPlanRef>) -> Self {
249 Self::new_logical_with_id(
250 core.ctx(),
251 core.plan_node_id(),
252 core.schema(),
253 core.stream_key(),
254 core.functional_dependency(),
255 )
256 }
257}
258
259impl PlanBase<Stream> {
260 pub fn new_stream(
261 ctx: OptimizerContextRef,
262 schema: Schema,
263 stream_key: Option<Vec<usize>>,
264 functional_dependency: FunctionalDependencySet,
265 dist: Distribution,
266 stream_kind: StreamKind,
267 emit_on_window_close: bool,
268 watermark_columns: WatermarkColumns,
269 columns_monotonicity: MonotonicityMap,
270 ) -> Self {
271 let id = ctx.next_plan_node_id();
272 Self::new_stream_with_id(
273 ctx,
274 id,
275 schema,
276 stream_key,
277 functional_dependency,
278 dist,
279 stream_kind,
280 emit_on_window_close,
281 watermark_columns,
282 columns_monotonicity,
283 )
284 }
285
286 fn new_stream_with_id(
287 ctx: OptimizerContextRef,
288 id: PlanNodeId,
289 schema: Schema,
290 stream_key: Option<Vec<usize>>,
291 functional_dependency: FunctionalDependencySet,
292 dist: Distribution,
293 stream_kind: StreamKind,
294 emit_on_window_close: bool,
295 watermark_columns: WatermarkColumns,
296 columns_monotonicity: MonotonicityMap,
297 ) -> Self {
298 Self {
299 id,
300 ctx,
301 schema,
302 stream_key,
303 functional_dependency,
304 extra: StreamExtra {
305 physical: PhysicalCommonExtra { dist },
306 stream_kind,
307 emit_on_window_close,
308 watermark_columns,
309 columns_monotonicity,
310 },
311 }
312 }
313
314 pub fn new_stream_with_core(
315 core: &impl GenericPlanNode,
316 dist: Distribution,
317 stream_kind: StreamKind,
318 emit_on_window_close: bool,
319 watermark_columns: WatermarkColumns,
320 columns_monotonicity: MonotonicityMap,
321 ) -> Self {
322 Self::new_stream(
323 core.ctx(),
324 core.schema(),
325 core.stream_key(),
326 core.functional_dependency(),
327 dist,
328 stream_kind,
329 emit_on_window_close,
330 watermark_columns,
331 columns_monotonicity,
332 )
333 }
334
335 pub fn new_stream_share(
336 core: &generic::Share<StreamPlanRef>,
337 dist: Distribution,
338 stream_kind: StreamKind,
339 emit_on_window_close: bool,
340 watermark_columns: WatermarkColumns,
341 columns_monotonicity: MonotonicityMap,
342 ) -> Self {
343 Self::new_stream_with_id(
344 core.ctx(),
345 core.plan_node_id(),
346 core.schema(),
347 core.stream_key(),
348 core.functional_dependency(),
349 dist,
350 stream_kind,
351 emit_on_window_close,
352 watermark_columns,
353 columns_monotonicity,
354 )
355 }
356}
357
358impl PlanBase<Batch> {
359 pub fn new_batch(
360 ctx: OptimizerContextRef,
361 schema: Schema,
362 dist: Distribution,
363 order: Order,
364 ) -> Self {
365 Self::new_batch_with_orders(ctx, schema, dist, vec![order])
366 }
367
368 pub fn new_batch_with_orders(
369 ctx: OptimizerContextRef,
370 schema: Schema,
371 dist: Distribution,
372 orders: Vec<Order>,
373 ) -> Self {
374 assert!(
375 !orders.is_empty(),
376 "batch plan node should always have at least one order"
377 );
378 let id = ctx.next_plan_node_id();
379 let functional_dependency = FunctionalDependencySet::new(schema.len());
380 Self {
381 id,
382 ctx,
383 schema,
384 stream_key: None,
385 functional_dependency,
386 extra: BatchExtra {
387 physical: PhysicalCommonExtra { dist },
388 orders,
389 },
390 }
391 }
392
393 pub fn new_batch_with_core(
394 core: &impl GenericPlanNode,
395 dist: Distribution,
396 order: Order,
397 ) -> Self {
398 Self::new_batch(core.ctx(), core.schema(), dist, order)
399 }
400
401 pub fn new_batch_with_core_and_orders(
402 core: &impl GenericPlanNode,
403 dist: Distribution,
404 orders: Vec<Order>,
405 ) -> Self {
406 Self::new_batch_with_orders(core.ctx(), core.schema(), dist, orders)
407 }
408}
409
410impl<C: ConventionMarker> PlanBase<C>
411where
412 C::Extra: GetPhysicalCommon,
413{
414 pub fn clone_with_new_distribution(&self, dist: Distribution) -> Self {
418 let mut new = self.clone();
419 new.extra.physical_mut().dist = dist;
420 new
421 }
422}
423
424#[cfg(test)]
426impl<C: ConventionMarker> PlanBase<C> {
427 pub fn functional_dependency_mut(&mut self) -> &mut FunctionalDependencySet {
428 &mut self.functional_dependency
429 }
430}