Skip to content

Commit

Permalink
Merge pull request #5771 from leiysky/create-table
Browse files Browse the repository at this point in the history
feature(planner): Support `CREATE TABLE` statement in new planner
  • Loading branch information
mergify[bot] authored Jun 4, 2022
2 parents f4770cc + 10e8b80 commit 7eba93e
Show file tree
Hide file tree
Showing 17 changed files with 851 additions and 394 deletions.
13 changes: 13 additions & 0 deletions common/ast/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,16 @@ fn write_comma_separated_list(
}
Ok(())
}

fn write_space_seperated_list(
f: &mut Formatter<'_>,
items: impl IntoIterator<Item = impl Display>,
) -> std::fmt::Result {
for (i, item) in items.into_iter().enumerate() {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{}", item)?;
}
Ok(())
}
68 changes: 52 additions & 16 deletions common/ast/src/ast/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::fmt::Formatter;
use common_meta_types::AuthType;
use common_meta_types::UserIdentity;

use super::write_space_seperated_list;
use super::Expr;
use crate::ast::expr::Literal;
use crate::ast::expr::TypeName;
Expand Down Expand Up @@ -77,16 +78,7 @@ pub enum Statement<'a> {
database: Option<Identifier<'a>>,
limit: Option<ShowLimit<'a>>,
},
CreateTable {
if_not_exists: bool,
database: Option<Identifier<'a>>,
table: Identifier<'a>,
source: Option<CreateTableSource<'a>>,
engine: Engine,
cluster_by: Vec<Expr<'a>>,
as_query: Option<Box<Query<'a>>>,
comment: Option<String>,
},
CreateTable(CreateTableStmt<'a>),
// Describe schema of a table
// Like `SHOW CREATE TABLE`
Describe {
Expand Down Expand Up @@ -222,6 +214,18 @@ pub enum InsertSource<'a> {
Select { query: Box<Query<'a>> },
}

#[derive(Debug, Clone, PartialEq)]
pub struct CreateTableStmt<'a> {
pub if_not_exists: bool,
pub database: Option<Identifier<'a>>,
pub table: Identifier<'a>,
pub source: Option<CreateTableSource<'a>>,
pub table_options: Vec<TableOption>,
pub cluster_by: Vec<Expr<'a>>,
pub as_query: Option<Box<Query<'a>>>,
pub comment: Option<String>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum CreateTableSource<'a> {
Columns(Vec<ColumnDefinition<'a>>),
Expand All @@ -231,6 +235,28 @@ pub enum CreateTableSource<'a> {
},
}

#[derive(Debug, Clone, PartialEq)]
pub enum TableOption {
Engine(Engine),
Comment(String),
}

impl TableOption {
pub fn option_key(&self) -> String {
match self {
TableOption::Engine(_) => "ENGINE".to_string(),
TableOption::Comment(_) => "COMMENT".to_string(),
}
}

pub fn option_value(&self) -> String {
match self {
TableOption::Engine(engine) => engine.to_string(),
TableOption::Comment(comment) => comment.clone(),
}
}
}

#[derive(Debug, Clone, PartialEq)]
pub enum Engine {
Null,
Expand Down Expand Up @@ -322,6 +348,15 @@ impl<'a> Display for ColumnDefinition<'a> {
}
}

impl Display for TableOption {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
TableOption::Engine(engine) => write!(f, "ENGINE = {engine}"),
TableOption::Comment(comment) => write!(f, "COMMENT = {comment}"),
}
}
}

