mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-26 09:50:40 +00:00
feat: table/column/flow COMMENT (#7060)
* initial impl Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * simplify impl Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * sqlness test Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * avoid unimplemented panic Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * validate flow Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * update sqlness result Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * fix table column comment Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * table level comment Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * simplify table info serde Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * don't txn Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * remove empty trait Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * wip: procedure Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * update proto Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * grpc support Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * Apply suggestions from code review Co-authored-by: dennis zhuang <killme2008@gmail.com> Co-authored-by: LFC <990479+MichaelScofield@users.noreply.github.com> Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * try from pb struct Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * doc comment Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * check unchanged fast case Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * tune errors Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * fix merge error Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * use try_as_raw_value Signed-off-by: Ruihang Xia <waynestxia@gmail.com> --------- Signed-off-by: Ruihang Xia <waynestxia@gmail.com> Co-authored-by: dennis zhuang <killme2008@gmail.com> Co-authored-by: LFC <990479+MichaelScofield@users.noreply.github.com>
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
mod admin;
|
||||
mod comment;
|
||||
mod copy_database;
|
||||
mod copy_query_to;
|
||||
mod copy_table_from;
|
||||
@@ -428,6 +429,7 @@ impl StatementExecutor {
|
||||
Statement::ShowCreateTrigger(show) => self.show_create_trigger(show, query_ctx).await,
|
||||
Statement::SetVariables(set_var) => self.set_variables(set_var, query_ctx),
|
||||
Statement::ShowVariables(show_variable) => self.show_variable(show_variable, query_ctx),
|
||||
Statement::Comment(stmt) => self.comment(stmt, query_ctx).await,
|
||||
Statement::ShowColumns(show_columns) => {
|
||||
self.show_columns(show_columns, query_ctx).await
|
||||
}
|
||||
|
||||
176
src/operator/src/statement/comment.rs
Normal file
176
src/operator/src/statement/comment.rs
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright 2023 Greptime Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use api::v1::CommentOnExpr;
|
||||
use common_error::ext::BoxedError;
|
||||
use common_meta::procedure_executor::ExecutorContext;
|
||||
use common_meta::rpc::ddl::{CommentObjectType, CommentOnTask, DdlTask, SubmitDdlTaskRequest};
|
||||
use common_query::Output;
|
||||
use session::context::QueryContextRef;
|
||||
use session::table_name::table_idents_to_full_name;
|
||||
use snafu::ResultExt;
|
||||
use sql::ast::ObjectNamePartExt;
|
||||
use sql::statements::comment::{Comment, CommentObject};
|
||||
|
||||
use crate::error::{ExecuteDdlSnafu, ExternalSnafu, InvalidSqlSnafu, Result};
|
||||
use crate::statement::StatementExecutor;
|
||||
|
||||
impl StatementExecutor {
|
||||
/// Adds a comment to a database object (table, column, or flow).
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `stmt`: A `Comment` struct containing the object to comment on and the comment text.
|
||||
/// * `query_ctx`: A `QueryContextRef` providing contextual information for the query.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A `Result` containing the `Output` of the operation, or an error if the operation fails.
|
||||
pub async fn comment(&self, stmt: Comment, query_ctx: QueryContextRef) -> Result<Output> {
|
||||
let comment_on_task = self.create_comment_on_task_from_stmt(stmt, &query_ctx)?;
|
||||
|
||||
let request = SubmitDdlTaskRequest {
|
||||
task: DdlTask::new_comment_on(comment_on_task),
|
||||
query_context: query_ctx,
|
||||
};
|
||||
|
||||
self.procedure_executor
|
||||
.submit_ddl_task(&ExecutorContext::default(), request)
|
||||
.await
|
||||
.context(ExecuteDdlSnafu)
|
||||
.map(|_| Output::new_with_affected_rows(0))
|
||||
}
|
||||
|
||||
pub async fn comment_by_expr(
|
||||
&self,
|
||||
expr: CommentOnExpr,
|
||||
query_ctx: QueryContextRef,
|
||||
) -> Result<Output> {
|
||||
let comment_on_task = self.create_comment_on_task_from_expr(expr)?;
|
||||
|
||||
let request = SubmitDdlTaskRequest {
|
||||
task: DdlTask::new_comment_on(comment_on_task),
|
||||
query_context: query_ctx,
|
||||
};
|
||||
|
||||
self.procedure_executor
|
||||
.submit_ddl_task(&ExecutorContext::default(), request)
|
||||
.await
|
||||
.context(ExecuteDdlSnafu)
|
||||
.map(|_| Output::new_with_affected_rows(0))
|
||||
}
|
||||
|
||||
fn create_comment_on_task_from_expr(&self, expr: CommentOnExpr) -> Result<CommentOnTask> {
|
||||
let object_type = match expr.object_type {
|
||||
0 => CommentObjectType::Table,
|
||||
1 => CommentObjectType::Column,
|
||||
2 => CommentObjectType::Flow,
|
||||
_ => {
|
||||
return InvalidSqlSnafu {
|
||||
err_msg: format!(
|
||||
"Invalid CommentObjectType value: {}. Valid values are: 0 (Table), 1 (Column), 2 (Flow)",
|
||||
expr.object_type
|
||||
),
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
};
|
||||
|
||||
Ok(CommentOnTask {
|
||||
catalog_name: expr.catalog_name,
|
||||
schema_name: expr.schema_name,
|
||||
object_type,
|
||||
object_name: expr.object_name,
|
||||
column_name: if expr.column_name.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(expr.column_name)
|
||||
},
|
||||
object_id: None,
|
||||
comment: if expr.comment.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(expr.comment)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn create_comment_on_task_from_stmt(
|
||||
&self,
|
||||
stmt: Comment,
|
||||
query_ctx: &QueryContextRef,
|
||||
) -> Result<CommentOnTask> {
|
||||
match stmt.object {
|
||||
CommentObject::Table(table) => {
|
||||
let (catalog_name, schema_name, table_name) =
|
||||
table_idents_to_full_name(&table, query_ctx)
|
||||
.map_err(BoxedError::new)
|
||||
.context(ExternalSnafu)?;
|
||||
|
||||
Ok(CommentOnTask {
|
||||
catalog_name,
|
||||
schema_name,
|
||||
object_type: CommentObjectType::Table,
|
||||
object_name: table_name,
|
||||
column_name: None,
|
||||
object_id: None,
|
||||
comment: stmt.comment,
|
||||
})
|
||||
}
|
||||
CommentObject::Column { table, column } => {
|
||||
let (catalog_name, schema_name, table_name) =
|
||||
table_idents_to_full_name(&table, query_ctx)
|
||||
.map_err(BoxedError::new)
|
||||
.context(ExternalSnafu)?;
|
||||
|
||||
Ok(CommentOnTask {
|
||||
catalog_name,
|
||||
schema_name,
|
||||
object_type: CommentObjectType::Column,
|
||||
object_name: table_name,
|
||||
column_name: Some(column.value),
|
||||
object_id: None,
|
||||
comment: stmt.comment,
|
||||
})
|
||||
}
|
||||
CommentObject::Flow(flow_name) => {
|
||||
let (catalog_name, flow_name_str) = match &flow_name.0[..] {
|
||||
[flow] => (
|
||||
query_ctx.current_catalog().to_string(),
|
||||
flow.to_string_unquoted(),
|
||||
),
|
||||
[catalog, flow] => (catalog.to_string_unquoted(), flow.to_string_unquoted()),
|
||||
_ => {
|
||||
return InvalidSqlSnafu {
|
||||
err_msg: format!(
|
||||
"expect flow name to be <catalog>.<flow_name> or <flow_name>, actual: {flow_name}"
|
||||
),
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
};
|
||||
|
||||
Ok(CommentOnTask {
|
||||
catalog_name,
|
||||
schema_name: String::new(), // Flow doesn't use schema
|
||||
object_type: CommentObjectType::Flow,
|
||||
object_name: flow_name_str,
|
||||
column_name: None,
|
||||
object_id: None,
|
||||
comment: stmt.comment,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use common_error::ext::BoxedError;
|
||||
use common_meta::key::schema_name::SchemaNameKey;
|
||||
use common_query::Output;
|
||||
@@ -120,7 +122,30 @@ impl StatementExecutor {
|
||||
table: TableRef,
|
||||
query_ctx: QueryContextRef,
|
||||
) -> Result<Output> {
|
||||
let table_info = table.table_info();
|
||||
let mut table_info = table.table_info();
|
||||
let partition_column_names: Vec<_> =
|
||||
table_info.meta.partition_column_names().cloned().collect();
|
||||
|
||||
if let Some(latest) = self
|
||||
.table_metadata_manager
|
||||
.table_info_manager()
|
||||
.get(table_info.table_id())
|
||||
.await
|
||||
.context(TableMetadataManagerSnafu)?
|
||||
{
|
||||
let mut latest_info = TableInfo::try_from(latest.into_inner().table_info)
|
||||
.context(error::CreateTableInfoSnafu)?;
|
||||
|
||||
if !partition_column_names.is_empty() {
|
||||
latest_info.meta.partition_key_indices = partition_column_names
|
||||
.iter()
|
||||
.filter_map(|name| latest_info.meta.schema.column_index_by_name(name.as_str()))
|
||||
.collect();
|
||||
}
|
||||
|
||||
table_info = Arc::new(latest_info);
|
||||
}
|
||||
|
||||
if table_info.table_type != TableType::Base {
|
||||
return error::ShowCreateTableBaseOnlySnafu {
|
||||
table_name: table_name.to_string(),
|
||||
@@ -150,7 +175,7 @@ impl StatementExecutor {
|
||||
|
||||
let partitions = create_partitions_stmt(&table_info, partitions)?;
|
||||
|
||||
query::sql::show_create_table(table, schema_options, partitions, query_ctx)
|
||||
query::sql::show_create_table(table_info, schema_options, partitions, query_ctx)
|
||||
.context(ExecuteStatementSnafu)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user