risingwave_frontend/binder/
delete.rs1use risingwave_common::acl::AclMode;
16use risingwave_common::catalog::{Schema, TableVersionId};
17use risingwave_pb::user::grant_privilege::PbObject;
18use risingwave_sqlparser::ast::{Expr, ObjectName, SelectItem};
19
20use super::statement::RewriteExprsRecursive;
21use super::{Binder, BoundBaseTable};
22use crate::catalog::TableId;
23use crate::error::{ErrorCode, Result, RwError};
24use crate::expr::ExprImpl;
25use crate::handler::privilege::ObjectCheckItem;
26use crate::user::UserId;
27
28#[derive(Debug, Clone)]
29pub struct BoundDelete {
30 pub table_id: TableId,
32
33 pub table_version_id: TableVersionId,
35
36 pub table_name: String,
38
39 pub owner: UserId,
41
42 pub table: BoundBaseTable,
44
45 pub selection: Option<ExprImpl>,
46
47 pub returning_list: Vec<ExprImpl>,
51
52 pub returning_schema: Option<Schema>,
53}
54
55impl RewriteExprsRecursive for BoundDelete {
56 fn rewrite_exprs_recursive(&mut self, rewriter: &mut impl crate::expr::ExprRewriter) {
57 self.selection =
58 std::mem::take(&mut self.selection).map(|expr| rewriter.rewrite_expr(expr));
59
60 let new_returning_list = std::mem::take(&mut self.returning_list)
61 .into_iter()
62 .map(|expr| rewriter.rewrite_expr(expr))
63 .collect::<Vec<_>>();
64 self.returning_list = new_returning_list;
65 }
66}
67
68impl Binder {
69 pub(super) fn bind_delete(
70 &mut self,
71 name: ObjectName,
72 selection: Option<Expr>,
73 returning_items: Vec<SelectItem>,
74 ) -> Result<BoundDelete> {
75 let (schema_name, table_name) = Self::resolve_schema_qualified_name(&self.db_name, name)?;
76 let schema_name = schema_name.as_deref();
77 let table = self.bind_table(schema_name, &table_name)?;
78
79 let table_catalog = &table.table_catalog;
80 Self::check_for_dml(table_catalog, false)?;
81 self.check_privilege(
82 ObjectCheckItem::new(
83 table_catalog.owner,
84 AclMode::Delete,
85 table_name.clone(),
86 PbObject::TableId(table_catalog.id.table_id),
87 ),
88 table_catalog.database_id,
89 )?;
90
91 if !returning_items.is_empty() && table_catalog.has_generated_column() {
92 return Err(RwError::from(ErrorCode::BindError(
93 "`RETURNING` clause is not supported for tables with generated columns".to_owned(),
94 )));
95 }
96 let table_id = table_catalog.id;
97 let owner = table_catalog.owner;
98 let table_version_id = table_catalog.version_id().expect("table must be versioned");
99
100 let (returning_list, fields) = self.bind_returning_list(returning_items)?;
101 let returning = !returning_list.is_empty();
102 let delete = BoundDelete {
103 table_id,
104 table_version_id,
105 table_name,
106 owner,
107 table,
108 selection: selection
109 .map(|expr| self.bind_expr(expr)?.enforce_bool_clause("WHERE"))
110 .transpose()?,
111 returning_list,
112 returning_schema: if returning {
113 Some(Schema { fields })
114 } else {
115 None
116 },
117 };
118 Ok(delete)
119 }
120}