Skip to main content

risingwave_frontend/optimizer/plan_node/
logical_iceberg_metadata_scan.rs

1// Copyright 2026 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use pretty_xmlish::{Pretty, XmlNode};
16use risingwave_common::bail;
17
18use super::generic::GenericPlanRef;
19use super::utils::{Distill, childless_record, column_names_pretty};
20use super::{
21    BatchIcebergMetadataScan, ColPrunable, ExprRewritable, Logical, LogicalPlanRef as PlanRef,
22    PlanBase, PredicatePushdown, ToBatch, ToStream, generic,
23};
24use crate::error::Result;
25use crate::optimizer::plan_node::expr_visitable::ExprVisitable;
26use crate::optimizer::plan_node::{
27    ColumnPruningContext, LogicalFilter, LogicalProject, PredicatePushdownContext,
28    RewriteStreamContext, ToStreamContext,
29};
30use crate::utils::{ColIndexMapping, Condition};
31
32#[derive(Debug, Clone, PartialEq, Eq, Hash)]
33pub struct LogicalIcebergMetadataScan {
34    pub base: PlanBase<Logical>,
35    pub core: generic::IcebergMetadataScan,
36}
37
38impl LogicalIcebergMetadataScan {
39    pub fn new(core: generic::IcebergMetadataScan) -> Self {
40        let base = PlanBase::new_logical_with_core(&core);
41        Self { base, core }
42    }
43}
44
45impl_plan_tree_node_for_leaf! { Logical, LogicalIcebergMetadataScan }
46
47impl Distill for LogicalIcebergMetadataScan {
48    fn distill<'a>(&self) -> XmlNode<'a> {
49        let fields = vec![
50            (
51                "metadata_type",
52                Pretty::debug(&self.core.metadata_type.suffix()),
53            ),
54            ("columns", column_names_pretty(self.schema())),
55        ];
56        childless_record("LogicalIcebergMetadataScan", fields)
57    }
58}
59
60impl ColPrunable for LogicalIcebergMetadataScan {
61    fn prune_col(&self, required_cols: &[usize], _ctx: &mut ColumnPruningContext) -> PlanRef {
62        LogicalProject::with_out_col_idx(self.clone().into(), required_cols.iter().copied()).into()
63    }
64}
65
66impl ExprRewritable<Logical> for LogicalIcebergMetadataScan {}
67
68impl ExprVisitable for LogicalIcebergMetadataScan {}
69
70impl PredicatePushdown for LogicalIcebergMetadataScan {
71    fn predicate_pushdown(
72        &self,
73        predicate: Condition,
74        _ctx: &mut PredicatePushdownContext,
75    ) -> PlanRef {
76        LogicalFilter::create(self.clone().into(), predicate)
77    }
78}
79
80impl ToBatch for LogicalIcebergMetadataScan {
81    fn to_batch(&self) -> Result<crate::optimizer::plan_node::BatchPlanRef> {
82        Ok(BatchIcebergMetadataScan::new(self.core.clone()).into())
83    }
84}
85
86impl ToStream for LogicalIcebergMetadataScan {
87    fn to_stream(
88        &self,
89        _ctx: &mut ToStreamContext,
90    ) -> Result<crate::optimizer::plan_node::StreamPlanRef> {
91        bail!("Iceberg metadata relations are not supported in streaming queries")
92    }
93
94    fn logical_rewrite_for_stream(
95        &self,
96        _ctx: &mut RewriteStreamContext,
97    ) -> Result<(PlanRef, ColIndexMapping)> {
98        bail!("Iceberg metadata relations are not supported in streaming queries")
99    }
100}