Skip to content

Commit

Permalink
add statement
Browse files Browse the repository at this point in the history
  • Loading branch information
andylokandy committed Apr 19, 2022
1 parent c91d088 commit 596102b
Show file tree
Hide file tree
Showing 8 changed files with 410 additions and 23 deletions.
16 changes: 8 additions & 8 deletions common/ast/src/parser/rule/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,20 +464,20 @@ pub fn expr_element(i: Input) -> IResult<WithSpan> {
let literal = map(literal, ExprElement::Literal);

let (rest, elem) = rule! (
#is_null : "`... IS [NOT] NULL` expression"
| #in_list : "`[NOT] IN (<expr>, ...)` expression"
| #in_subquery : "`[NOT] IN (SELECT ...)` expression"
| #between : "`[NOT] BETWEEN ... AND ...` expression"
#is_null : "`... IS [NOT] NULL`"
| #in_list : "`[NOT] IN (<expr>, ...)`"
| #in_subquery : "`[NOT] IN (SELECT ...)`"
| #between : "`[NOT] BETWEEN ... AND ...`"
| #binary_op : "<operator>"
| #unary_op : "<operator>"
| #cast : "`CAST(... AS ...)` expression"
| #cast : "`CAST(... AS ...)`"
| #count_all : "COUNT(*)"
| #literal : "<literal>"
| #function_call_with_param : "<function>"
| #function_call : "<function>"
| #case : "`CASE ... END` expression"
| #exists : "`EXISTS (SELECT ...)` expression"
| #subquery : "`(SELECT ...)` expression"
| #case : "`CASE ... END`"
| #exists : "`EXISTS (SELECT ...)`"
| #subquery : "`(SELECT ...)`"
| #group : "expression between `(...)`"
| #column_ref : "<column>"
)(i)?;
Expand Down
140 changes: 134 additions & 6 deletions common/ast/src/parser/rule/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,84 @@ use nom::combinator::value;

use crate::parser::ast::*;
use crate::parser::rule::expr::expr;
use crate::parser::rule::expr::literal;
use crate::parser::rule::expr::type_name;
use crate::parser::rule::util::*;
use crate::parser::token::*;
use crate::rule;

pub fn statement(i: Input) -> IResult<Statement> {
let truncate_table = map(
let query = map(query, |query| Statement::Select(Box::new(query)));
let show_tables = value(Statement::ShowTables, rule! { SHOW ~ TABLES ~ ";" });
let show_databases = value(Statement::ShowDatabases, rule! { SHOW ~ DATABASES~ ";" });
let show_settings = value(Statement::ShowSettings, rule! { SHOW ~ SETTINGS ~ ";" });
let show_process_list = value(
Statement::ShowProcessList,
rule! { SHOW ~ PROCESSLIST ~ ";" },
);
let show_create_table = map(
rule! {
TRUNCATE ~ TABLE ~ ( #ident ~ "." )? ~ #ident ~ ";"
SHOW ~ CREATE ~ TABLE ~ ( #ident ~ "." )? ~ #ident ~ ";"
},
|(_, _, database, table, _)| Statement::TruncateTable {
|(_, _, _, database, table, _)| Statement::ShowCreateTable {
database: database.map(|(name, _)| name),
table,
},
);
let explain = map(
rule! {
EXPLAIN ~ ANALYZE? ~ #statement ~ ";"
},
|(_, analyze, statement, _)| Statement::Explain {
analyze: analyze.is_some(),
query: Box::new(statement),
},
);
let describe = map(
rule! {
DESCRIBE ~ ( #ident ~ "." )? ~ #ident ~ ";"
},
|(_, database, table, _)| Statement::Describe {
database: database.map(|(name, _)| name),
table,
},
);
let create_table = map(
rule! {
CREATE ~ TABLE~ ( IF ~ NOT ~ EXISTS )?
~ ( #ident ~ "." )? ~ #ident
~ "(" ~ #comma_separated_list1(column_def) ~ ")" ~ ";"
},
|(_, _, if_not_exists, database, table, _, columns, _, _)| Statement::CreateTable {
if_not_exists: if_not_exists.is_some(),
database: database.map(|(name, _)| name),
table,
columns,
engine: "".to_string(),
options: vec![],
like_db: None,
like_table: None,
},
);
let create_table_like = map(
rule! {
CREATE ~ TABLE~ ( IF ~ NOT ~ EXISTS )?
~ ( #ident ~ "." )? ~ #ident
~ LIKE ~ ( #ident ~ "." )? ~ #ident ~ ";"
},
|(_, _, if_not_exists, database, table, _, like_db, like_table, _)| {
Statement::CreateTable {
if_not_exists: if_not_exists.is_some(),
database: database.map(|(name, _)| name),
table,
columns: vec![],
engine: "".to_string(),
options: vec![],
like_db: like_db.map(|(like_db, _)| like_db),
like_table: Some(like_table),
}
},
);
let drop_table = map(
rule! {
DROP ~ TABLE ~ ( IF ~ EXISTS )? ~ ( #ident ~ "." )? ~ #ident ~ ";"
Expand All @@ -43,10 +107,74 @@ pub fn statement(i: Input) -> IResult<Statement> {
table,
},
);
let truncate_table = map(
rule! {
TRUNCATE ~ TABLE ~ ( #ident ~ "." )? ~ #ident ~ ";"
},
|(_, _, database, table, _)| Statement::TruncateTable {
database: database.map(|(name, _)| name),
table,
},
);
let create_database = map(
rule! {
CREATE ~ DATABASE ~ ( IF ~ NOT ~ EXISTS )? ~ #ident ~ ";"
},
|(_, _, if_not_exists, name, _)| Statement::CreateDatabase {
if_not_exists: if_not_exists.is_some(),
name,
engine: "".to_string(),
options: vec![],
},
);
let use_database = map(
rule! {
USE ~ #ident ~ ";"
},
|(_, name, _)| Statement::UseDatabase { name },
);
let kill = map(
rule! {
KILL ~ #ident ~ ";"
},
|(_, object_id, _)| Statement::KillStmt { object_id },
);

rule!(
#truncate_table : "TRUNCATE TABLE statement"
| #drop_table : "DROP TABLE statement"
#query
| #show_tables : "`SHOW TABLES`"
| #show_databases : "`SHOW DATABASES`"
| #show_settings : "`SHOW SETTINGS`"
| #show_process_list : "`SHOW PROCESSLIST`"
| #show_create_table : "`SHOW CREATE TABLE [<database>.]<table>`"
| #explain : "`EXPLAIN [ANALYZE] <statement>`"
| #describe : "`DESCRIBE [<database>.]<table>`"
| #create_table : "`CREATE TABLE [IF NOT EXISTS] [<database>.]<table> (<column definition>, ...)`"
| #create_table_like : "`CREATE TABLE [IF NOT EXISTS] [<database>.]<table> LIKE [<database>.]<table>`"
| #drop_table : "`DROP TABLE [IF EXIST] [<database>.]<table>`"
| #truncate_table : "`TRUNCATE TABLE [<database>.]<table>`"
| #create_database : "`CREATE DATABASE [IF NOT EXIST] <database>`"
| #use_database : "`USE <database>`"
| #kill : "`KILL <object id>`"
)(i)
}

pub fn column_def(i: Input) -> IResult<ColumnDefinition> {
let nullable = alt((
value(true, rule! { NULL }),
value(false, rule! { NOT ~ NULL }),
));

map(
rule! {
#ident ~ #type_name ~ #nullable? ~ ( DEFAULT ~ #literal )? : "`<column name> <type> [NOT NULL | NULL] [DEFAULT <default value>]`"
},
|(name, data_type, nullable, default_value)| ColumnDefinition {
name,
data_type,
nullable: nullable.unwrap_or(true),
default_value: default_value.map(|(_, value)| value),
},
)(i)
}

Expand All @@ -60,7 +188,7 @@ pub fn query(i: Input) -> IResult<Query> {
~ ( HAVING ~ #expr )?
~ ( ORDER ~ BY ~ #comma_separated_list1(order_by_expr) )?
~ ( LIMIT ~ #comma_separated_list1(expr) )?
: "SELECT statement"
: "`SELECT ...`"
},
|(
_select,
Expand Down
10 changes: 10 additions & 0 deletions common/ast/src/parser/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,16 @@ pub enum TokenKind {
YEAR,
#[token("ZONE", ignore(ascii_case))]
ZONE,
#[token("DATABASES", ignore(ascii_case))]
DATABASES,
#[token("SETTINGS", ignore(ascii_case))]
SETTINGS,
#[token("PROCESSLIST", ignore(ascii_case))]
PROCESSLIST,
#[token("KILL", ignore(ascii_case))]
KILL,
#[token("USE", ignore(ascii_case))]
USE,
}

#[derive(Clone, Debug, PartialEq)]
Expand Down
11 changes: 11 additions & 0 deletions common/ast/tests/it/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,19 @@ fn test_statement() {
let mut mint = Mint::new("tests/it/testdata");
let mut file = mint.new_goldenfile("statement.txt").unwrap();
let cases = &[
"show tables;",
"show processlist;",
"show create table a.b;",
"explain analyze select a from b;",
"describe a;",
"create table if not exists a.b (c integer not null default 1, b varchar(10));",
"create table a.b like c.d;",
"truncate table a;",
r#"truncate table "a".b;"#,
"drop table a;",
r#"drop table if exists a."b";"#,
r#"use "a";"#,
"create database if not exists a;",
];

for case in cases {
Expand All @@ -71,11 +80,13 @@ fn test_statement_error() {
let mut file = mint.new_goldenfile("statement-error.txt").unwrap();

let cases = &[
"create table a.b (c integer not null 1, b varchar(10));",
"drop table if a.b;",
"truncate table a",
"truncate table a.b.c.d",
"truncate a",
"drop a",
"kill a",
];

for case in cases {
Expand Down
4 changes: 2 additions & 2 deletions common/ast/tests/it/testdata/expr-error.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ error:
1 | G.E.B IS NOT NULL AND
| - while parsing expression
2 | col1 NOT BETWEEN col2 AND
| --- while parsing `[NOT] BETWEEN ... AND ...` expression
| --- while parsing `[NOT] BETWEEN ... AND ...`
3 | AND 1 + col3 DIV sum(col4)
| ^^^ unexpected end of expression

Expand All @@ -48,7 +48,7 @@ error:
1 | CAST(col1 AS VARCHAR(0.1))
| ---- ^^^ unable to parse int because it contains invalid characters
| |
| while parsing `CAST(... AS ...)` expression
| while parsing `CAST(... AS ...)`
| while parsing expression


4 changes: 2 additions & 2 deletions common/ast/tests/it/testdata/query-error.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ error:
1 | select * from customer natural inner join orders on a = b;
| ------ ^^^^^ expected token <JOIN>
| |
| while parsing SELECT statement
| while parsing `SELECT ...`


---------- Input ----------
Expand All @@ -19,6 +19,6 @@ error:
1 | select * from customer join where a = b;
| ------ ^^^^^ expected token <Ident>
| |
| while parsing SELECT statement
| while parsing `SELECT ...`


34 changes: 29 additions & 5 deletions common/ast/tests/it/testdata/statement-error.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
---------- Input ----------
create table a.b (c integer not null 1, b varchar(10));
---------- Output ---------
error:
--> SQL:1:38
|
1 | create table a.b (c integer not null 1, b varchar(10));
| ------ ^ expected token ")"
| |
| while parsing `CREATE TABLE [IF NOT EXISTS] [<database>.]<table> (<column definition>, ...)`


---------- Input ----------
drop table if a.b;
---------- Output ---------
Expand All @@ -7,7 +19,7 @@ error:
1 | drop table if a.b;
| ---- ^^ expected token <Ident>
| |
| while parsing DROP TABLE statement
| while parsing `DROP TABLE [IF EXIST] [<database>.]<table>`


---------- Input ----------
Expand All @@ -19,7 +31,7 @@ error:
1 | truncate table a
| -------- ^ expected token ";"
| |
| while parsing TRUNCATE TABLE statement
| while parsing `TRUNCATE TABLE [<database>.]<table>`


---------- Input ----------
Expand All @@ -31,7 +43,7 @@ error:
1 | truncate table a.b.c.d
| -------- ^ expected token ";"
| |
| while parsing TRUNCATE TABLE statement
| while parsing `TRUNCATE TABLE [<database>.]<table>`


---------- Input ----------
Expand All @@ -43,7 +55,7 @@ error:
1 | truncate a
| -------- ^ expected token <TABLE>
| |
| while parsing TRUNCATE TABLE statement
| while parsing `TRUNCATE TABLE [<database>.]<table>`


---------- Input ----------
Expand All @@ -55,6 +67,18 @@ error:
1 | drop a
| ---- ^ expected token <TABLE>
| |
| while parsing DROP TABLE statement
| while parsing `DROP TABLE [IF EXIST] [<database>.]<table>`


---------- Input ----------
kill a
---------- Output ---------
error:
--> SQL:1:7
|
1 | kill a
| ---- ^ expected token ";"
| |
| while parsing `KILL <object id>`


Loading

0 comments on commit 596102b

Please sign in to comment.