operator/statement/
comment.rs1use api::v1::CommentOnExpr;
16use common_error::ext::BoxedError;
17use common_meta::cache_invalidator::Context;
18use common_meta::procedure_executor::ExecutorContext;
19use common_meta::rpc::ddl::{CommentObjectType, CommentOnTask, DdlTask, SubmitDdlTaskRequest};
20use common_query::Output;
21use session::context::QueryContextRef;
22use session::table_name::table_idents_to_full_name;
23use snafu::ResultExt;
24use sql::ast::ObjectNamePartExt;
25use sql::statements::comment::{Comment, CommentObject};
26
27use crate::error::{
28 self, ExecuteDdlSnafu, ExternalSnafu, InvalidSqlSnafu, Result, TableMetadataManagerSnafu,
29};
30use crate::statement::StatementExecutor;
31use crate::utils::to_meta_query_context;
32
33impl StatementExecutor {
34 pub async fn comment(&self, stmt: Comment, query_ctx: QueryContextRef) -> Result<Output> {
45 let mut comment_on_task = self.create_comment_on_task_from_stmt(stmt, &query_ctx)?;
46 comment_on_task
47 .enrich_object_id(
48 self.table_metadata_manager.table_name_manager(),
49 self.flow_metadata_manager.flow_name_manager(),
50 )
51 .await
52 .context(TableMetadataManagerSnafu)?;
53 let cache_idents = comment_on_task.cache_idents();
54
55 let request = SubmitDdlTaskRequest::new(
56 to_meta_query_context(query_ctx),
57 DdlTask::new_comment_on(comment_on_task),
58 );
59
60 self.procedure_executor
61 .submit_ddl_task(&ExecutorContext::default(), request)
62 .await
63 .context(ExecuteDdlSnafu)?;
64
65 self.cache_invalidator
67 .invalidate(&Context::default(), &cache_idents)
68 .await
69 .context(error::InvalidateTableCacheSnafu)?;
70
71 Ok(Output::new_with_affected_rows(0))
72 }
73
74 pub async fn comment_by_expr(
75 &self,
76 expr: CommentOnExpr,
77 query_ctx: QueryContextRef,
78 ) -> Result<Output> {
79 let mut comment_on_task = self.create_comment_on_task_from_expr(expr)?;
80 comment_on_task
81 .enrich_object_id(
82 self.table_metadata_manager.table_name_manager(),
83 self.flow_metadata_manager.flow_name_manager(),
84 )
85 .await
86 .context(TableMetadataManagerSnafu)?;
87 let cache_idents = comment_on_task.cache_idents();
88
89 let request = SubmitDdlTaskRequest::new(
90 to_meta_query_context(query_ctx),
91 DdlTask::new_comment_on(comment_on_task),
92 );
93
94 self.procedure_executor
95 .submit_ddl_task(&ExecutorContext::default(), request)
96 .await
97 .context(ExecuteDdlSnafu)?;
98
99 self.cache_invalidator
101 .invalidate(&Context::default(), &cache_idents)
102 .await
103 .context(error::InvalidateTableCacheSnafu)?;
104
105 Ok(Output::new_with_affected_rows(0))
106 }
107
108 fn create_comment_on_task_from_expr(&self, expr: CommentOnExpr) -> Result<CommentOnTask> {
109 let object_type = match expr.object_type {
110 0 => CommentObjectType::Table,
111 1 => CommentObjectType::Column,
112 2 => CommentObjectType::Flow,
113 _ => {
114 return InvalidSqlSnafu {
115 err_msg: format!(
116 "Invalid CommentObjectType value: {}. Valid values are: 0 (Table), 1 (Column), 2 (Flow)",
117 expr.object_type
118 ),
119 }
120 .fail();
121 }
122 };
123
124 Ok(CommentOnTask {
125 catalog_name: expr.catalog_name,
126 schema_name: expr.schema_name,
127 object_type,
128 object_name: expr.object_name,
129 column_name: if expr.column_name.is_empty() {
130 None
131 } else {
132 Some(expr.column_name)
133 },
134 object_id: None,
135 comment: if expr.comment.is_empty() {
136 None
137 } else {
138 Some(expr.comment)
139 },
140 })
141 }
142
143 fn create_comment_on_task_from_stmt(
144 &self,
145 stmt: Comment,
146 query_ctx: &QueryContextRef,
147 ) -> Result<CommentOnTask> {
148 match stmt.object {
149 CommentObject::Table(table) => {
150 let (catalog_name, schema_name, table_name) =
151 table_idents_to_full_name(&table, query_ctx)
152 .map_err(BoxedError::new)
153 .context(ExternalSnafu)?;
154
155 Ok(CommentOnTask {
156 catalog_name,
157 schema_name,
158 object_type: CommentObjectType::Table,
159 object_name: table_name,
160 column_name: None,
161 object_id: None,
162 comment: stmt.comment,
163 })
164 }
165 CommentObject::Column { table, column } => {
166 let (catalog_name, schema_name, table_name) =
167 table_idents_to_full_name(&table, query_ctx)
168 .map_err(BoxedError::new)
169 .context(ExternalSnafu)?;
170
171 Ok(CommentOnTask {
172 catalog_name,
173 schema_name,
174 object_type: CommentObjectType::Column,
175 object_name: table_name,
176 column_name: Some(column.value),
177 object_id: None,
178 comment: stmt.comment,
179 })
180 }
181 CommentObject::Flow(flow_name) => {
182 let (catalog_name, flow_name_str) = match &flow_name.0[..] {
183 [flow] => (
184 query_ctx.current_catalog().to_string(),
185 flow.to_string_unquoted(),
186 ),
187 [catalog, flow] => (catalog.to_string_unquoted(), flow.to_string_unquoted()),
188 _ => {
189 return InvalidSqlSnafu {
190 err_msg: format!(
191 "expect flow name to be <catalog>.<flow_name> or <flow_name>, actual: {flow_name}"
192 ),
193 }
194 .fail();
195 }
196 };
197
198 Ok(CommentOnTask {
199 catalog_name,
200 schema_name: String::new(), object_type: CommentObjectType::Flow,
202 object_name: flow_name_str,
203 column_name: None,
204 object_id: None,
205 comment: stmt.comment,
206 })
207 }
208 }
209 }
210}