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