feat: create database if not exists (#1009)

This commit is contained in:
LFC
2023-02-15 17:47:46 +08:00
committed by GitHub
parent cd0d58cb24
commit 34fdba77df
10 changed files with 70 additions and 24 deletions

View File

@@ -222,7 +222,7 @@ pub enum Error {
source: catalog::error::Error,
},
#[snafu(display("Schema already exists, name: {}", name))]
#[snafu(display("Schema {} already exists", name))]
SchemaExists { name: String, backtrace: Backtrace },
#[snafu(display("Failed to convert alter expr to request: {}", source))]

View File

@@ -30,12 +30,16 @@ use crate::error::{self, DecodeLogicalPlanSnafu, ExecuteSqlSnafu, Result};
use crate::instance::Instance;
impl Instance {
pub(crate) async fn handle_create_database(&self, expr: CreateDatabaseExpr) -> Result<Output> {
pub(crate) async fn handle_create_database(
&self,
expr: CreateDatabaseExpr,
query_ctx: QueryContextRef,
) -> Result<Output> {
let req = CreateDatabaseRequest {
db_name: expr.database_name,
create_if_not_exists: expr.create_if_not_exists,
};
self.sql_handler().create_database(req).await
self.sql_handler.create_database(req, query_ctx).await
}
pub(crate) async fn execute_logical(&self, plan_bytes: Vec<u8>) -> Result<Output> {
@@ -83,14 +87,14 @@ impl Instance {
Ok(Output::AffectedRows(affected_rows))
}
async fn handle_ddl(&self, request: DdlRequest) -> Result<Output> {
async fn handle_ddl(&self, request: DdlRequest, query_ctx: QueryContextRef) -> Result<Output> {
let expr = request.expr.context(error::MissingRequiredFieldSnafu {
name: "DdlRequest.expr",
})?;
match expr {
DdlExpr::CreateTable(expr) => self.handle_create(expr).await,
DdlExpr::Alter(expr) => self.handle_alter(expr).await,
DdlExpr::CreateDatabase(expr) => self.handle_create_database(expr).await,
DdlExpr::CreateDatabase(expr) => self.handle_create_database(expr, query_ctx).await,
DdlExpr::DropTable(expr) => self.handle_drop_table(expr).await,
}
}
@@ -111,7 +115,7 @@ impl GrpcQueryHandler for Instance {
})?;
self.handle_query(query, ctx).await
}
GrpcRequest::Ddl(request) => self.handle_ddl(request).await,
GrpcRequest::Ddl(request) => self.handle_ddl(request, ctx).await,
}
}
}

View File

@@ -78,7 +78,7 @@ impl SqlHandler {
let result = match request {
SqlRequest::Insert(req) => self.insert(req).await,
SqlRequest::CreateTable(req) => self.create_table(req).await,
SqlRequest::CreateDatabase(req) => self.create_database(req).await,
SqlRequest::CreateDatabase(req) => self.create_database(req, query_ctx.clone()).await,
SqlRequest::Alter(req) => self.alter(req).await,
SqlRequest::DropTable(req) => self.drop_table(req).await,
SqlRequest::Delete(stmt) => self.delete(query_ctx.clone(), stmt).await,

View File

@@ -16,11 +16,11 @@ use std::collections::HashMap;
use std::sync::Arc;
use catalog::{RegisterSchemaRequest, RegisterTableRequest};
use common_catalog::consts::DEFAULT_CATALOG_NAME;
use common_query::Output;
use common_telemetry::tracing::info;
use common_telemetry::tracing::log::error;
use datatypes::schema::SchemaBuilder;
use session::context::QueryContextRef;
use snafu::{ensure, OptionExt, ResultExt};
use sql::ast::{ColumnOption, TableConstraint};
use sql::statements::column_def_to_schema;
@@ -38,25 +38,35 @@ use crate::error::{
use crate::sql::SqlHandler;
impl SqlHandler {
pub(crate) async fn create_database(&self, req: CreateDatabaseRequest) -> Result<Output> {
pub(crate) async fn create_database(
&self,
req: CreateDatabaseRequest,
query_ctx: QueryContextRef,
) -> Result<Output> {
let catalog = query_ctx.current_catalog();
let schema = req.db_name;
if self
.catalog_manager
.schema(&catalog, &schema)
.context(CatalogSnafu)?
.is_some()
{
return if req.create_if_not_exists {
Ok(Output::AffectedRows(1))
} else {
SchemaExistsSnafu { name: schema }.fail()
};
}
let reg_req = RegisterSchemaRequest {
catalog: DEFAULT_CATALOG_NAME.to_string(),
catalog,
schema: schema.clone(),
};
let success = self
.catalog_manager
self.catalog_manager
.register_schema(reg_req)
.await
.context(RegisterSchemaSnafu)?;
// FIXME(dennis): looks like register_schema always returns true even
// even when the schema already exists.
ensure!(
success || req.create_if_not_exists,
SchemaExistsSnafu { name: schema }
);
info!("Successfully created database: {:?}", schema);
Ok(Output::AffectedRows(1))
}