risingwave_frontend/optimizer/plan_node/
stream_group_topn.rs1use pretty_xmlish::XmlNode;
16use risingwave_common::util::sort_util::topn_watermark_forwardable_order_key;
17use risingwave_pb::stream_plan::stream_node::PbNodeBody;
18
19use super::generic::{DistillUnit, TopNLimit};
20use super::stream::prelude::*;
21use super::utils::{Distill, plan_node_name, watermark_pretty};
22use super::{
23 ExprRewritable, PlanBase, PlanTreeNodeUnary, StreamNode, StreamPlanRef as PlanRef, generic,
24};
25use crate::error::Result;
26use crate::optimizer::plan_node::expr_visitable::ExprVisitable;
27use crate::optimizer::plan_node::generic::GenericPlanNode;
28use crate::optimizer::property::{MonotonicityMap, Order};
29use crate::stream_fragmenter::BuildFragmentGraphState;
30
31#[derive(Debug, Clone, PartialEq, Eq, Hash)]
32pub struct StreamGroupTopN {
33 pub base: PlanBase<Stream>,
34 core: generic::TopN<PlanRef>,
35 vnode_col_idx: Option<usize>,
38}
39
40impl StreamGroupTopN {
41 pub fn new(core: generic::TopN<PlanRef>, vnode_col_idx: Option<usize>) -> Result<Self> {
42 assert!(!core.group_key.is_empty());
43 assert!(core.limit_attr.limit() > 0);
44 reject_upsert_input!(core.input);
45
46 let input = &core.input;
47
48 let watermark_columns = {
53 let mut cols = core.group_key.clone();
54 cols.extend(topn_watermark_forwardable_order_key(
55 &core.order.column_orders,
56 ));
57 input.watermark_columns().retain_clone(&cols)
58 };
59
60 let mut stream_key = core
61 .stream_key()
62 .expect("logical node should have stream key here");
63 if let Some(vnode_col_idx) = vnode_col_idx
64 && stream_key.len() > 1
65 {
66 stream_key.remove(stream_key.iter().position(|i| *i == vnode_col_idx).unwrap());
71 }
72
73 let base = PlanBase::new_stream(
74 core.ctx(),
75 core.schema(),
76 Some(stream_key),
77 core.functional_dependency(),
78 input.distribution().clone(),
79 StreamKind::Retract,
80 false,
82 watermark_columns,
83 MonotonicityMap::new(), );
85
86 Ok(StreamGroupTopN {
87 base,
88 core,
89 vnode_col_idx,
90 })
91 }
92
93 pub fn limit_attr(&self) -> TopNLimit {
94 self.core.limit_attr
95 }
96
97 pub fn offset(&self) -> u64 {
98 self.core.offset
99 }
100
101 pub fn topn_order(&self) -> &Order {
102 &self.core.order
103 }
104
105 pub fn group_key(&self) -> &[usize] {
106 &self.core.group_key
107 }
108}
109
110impl StreamNode for StreamGroupTopN {
111 fn to_stream_prost_body(&self, state: &mut BuildFragmentGraphState) -> PbNodeBody {
112 use risingwave_pb::stream_plan::*;
113
114 let input = self.input();
115 let table = self
116 .core
117 .infer_internal_table_catalog(
118 input.schema(),
119 input.ctx(),
120 input.expect_stream_key(),
121 self.vnode_col_idx,
122 )
123 .with_id(state.gen_table_id_wrapped());
124 assert!(!self.group_key().is_empty());
125 let group_topn_node = GroupTopNNode {
126 limit: self.limit_attr().limit(),
127 offset: self.offset(),
128 with_ties: self.limit_attr().with_ties(),
129 group_key: self.group_key().iter().map(|idx| *idx as u32).collect(),
130 table: Some(table.to_internal_table_prost()),
131 order_by: self.topn_order().to_protobuf(),
132 };
133 if self.input().append_only() {
134 PbNodeBody::AppendOnlyGroupTopN(Box::new(group_topn_node))
135 } else {
136 PbNodeBody::GroupTopN(Box::new(group_topn_node))
137 }
138 }
139}
140
141impl Distill for StreamGroupTopN {
142 fn distill<'a>(&self) -> XmlNode<'a> {
143 let name = plan_node_name!("StreamGroupTopN",
144 { "append_only", self.input().append_only() },
145 );
146 let mut node = self.core.distill_with_name(name);
147 if let Some(ow) = watermark_pretty(self.base.watermark_columns(), self.schema()) {
148 node.fields.push(("output_watermarks".into(), ow));
149 }
150 node
151 }
152}
153
154impl_plan_tree_node_for_unary! { Stream, StreamGroupTopN }
155
156impl PlanTreeNodeUnary<Stream> for StreamGroupTopN {
157 fn input(&self) -> PlanRef {
158 self.core.input.clone()
159 }
160
161 fn clone_with_input(&self, input: PlanRef) -> Self {
162 let mut core = self.core.clone();
163 core.input = input;
164 Self::new(core, self.vnode_col_idx).unwrap()
165 }
166}
167
168impl ExprRewritable<Stream> for StreamGroupTopN {}
169
170impl ExprVisitable for StreamGroupTopN {}