Skip to content

Commit

Permalink
feat: show create database (#4642)
Browse files Browse the repository at this point in the history
* feat: show create database

* feat: add sqlness test

* chore: reorder mod and use

* feat: show create schema

* Update src/frontend/src/instance.rs
  • Loading branch information
fengjiachun authored Aug 30, 2024
1 parent 9286e96 commit f641c56
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 27 deletions.
26 changes: 13 additions & 13 deletions src/cmd/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use async_trait::async_trait;
use bench::BenchTableMetadataCommand;
use clap::Parser;
use common_telemetry::logging::{LoggingOptions, TracingOptions};
pub use repl::Repl;
use tracing_appender::non_blocking::WorkerGuard;

use self::export::ExportCommand;
use crate::cli::import::ImportCommand;
use crate::error::Result;
use crate::options::GlobalOptions;
use crate::App;

mod bench;

// Wait for https://github.com/GreptimeTeam/greptimedb/issues/2373
Expand All @@ -39,6 +26,19 @@ mod import;
#[allow(unused)]
mod repl;

use async_trait::async_trait;
use bench::BenchTableMetadataCommand;
use clap::Parser;
use common_telemetry::logging::{LoggingOptions, TracingOptions};
pub use repl::Repl;
use tracing_appender::non_blocking::WorkerGuard;

use self::export::ExportCommand;
use crate::cli::import::ImportCommand;
use crate::error::Result;
use crate::options::GlobalOptions;
use crate::App;

pub const APP_NAME: &str = "greptime-cli";

#[async_trait]
Expand Down
13 changes: 13 additions & 0 deletions src/common/meta/src/key/schema_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ impl TryFrom<&HashMap<String, String>> for SchemaNameValue {
}
}

impl From<SchemaNameValue> for HashMap<String, String> {
fn from(value: SchemaNameValue) -> Self {
let mut opts = HashMap::new();
if let Some(ttl) = value.ttl {
opts.insert(
OPT_KEY_TTL.to_string(),
format!("{}", humantime::format_duration(ttl)),
);
}
opts
}
}

