Skip to content

Commit

Permalink
Merge pull request #1478 from leiysky/refactor/sql-parser
Browse files Browse the repository at this point in the history
sql: introduce datafuse standard AST and transformer from `sqlparser-rs`
  • Loading branch information
databend-bot committed Aug 18, 2021
2 parents 4f87741 + 25aca3c commit fd1c308
Show file tree
Hide file tree
Showing 10 changed files with 2,073 additions and 0 deletions.
1 change: 1 addition & 0 deletions query/src/sql/mod.rs
Expand Up @@ -17,6 +17,7 @@ mod plan_parser_test;
#[cfg(test)]
mod sql_parser_test;

mod parser;
mod plan_parser;
mod sql_common;
mod sql_parser;
Expand Down
191 changes: 191 additions & 0 deletions query/src/sql/parser/ast/ast_display_test.rs
@@ -0,0 +1,191 @@
// Copyright 2020 Datafuse Labs.
//
// 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.

#[cfg(test)]
mod test {
use crate::sql::parser::ast::*;

#[test]
fn test_display_create_database() {
let stmt = Statement::CreateDatabase {
if_not_exists: true,
name: vec![Identifier {
name: String::from("column"),
quote: Some('`'),
}],
engine: "".to_string(),
options: vec![],
};
assert_eq!(
format!("{}", stmt),
r#"CREATE DATABASE IF NOT EXISTS `column`"#
);
}

#[test]
fn test_display_create_table() {
let stmt = Statement::CreateTable {
if_not_exists: true,
name: vec![
Identifier {
name: "db".to_owned(),
quote: Some('`'),
},
Identifier {
name: "table".to_owned(),
quote: Some('`'),
},
],
columns: vec![ColumnDefinition {
name: Identifier {
name: "column".to_owned(),
quote: None,
},
data_type: TypeName::Int,
nullable: false,
default_value: Some(Literal::Number("123".to_owned())),
}],
engine: "".to_string(),
options: vec![],
};
assert_eq!(
format!("{}", stmt),
r#"CREATE TABLE IF NOT EXISTS `db`.`table` (column INTEGER NOT NULL DEFAULT 123)"#
);
}

#[test]
fn test_display_query() {
let stmt = SelectStmt {
distinct: true,
select_list: vec![
SelectTarget::Indirections(vec![
Indirection::Identifier(Identifier {
name: "table".to_owned(),
quote: None,
}),
Indirection::Identifier(Identifier {
name: "column".to_owned(),
quote: None,
}),
]),
SelectTarget::Indirections(vec![Indirection::Star]),
],
from: vec![
TableReference::Table {
name: vec![Identifier {
name: "table".to_owned(),
quote: None,
}],
alias: Some(TableAlias {
name: Identifier {
name: "table1".to_owned(),
quote: None,
},
columns: vec![],
}),
},
TableReference::Join(Join {
op: JoinOperator::Inner,
condition: JoinCondition::Natural,
left: Box::new(TableReference::Table {
name: vec![Identifier {
name: "left_table".to_owned(),
quote: None,
}],
alias: None,
}),
right: Box::new(TableReference::Table {
name: vec![Identifier {
name: "right_table".to_owned(),
quote: None,
}],
alias: None,
}),
}),
],
selection: Some(Expr::BinaryOp {
op: BinaryOperator::Eq,
left: Box::new(Expr::ColumnRef(vec![Identifier {
name: "a".to_owned(),
quote: None,
}])),
right: Box::new(Expr::ColumnRef(vec![Identifier {
name: "b".to_owned(),
quote: None,
}])),
}),
group_by: vec![Expr::ColumnRef(vec![Identifier {
name: "a".to_owned(),
quote: None,
}])],
having: Some(Expr::BinaryOp {
op: BinaryOperator::NotEq,
left: Box::new(Expr::ColumnRef(vec![Identifier {
name: "a".to_owned(),
quote: None,
}])),
right: Box::new(Expr::ColumnRef(vec![Identifier {
name: "b".to_owned(),
quote: None,
}])),
}),
};

assert_eq!(
format!("{}", stmt),
r#"SELECT DISTINCT table.column, * FROM table AS table1, left_table NATURAL INNER JOIN right_table WHERE a = b GROUP BY a HAVING a <> b"#
);
}

#[test]
fn test_display_expr() {
let expr = Expr::BinaryOp {
op: BinaryOperator::And,
left: Box::new(Expr::FunctionCall {
distinct: true,
name: "FUNC".to_owned(),
args: vec![
Expr::Cast {
expr: Box::new(Expr::Wildcard),
target_type: TypeName::Int,
},
Expr::Between {
expr: Box::new(Expr::Wildcard),
negated: true,
low: Box::new(Expr::Wildcard),
high: Box::new(Expr::Wildcard),
},
Expr::InList {
expr: Box::new(Expr::Wildcard),
list: vec![Expr::Wildcard, Expr::Wildcard],
not: true,
},
],
params: vec![Literal::Number("123".to_owned())],
}),
right: Box::new(Expr::Case {
operand: Some(Box::new(Expr::Wildcard)),
conditions: vec![Expr::Wildcard],
results: vec![Expr::Wildcard],
else_result: Some(Box::new(Expr::Wildcard)),
}),
};

assert_eq!(
format!("{}", expr),
r#"FUNC(123)(DISTINCT CAST(* AS INTEGER), * NOT BETWEEN * AND *, * NOT IN(*, *)) AND CASE * WHEN * THEN * ELSE * END"#
);
}
}

0 comments on commit fd1c308

Please sign in to comment.