risingwave_frontend/binder/
statement.rs

1// Copyright 2025 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 risingwave_common::bail_not_implemented;
16use risingwave_common::catalog::Field;
17use risingwave_sqlparser::ast::{DeclareCursor, Statement};
18
19use super::declare_cursor::{BoundDeclareCursor, BoundDeclareSubscriptionCursor};
20use super::delete::BoundDelete;
21use super::fetch_cursor::BoundFetchCursor;
22use super::update::BoundUpdate;
23use crate::binder::create_view::BoundCreateView;
24use crate::binder::{Binder, BoundInsert, BoundQuery};
25use crate::error::Result;
26use crate::expr::ExprRewriter;
27
28#[derive(Debug, Clone)]
29pub enum BoundStatement {
30    Insert(Box<BoundInsert>),
31    Delete(Box<BoundDelete>),
32    Update(Box<BoundUpdate>),
33    Query(Box<BoundQuery>),
34    DeclareCursor(Box<BoundDeclareCursor>),
35    DeclareSubscriptionCursor(Box<BoundDeclareSubscriptionCursor>),
36    FetchCursor(Box<BoundFetchCursor>),
37    CreateView(Box<BoundCreateView>),
38}
39
40impl BoundStatement {
41    pub fn output_fields(&self) -> Vec<Field> {
42        match self {
43            BoundStatement::Insert(i) => i
44                .returning_schema
45                .as_ref()
46                .map_or(vec![], |s| s.fields().into()),
47            BoundStatement::Delete(d) => d
48                .returning_schema
49                .as_ref()
50                .map_or(vec![], |s| s.fields().into()),
51            BoundStatement::Update(u) => u
52                .returning_schema
53                .as_ref()
54                .map_or(vec![], |s| s.fields().into()),
55            BoundStatement::Query(q) => q.schema().fields().into(),
56            BoundStatement::DeclareCursor(_) => vec![],
57            BoundStatement::DeclareSubscriptionCursor(_) => vec![],
58            BoundStatement::FetchCursor(f) => f
59                .returning_schema
60                .as_ref()
61                .map_or(vec![], |s| s.fields().into()),
62            BoundStatement::CreateView(_) => vec![],
63        }
64    }
65}
66
67impl Binder {
68    pub(super) fn bind_statement(&mut self, stmt: Statement) -> Result<BoundStatement> {
69        match stmt {
70            Statement::Insert {
71                table_name,
72                columns,
73                source,
74                returning,
75            } => Ok(BoundStatement::Insert(
76                self.bind_insert(table_name, columns, *source, returning)?
77                    .into(),
78            )),
79
80            Statement::Delete {
81                table_name,
82                selection,
83                returning,
84            } => Ok(BoundStatement::Delete(
85                self.bind_delete(table_name, selection, returning)?.into(),
86            )),
87
88            Statement::Update {
89                table_name,
90                assignments,
91                selection,
92                returning,
93            } => Ok(BoundStatement::Update(
94                self.bind_update(table_name, assignments, selection, returning)?
95                    .into(),
96            )),
97
98            Statement::Query(q) => Ok(BoundStatement::Query(self.bind_query(*q)?.into())),
99
100            Statement::DeclareCursor { stmt } => match stmt.declare_cursor {
101                DeclareCursor::Query(body) => {
102                    let query = self.bind_query(*body)?;
103                    Ok(BoundStatement::DeclareCursor(
104                        BoundDeclareCursor {
105                            cursor_name: stmt.cursor_name,
106                            query: query.into(),
107                        }
108                        .into(),
109                    ))
110                }
111                DeclareCursor::Subscription(subscription_name, rw_timestamp) => {
112                    Ok(BoundStatement::DeclareSubscriptionCursor(
113                        BoundDeclareSubscriptionCursor {
114                            cursor_name: stmt.cursor_name,
115                            subscription_name,
116                            rw_timestamp,
117                        }
118                        .into(),
119                    ))
120                }
121            },
122
123            // Note(eric): Can I just bind CreateView to Query??
124            Statement::CreateView {
125                or_replace,
126                materialized,
127                if_not_exists,
128                name,
129                columns,
130                query,
131                emit_mode,
132                with_options,
133            } => {
134                let query = self.bind_query(*query)?;
135                let create_view = BoundCreateView::new(
136                    or_replace,
137                    materialized,
138                    if_not_exists,
139                    name,
140                    columns,
141                    query,
142                    emit_mode,
143                    with_options,
144                );
145                Ok(BoundStatement::CreateView(create_view.into()))
146            }
147
148            _ => bail_not_implemented!("unsupported statement {:?}", stmt),
149        }
150    }
151}
152
153pub(crate) trait RewriteExprsRecursive {
154    fn rewrite_exprs_recursive(&mut self, rewriter: &mut impl ExprRewriter);
155}
156
157impl RewriteExprsRecursive for BoundStatement {
158    fn rewrite_exprs_recursive(&mut self, rewriter: &mut impl ExprRewriter) {
159        match self {
160            BoundStatement::Insert(inner) => inner.rewrite_exprs_recursive(rewriter),
161            BoundStatement::Delete(inner) => inner.rewrite_exprs_recursive(rewriter),
162            BoundStatement::Update(inner) => inner.rewrite_exprs_recursive(rewriter),
163            BoundStatement::Query(inner) => inner.rewrite_exprs_recursive(rewriter),
164            BoundStatement::DeclareCursor(inner) => inner.rewrite_exprs_recursive(rewriter),
165            BoundStatement::FetchCursor(_) => {}
166            BoundStatement::DeclareSubscriptionCursor(_) => {}
167            BoundStatement::CreateView(inner) => inner.rewrite_exprs_recursive(rewriter),
168        }
169    }
170}