From 5e8cefca604f847b851cf148f979d5596a2c559a Mon Sep 17 00:00:00 2001 From: Andy Lok Date: Thu, 12 May 2022 03:07:24 +0800 Subject: [PATCH 1/2] feat(parser): add span for expression --- common/ast/src/ast/expr.rs | 111 ++- common/ast/src/ast/statement.rs | 4 +- common/ast/src/parser/error.rs | 2 +- common/ast/src/parser/expr.rs | 75 +- common/ast/tests/it/parser.rs | 5 +- common/ast/tests/it/testdata/expr.txt | 860 ++++++++++++++++++--- common/ast/tests/it/testdata/query.txt | 133 +++- common/ast/tests/it/testdata/statement.txt | 164 +++- 8 files changed, 1168 insertions(+), 186 deletions(-) diff --git a/common/ast/src/ast/expr.rs b/common/ast/src/ast/expr.rs index 54ad8dafc429..d102afc4720d 100644 --- a/common/ast/src/ast/expr.rs +++ b/common/ast/src/ast/expr.rs @@ -19,31 +19,40 @@ use crate::ast::write_comma_separated_list; use crate::ast::write_period_separated_list; use crate::ast::Identifier; use crate::ast::Query; +use crate::parser::token::Token; #[derive(Debug, Clone, PartialEq)] pub enum Expr<'a> { /// Column reference, with indirection like `table.column` ColumnRef { + span: &'a [Token<'a>], database: Option>, table: Option>, column: Identifier<'a>, }, /// `IS [ NOT ] NULL` expression - IsNull { expr: Box>, not: bool }, + IsNull { + span: &'a [Token<'a>], + expr: Box>, + not: bool, + }, /// `[ NOT ] IN (expr, ...)` InList { + span: &'a [Token<'a>], expr: Box>, list: Vec>, not: bool, }, /// `[ NOT ] IN (SELECT ...)` InSubquery { + span: &'a [Token<'a>], expr: Box>, subquery: Box>, not: bool, }, /// `BETWEEN ... AND ...` Between { + span: &'a [Token<'a>], expr: Box>, low: Box>, high: Box>, @@ -51,38 +60,45 @@ pub enum Expr<'a> { }, /// Binary operation BinaryOp { + span: &'a [Token<'a>], op: BinaryOperator, left: Box>, right: Box>, }, /// Unary operation UnaryOp { + span: &'a [Token<'a>], op: UnaryOperator, expr: Box>, }, /// `CAST` expression, like `CAST(expr AS target_type)` Cast { + span: &'a [Token<'a>], expr: Box>, target_type: TypeName, pg_style: bool, }, /// `TRY_CAST` expression` TryCast { + span: &'a [Token<'a>], expr: Box>, target_type: TypeName, }, /// EXTRACT(DateTimeField FROM ) Extract { + span: &'a [Token<'a>], field: DateTimeField, expr: Box>, }, /// POSITION( IN ) Position { + span: &'a [Token<'a>], substr_expr: Box>, str_expr: Box>, }, /// SUBSTRING( [FROM ] [FOR ]) Substring { + span: &'a [Token<'a>], expr: Box>, substring_from: Option>>, substring_for: Option>>, @@ -91,18 +107,23 @@ pub enum Expr<'a> { /// Or /// TRIM() Trim { + span: &'a [Token<'a>], expr: Box>, // ([BOTH | LEADING | TRAILING], ) trim_where: Option<(TrimWhere, Box>)>, }, /// A literal value, such as string, number, date or NULL - Literal(Literal), + Literal { span: &'a [Token<'a>], lit: Literal }, /// `COUNT(*)` expression - CountAll, + CountAll { span: &'a [Token<'a>] }, /// `(foo, bar)` - Tuple { exprs: Vec> }, + Tuple { + span: &'a [Token<'a>], + exprs: Vec>, + }, /// Scalar function call FunctionCall { + span: &'a [Token<'a>], /// Set to true if the function is aggregate function with `DISTINCT`, like `COUNT(DISTINCT a)` distinct: bool, name: Identifier<'a>, @@ -111,18 +132,26 @@ pub enum Expr<'a> { }, /// `CASE ... WHEN ... ELSE ...` expression Case { + span: &'a [Token<'a>], operand: Option>>, conditions: Vec>, results: Vec>, else_result: Option>>, }, /// `EXISTS` expression - Exists(Box>), + Exists { + span: &'a [Token<'a>], + subquery: Box>, + }, /// Scalar subquery, which will only return a single row with a single column. - Subquery(Box>), + Subquery { + span: &'a [Token<'a>], + subquery: Box>, + }, // TODO(andylokandy): allow interval, function, and others alike to be a key /// Access elements of `Array`, `Object` and `Variant` by index or key, like `arr[0]`, or `obj:k1` MapAccess { + span: &'a [Token<'a>], expr: Box>, accessor: MapAccessor<'a>, }, @@ -252,6 +281,34 @@ pub enum UnaryOperator { Not, } +impl<'a> Expr<'a> { + pub fn span(&self) -> &'a [Token<'a>] { + match self { + Expr::ColumnRef { span, .. } => span, + Expr::IsNull { span, .. } => span, + Expr::InList { span, .. } => span, + Expr::InSubquery { span, .. } => span, + Expr::Between { span, .. } => span, + Expr::BinaryOp { span, .. } => span, + Expr::UnaryOp { span, .. } => span, + Expr::Cast { span, .. } => span, + Expr::TryCast { span, .. } => span, + Expr::Extract { span, .. } => span, + Expr::Position { span, .. } => span, + Expr::Substring { span, .. } => span, + Expr::Trim { span, .. } => span, + Expr::Literal { span, .. } => span, + Expr::CountAll { span } => span, + Expr::Tuple { span, .. } => span, + Expr::FunctionCall { span, .. } => span, + Expr::Case { span, .. } => span, + Expr::Exists { span, .. } => span, + Expr::Subquery { span, .. } => span, + Expr::MapAccess { span, .. } => span, + } + } +} + impl Display for UnaryOperator { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { @@ -493,17 +550,20 @@ impl<'a> Display for Expr<'a> { database, table, column, + .. } => { write_period_separated_list(f, database.iter().chain(table).chain(Some(column)))?; } - Expr::IsNull { expr, not } => { + Expr::IsNull { expr, not, .. } => { write!(f, "{expr} IS")?; if *not { write!(f, " NOT")?; } write!(f, " NULL")?; } - Expr::InList { expr, list, not } => { + Expr::InList { + expr, list, not, .. + } => { write!(f, "{expr}")?; if *not { write!(f, " NOT")?; @@ -516,6 +576,7 @@ impl<'a> Display for Expr<'a> { expr, subquery, not, + .. } => { write!(f, "{expr}")?; if *not { @@ -528,6 +589,7 @@ impl<'a> Display for Expr<'a> { low, high, not, + .. } => { write!(f, "{expr}")?; if *not { @@ -535,16 +597,19 @@ impl<'a> Display for Expr<'a> { } write!(f, " BETWEEN {low} AND {high}")?; } - Expr::UnaryOp { op, expr } => { + Expr::UnaryOp { op, expr, .. } => { write!(f, "{op} {expr}")?; } - Expr::BinaryOp { op, left, right } => { + Expr::BinaryOp { + op, left, right, .. + } => { write!(f, "{left} {op} {right}")?; } Expr::Cast { expr, target_type, pg_style, + .. } => { if *pg_style { write!(f, "{expr}::{target_type}")?; @@ -552,15 +617,18 @@ impl<'a> Display for Expr<'a> { write!(f, "CAST({expr} AS {target_type})")?; } } - Expr::TryCast { expr, target_type } => { + Expr::TryCast { + expr, target_type, .. + } => { write!(f, "TRY_CAST({expr} AS {target_type})")?; } - Expr::Extract { field, expr } => { + Expr::Extract { field, expr, .. } => { write!(f, "EXTRACT({field} FROM {expr})")?; } Expr::Position { substr_expr, str_expr, + .. } => { write!(f, "POSITION({substr_expr} IN {str_expr})")?; } @@ -568,6 +636,7 @@ impl<'a> Display for Expr<'a> { expr, substring_from, substring_for, + .. } => { write!(f, "SUBSTRING({expr}")?; if let Some(substring_from) = substring_from { @@ -578,20 +647,22 @@ impl<'a> Display for Expr<'a> { } write!(f, ")")?; } - Expr::Trim { expr, trim_where } => { + Expr::Trim { + expr, trim_where, .. + } => { write!(f, "TRIM(")?; if let Some((trim_where, trim_str)) = trim_where { write!(f, "{trim_where} {trim_str} FROM ")?; } write!(f, "{expr})")?; } - Expr::Literal(lit) => { + Expr::Literal { lit, .. } => { write!(f, "{lit}")?; } - Expr::CountAll => { + Expr::CountAll { .. } => { write!(f, "COUNT(*)")?; } - Expr::Tuple { exprs } => { + Expr::Tuple { exprs, .. } => { write!(f, "(")?; write_comma_separated_list(f, exprs)?; if exprs.len() == 1 { @@ -604,6 +675,7 @@ impl<'a> Display for Expr<'a> { name, args, params, + .. } => { write!(f, "{name}")?; if !params.is_empty() { @@ -623,6 +695,7 @@ impl<'a> Display for Expr<'a> { conditions, results, else_result, + .. } => { write!(f, "CASE")?; if let Some(op) = operand { @@ -636,13 +709,13 @@ impl<'a> Display for Expr<'a> { } write!(f, " END")?; } - Expr::Exists(subquery) => { + Expr::Exists { subquery, .. } => { write!(f, "EXITS ({subquery})")?; } - Expr::Subquery(subquery) => { + Expr::Subquery { subquery, .. } => { write!(f, "({subquery})")?; } - Expr::MapAccess { expr, accessor } => { + Expr::MapAccess { expr, accessor, .. } => { write!(f, "{}", expr)?; match accessor { MapAccessor::Bracket { key } => write!(f, "[{key}]")?, diff --git a/common/ast/src/ast/statement.rs b/common/ast/src/ast/statement.rs index bbc6bb9d3ff4..e83dcb5c6df6 100644 --- a/common/ast/src/ast/statement.rs +++ b/common/ast/src/ast/statement.rs @@ -695,13 +695,13 @@ impl<'a> Display for Statement<'a> { write!(f, " WITH {}", auth_type.to_str())?; } if let Some(password) = &auth_option.password { - write!(f, " BY '{password}'", password = password)?; + write!(f, " BY '{password}'")?; } } if !role_options.is_empty() { write!(f, " WITH")?; for with_option in role_options { - write!(f, " {with_option}", with_option = with_option)?; + write!(f, " {with_option}")?; } } } diff --git a/common/ast/src/parser/error.rs b/common/ast/src/parser/error.rs index db787088ab0c..76251efa0a0d 100644 --- a/common/ast/src/parser/error.rs +++ b/common/ast/src/parser/error.rs @@ -173,7 +173,7 @@ impl<'a> DisplayError for Token<'a> { } } -impl<'a, 'b> DisplayError for &'b [Token<'a>] { +impl<'a> DisplayError for &'a [Token<'a>] { type Message = String; fn display_error(&self, message: String) -> String { diff --git a/common/ast/src/parser/expr.rs b/common/ast/src/parser/expr.rs index f2e473d64673..819d56e6b511 100644 --- a/common/ast/src/parser/expr.rs +++ b/common/ast/src/parser/expr.rs @@ -14,10 +14,10 @@ use itertools::Itertools; use nom::branch::alt; +use nom::combinator::consumed; use nom::combinator::map; use nom::combinator::value; use nom::error::context; -use nom::Offset as _; use nom::Slice as _; use pratt::Affix; use pratt::Associativity; @@ -146,8 +146,8 @@ fn map_pratt_error<'a>( #[derive(Debug, Clone)] pub struct WithSpan<'a> { - elem: ExprElement<'a>, span: Input<'a>, + elem: ExprElement<'a>, } /// A 'flattened' AST of expressions. @@ -242,9 +242,9 @@ pub enum ExprElement<'a> { else_result: Option>>, }, /// `EXISTS` expression - Exists(Query<'a>), + Exists { subquery: Query<'a> }, /// Scalar subquery, which will only return a single row with a single column. - Subquery(Query<'a>), + Subquery { subquery: Query<'a> }, /// Access elements of `Array`, `Object` and `Variant` by index or key, like `arr[0]`, or `obj:k1` MapAccess { accessor: MapAccessor<'a> }, /// An expression between parentheses @@ -317,21 +317,32 @@ impl<'a, I: Iterator>> PrattParser for ExprParser { table, column, } => Expr::ColumnRef { + span: elem.span.0, database, table, column, }, ExprElement::Cast { expr, target_type } => Expr::Cast { + span: elem.span.0, expr, target_type, pg_style: false, }, - ExprElement::TryCast { expr, target_type } => Expr::TryCast { expr, target_type }, - ExprElement::Extract { field, expr } => Expr::Extract { field, expr }, + ExprElement::TryCast { expr, target_type } => Expr::TryCast { + span: elem.span.0, + expr, + target_type, + }, + ExprElement::Extract { field, expr } => Expr::Extract { + span: elem.span.0, + field, + expr, + }, ExprElement::Position { substr_expr, str_expr, } => Expr::Position { + span: elem.span.0, substr_expr, str_expr, }, @@ -340,20 +351,32 @@ impl<'a, I: Iterator>> PrattParser for ExprParser { substring_from, substring_for, } => Expr::Substring { + span: elem.span.0, expr, substring_from, substring_for, }, - ExprElement::Trim { expr, trim_where } => Expr::Trim { expr, trim_where }, - ExprElement::Literal(lit) => Expr::Literal(lit), - ExprElement::CountAll => Expr::CountAll, - ExprElement::Tuple { exprs } => Expr::Tuple { exprs }, + ExprElement::Trim { expr, trim_where } => Expr::Trim { + span: elem.span.0, + expr, + trim_where, + }, + ExprElement::Literal(lit) => Expr::Literal { + span: elem.span.0, + lit, + }, + ExprElement::CountAll => Expr::CountAll { span: elem.span.0 }, + ExprElement::Tuple { exprs } => Expr::Tuple { + span: elem.span.0, + exprs, + }, ExprElement::FunctionCall { distinct, name, args, params, } => Expr::FunctionCall { + span: elem.span.0, distinct, name, args, @@ -365,13 +388,20 @@ impl<'a, I: Iterator>> PrattParser for ExprParser { results, else_result, } => Expr::Case { + span: elem.span.0, operand, conditions, results, else_result, }, - ExprElement::Exists(subquery) => Expr::Exists(Box::new(subquery)), - ExprElement::Subquery(subquery) => Expr::Subquery(Box::new(subquery)), + ExprElement::Exists { subquery } => Expr::Exists { + span: elem.span.0, + subquery: Box::new(subquery), + }, + ExprElement::Subquery { subquery } => Expr::Subquery { + span: elem.span.0, + subquery: Box::new(subquery), + }, ExprElement::Group(expr) => expr, _ => unreachable!(), }; @@ -386,6 +416,7 @@ impl<'a, I: Iterator>> PrattParser for ExprParser { ) -> pratt::Result> { let expr = match elem.elem { ExprElement::BinaryOp { op } => Expr::BinaryOp { + span: elem.span.0, left: Box::new(lhs), right: Box::new(rhs), op, @@ -398,6 +429,7 @@ impl<'a, I: Iterator>> PrattParser for ExprParser { fn prefix(&mut self, elem: WithSpan<'a>, rhs: Expr<'a>) -> pratt::Result> { let expr = match elem.elem { ExprElement::UnaryOp { op } => Expr::UnaryOp { + span: elem.span.0, op, expr: Box::new(rhs), }, @@ -409,30 +441,36 @@ impl<'a, I: Iterator>> PrattParser for ExprParser { fn postfix(&mut self, lhs: Expr<'a>, elem: WithSpan<'a>) -> pratt::Result> { let expr = match elem.elem { ExprElement::MapAccess { accessor } => Expr::MapAccess { + span: elem.span.0, expr: Box::new(lhs), accessor, }, ExprElement::IsNull { not } => Expr::IsNull { + span: elem.span.0, expr: Box::new(lhs), not, }, ExprElement::InList { list, not } => Expr::InList { + span: elem.span.0, expr: Box::new(lhs), list, not, }, ExprElement::InSubquery { subquery, not } => Expr::InSubquery { + span: elem.span.0, expr: Box::new(lhs), subquery, not, }, ExprElement::Between { low, high, not } => Expr::Between { + span: elem.span.0, expr: Box::new(lhs), low, high, not, }, ExprElement::PgCast { target_type } => Expr::Cast { + span: elem.span.0, expr: Box::new(lhs), target_type, pg_style: true, @@ -664,7 +702,7 @@ pub fn expr_element(i: Input) -> IResult { ); let exists = map( rule! { EXISTS ~ ^"(" ~ ^#query ~ ^")" }, - |(_, _, subquery, _)| ExprElement::Exists(subquery), + |(_, _, subquery, _)| ExprElement::Exists { subquery }, ); let subquery = map( rule! { @@ -672,7 +710,7 @@ pub fn expr_element(i: Input) -> IResult { ~ #query ~ ^")" }, - |(_, subquery, _)| ExprElement::Subquery(subquery), + |(_, subquery, _)| ExprElement::Subquery { subquery }, ); let group = map( rule! { @@ -687,7 +725,7 @@ pub fn expr_element(i: Input) -> IResult { let literal = map(literal, ExprElement::Literal); let map_access = map(map_access, |accessor| ExprElement::MapAccess { accessor }); - let (rest, elem) = alt(( + let (rest, (span, elem)) = consumed(alt(( rule! ( #is_null : "`... IS [NOT] NULL`" | #in_list : "`[NOT] IN (, ...)`" @@ -716,12 +754,9 @@ pub fn expr_element(i: Input) -> IResult { | #group | #column_ref : "" ), - ))(i)?; - - let offset = i.offset(&rest); - let span = Input(&i.0[..offset], i.1); + )))(i)?; - Ok((rest, WithSpan { elem, span })) + Ok((rest, WithSpan { span, elem })) } pub fn unary_op(i: Input) -> IResult { diff --git a/common/ast/tests/it/parser.rs b/common/ast/tests/it/parser.rs index 75be87a53f91..7d982e36e1cd 100644 --- a/common/ast/tests/it/parser.rs +++ b/common/ast/tests/it/parser.rs @@ -145,7 +145,10 @@ fn test_statements_in_legacy_suites() { let tokens = tokenize_sql(&file_str).unwrap(); let backtrace = Backtrace::new(); - parse_sql(&tokens, &backtrace).unwrap(); + parse_sql(&tokens, &backtrace).expect( + "Parser error should not exist in integration suites. \ + Please add parser error cases to `common/ast/tests/it/parser.rs`", + ); } } diff --git a/common/ast/tests/it/testdata/expr.txt b/common/ast/tests/it/testdata/expr.txt index adda0f1c9a5e..44297b9cc08e 100644 --- a/common/ast/tests/it/testdata/expr.txt +++ b/common/ast/tests/it/testdata/expr.txt @@ -4,6 +4,9 @@ a a ---------- AST ------------ ColumnRef { + span: [ + Ident(0..1), + ], database: None, table: None, column: Identifier { @@ -20,12 +23,18 @@ ColumnRef { - 1 ---------- AST ------------ UnaryOp { + span: [ + Minus(0..1), + ], op: Minus, - expr: Literal( - Number( + expr: Literal { + span: [ + LiteralNumber(1..2), + ], + lit: Number( "1", ), - ), + }, } @@ -35,12 +44,21 @@ UnaryOp { (1,) ---------- AST ------------ Tuple { + span: [ + LParen(0..1), + LiteralNumber(1..2), + Comma(2..3), + RParen(3..4), + ], exprs: [ - Literal( - Number( + Literal { + span: [ + LiteralNumber(1..2), + ], + lit: Number( "1", ), - ), + }, ], } @@ -51,17 +69,30 @@ Tuple { (1, 2) ---------- AST ------------ Tuple { + span: [ + LParen(0..1), + LiteralNumber(1..2), + Comma(2..3), + LiteralNumber(3..4), + RParen(4..5), + ], exprs: [ - Literal( - Number( + Literal { + span: [ + LiteralNumber(1..2), + ], + lit: Number( "1", ), - ), - Literal( - Number( + }, + Literal { + span: [ + LiteralNumber(3..4), + ], + lit: Number( "2", ), - ), + }, ], } @@ -72,17 +103,31 @@ Tuple { (1, 2) ---------- AST ------------ Tuple { + span: [ + LParen(0..1), + LiteralNumber(1..2), + Comma(2..3), + LiteralNumber(3..4), + Comma(4..5), + RParen(5..6), + ], exprs: [ - Literal( - Number( + Literal { + span: [ + LiteralNumber(1..2), + ], + lit: Number( "1", ), - ), - Literal( - Number( + }, + Literal { + span: [ + LiteralNumber(3..4), + ], + lit: Number( "2", ), - ), + }, ], } @@ -93,6 +138,14 @@ typeof(1 + 2) typeof(1 + 2) ---------- AST ------------ FunctionCall { + span: [ + Ident(0..6), + LParen(6..7), + LiteralNumber(7..8), + Plus(9..10), + LiteralNumber(11..12), + RParen(12..13), + ], distinct: false, name: Identifier { name: "typeof", @@ -101,17 +154,26 @@ FunctionCall { }, args: [ BinaryOp { + span: [ + Plus(9..10), + ], op: Plus, - left: Literal( - Number( + left: Literal { + span: [ + LiteralNumber(7..8), + ], + lit: Number( "1", ), - ), - right: Literal( - Number( + }, + right: Literal { + span: [ + LiteralNumber(11..12), + ], + lit: Number( "2", ), - ), + }, }, ], params: [], @@ -124,31 +186,61 @@ FunctionCall { - - + + - 1 + + - 2 ---------- AST ------------ UnaryOp { + span: [ + Minus(0..1), + ], op: Minus, expr: UnaryOp { + span: [ + Minus(2..3), + ], op: Minus, expr: UnaryOp { + span: [ + Plus(4..5), + ], op: Plus, expr: UnaryOp { + span: [ + Plus(6..7), + ], op: Plus, expr: UnaryOp { + span: [ + Minus(8..9), + ], op: Minus, expr: BinaryOp { + span: [ + Plus(12..13), + ], op: Plus, - left: Literal( - Number( + left: Literal { + span: [ + LiteralNumber(10..11), + ], + lit: Number( "1", ), - ), + }, right: UnaryOp { + span: [ + Plus(14..15), + ], op: Plus, expr: UnaryOp { + span: [ + Minus(16..17), + ], op: Minus, - expr: Literal( - Number( + expr: Literal { + span: [ + LiteralNumber(18..19), + ], + lit: Number( "2", ), - ), + }, }, }, }, @@ -165,15 +257,27 @@ UnaryOp { 1 + a * c.d ---------- AST ------------ BinaryOp { + span: [ + Plus(2..3), + ], op: Plus, - left: Literal( - Number( + left: Literal { + span: [ + LiteralNumber(0..1), + ], + lit: Number( "1", ), - ), + }, right: BinaryOp { + span: [ + Multiply(6..7), + ], op: Multiply, left: ColumnRef { + span: [ + Ident(4..5), + ], database: None, table: None, column: Identifier { @@ -183,6 +287,11 @@ BinaryOp { }, }, right: ColumnRef { + span: [ + Ident(8..9), + Period(9..10), + Ident(10..11), + ], database: None, table: Some( Identifier { @@ -207,8 +316,14 @@ number % 2 number % 2 ---------- AST ------------ BinaryOp { + span: [ + Modulo(7..8), + ], op: Modulo, left: ColumnRef { + span: [ + Ident(0..6), + ], database: None, table: None, column: Identifier { @@ -217,11 +332,14 @@ BinaryOp { span: Ident(0..6), }, }, - right: Literal( - Number( + right: Literal { + span: [ + LiteralNumber(9..10), + ], + lit: Number( "2", ), - ), + }, } @@ -231,7 +349,17 @@ col1 not between 1 and 2 col1 NOT BETWEEN 1 AND 2 ---------- AST ------------ Between { + span: [ + NOT(5..8), + BETWEEN(9..16), + LiteralNumber(17..18), + AND(19..22), + LiteralNumber(23..24), + ], expr: ColumnRef { + span: [ + Ident(0..4), + ], database: None, table: None, column: Identifier { @@ -240,16 +368,22 @@ Between { span: Ident(0..4), }, }, - low: Literal( - Number( + low: Literal { + span: [ + LiteralNumber(17..18), + ], + lit: Number( "1", ), - ), - high: Literal( - Number( + }, + high: Literal { + span: [ + LiteralNumber(23..24), + ], + lit: Number( "2", ), - ), + }, not: true, } @@ -260,6 +394,12 @@ sum(col1) sum(col1) ---------- AST ------------ FunctionCall { + span: [ + Ident(0..3), + LParen(3..4), + Ident(4..8), + RParen(8..9), + ], distinct: false, name: Identifier { name: "sum", @@ -268,6 +408,9 @@ FunctionCall { }, args: [ ColumnRef { + span: [ + Ident(4..8), + ], database: None, table: None, column: Identifier { @@ -287,6 +430,11 @@ FunctionCall { "random"() ---------- AST ------------ FunctionCall { + span: [ + QuotedIdent(0..8), + LParen(8..9), + RParen(9..10), + ], distinct: false, name: Identifier { name: "random", @@ -306,6 +454,12 @@ random(distinct) random(DISTINCT ) ---------- AST ------------ FunctionCall { + span: [ + Ident(0..6), + LParen(6..7), + DISTINCT(7..15), + RParen(15..16), + ], distinct: true, name: Identifier { name: "random", @@ -323,6 +477,14 @@ covar_samp(number, number) covar_samp(number, number) ---------- AST ------------ FunctionCall { + span: [ + Ident(0..10), + LParen(10..11), + Ident(11..17), + Comma(17..18), + Ident(19..25), + RParen(25..26), + ], distinct: false, name: Identifier { name: "covar_samp", @@ -331,6 +493,9 @@ FunctionCall { }, args: [ ColumnRef { + span: [ + Ident(11..17), + ], database: None, table: None, column: Identifier { @@ -340,6 +505,9 @@ FunctionCall { }, }, ColumnRef { + span: [ + Ident(19..25), + ], database: None, table: None, column: Identifier { @@ -359,7 +527,19 @@ CAST(col1 AS BIGINT UNSIGNED) CAST(col1 AS UInt64) ---------- AST ------------ Cast { + span: [ + CAST(0..4), + LParen(4..5), + Ident(5..9), + AS(10..12), + BIGINT(13..19), + UNSIGNED(20..28), + RParen(28..29), + ], expr: ColumnRef { + span: [ + Ident(5..9), + ], database: None, table: None, column: Identifier { @@ -379,7 +559,19 @@ TRY_CAST(col1 AS BIGINT UNSIGNED) TRY_CAST(col1 AS UInt64) ---------- AST ------------ TryCast { + span: [ + TRY_CAST(0..8), + LParen(8..9), + Ident(9..13), + AS(14..16), + BIGINT(17..23), + UNSIGNED(24..32), + RParen(32..33), + ], expr: ColumnRef { + span: [ + Ident(9..13), + ], database: None, table: None, column: Identifier { @@ -398,19 +590,34 @@ trim(leading 'abc' from 'def') TRIM(LEADING 'abc' FROM 'def') ---------- AST ------------ Trim { - expr: Literal( - String( + span: [ + TRIM(0..4), + LParen(4..5), + LEADING(5..12), + QuotedIdent(13..18), + FROM(19..23), + QuotedIdent(24..29), + RParen(29..30), + ], + expr: Literal { + span: [ + QuotedIdent(24..29), + ], + lit: String( "def", ), - ), + }, trim_where: Some( ( Leading, - Literal( - String( + Literal { + span: [ + QuotedIdent(13..18), + ], + lit: String( "abc", ), - ), + }, ), ), } @@ -422,8 +629,19 @@ extract(year from d) EXTRACT(YEAR FROM d) ---------- AST ------------ Extract { + span: [ + EXTRACT(0..7), + LParen(7..8), + YEAR(8..12), + FROM(13..17), + Ident(18..19), + RParen(19..20), + ], field: Year, expr: ColumnRef { + span: [ + Ident(18..19), + ], database: None, table: None, column: Identifier { @@ -441,12 +659,26 @@ position('a' in str) POSITION('a' IN str) ---------- AST ------------ Position { - substr_expr: Literal( - String( + span: [ + POSITION(0..8), + LParen(8..9), + QuotedIdent(9..12), + IN(13..15), + Ident(16..19), + RParen(19..20), + ], + substr_expr: Literal { + span: [ + QuotedIdent(9..12), + ], + lit: String( "a", ), - ), + }, str_expr: ColumnRef { + span: [ + Ident(16..19), + ], database: None, table: None, column: Identifier { @@ -464,7 +696,20 @@ substring(a from b for c) SUBSTRING(a FROM b FOR c) ---------- AST ------------ Substring { + span: [ + SUBSTRING(0..9), + LParen(9..10), + Ident(10..11), + FROM(12..16), + Ident(17..18), + FOR(19..22), + Ident(23..24), + RParen(24..25), + ], expr: ColumnRef { + span: [ + Ident(10..11), + ], database: None, table: None, column: Identifier { @@ -475,6 +720,9 @@ Substring { }, substring_from: Some( ColumnRef { + span: [ + Ident(17..18), + ], database: None, table: None, column: Identifier { @@ -486,6 +734,9 @@ Substring { ), substring_for: Some( ColumnRef { + span: [ + Ident(23..24), + ], database: None, table: None, column: Identifier { @@ -504,7 +755,20 @@ substring(a, b, c) SUBSTRING(a FROM b FOR c) ---------- AST ------------ Substring { + span: [ + SUBSTRING(0..9), + LParen(9..10), + Ident(10..11), + Comma(11..12), + Ident(13..14), + Comma(14..15), + Ident(16..17), + RParen(17..18), + ], expr: ColumnRef { + span: [ + Ident(10..11), + ], database: None, table: None, column: Identifier { @@ -515,6 +779,9 @@ Substring { }, substring_from: Some( ColumnRef { + span: [ + Ident(13..14), + ], database: None, table: None, column: Identifier { @@ -526,6 +793,9 @@ Substring { ), substring_for: Some( ColumnRef { + span: [ + Ident(16..17), + ], database: None, table: None, column: Identifier { @@ -544,7 +814,14 @@ col1::UInt8 col1::UInt8 ---------- AST ------------ Cast { + span: [ + DoubleColon(4..6), + UINT8(6..11), + ], expr: ColumnRef { + span: [ + Ident(0..4), + ], database: None, table: None, column: Identifier { @@ -564,9 +841,25 @@ Cast { arr[0]:a.b ---------- AST ------------ MapAccess { + span: [ + Period(10..11), + Ident(11..12), + ], expr: MapAccess { + span: [ + Colon(7..8), + Ident(8..9), + ], expr: MapAccess { + span: [ + LBracket(4..5), + LiteralNumber(5..6), + RBracket(6..7), + ], expr: ColumnRef { + span: [ + Ident(1..4), + ], database: None, table: None, column: Identifier { @@ -605,8 +898,21 @@ arr[4]["k"] arr[4]['k'] ---------- AST ------------ MapAccess { + span: [ + LBracket(6..7), + QuotedIdent(7..10), + RBracket(10..11), + ], expr: MapAccess { + span: [ + LBracket(3..4), + LiteralNumber(4..5), + RBracket(5..6), + ], expr: ColumnRef { + span: [ + Ident(0..3), + ], database: None, table: None, column: Identifier { @@ -635,8 +941,14 @@ a rlike '^11' a RLIKE '^11' ---------- AST ------------ BinaryOp { + span: [ + RLIKE(2..7), + ], op: RLike, left: ColumnRef { + span: [ + Ident(0..1), + ], database: None, table: None, column: Identifier { @@ -645,11 +957,14 @@ BinaryOp { span: Ident(0..1), }, }, - right: Literal( - String( + right: Literal { + span: [ + QuotedIdent(8..13), + ], + lit: String( "^11", ), - ), + }, } @@ -659,9 +974,24 @@ G.E.B IS NOT NULL AND col1 not between col2 and (1 + col3) DIV sum(col4) G.E.B IS NOT NULL AND col1 NOT BETWEEN col2 AND 1 + col3 DIV sum(col4) ---------- AST ------------ BinaryOp { + span: [ + AND(18..21), + ], op: And, left: IsNull { + span: [ + IS(6..8), + NOT(9..12), + NULL(13..17), + ], expr: ColumnRef { + span: [ + Ident(0..1), + Period(1..2), + Ident(2..3), + Period(3..4), + Ident(4..5), + ], database: Some( Identifier { name: "G", @@ -685,7 +1015,26 @@ BinaryOp { not: true, }, right: Between { + span: [ + NOT(27..30), + BETWEEN(31..38), + Ident(39..43), + AND(44..47), + LParen(48..49), + LiteralNumber(49..50), + Plus(51..52), + Ident(53..57), + RParen(57..58), + DIV(59..62), + Ident(63..66), + LParen(66..67), + Ident(67..71), + RParen(71..72), + ], expr: ColumnRef { + span: [ + Ident(22..26), + ], database: None, table: None, column: Identifier { @@ -695,6 +1044,9 @@ BinaryOp { }, }, low: ColumnRef { + span: [ + Ident(39..43), + ], database: None, table: None, column: Identifier { @@ -704,15 +1056,27 @@ BinaryOp { }, }, high: BinaryOp { + span: [ + DIV(59..62), + ], op: Div, left: BinaryOp { + span: [ + Plus(51..52), + ], op: Plus, - left: Literal( - Number( + left: Literal { + span: [ + LiteralNumber(49..50), + ], + lit: Number( "1", ), - ), + }, right: ColumnRef { + span: [ + Ident(53..57), + ], database: None, table: None, column: Identifier { @@ -723,6 +1087,12 @@ BinaryOp { }, }, right: FunctionCall { + span: [ + Ident(63..66), + LParen(66..67), + Ident(67..71), + RParen(71..72), + ], distinct: false, name: Identifier { name: "sum", @@ -731,6 +1101,9 @@ BinaryOp { }, args: [ ColumnRef { + span: [ + Ident(67..71), + ], database: None, table: None, column: Identifier { @@ -754,8 +1127,28 @@ sum(CASE WHEN n2.n_name = 'GERMANY' THEN ol_amount ELSE 0 END) / CASE WHEN sum(o sum(CASE WHEN n2.n_name = 'GERMANY' THEN ol_amount ELSE 0 END) / CASE WHEN sum(ol_amount) = 0 THEN 1 ELSE sum(ol_amount) END ---------- AST ------------ BinaryOp { + span: [ + Divide(63..64), + ], op: Divide, left: FunctionCall { + span: [ + Ident(0..3), + LParen(3..4), + CASE(4..8), + WHEN(9..13), + Ident(14..16), + Period(16..17), + Ident(17..23), + Eq(24..25), + QuotedIdent(26..35), + THEN(36..40), + Ident(41..50), + ELSE(51..55), + LiteralNumber(56..57), + END(58..61), + RParen(61..62), + ], distinct: false, name: Identifier { name: "sum", @@ -764,11 +1157,33 @@ BinaryOp { }, args: [ Case { + span: [ + CASE(4..8), + WHEN(9..13), + Ident(14..16), + Period(16..17), + Ident(17..23), + Eq(24..25), + QuotedIdent(26..35), + THEN(36..40), + Ident(41..50), + ELSE(51..55), + LiteralNumber(56..57), + END(58..61), + ], operand: None, conditions: [ BinaryOp { + span: [ + Eq(24..25), + ], op: Eq, left: ColumnRef { + span: [ + Ident(14..16), + Period(16..17), + Ident(17..23), + ], database: None, table: Some( Identifier { @@ -783,15 +1198,21 @@ BinaryOp { span: Ident(17..23), }, }, - right: Literal( - String( + right: Literal { + span: [ + QuotedIdent(26..35), + ], + lit: String( "GERMANY", ), - ), + }, }, ], results: [ ColumnRef { + span: [ + Ident(41..50), + ], database: None, table: None, column: Identifier { @@ -802,22 +1223,52 @@ BinaryOp { }, ], else_result: Some( - Literal( - Number( + Literal { + span: [ + LiteralNumber(56..57), + ], + lit: Number( "0", ), - ), + }, ), }, ], params: [], }, right: Case { + span: [ + CASE(65..69), + WHEN(70..74), + Ident(75..78), + LParen(78..79), + Ident(79..88), + RParen(88..89), + Eq(90..91), + LiteralNumber(92..93), + THEN(94..98), + LiteralNumber(99..100), + ELSE(101..105), + Ident(106..109), + LParen(109..110), + Ident(110..119), + RParen(119..120), + END(121..124), + ], operand: None, conditions: [ BinaryOp { + span: [ + Eq(90..91), + ], op: Eq, left: FunctionCall { + span: [ + Ident(75..78), + LParen(78..79), + Ident(79..88), + RParen(88..89), + ], distinct: false, name: Identifier { name: "sum", @@ -826,6 +1277,9 @@ BinaryOp { }, args: [ ColumnRef { + span: [ + Ident(79..88), + ], database: None, table: None, column: Identifier { @@ -837,22 +1291,34 @@ BinaryOp { ], params: [], }, - right: Literal( - Number( + right: Literal { + span: [ + LiteralNumber(92..93), + ], + lit: Number( "0", ), - ), + }, }, ], results: [ - Literal( - Number( + Literal { + span: [ + LiteralNumber(99..100), + ], + lit: Number( "1", ), - ), + }, ], else_result: Some( FunctionCall { + span: [ + Ident(106..109), + LParen(109..110), + Ident(110..119), + RParen(119..120), + ], distinct: false, name: Identifier { name: "sum", @@ -861,6 +1327,9 @@ BinaryOp { }, args: [ ColumnRef { + span: [ + Ident(110..119), + ], database: None, table: None, column: Identifier { @@ -889,22 +1358,49 @@ p_partkey = l_partkey p_partkey = l_partkey AND p_brand = 'Brand#12' AND p_container IN('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') AND l_quantity >= CAST(1 AS Int16) AND l_quantity <= CAST(1 + 10 AS Int16) AND p_size BETWEEN CAST(1 AS Int16) AND CAST(5 AS Int16) AND l_shipmode IN('AIR', 'AIR REG') AND l_shipinstruct = 'DELIVER IN PERSON' ---------- AST ------------ BinaryOp { + span: [ + AND(366..369), + ], op: And, left: BinaryOp { + span: [ + AND(317..320), + ], op: And, left: BinaryOp { + span: [ + AND(240..243), + ], op: And, left: BinaryOp { + span: [ + AND(184..187), + ], op: And, left: BinaryOp { + span: [ + AND(145..148), + ], op: And, left: BinaryOp { + span: [ + AND(71..74), + ], op: And, left: BinaryOp { + span: [ + AND(34..37), + ], op: And, left: BinaryOp { + span: [ + Eq(10..11), + ], op: Eq, left: ColumnRef { + span: [ + Ident(0..9), + ], database: None, table: None, column: Identifier { @@ -914,6 +1410,9 @@ BinaryOp { }, }, right: ColumnRef { + span: [ + Ident(12..21), + ], database: None, table: None, column: Identifier { @@ -924,8 +1423,14 @@ BinaryOp { }, }, right: BinaryOp { + span: [ + Eq(46..47), + ], op: Eq, left: ColumnRef { + span: [ + Ident(38..45), + ], database: None, table: None, column: Identifier { @@ -934,15 +1439,33 @@ BinaryOp { span: Ident(38..45), }, }, - right: Literal( - String( + right: Literal { + span: [ + QuotedIdent(48..58), + ], + lit: String( "Brand#12", ), - ), + }, }, }, right: InList { + span: [ + IN(87..89), + LParen(90..91), + QuotedIdent(91..100), + Comma(100..101), + QuotedIdent(102..110), + Comma(110..111), + QuotedIdent(112..121), + Comma(121..122), + QuotedIdent(123..131), + RParen(131..132), + ], expr: ColumnRef { + span: [ + Ident(75..86), + ], database: None, table: None, column: Identifier { @@ -952,33 +1475,51 @@ BinaryOp { }, }, list: [ - Literal( - String( + Literal { + span: [ + QuotedIdent(91..100), + ], + lit: String( "SM CASE", ), - ), - Literal( - String( + }, + Literal { + span: [ + QuotedIdent(102..110), + ], + lit: String( "SM BOX", ), - ), - Literal( - String( + }, + Literal { + span: [ + QuotedIdent(112..121), + ], + lit: String( "SM PACK", ), - ), - Literal( - String( + }, + Literal { + span: [ + QuotedIdent(123..131), + ], + lit: String( "SM PKG", ), - ), + }, ], not: false, }, }, right: BinaryOp { + span: [ + Gte(160..162), + ], op: Gte, left: ColumnRef { + span: [ + Ident(149..159), + ], database: None, table: None, column: Identifier { @@ -988,19 +1529,36 @@ BinaryOp { }, }, right: Cast { - expr: Literal( - Number( + span: [ + CAST(163..167), + LParen(168..169), + LiteralNumber(169..170), + AS(171..173), + SMALLINT(174..182), + RParen(182..183), + ], + expr: Literal { + span: [ + LiteralNumber(169..170), + ], + lit: Number( "1", ), - ), + }, target_type: Int16, pg_style: false, }, }, }, right: BinaryOp { + span: [ + Lte(199..201), + ], op: Lte, left: ColumnRef { + span: [ + Ident(188..198), + ], database: None, table: None, column: Identifier { @@ -1010,18 +1568,37 @@ BinaryOp { }, }, right: Cast { + span: [ + CAST(202..206), + LParen(207..208), + LiteralNumber(208..209), + Plus(210..211), + LiteralNumber(212..214), + AS(215..217), + SMALLINT(218..226), + RParen(226..227), + ], expr: BinaryOp { + span: [ + Plus(210..211), + ], op: Plus, - left: Literal( - Number( + left: Literal { + span: [ + LiteralNumber(208..209), + ], + lit: Number( "1", ), - ), - right: Literal( - Number( + }, + right: Literal { + span: [ + LiteralNumber(212..214), + ], + lit: Number( "10", ), - ), + }, }, target_type: Int16, pg_style: false, @@ -1029,7 +1606,26 @@ BinaryOp { }, }, right: Between { + span: [ + BETWEEN(251..258), + CAST(259..263), + LParen(264..265), + LiteralNumber(265..266), + AS(267..269), + SMALLINT(270..278), + RParen(278..279), + AND(280..283), + CAST(284..288), + LParen(289..290), + LiteralNumber(290..291), + AS(292..294), + SMALLINT(295..303), + RParen(303..304), + ], expr: ColumnRef { + span: [ + Ident(244..250), + ], database: None, table: None, column: Identifier { @@ -1039,20 +1635,42 @@ BinaryOp { }, }, low: Cast { - expr: Literal( - Number( + span: [ + CAST(259..263), + LParen(264..265), + LiteralNumber(265..266), + AS(267..269), + SMALLINT(270..278), + RParen(278..279), + ], + expr: Literal { + span: [ + LiteralNumber(265..266), + ], + lit: Number( "1", ), - ), + }, target_type: Int16, pg_style: false, }, high: Cast { - expr: Literal( - Number( + span: [ + CAST(284..288), + LParen(289..290), + LiteralNumber(290..291), + AS(292..294), + SMALLINT(295..303), + RParen(303..304), + ], + expr: Literal { + span: [ + LiteralNumber(290..291), + ], + lit: Number( "5", ), - ), + }, target_type: Int16, pg_style: false, }, @@ -1060,7 +1678,18 @@ BinaryOp { }, }, right: InList { + span: [ + IN(332..334), + LParen(335..336), + QuotedIdent(336..341), + Comma(341..342), + QuotedIdent(343..352), + RParen(352..353), + ], expr: ColumnRef { + span: [ + Ident(321..331), + ], database: None, table: None, column: Identifier { @@ -1070,23 +1699,35 @@ BinaryOp { }, }, list: [ - Literal( - String( + Literal { + span: [ + QuotedIdent(336..341), + ], + lit: String( "AIR", ), - ), - Literal( - String( + }, + Literal { + span: [ + QuotedIdent(343..352), + ], + lit: String( "AIR REG", ), - ), + }, ], not: false, }, }, right: BinaryOp { + span: [ + Eq(385..386), + ], op: Eq, left: ColumnRef { + span: [ + Ident(370..384), + ], database: None, table: None, column: Identifier { @@ -1095,11 +1736,14 @@ BinaryOp { span: Ident(370..384), }, }, - right: Literal( - String( + right: Literal { + span: [ + QuotedIdent(387..406), + ], + lit: String( "DELIVER IN PERSON", ), - ), + }, }, } diff --git a/common/ast/tests/it/testdata/query.txt b/common/ast/tests/it/testdata/query.txt index 72cd8c0dfac6..007a36f9dcab 100644 --- a/common/ast/tests/it/testdata/query.txt +++ b/common/ast/tests/it/testdata/query.txt @@ -50,8 +50,14 @@ Query { op: Inner, condition: On( BinaryOp { + span: [ + Eq(46..47), + ], op: Eq, left: ColumnRef { + span: [ + Ident(44..45), + ], database: None, table: None, column: Identifier { @@ -61,6 +67,9 @@ Query { }, }, right: ColumnRef { + span: [ + Ident(48..49), + ], database: None, table: None, column: Identifier { @@ -101,11 +110,14 @@ Query { ), order_by: [], limit: [ - Literal( - Number( + Literal { + span: [ + LiteralNumber(56..57), + ], + lit: Number( "1", ), - ), + }, ], offset: None, } @@ -167,8 +179,14 @@ Query { op: Inner, condition: On( BinaryOp { + span: [ + Eq(46..47), + ], op: Eq, left: ColumnRef { + span: [ + Ident(44..45), + ], database: None, table: None, column: Identifier { @@ -178,6 +196,9 @@ Query { }, }, right: ColumnRef { + span: [ + Ident(48..49), + ], database: None, table: None, column: Identifier { @@ -218,18 +239,24 @@ Query { ), order_by: [], limit: [ - Literal( - Number( + Literal { + span: [ + LiteralNumber(56..57), + ], + lit: Number( "2", ), - ), + }, ], offset: Some( - Literal( - Number( + Literal { + span: [ + LiteralNumber(65..66), + ], + lit: Number( "3", ), - ), + }, ), } @@ -587,6 +614,9 @@ Query { select_list: [ AliasedExpr { expr: ColumnRef { + span: [ + Ident(7..14), + ], database: None, table: None, column: Identifier { @@ -598,7 +628,14 @@ Query { alias: None, }, AliasedExpr { - expr: CountAll, + expr: CountAll { + span: [ + COUNT(16..21), + LParen(21..22), + Multiply(22..23), + RParen(23..24), + ], + }, alias: Some( Identifier { name: "custdist", @@ -609,6 +646,12 @@ Query { }, AliasedExpr { expr: FunctionCall { + span: [ + Ident(38..41), + LParen(41..42), + Ident(42..51), + RParen(51..52), + ], distinct: false, name: Identifier { name: "sum", @@ -617,6 +660,9 @@ Query { }, args: [ ColumnRef { + span: [ + Ident(42..51), + ], database: None, table: None, column: Identifier { @@ -739,6 +785,9 @@ Query { select_list: [ AliasedExpr { expr: ColumnRef { + span: [ + Ident(175..184), + ], database: None, table: None, column: Identifier { @@ -751,6 +800,12 @@ Query { }, AliasedExpr { expr: FunctionCall { + span: [ + COUNT(210..215), + LParen(215..216), + Ident(216..226), + RParen(226..227), + ], distinct: false, name: Identifier { name: "count", @@ -759,6 +814,9 @@ Query { }, args: [ ColumnRef { + span: [ + Ident(216..226), + ], database: None, table: None, column: Identifier { @@ -779,10 +837,19 @@ Query { op: LeftOuter, condition: On( BinaryOp { + span: [ + AND(390..393), + ], op: And, left: BinaryOp { + span: [ + Eq(350..351), + ], op: Eq, left: ColumnRef { + span: [ + Ident(340..349), + ], database: None, table: None, column: Identifier { @@ -792,6 +859,9 @@ Query { }, }, right: ColumnRef { + span: [ + Ident(352..361), + ], database: None, table: None, column: Identifier { @@ -802,8 +872,15 @@ Query { }, }, right: BinaryOp { + span: [ + NOT(404..407), + LIKE(408..412), + ], op: NotLike, left: ColumnRef { + span: [ + Ident(394..403), + ], database: None, table: None, column: Identifier { @@ -812,11 +889,14 @@ Query { span: Ident(394..403), }, }, - right: Literal( - String( + right: Literal { + span: [ + QuotedIdent(413..422), + ], + lit: String( "%:1%:2%", ), - ), + }, }, }, ), @@ -846,6 +926,9 @@ Query { selection: None, group_by: [ ColumnRef { + span: [ + Ident(476..485), + ], database: None, table: None, column: Identifier { @@ -879,6 +962,9 @@ Query { selection: None, group_by: [ ColumnRef { + span: [ + Ident(537..544), + ], database: None, table: None, column: Identifier { @@ -894,6 +980,9 @@ Query { order_by: [ OrderByExpr { expr: ColumnRef { + span: [ + Ident(566..574), + ], database: None, table: None, column: Identifier { @@ -909,6 +998,9 @@ Query { }, OrderByExpr { expr: ColumnRef { + span: [ + Ident(581..588), + ], database: None, table: None, column: Identifier { @@ -924,6 +1016,9 @@ Query { }, OrderByExpr { expr: ColumnRef { + span: [ + Ident(594..604), + ], database: None, table: None, column: Identifier { @@ -937,12 +1032,18 @@ Query { }, ], limit: [ - Literal( - Number( + Literal { + span: [ + LiteralNumber(623..625), + ], + lit: Number( "10", ), - ), + }, ColumnRef { + span: [ + Ident(627..637), + ], database: None, table: None, column: Identifier { diff --git a/common/ast/tests/it/testdata/statement.txt b/common/ast/tests/it/testdata/statement.txt index e7cbbdf8cc28..220e4b65b0de 100644 --- a/common/ast/tests/it/testdata/statement.txt +++ b/common/ast/tests/it/testdata/statement.txt @@ -66,6 +66,9 @@ Explain { select_list: [ AliasedExpr { expr: ColumnRef { + span: [ + Ident(24..25), + ], database: None, table: None, column: Identifier { @@ -179,11 +182,14 @@ CreateTable { data_type: Int32, nullable: false, default_expr: Some( - Literal( - Number( + Literal { + span: [ + LiteralNumber(59..60), + ], + lit: Number( "1", ), - ), + }, ), }, ColumnDefinition { @@ -237,11 +243,14 @@ CreateTable { data_type: Int32, nullable: false, default_expr: Some( - Literal( - Number( + Literal { + span: [ + LiteralNumber(50..51), + ], + lit: Number( "1", ), - ), + }, ), }, ColumnDefinition { @@ -753,11 +762,14 @@ CreateTable { data_type: Int32, nullable: false, default_expr: Some( - Literal( - Number( + Literal { + span: [ + LiteralNumber(30..31), + ], + lit: Number( "1", ), - ), + }, ), }, ], @@ -856,6 +868,9 @@ Query( select_list: [ AliasedExpr { expr: ColumnRef { + span: [ + Ident(16..17), + ], database: None, table: None, column: Identifier { @@ -867,7 +882,14 @@ Query( alias: None, }, AliasedExpr { - expr: CountAll, + expr: CountAll { + span: [ + COUNT(19..24), + LParen(24..25), + Multiply(25..26), + RParen(26..27), + ], + }, alias: None, }, ], @@ -885,10 +907,19 @@ Query( ), selection: Some( BinaryOp { + span: [ + AND(47..50), + ], op: And, left: BinaryOp { + span: [ + Eq(43..44), + ], op: Eq, left: ColumnRef { + span: [ + Ident(41..42), + ], database: None, table: None, column: Identifier { @@ -897,17 +928,29 @@ Query( span: Ident(41..42), }, }, - right: Literal( - Number( + right: Literal { + span: [ + LiteralNumber(45..46), + ], + lit: Number( "1", ), - ), + }, }, right: BinaryOp { + span: [ + Lt(57..58), + ], op: Lt, left: BinaryOp { + span: [ + Minus(53..54), + ], op: Minus, left: ColumnRef { + span: [ + Ident(51..52), + ], database: None, table: None, column: Identifier { @@ -916,13 +959,19 @@ Query( span: Ident(51..52), }, }, - right: Literal( - Number( + right: Literal { + span: [ + LiteralNumber(55..56), + ], + lit: Number( "1", ), - ), + }, }, right: ColumnRef { + span: [ + Ident(59..60), + ], database: None, table: None, column: Identifier { @@ -936,6 +985,9 @@ Query( ), group_by: [ ColumnRef { + span: [ + Ident(70..71), + ], database: None, table: None, column: Identifier { @@ -947,8 +999,14 @@ Query( ], having: Some( BinaryOp { + span: [ + Eq(81..82), + ], op: Eq, left: ColumnRef { + span: [ + Ident(79..80), + ], database: None, table: None, column: Identifier { @@ -957,11 +1015,14 @@ Query( span: Ident(79..80), }, }, - right: Literal( - Number( + right: Literal { + span: [ + LiteralNumber(83..84), + ], + lit: Number( "1", ), - ), + }, }, ), }, @@ -1237,8 +1298,16 @@ Query( op: Inner, condition: On( BinaryOp { + span: [ + Eq(30..31), + ], op: Eq, left: ColumnRef { + span: [ + Ident(26..27), + Period(27..28), + Ident(28..29), + ], database: None, table: Some( Identifier { @@ -1254,6 +1323,11 @@ Query( }, }, right: ColumnRef { + span: [ + Ident(32..33), + Period(33..34), + Ident(34..35), + ], database: None, table: Some( Identifier { @@ -1364,8 +1438,16 @@ Query( op: LeftOuter, condition: On( BinaryOp { + span: [ + Eq(41..42), + ], op: Eq, left: ColumnRef { + span: [ + Ident(37..38), + Period(38..39), + Ident(39..40), + ], database: None, table: Some( Identifier { @@ -1381,6 +1463,11 @@ Query( }, }, right: ColumnRef { + span: [ + Ident(43..44), + Period(44..45), + Ident(45..46), + ], database: None, table: Some( Identifier { @@ -1491,8 +1578,16 @@ Query( op: RightOuter, condition: On( BinaryOp { + span: [ + Eq(42..43), + ], op: Eq, left: ColumnRef { + span: [ + Ident(38..39), + Period(39..40), + Ident(40..41), + ], database: None, table: Some( Identifier { @@ -1508,6 +1603,11 @@ Query( }, }, right: ColumnRef { + span: [ + Ident(44..45), + Period(45..46), + Ident(46..47), + ], database: None, table: Some( Identifier { @@ -1618,8 +1718,16 @@ Query( op: FullOuter, condition: On( BinaryOp { + span: [ + Eq(41..42), + ], op: Eq, left: ColumnRef { + span: [ + Ident(37..38), + Period(38..39), + Ident(39..40), + ], database: None, table: Some( Identifier { @@ -1635,6 +1743,11 @@ Query( }, }, right: ColumnRef { + span: [ + Ident(43..44), + Period(44..45), + Ident(45..46), + ], database: None, table: Some( Identifier { @@ -1743,8 +1856,16 @@ Query( op: Inner, condition: On( BinaryOp { + span: [ + Eq(36..37), + ], op: Eq, left: ColumnRef { + span: [ + Ident(32..33), + Period(33..34), + Ident(34..35), + ], database: None, table: Some( Identifier { @@ -1760,6 +1881,11 @@ Query( }, }, right: ColumnRef { + span: [ + Ident(38..39), + Period(39..40), + Ident(40..41), + ], database: None, table: Some( Identifier { From b5b2e5a00f0e1c8907f9db0fa0921c8286fee189 Mon Sep 17 00:00:00 2001 From: Andy Lok Date: Thu, 12 May 2022 03:31:11 +0800 Subject: [PATCH 2/2] fix clippy --- common/ast/src/ast/query.rs | 2 +- common/ast/src/parser/expr.rs | 6 ++--- common/ast/src/parser/query.rs | 2 +- query/src/sql/planner/metadata.rs | 20 +++++++++------ query/src/sql/planner/semantic/type_check.rs | 26 ++++++++++++++------ 5 files changed, 36 insertions(+), 20 deletions(-) diff --git a/common/ast/src/ast/query.rs b/common/ast/src/ast/query.rs index 0f186b35435f..f80673779d67 100644 --- a/common/ast/src/ast/query.rs +++ b/common/ast/src/ast/query.rs @@ -165,7 +165,7 @@ pub enum JoinOperator { #[derive(Debug, Clone, PartialEq)] pub enum JoinCondition<'a> { - On(Expr<'a>), + On(Box>), Using(Vec>), Natural, None, diff --git a/common/ast/src/parser/expr.rs b/common/ast/src/parser/expr.rs index 819d56e6b511..f34c69fd27fe 100644 --- a/common/ast/src/parser/expr.rs +++ b/common/ast/src/parser/expr.rs @@ -221,7 +221,7 @@ pub enum ExprElement<'a> { trim_where: Option<(TrimWhere, Box>)>, }, /// A literal value, such as string, number, date or NULL - Literal(Literal), + Literal { lit: Literal }, /// `Count(*)` expression CountAll, /// `(foo, bar)` @@ -361,7 +361,7 @@ impl<'a, I: Iterator>> PrattParser for ExprParser { expr, trim_where, }, - ExprElement::Literal(lit) => Expr::Literal { + ExprElement::Literal { lit } => Expr::Literal { span: elem.span.0, lit, }, @@ -722,7 +722,7 @@ pub fn expr_element(i: Input) -> IResult { ); let binary_op = map(binary_op, |op| ExprElement::BinaryOp { op }); let unary_op = map(unary_op, |op| ExprElement::UnaryOp { op }); - let literal = map(literal, ExprElement::Literal); + let literal = map(literal, |lit| ExprElement::Literal { lit }); let map_access = map(map_access, |accessor| ExprElement::MapAccess { accessor }); let (rest, (span, elem)) = consumed(alt(( diff --git a/common/ast/src/parser/query.rs b/common/ast/src/parser/query.rs index 34feb68a8567..daca53b070d5 100644 --- a/common/ast/src/parser/query.rs +++ b/common/ast/src/parser/query.rs @@ -227,7 +227,7 @@ pub fn joined_tables(i: Input) -> IResult { rule! { ON ~ #expr }, - |(_, expr)| JoinCondition::On(expr), + |(_, expr)| JoinCondition::On(Box::new(expr)), ); let join_condition_using = map( rule! { diff --git a/query/src/sql/planner/metadata.rs b/query/src/sql/planner/metadata.rs index 0ac2e03ba7d7..9792a96633ff 100644 --- a/query/src/sql/planner/metadata.rs +++ b/query/src/sql/planner/metadata.rs @@ -126,9 +126,9 @@ impl Metadata { match expr { Expr::ColumnRef { column, .. } => Ok(column.name.clone()), - Expr::Literal(literal) => Ok(format!("{}", literal)), + Expr::Literal { lit, .. } => Ok(format!("{lit}")), - Expr::CountAll => Ok("count(*)".to_string()), + Expr::CountAll { .. } => Ok("count(*)".to_string()), Expr::FunctionCall { name, @@ -155,13 +155,15 @@ impl Metadata { }) } - Expr::IsNull { expr, not } => Ok(format!( + Expr::IsNull { expr, not, .. } => Ok(format!( "{} IS {}NULL", expr, if *not { "NOT " } else { "" } )), - Expr::InList { expr, list, not } => { + Expr::InList { + expr, list, not, .. + } => { let mut w = vec![]; write!(&mut w, "{} {}IN (", expr, if *not { "NOT " } else { "" })?; for (i, expr) in list.iter().enumerate() { @@ -180,6 +182,7 @@ impl Metadata { low, high, not, + .. } => Ok(format!( "{} {}BETWEEN {} AND {}", expr, @@ -188,9 +191,11 @@ impl Metadata { high )), - Expr::BinaryOp { op, left, right } => Ok(format!("{} {} {}", left, op, right)), + Expr::BinaryOp { + op, left, right, .. + } => Ok(format!("{} {} {}", left, op, right)), - Expr::UnaryOp { op, expr } => Ok(format!("{} {}", op, expr)), + Expr::UnaryOp { op, expr, .. } => Ok(format!("{} {}", op, expr)), Expr::Cast { expr, target_type, .. @@ -200,6 +205,7 @@ impl Metadata { expr, substring_from, substring_for, + .. } => Ok(format!( "SUBSTRING({}{}{})", expr, @@ -266,5 +272,5 @@ pub fn optimize_remove_count_args(name: &str, distinct: bool, args: &[&Expr]) -> && !distinct && args .iter() - .all(|expr| matches!(expr, Expr::Literal(literal) if *literal!=Literal::Null)) + .all(|expr| matches!(expr, Expr::Literal{lit,..} if *lit!=Literal::Null)) } diff --git a/query/src/sql/planner/semantic/type_check.rs b/query/src/sql/planner/semantic/type_check.rs index d5a7f92ffc68..9114fc7544c2 100644 --- a/query/src/sql/planner/semantic/type_check.rs +++ b/query/src/sql/planner/semantic/type_check.rs @@ -79,6 +79,7 @@ impl<'a> TypeChecker<'a> { database: _, table, column, + .. } => { let column = self .bind_context @@ -88,7 +89,7 @@ impl<'a> TypeChecker<'a> { Ok((BoundColumnRef { column }.into(), data_type)) } - Expr::IsNull { expr, not } => { + Expr::IsNull { expr, not, .. } => { let func_name = if *not { "is_not_null".to_string() } else { @@ -99,7 +100,9 @@ impl<'a> TypeChecker<'a> { .await } - Expr::InList { expr, list, not } => { + Expr::InList { + expr, list, not, .. + } => { let func_name = if *not { "not_in".to_string() } else { @@ -119,6 +122,7 @@ impl<'a> TypeChecker<'a> { low, high, not, + .. } => { if !*not { // Rewrite `expr BETWEEN low AND high` @@ -157,12 +161,16 @@ impl<'a> TypeChecker<'a> { } } - Expr::BinaryOp { op, left, right } => { + Expr::BinaryOp { + op, left, right, .. + } => { self.resolve_binary_op(op, &**left, &**right, required_type) .await } - Expr::UnaryOp { op, expr } => self.resolve_unary_op(op, &**expr, required_type).await, + Expr::UnaryOp { op, expr, .. } => { + self.resolve_unary_op(op, &**expr, required_type).await + } Expr::Cast { expr, target_type, .. @@ -188,6 +196,7 @@ impl<'a> TypeChecker<'a> { expr, substring_from, substring_for, + .. } => { let mut arguments = vec![&**expr]; match (substring_from, substring_for) { @@ -205,8 +214,8 @@ impl<'a> TypeChecker<'a> { .await } - Expr::Literal(literal) => { - let value = self.parse_literal(literal, required_type)?; + Expr::Literal { lit, .. } => { + let value = self.parse_literal(lit, required_type)?; let data_type = value.data_type(); Ok((ConstantExpr { value }.into(), data_type)) } @@ -216,6 +225,7 @@ impl<'a> TypeChecker<'a> { name, args, params, + .. } => { let args: Vec<&Expr> = args.iter().collect(); let func_name = name.name.as_str(); @@ -267,7 +277,7 @@ impl<'a> TypeChecker<'a> { } } - Expr::CountAll => { + Expr::CountAll { .. } => { let agg_func = AggregateFunctionFactory::instance().get("count", vec![], vec![])?; Ok(( @@ -283,7 +293,7 @@ impl<'a> TypeChecker<'a> { )) } - Expr::Subquery(subquery) => self.resolve_subquery(subquery, false, None).await, + Expr::Subquery { subquery, .. } => self.resolve_subquery(subquery, false, None).await, _ => Err(ErrorCode::UnImplement(format!( "Unsupported expr: {:?}",