impl Display for Engine {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Expand Down Expand Up @@ -457,16 +492,16 @@ impl<'a> Display for Statement<'a> {
write!(f, " {limit}")?;
}
}
Statement::CreateTable {
Statement::CreateTable(CreateTableStmt {
if_not_exists,
database,
table,
source,
engine,
table_options,
comment,
cluster_by,
as_query,
} => {
}) => {
write!(f, "CREATE TABLE ")?;
if *if_not_exists {
write!(f, "IF NOT EXISTS ")?;
Expand All @@ -484,9 +519,10 @@ impl<'a> Display for Statement<'a> {
}
None => (),
}
if *engine != Engine::Null {
write!(f, " ENGINE = {engine}")?;
}

// Format table options
write_space_seperated_list(f, table_options.iter())?;

if let Some(comment) = comment {
write!(f, " COMMENT = {comment}")?;
}
Expand Down
24 changes: 18 additions & 6 deletions common/ast/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ pub fn statement(i: Input) -> IResult<Statement> {
CREATE ~ TABLE ~ ( IF ~ NOT ~ EXISTS )?
~ ( #ident ~ "." )? ~ #ident
~ #create_table_source?
~ #engine?
~ ( #table_option )*
~ ( COMMENT ~ "=" ~ #literal_string )?
~ ( CLUSTER ~ ^BY ~ ^"(" ~ ^#comma_separated_list1(expr) ~ ^")" )?
~ ( AS ~ ^#query )?
Expand All @@ -146,23 +146,23 @@ pub fn statement(i: Input) -> IResult<Statement> {
opt_database,
table,
source,
opt_engine,
table_options,
opt_comment,
opt_cluster_by,
opt_as_query,
)| {
Statement::CreateTable {
Statement::CreateTable(CreateTableStmt {
if_not_exists: opt_if_not_exists.is_some(),
database: opt_database.map(|(database, _)| database),
table,
source,
engine: opt_engine.unwrap_or(Engine::Null),
table_options,
comment: opt_comment.map(|(_, _, comment)| comment),
cluster_by: opt_cluster_by
.map(|(_, _, _, exprs, _)| exprs)
.unwrap_or_default(),
as_query: opt_as_query.map(|(_, query)| Box::new(query)),
}
})
},
);
let describe = map(
Expand Down Expand Up @@ -429,7 +429,7 @@ pub fn statement(i: Input) -> IResult<Statement> {
| #show_tables : "`SHOW [FULL] TABLES [FROM <database>] [<show_limit>]`"
| #show_create_table : "`SHOW CREATE TABLE [<database>.]<table>`"
| #show_tables_status : "`SHOW TABLES STATUS [FROM <database>] [<show_limit>]`"
| #create_table : "`CREATE TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [ENGINE = <engine>]`"
| #create_table : "`CREATE TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [<table_options>]`"
| #describe : "`DESCRIBE [<database>.]<table>`"
| #drop_table : "`DROP TABLE [IF EXISTS] [<database>.]<table>`"
| #undrop_table : "`UNDROP TABLE [<database>.]<table>`"
Expand Down Expand Up @@ -616,6 +616,18 @@ pub fn show_limit(i: Input) -> IResult<ShowLimit> {
)(i)
}

pub fn table_option(i: Input) -> IResult<TableOption> {
alt((
map(engine, TableOption::Engine),
map(
rule! {
COMMENT ~ ^"=" ~ #literal_string
},
|(_, _, comment)| TableOption::Comment(comment),
),
))(i)
}

pub fn engine(i: Input) -> IResult<Engine> {
let engine = alt((
value(Engine::Null, rule! { NULL }),
Expand Down
6 changes: 3 additions & 3 deletions common/ast/tests/it/testdata/statement-error.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ error:
1 | create table a.b (c integer not null 1, b float(10))
| ------ ^ expected `)`, `NULL`, `NOT`, `DEFAULT`, or `,`
| |
| while parsing `CREATE TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [ENGINE = <engine>]`
| while parsing `CREATE TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [<table_options>]`


---------- Input ----------
Expand All @@ -19,7 +19,7 @@ error:
1 | create table a (c float(10))
| ------ ^ expected `)`, `NULL`, `NOT`, `DEFAULT`, or `,`
| |
| while parsing `CREATE TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [ENGINE = <engine>]`
| while parsing `CREATE TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [<table_options>]`


---------- Input ----------
Expand All @@ -34,7 +34,7 @@ error:
| | | expected `BOOLEAN`, `BOOL`, `UINT8`, `TINYINT`, `UINT16`, `SMALLINT`, or 25 more ...
| | | while parsing type name
| | while parsing `<column name> <type> [NOT NULL | NULL] [DEFAULT <default value>]`
| while parsing `CREATE TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [ENGINE = <engine>]`
| while parsing `CREATE TABLE [IF NOT EXISTS] [<database>.]<table> [<source>] [<table_options>]`


---------- Input ----------
Expand Down
Loading

0 comments on commit 7eba93e

Please sign in to comment.