impl<'a> SchemaNameKey<'a> {
pub fn new(catalog: &'a str, schema: &'a str) -> Self {
Self { catalog, schema }
Expand Down
33 changes: 28 additions & 5 deletions src/frontend/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ pub use standalone::StandaloneDatanodeManager;

use self::prom_store::ExportMetricHandler;
use crate::error::{
self, Error, ExecLogicalPlanSnafu, ExecutePromqlSnafu, ExternalSnafu, ParseSqlSnafu,
PermissionSnafu, PlanStatementSnafu, Result, SqlExecInterceptedSnafu, StartServerSnafu,
TableOperationSnafu,
self, Error, ExecLogicalPlanSnafu, ExecutePromqlSnafu, ExternalSnafu, InvalidSqlSnafu,
ParseSqlSnafu, PermissionSnafu, PlanStatementSnafu, Result, SqlExecInterceptedSnafu,
StartServerSnafu, TableOperationSnafu,
};
use crate::frontend::FrontendOptions;
use crate::heartbeat::HeartbeatTask;
Expand Down Expand Up @@ -452,6 +452,9 @@ pub fn check_permission(
| Statement::DropDatabase(_)
| Statement::DropFlow(_)
| Statement::Use(_) => {}
Statement::ShowCreateDatabase(stmt) => {
validate_database(&stmt.database_name, query_ctx)?;
}
Statement::ShowCreateTable(stmt) => {
validate_param(&stmt.table_name, query_ctx)?;
}
Expand Down Expand Up @@ -527,8 +530,8 @@ pub fn check_permission(
},
Statement::Copy(sql::statements::copy::Copy::CopyDatabase(copy_database)) => {
match copy_database {
CopyDatabase::To(stmt) => validate_param(&stmt.database_name, query_ctx)?,
CopyDatabase::From(stmt) => validate_param(&stmt.database_name, query_ctx)?,
CopyDatabase::To(stmt) => validate_database(&stmt.database_name, query_ctx)?,
CopyDatabase::From(stmt) => validate_database(&stmt.database_name, query_ctx)?,
}
}
Statement::TruncateTable(stmt) => {
Expand All @@ -548,6 +551,26 @@ fn validate_param(name: &ObjectName, query_ctx: &QueryContextRef) -> Result<()>
.context(SqlExecInterceptedSnafu)
}

fn validate_database(name: &ObjectName, query_ctx: &QueryContextRef) -> Result<()> {
let (catalog, schema) = match &name.0[..] {
[schema] => (
query_ctx.current_catalog().to_string(),
schema.value.clone(),
),
[catalog, schema] => (catalog.value.clone(), schema.value.clone()),
_ => InvalidSqlSnafu {
err_msg: format!(
"expect database name to be <catalog>.<schema> or <schema>, actual: {name}",
),
}
.fail()?,
};

validate_catalog_and_schema(&catalog, &schema, query_ctx)
.map_err(BoxedError::new)
.context(SqlExecInterceptedSnafu)
}

#[cfg(test)]
mod tests {
use std::collections::HashMap;
Expand Down
8 changes: 8 additions & 0 deletions src/operator/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,12 @@ pub enum Error {
#[snafu(implicit)]
location: Location,
},

#[snafu(display("Failed to upgrade catalog manager reference"))]
UpgradeCatalogManagerRef {
#[snafu(implicit)]
location: Location,
},
}

pub type Result<T> = std::result::Result<T, Error>;
Expand Down Expand Up @@ -931,6 +937,8 @@ impl ErrorExt for Error {

Error::ExecuteAdminFunction { source, .. } => source.status_code(),
Error::BuildRecordBatch { source, .. } => source.status_code(),

Error::UpgradeCatalogManagerRef { .. } => StatusCode::Internal,
}
}

Expand Down
29 changes: 28 additions & 1 deletion src/operator/src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@ mod set;
mod show;
mod tql;

use std::collections::HashMap;
use std::sync::Arc;

use catalog::kvbackend::KvBackendCatalogManager;
use catalog::CatalogManagerRef;
use client::RecordBatches;
use common_error::ext::BoxedError;
use common_meta::cache::TableRouteCacheRef;
use common_meta::cache_invalidator::CacheInvalidatorRef;
use common_meta::ddl::ProcedureExecutorRef;
use common_meta::key::flow::{FlowMetadataManager, FlowMetadataManagerRef};
use common_meta::key::schema_name::SchemaNameKey;
use common_meta::key::view_info::{ViewInfoManager, ViewInfoManagerRef};
use common_meta::key::{TableMetadataManager, TableMetadataManagerRef};
use common_meta::kv_backend::KvBackendRef;
Expand Down Expand Up @@ -60,7 +63,8 @@ use table::TableRef;
use self::set::{set_bytea_output, set_datestyle, set_timezone, validate_client_encoding};
use crate::error::{
self, CatalogSnafu, ExecLogicalPlanSnafu, ExternalSnafu, InvalidSqlSnafu, NotSupportedSnafu,
PlanStatementSnafu, Result, SchemaNotFoundSnafu, TableNotFoundSnafu,
PlanStatementSnafu, Result, SchemaNotFoundSnafu, TableMetadataManagerSnafu, TableNotFoundSnafu,
UpgradeCatalogManagerRefSnafu,
};
use crate::insert::InserterRef;
use crate::statement::copy_database::{COPY_DATABASE_TIME_END_KEY, COPY_DATABASE_TIME_START_KEY};
Expand Down Expand Up @@ -251,6 +255,29 @@ impl StatementExecutor {
)
.await
}
Statement::ShowCreateDatabase(show) => {
let (catalog, database) =
idents_to_full_database_name(&show.database_name, &query_ctx)
.map_err(BoxedError::new)
.context(ExternalSnafu)?;
let table_metadata_manager = self
.catalog_manager
.as_any()
.downcast_ref::<KvBackendCatalogManager>()
.map(|manager| manager.table_metadata_manager_ref().clone())
.context(UpgradeCatalogManagerRefSnafu)?;
let opts: HashMap<String, String> = table_metadata_manager
.schema_manager()
.get(SchemaNameKey::new(&catalog, &database))
.await
.context(TableMetadataManagerSnafu)?
.context(SchemaNotFoundSnafu {
schema_info: &database,
})?
.into();

self.show_create_database(&database, opts.into()).await
}
Statement::ShowCreateTable(show) => {
let (catalog, schema, table) =
table_idents_to_full_name(&show.table_name, &query_ctx)
Expand Down
13 changes: 11 additions & 2 deletions src/operator/src/statement/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use sql::statements::show::{
ShowColumns, ShowCreateFlow, ShowCreateView, ShowDatabases, ShowFlows, ShowIndex, ShowKind,
ShowTableStatus, ShowTables, ShowVariables, ShowViews,
};
use sql::statements::OptionMap;
use table::metadata::TableType;
use table::table_name::TableName;
use table::TableRef;
Expand Down Expand Up @@ -92,6 +93,15 @@ impl StatementExecutor {
.context(ExecuteStatementSnafu)
}

#[tracing::instrument(skip_all)]
pub async fn show_create_database(
&self,
database_name: &str,
opts: OptionMap,
) -> Result<Output> {
query::sql::show_create_database(database_name, opts).context(ExecuteStatementSnafu)
}

#[tracing::instrument(skip_all)]
pub async fn show_create_table(
&self,
Expand All @@ -118,8 +128,7 @@ impl StatementExecutor {

let partitions = create_partitions_stmt(partitions)?;

query::sql::show_create_table(table, partitions, query_ctx)
.context(error::ExecuteStatementSnafu)
query::sql::show_create_table(table, partitions, query_ctx).context(ExecuteStatementSnafu)
}

#[tracing::instrument(skip_all)]
Expand Down
34 changes: 33 additions & 1 deletion src/query/src/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,13 @@ pub use show_create_table::create_table_stmt;
use snafu::{ensure, OptionExt, ResultExt};
use sql::ast::Ident;
use sql::parser::ParserContext;
use sql::statements::create::{CreateFlow, CreateView, Partitions};
use sql::statements::create::{CreateDatabase, CreateFlow, CreateView, Partitions};
use sql::statements::show::{
ShowColumns, ShowDatabases, ShowFlows, ShowIndex, ShowKind, ShowTableStatus, ShowTables,
ShowVariables, ShowViews,
};
use sql::statements::statement::Statement;
use sql::statements::OptionMap;
use sqlparser::ast::ObjectName;
use table::requests::{FILE_TABLE_LOCATION_KEY, FILE_TABLE_PATTERN_KEY};
use table::TableRef;
Expand Down Expand Up @@ -136,6 +137,17 @@ static DESCRIBE_TABLE_OUTPUT_SCHEMA: Lazy<Arc<Schema>> = Lazy::new(|| {
]))
});

