risingwave_frontend/optimizer/plan_node/generic/
table_function.rs1use educe::Educe;
16use pretty_xmlish::{Pretty, Str, XmlNode};
17use risingwave_common::catalog::{Field, Schema};
18use risingwave_common::types::DataType;
19
20use super::{DistillUnit, GenericPlanNode};
21use crate::expr::{Expr, ExprRewriter, ExprVisitor, TableFunction as ExprTableFunction};
22use crate::optimizer::optimizer_context::OptimizerContextRef;
23use crate::optimizer::plan_node::utils::childless_record;
24use crate::optimizer::property::FunctionalDependencySet;
25
26#[derive(Debug, Clone, Educe)]
28#[educe(PartialEq, Eq, Hash)]
29pub struct TableFunction {
30 pub table_function: ExprTableFunction,
31 pub with_ordinality: bool,
32
33 #[educe(PartialEq(ignore))]
34 #[educe(Hash(ignore))]
35 pub ctx: OptimizerContextRef,
36}
37
38impl TableFunction {
39 pub fn new(
40 table_function: ExprTableFunction,
41 with_ordinality: bool,
42 ctx: OptimizerContextRef,
43 ) -> Self {
44 Self {
45 table_function,
46 with_ordinality,
47 ctx,
48 }
49 }
50
51 pub fn rewrite_exprs(&mut self, r: &mut dyn ExprRewriter) {
52 self.table_function.args = std::mem::take(&mut self.table_function.args)
53 .into_iter()
54 .map(|e| r.rewrite_expr(e))
55 .collect();
56 }
57
58 pub fn visit_exprs(&self, v: &mut dyn ExprVisitor) {
59 self.table_function
60 .args
61 .iter()
62 .for_each(|e| v.visit_expr(e));
63 }
64}
65
66impl GenericPlanNode for TableFunction {
67 fn schema(&self) -> Schema {
68 let mut schema = if let DataType::Struct(s) = self.table_function.return_type() {
69 Schema::from(&s)
71 } else {
72 Schema {
73 fields: vec![Field::with_name(
74 self.table_function.return_type(),
75 self.table_function.name(),
76 )],
77 }
78 };
79 if self.with_ordinality {
80 schema
81 .fields
82 .push(Field::with_name(DataType::Int64, "ordinality"));
83 }
84 schema
85 }
86
87 fn stream_key(&self) -> Option<Vec<usize>> {
88 None
89 }
90
91 fn ctx(&self) -> OptimizerContextRef {
92 self.ctx.clone()
93 }
94
95 fn functional_dependency(&self) -> FunctionalDependencySet {
96 FunctionalDependencySet::new(self.schema().len())
97 }
98}
99
100impl DistillUnit for TableFunction {
101 fn distill_with_name<'a>(&self, name: impl Into<Str<'a>>) -> XmlNode<'a> {
102 childless_record(
103 name,
104 vec![("table_function", Pretty::debug(&self.table_function))],
105 )
106 }
107}