static SHOW_CREATE_DATABASE_OUTPUT_SCHEMA: Lazy<Arc<Schema>> = Lazy::new(|| {
Arc::new(Schema::new(vec![
ColumnSchema::new("Database", ConcreteDataType::string_datatype(), false),
ColumnSchema::new(
"Create Database",
ConcreteDataType::string_datatype(),
false,
),
]))
});

static SHOW_CREATE_TABLE_OUTPUT_SCHEMA: Lazy<Arc<Schema>> = Lazy::new(|| {
Arc::new(Schema::new(vec![
ColumnSchema::new("Table", ConcreteDataType::string_datatype(), false),
Expand Down Expand Up @@ -668,6 +680,26 @@ pub async fn show_status(_query_ctx: QueryContextRef) -> Result<Output> {
Ok(Output::new_with_record_batches(records))
}

pub fn show_create_database(database_name: &str, options: OptionMap) -> Result<Output> {
let stmt = CreateDatabase {
name: ObjectName(vec![Ident {
value: database_name.to_string(),
quote_style: None,
}]),
if_not_exists: true,
options,
};
let sql = format!("{stmt}");
let columns = vec![
Arc::new(StringVector::from(vec![database_name.to_string()])) as _,
Arc::new(StringVector::from(vec![sql])) as _,
];
let records =
RecordBatches::try_from_columns(SHOW_CREATE_DATABASE_OUTPUT_SCHEMA.clone(), columns)
.context(error::CreateRecordBatchSnafu)?;
Ok(Output::new_with_record_batches(records))
}

pub fn show_create_table(
table: TableRef,
partitions: Option<Partitions>,
Expand Down
28 changes: 25 additions & 3 deletions src/sql/src/parsers/show_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ use crate::error::{
};
use crate::parser::ParserContext;
use crate::statements::show::{
ShowColumns, ShowCreateFlow, ShowCreateTable, ShowCreateView, ShowDatabases, ShowFlows,
ShowIndex, ShowKind, ShowStatus, ShowTableStatus, ShowTables, ShowVariables, ShowViews,
ShowColumns, ShowCreateDatabase, ShowCreateFlow, ShowCreateTable, ShowCreateView,
ShowDatabases, ShowFlows, ShowIndex, ShowKind, ShowStatus, ShowTableStatus, ShowTables,
ShowVariables, ShowViews,
};
use crate::statements::statement::Statement;

Expand Down Expand Up @@ -74,7 +75,9 @@ impl<'a> ParserContext<'a> {
// SHOW {INDEX | INDEXES | KEYS}
self.parse_show_index()
} else if self.consume_token("CREATE") {
if self.consume_token("TABLE") {
if self.consume_token("DATABASE") || self.consume_token("SCHEMA") {
self.parse_show_create_database()
} else if self.consume_token("TABLE") {
self.parse_show_create_table()
} else if self.consume_token("FLOW") {
self.parse_show_create_flow()
Expand Down Expand Up @@ -109,6 +112,25 @@ impl<'a> ParserContext<'a> {
}
}

fn parse_show_create_database(&mut self) -> Result<Statement> {
let raw_database_name =
self.parse_object_name()
.with_context(|_| error::UnexpectedSnafu {
expected: "a database name",
actual: self.peek_token_as_string(),
})?;
let database_name = Self::canonicalize_object_name(raw_database_name);
ensure!(
!database_name.0.is_empty(),
InvalidDatabaseNameSnafu {
name: database_name.to_string(),
}
);
Ok(Statement::ShowCreateDatabase(ShowCreateDatabase {
database_name,
}))
}

/// Parse SHOW CREATE TABLE statement
fn parse_show_create_table(&mut self) -> Result<Statement> {
let raw_table_name = self
Expand Down
13 changes: 13 additions & 0 deletions src/sql/src/statements/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,19 @@ impl Display for ShowTableStatus {
}
}

/// SQL structure for `SHOW CREATE DATABASE`.
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
pub struct ShowCreateDatabase {
pub database_name: ObjectName,
}

impl Display for ShowCreateDatabase {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let database_name = &self.database_name;
write!(f, r#"SHOW CREATE DATABASE {database_name}"#)
}
}

/// SQL structure for `SHOW CREATE TABLE`.
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
pub struct ShowCreateTable {
Expand Down
8 changes: 6 additions & 2 deletions src/sql/src/statements/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ use crate::statements::insert::Insert;
use crate::statements::query::Query;
use crate::statements::set_variables::SetVariables;
use crate::statements::show::{
ShowColumns, ShowCreateFlow, ShowCreateTable, ShowCreateView, ShowDatabases, ShowFlows,
ShowIndex, ShowKind, ShowStatus, ShowTableStatus, ShowTables, ShowVariables, ShowViews,
ShowColumns, ShowCreateDatabase, ShowCreateFlow, ShowCreateTable, ShowCreateView,
ShowDatabases, ShowFlows, ShowIndex, ShowKind, ShowStatus, ShowTableStatus, ShowTables,
ShowVariables, ShowViews,
};
use crate::statements::tql::Tql;
use crate::statements::truncate::TruncateTable;
Expand Down Expand Up @@ -84,6 +85,8 @@ pub enum Statement {
ShowCollation(ShowKind),
// SHOW INDEX
ShowIndex(ShowIndex),
// SHOW CREATE DATABASE
ShowCreateDatabase(ShowCreateDatabase),
// SHOW CREATE TABLE
ShowCreateTable(ShowCreateTable),
// SHOW CREATE FLOW
Expand Down Expand Up @@ -139,6 +142,7 @@ impl Display for Statement {
Statement::ShowCreateTable(s) => s.fmt(f),
Statement::ShowCreateFlow(s) => s.fmt(f),
Statement::ShowFlows(s) => s.fmt(f),
Statement::ShowCreateDatabase(s) => s.fmt(f),
Statement::ShowCreateView(s) => s.fmt(f),
Statement::ShowViews(s) => s.fmt(f),
Statement::ShowStatus(s) => s.fmt(f),
Expand Down
Loading

0 comments on commit f641c56

Please sign in to comment.