From 15a4e628b8d2e53bdabd55bc88a86d875739858c Mon Sep 17 00:00:00 2001 From: Igor Kuznetsov <kuznetsovin@gmail.com> Date: Mon, 17 Jan 2022 15:06:50 +0300 Subject: [PATCH] feat: add transformation ast to ir for simple and union query --- src/errors.rs | 20 + src/frontend/sql.rs | 1 + src/frontend/sql/ast.rs | 33 +- src/frontend/sql/ast/tests.rs | 19 +- src/frontend/sql/grammar.pest | 44 +- src/frontend/sql/ir.rs | 238 +++++++ src/frontend/sql/ir/tests.rs | 203 ++++++ src/ir/value.rs | 1 - .../frontend/sql/ir/complex_cond_query.yaml | 282 ++++++++ .../sql/ir/complex_union_cond_query.yaml | 667 ++++++++++++++++++ .../frontend/sql/ir/simple_query.yaml | 205 ++++++ .../frontend/sql/ir/simple_union_query.yaml | 563 +++++++++++++++ .../frontend/sql/simple_query.yaml | 10 +- .../frontend/sql/transform_select_2.yaml | 2 +- .../frontend/sql/transform_select_3.yaml | 4 +- .../frontend/sql/transform_select_4.yaml | 4 +- .../frontend/sql/transform_select_5.yaml | 6 +- 17 files changed, 2244 insertions(+), 58 deletions(-) create mode 100644 src/frontend/sql/ir.rs create mode 100644 src/frontend/sql/ir/tests.rs create mode 100644 tests/artifactory/frontend/sql/ir/complex_cond_query.yaml create mode 100644 tests/artifactory/frontend/sql/ir/complex_union_cond_query.yaml create mode 100644 tests/artifactory/frontend/sql/ir/simple_query.yaml create mode 100644 tests/artifactory/frontend/sql/ir/simple_union_query.yaml diff --git a/src/errors.rs b/src/errors.rs index 1eeeb3ec4d..58259178e8 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -9,6 +9,11 @@ const EMPTY_PLAN_RELATION: &str = "empty plan relations"; const EMPTY_RESULT: &str = "empty result"; const INCORRECT_BUCKET_ID_ERROR: &str = "incorrect bucket id"; const INVALID_AST: &str = "invalid AST"; +const INVALID_AST_CONDITION_NODE: &str = "Invalid selection condition part"; +const INVALID_AST_SCAN_NODE: &str = "Invalid scan node"; +const INVALID_AST_SELECTION_NODE: &str = "Selection node not found"; +const INVALID_AST_SUBQUERY_NODE: &str = "Invalid subquery node"; +const INVALID_AST_TOP_NODE: &str = "Top node not found"; const INVALID_BOOL_ERROR: &str = "invalid boolean"; const INVALID_CONSTANT: &str = "invalid constant"; const INVALID_COLUMN_NAME: &str = "invalid column name"; @@ -34,18 +39,25 @@ const SIMPLE_UNION_QUERY_ERROR: &str = "query doesn't simple union"; const SPACE_NOT_FOUND: &str = "space not found"; const SPACE_FORMAT_NOT_FOUND: &str = "space format not found"; const UNINITIALIZED_DISTRIBUTION: &str = "uninitialized distribution"; +const UNSUPPORTED_TYPE_IR_VALUE: &str = "unsupported type ir value"; const VALUE_OUT_OF_RANGE_ERROR: &str = "value out of range"; const TYPE_NOT_IMPLEMENTED: &str = "type is not implemented"; #[derive(Debug, Clone, PartialEq, Serialize)] pub enum QueryPlannerError { BucketIdError, + CustomError(String), DoSkip, DuplicateColumn, EmptyPlanRelations, EmptyResult, IncorrectBucketIdError, InvalidAst, + InvalidAstConditionNode, + InvalidAstScanNode, + InvalidAstSelectionNode, + InvalidAstSubQueryNode, + InvalidAstTopNode, InvalidBool, InvalidConstant, InvalidColumnName, @@ -73,11 +85,13 @@ pub enum QueryPlannerError { UninitializedDistribution, ValueOutOfRange, TypeNotImplemented, + UnsupportedIrValueType, } impl fmt::Display for QueryPlannerError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let p = match self { + QueryPlannerError::CustomError(s) => s.as_str(), QueryPlannerError::BucketIdError => BUCKET_ID_ERROR, QueryPlannerError::DoSkip => DO_SKIP, QueryPlannerError::DuplicateColumn => DUPLICATE_COLUMN_ERROR, @@ -85,6 +99,11 @@ impl fmt::Display for QueryPlannerError { QueryPlannerError::EmptyResult => EMPTY_RESULT, QueryPlannerError::IncorrectBucketIdError => INCORRECT_BUCKET_ID_ERROR, QueryPlannerError::InvalidAst => INVALID_AST, + QueryPlannerError::InvalidAstConditionNode => INVALID_AST_CONDITION_NODE, + QueryPlannerError::InvalidAstScanNode => INVALID_AST_SCAN_NODE, + QueryPlannerError::InvalidAstSelectionNode => INVALID_AST_SELECTION_NODE, + QueryPlannerError::InvalidAstSubQueryNode => INVALID_AST_SUBQUERY_NODE, + QueryPlannerError::InvalidAstTopNode => INVALID_AST_TOP_NODE, QueryPlannerError::InvalidBool => INVALID_BOOL_ERROR, QueryPlannerError::InvalidConstant => INVALID_CONSTANT, QueryPlannerError::InvalidColumnName => INVALID_COLUMN_NAME, @@ -112,6 +131,7 @@ impl fmt::Display for QueryPlannerError { QueryPlannerError::UninitializedDistribution => UNINITIALIZED_DISTRIBUTION, QueryPlannerError::ValueOutOfRange => VALUE_OUT_OF_RANGE_ERROR, QueryPlannerError::TypeNotImplemented => TYPE_NOT_IMPLEMENTED, + QueryPlannerError::UnsupportedIrValueType => UNSUPPORTED_TYPE_IR_VALUE, }; write!(f, "{}", p) } diff --git a/src/frontend/sql.rs b/src/frontend/sql.rs index 851c0bc27f..f4ae8f2b1a 100644 --- a/src/frontend/sql.rs +++ b/src/frontend/sql.rs @@ -1 +1,2 @@ pub mod ast; +pub mod ir; diff --git a/src/frontend/sql/ast.rs b/src/frontend/sql/ast.rs index 071533177b..87b022c9cd 100644 --- a/src/frontend/sql/ast.rs +++ b/src/frontend/sql/ast.rs @@ -1,10 +1,12 @@ extern crate pest; -use crate::errors::QueryPlannerError; +use std::cell::RefCell; + use pest::iterators::Pair; use pest::Parser; use serde::{Deserialize, Serialize}; -use std::cell::RefCell; + +use crate::errors::QueryPlannerError; /// Parse tree #[derive(Parser)] @@ -14,7 +16,7 @@ pub struct ParseTree; /// A list of current rules from the actual grammar. /// When new tokens are added to the grammar they /// should be also added in the current list. -#[derive(Serialize, Deserialize, PartialEq, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub enum Type { Alias, And, @@ -30,6 +32,7 @@ pub enum Type { Insert, Lt, LtEq, + Name, NotEq, Null, Number, @@ -37,13 +40,14 @@ pub enum Type { Parentheses, Primary, Projection, - QuotedName, + ProjectedName, Row, Scan, Select, Selection, String, SubQuery, + SubQueryName, Table, UnionAll, Value, @@ -68,6 +72,7 @@ impl Type { Rule::Insert => Ok(Type::Insert), Rule::Lt => Ok(Type::Lt), Rule::LtEq => Ok(Type::LtEq), + Rule::Name => Ok(Type::Name), Rule::NotEq => Ok(Type::NotEq), Rule::Null => Ok(Type::Null), Rule::Number => Ok(Type::Number), @@ -75,13 +80,14 @@ impl Type { Rule::Parentheses => Ok(Type::Parentheses), Rule::Primary => Ok(Type::Primary), Rule::Projection => Ok(Type::Projection), - Rule::QuotedName => Ok(Type::QuotedName), + Rule::ProjectedName => Ok(Type::ProjectedName), Rule::Row => Ok(Type::Row), Rule::Scan => Ok(Type::Scan), Rule::Select => Ok(Type::Select), Rule::Selection => Ok(Type::Selection), Rule::String => Ok(Type::String), Rule::SubQuery => Ok(Type::SubQuery), + Rule::SubQueryName => Ok(Type::SubQueryName), Rule::Table => Ok(Type::Table), Rule::UnionAll => Ok(Type::UnionAll), Rule::Value => Ok(Type::Value), @@ -91,11 +97,11 @@ impl Type { } } -#[derive(Serialize, Deserialize, PartialEq, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct Node { children: Vec<usize>, - rule: Type, - value: Option<String>, + pub(in crate::frontend::sql) rule: Type, + pub(in crate::frontend::sql) value: Option<String>, } #[allow(dead_code)] @@ -109,7 +115,7 @@ impl Node { } } -#[derive(Serialize, Deserialize, PartialEq, Debug)] +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct Nodes { arena: Vec<Node>, } @@ -189,8 +195,8 @@ impl<'n> StackNode<'n> { /// Positions in a list act like references. #[derive(Serialize, Deserialize, PartialEq, Debug)] pub struct AbstractSyntaxTree { - nodes: Nodes, - top: Option<usize>, + pub(in crate::frontend::sql) nodes: Nodes, + pub(in crate::frontend::sql) top: Option<usize>, } #[allow(dead_code)] @@ -255,12 +261,15 @@ impl AbstractSyntaxTree { } ast.set_top(0)?; + + ast.transform_select()?; + Ok(ast) } /// `Select` node is not IR-friendly as it can have up to five children. /// Transform this node in IR-way (to a binary sub-tree). - pub fn transform_select(&mut self) -> Result<(), QueryPlannerError> { + fn transform_select(&mut self) -> Result<(), QueryPlannerError> { let mut selects: Vec<usize> = Vec::new(); for (pos, node) in self.nodes.arena.iter().enumerate() { if node.rule == Type::Select { diff --git a/src/frontend/sql/ast/tests.rs b/src/frontend/sql/ast/tests.rs index 0f0df3ce63..52dbd126f5 100644 --- a/src/frontend/sql/ast/tests.rs +++ b/src/frontend/sql/ast/tests.rs @@ -22,8 +22,7 @@ fn ast() { #[test] fn transfrom_select_2() { let query = r#"select a from t"#; - let mut ast = AbstractSyntaxTree::new(query).unwrap(); - ast.transform_select().unwrap(); + let ast = AbstractSyntaxTree::new(query).unwrap(); let path = Path::new("") .join("tests") .join("artifactory") @@ -38,8 +37,7 @@ fn transfrom_select_2() { #[test] fn transfrom_select_3() { let query = r#"select a from t where a = 1"#; - let mut ast = AbstractSyntaxTree::new(query).unwrap(); - ast.transform_select().unwrap(); + let ast = AbstractSyntaxTree::new(query).unwrap(); let path = Path::new("") .join("tests") .join("artifactory") @@ -54,8 +52,7 @@ fn transfrom_select_3() { #[test] fn transfrom_select_4() { let query = r#"select * from t1 inner join t2 on t1.a = t2.a"#; - let mut ast = AbstractSyntaxTree::new(query).unwrap(); - ast.transform_select().unwrap(); + let ast = AbstractSyntaxTree::new(query).unwrap(); let path = Path::new("") .join("tests") .join("artifactory") @@ -70,8 +67,7 @@ fn transfrom_select_4() { #[test] fn transfrom_select_5() { let query = r#"select * from t1 inner join t2 on t1.a = t2.a where t1.a > 0"#; - let mut ast = AbstractSyntaxTree::new(query).unwrap(); - ast.transform_select().unwrap(); + let ast = AbstractSyntaxTree::new(query).unwrap(); let path = Path::new("") .join("tests") .join("artifactory") @@ -86,8 +82,7 @@ fn transfrom_select_5() { #[test] fn traversal() { let query = r#"select a from t where a = 1"#; - let mut ast = AbstractSyntaxTree::new(query).unwrap(); - ast.transform_select().unwrap(); + let ast = AbstractSyntaxTree::new(query).unwrap(); let top = ast.top.unwrap(); let mut dft_pre = DftPost::new(&top, |node| ast.nodes.tree_iter(node)); @@ -101,7 +96,7 @@ fn traversal() { let (_, a_id) = dft_pre.next().unwrap(); let node = ast.nodes.get_node(*a_id).unwrap(); - assert_eq!(node.rule, Type::String); + assert_eq!(node.rule, Type::Name); let (_, num_id) = dft_pre.next().unwrap(); let node = ast.nodes.get_node(*num_id).unwrap(); @@ -117,7 +112,7 @@ fn traversal() { let (_, str_id) = dft_pre.next().unwrap(); let node = ast.nodes.get_node(*str_id).unwrap(); - assert_eq!(node.rule, Type::String); + assert_eq!(node.rule, Type::ProjectedName); let (_, col_id) = dft_pre.next().unwrap(); let node = ast.nodes.get_node(*col_id).unwrap(); diff --git a/src/frontend/sql/grammar.pest b/src/frontend/sql/grammar.pest index 2a6152fd67..62270d66f0 100644 --- a/src/frontend/sql/grammar.pest +++ b/src/frontend/sql/grammar.pest @@ -7,25 +7,28 @@ Query = _{ UnionAll | Select | Values | Insert } (^"on" ~ Condition)? ~ (^"where" ~ Selection)? } Projection = { Column ~ ("," ~ Column)*? } - Column = { Row | Asterisk | Alias | Value } - Alias = {Value ~ ^"as" ~ (String | QuotedName) } + Column = { Row | Asterisk | Alias | Value | ProjectedName } + Alias = {Value ~ ^"as" ~ ProjectedName } + ProjectedName = @{ Name } + Name = @{ String | "\"" ~ String ~ "\"" ~ (".\"" ~ String ~ "\"")?} Asterisk = @{ "*" } Selection = { Expr* } Scan = { SubQuery | Table } - Table = @{ String | QuotedName } + Table = @{ Name } InnerJoin = { Scan } Condition = { Selection } UnionAll = { (SubQuery | Select) ~ ^"union" ~ ^"all" ~ (UnionAll | SubQuery | Select) } - SubQuery = { "(" ~ (UnionAll | Select) ~ ")" ~ (^"as" ~ (String | QuotedName))? } + SubQuery = { "(" ~ (UnionAll | Select) ~ ")" ~ (^"as" ~ SubQueryName)? } + SubQueryName = @{ Name } Insert = { ^"insert" ~ ^"into" ~ Table ~ Values } Values = { ^"values" ~ Row ~ ("," ~ Row)*?} Expr = _{ Or | And | Cmp | Primary | Parentheses } Parentheses = _{ "(" ~ Expr ~ ")" } - Primary = _{ SubQuery | Value } + Primary = _{ SubQuery | Value | Name } Cmp = _{ Eq | In | Gt | GtEq | Lt | LtEq | NotEq } Eq = { EqLeft ~ "=" ~ EqRight } - EqLeft = _{ Primary | Parentheses } + EqLeft = _{ Primary } EqRight = _{ Eq | EqLeft } In = { InLeft ~ ^"in" ~ InRight } InLeft = _{ EqRight } @@ -44,7 +47,7 @@ Expr = _{ Or | And | Cmp | Primary | Parentheses } LtEqRight = _{ LtEq | LtEqLeft } NotEq = { NotEqLeft ~ ("<>" | "!=") ~ NotEqRight } NotEqLeft = _{ LtEqRight } - NotEqRight = _{ NotEq | NotEqLeft } + NotEqRight = _{ NotEq | NotEqLeft } And = { AndLeft ~ ^"and" ~ AndRight } AndLeft = _{ Cmp | Primary | Parentheses } AndRight = _{ And | AndLeft } @@ -52,22 +55,23 @@ Expr = _{ Or | And | Cmp | Primary | Parentheses } OrLeft = _{ AndRight } OrRight = _{ Or | OrLeft } -Value = _{ Row | Bool | Null | QuotedName | Number | String } - Bool = @{ ^"true" | ^"false" } - Null = @{ ^"null" } +String = @{ !(Keyword) ~ ('a'..'z' | "_" | Number)+ } + Keyword = { + ^"all" | ^"and" | ^"as" | ^"false" | ^"from" + | ^"in" | ^"inner" | ^"insert" | ^"into" | ^"join" | ^"null" + | ^"on" | ^"or" | ^"row" | ^"select" | ^"true" | ^"union" + | ^"where" | ^"values" + } Number = @{ Int ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ Int)? } Int = @{ ("+" | "-")? ~ ASCII_DIGIT+ } - String = @{ !(Keyword) ~ ('a'..'z' | "_" | Number)+ } - Keyword = { - ^"all" | ^"and" | ^"as" | ^"false" | ^"from" - | ^"in" | ^"inner" | ^"insert" | ^"into" | ^"join" | ^"null" - | ^"on" | ^"or" | ^"row" | ^"select" | ^"true" | ^"union" - | ^"where" | ^"values" - } - QuotedName = @{ "\"" ~ String ~ "\"" ~ ("." ~ "\"" ~ String ~ "\"")? } + +Value = _{ Row | Bool | Null | Number | SingleQuotedString } + Bool = @{ ^"true" | ^"false" } + Null = @{ ^"null" } + SingleQuotedString = _{ "'" ~ String ~ "'" } Row = { - ("(" ~ Value ~ ("," ~ Value)* ~ ")") - | (^"row" ~ "(" ~ Value ~ ("," ~ Value)* ~ ")") + ("(" ~ (Value | Name) ~ ("," ~ (Value | Name))* ~ ")") + | (^"row" ~ "(" ~ (Value | Name) ~ ("," ~ (Value | Name))* ~ ")") } EOF = { EOI | ";" } diff --git a/src/frontend/sql/ir.rs b/src/frontend/sql/ir.rs new file mode 100644 index 0000000000..858df22aee --- /dev/null +++ b/src/frontend/sql/ir.rs @@ -0,0 +1,238 @@ +use traversal::DftPost; + +use crate::cache::Metadata; +use crate::errors::QueryPlannerError; +use crate::frontend::sql::ast::{AbstractSyntaxTree, Node, Type}; +use crate::ir::operator::Bool; +use crate::ir::value::Value; +use crate::ir::Plan; + +impl Bool { + /// Create `Bool` from ast node type. + /// + /// # Errors + /// Returns `QueryPlannerError` when the operator is invalid. + #[allow(dead_code)] + fn from_node_type(s: &Type) -> Result<Self, QueryPlannerError> { + match s { + Type::And => Ok(Bool::And), + Type::Or => Ok(Bool::Or), + Type::Eq => Ok(Bool::Eq), + Type::In => Ok(Bool::In), + Type::Gt => Ok(Bool::Gt), + Type::GtEq => Ok(Bool::GtEq), + Type::Lt => Ok(Bool::Lt), + Type::LtEq => Ok(Bool::LtEq), + Type::NotEq => Ok(Bool::NotEq), + _ => Err(QueryPlannerError::InvalidBool), + } + } +} + +impl Value { + /// Create `Value` from ast node type and text. + /// + /// # Errors + /// Returns `QueryPlannerError` when the operator is invalid. + #[allow(dead_code)] + fn from_node(s: &Node) -> Result<Self, QueryPlannerError> { + let val = match s.clone().value { + Some(v) => v, + None => "".into(), + }; + + match s.rule { + Type::Number => Ok(Value::number_from_str(val.as_str())?), + Type::String => Ok(Value::string_from_str(val.as_str())), + Type::Null => Ok(Value::Null), + _ => Err(QueryPlannerError::UnsupportedIrValueType), + } + } +} + +/// Temporary stack for traversing ast +struct Stack { + store: Vec<usize>, +} + +impl Stack { + /// Create empty stack instance + fn new() -> Self { + Stack { store: vec![] } + } + + /// Function push element on the top of stack + fn push(&mut self, node_id: usize) { + self.store.push(node_id); + } + + /// Extract a top stack element or return an error from the `err` parameter + /// + /// # Errors + /// - failed to extract an element from the stack. + fn pop_or_err(&mut self, err: QueryPlannerError) -> Result<usize, QueryPlannerError> { + match self.store.pop() { + Some(v) => Ok(v), + None => Err(err), + } + } +} + +impl AbstractSyntaxTree { + /// Transform ast to ir plan tree. + /// + /// Creates a plan from AST (based on AST node type). + /// Traverse the tree in Post-Order with [Depth-First Traversal](https://en.wikipedia.org/wiki/Tree_traversal). + /// + /// # Errors + /// - IR plan can't be built. + #[allow(dead_code)] + #[allow(clippy::too_many_lines)] + pub fn to_ir(&self, metadata: &Metadata) -> Result<Plan, QueryPlannerError> { + let mut plan = Plan::new(); + + let top = match self.top { + Some(t) => t, + None => return Err(QueryPlannerError::InvalidAst), + }; + let dft_pre = DftPost::new(&top, |node| self.nodes.tree_iter(node)); + + let mut current_scan_id = 0; + let mut current_logical_id = 0; + let mut stack = Stack::new(); + let mut projection = vec![]; + let mut subquery_alias = ""; + + for (_, node_id) in dft_pre { + let node = self.nodes.get_node(*node_id)?; + + match node.clone().rule { + Type::Table => { + // add scan node to plan + + if let Some(node_val) = node.clone().value { + let table = node_val.as_str().trim_matches('\"'); + let t = metadata.get_table_segment(table)?; + plan.add_rel(t); + stack.push(plan.add_scan(table)?); + } + } + Type::Name => { + if let Some(name) = &node.value { + let col = name.trim_matches('\"'); + stack.push(plan.add_row_from_child( + current_logical_id, + current_scan_id, + &[col], + )?); + } + } + Type::Number | Type::String => { + let val = Value::from_node(node)?; + stack.push(plan.add_const(val)); + } + Type::And + | Type::Or + | Type::Eq + | Type::In + | Type::Gt + | Type::GtEq + | Type::Lt + | Type::LtEq + | Type::NotEq => { + let op = Bool::from_node_type(&node.rule)?; + + // Extract left and right nodes id from stack for creation condition plan node + let right_id = stack.pop_or_err(QueryPlannerError::CustomError( + "Incorrect right part of condition".to_string(), + ))?; + + let left_id = stack.pop_or_err(QueryPlannerError::CustomError( + "Incorrect left part of condition".to_string(), + ))?; + + stack.push(plan.add_cond(left_id, op, right_id)?); + } + Type::Selection => { + // extract from stack condition node id for creating selection plan node + let selection_id = + stack.pop_or_err(QueryPlannerError::InvalidAstConditionNode)?; + + stack.push(plan.add_select( + current_scan_id, + selection_id, + current_logical_id, + )?); + } + Type::ProjectedName => { + // save projection column for append it later + + if let Some(col) = &node.value { + projection.push(col.as_str().trim_matches('\"')); + } + } + Type::Projection => { + // extract from stack selection node id for creating projection plan node + + let selection_id = + stack.pop_or_err(QueryPlannerError::InvalidAstSelectionNode)?; + + stack.push(plan.add_proj(selection_id, &projection)?); + + // clear projection columns for next tables + projection.clear(); + } + Type::UnionAll => { + // extract from stack left and right union subtree node for creating union plan node + + let right_id = stack.pop_or_err(QueryPlannerError::CustomError( + "Invalid right union part".to_string(), + ))?; + + let left_id = stack.pop_or_err(QueryPlannerError::CustomError( + "Invalid left union part".to_string(), + ))?; + + stack.push(plan.add_union_all(left_id, right_id)?); + } + Type::SubQueryName => { + // save alias name for using in the next step + if let Some(v) = &node.value { + subquery_alias = v.as_str().trim_matches('\"'); + } + } + Type::SubQuery => { + // add subquery node for it stack must have scan (or union) node id + + let sq_id = stack.pop_or_err(QueryPlannerError::InvalidAstSubQueryNode)?; + + stack.push(plan.add_sub_query(sq_id, subquery_alias)?); + } + Type::Asterisk => { + projection.clear(); + } + Type::Scan => { + // extract current scan node id from stack and getting logical id for appending other node + current_scan_id = stack.pop_or_err(QueryPlannerError::InvalidAstScanNode)?; + current_logical_id = plan.next_id(); + } + Type::Column | Type::Select => {} + rule => { + return Err(QueryPlannerError::CustomError(format!( + "Not implements type: {:?}", + rule + ))); + } + } + } + + // get root node id + let top_id = stack.pop_or_err(QueryPlannerError::InvalidAstTopNode)?; + plan.set_top(top_id)?; + + Ok(plan) + } +} + +#[cfg(test)] +mod tests; diff --git a/src/frontend/sql/ir/tests.rs b/src/frontend/sql/ir/tests.rs new file mode 100644 index 0000000000..c0b154f169 --- /dev/null +++ b/src/frontend/sql/ir/tests.rs @@ -0,0 +1,203 @@ +use std::fs; +use std::path::Path; + +use crate::cache::Metadata; +use crate::ir::Plan; + +use super::*; +use pretty_assertions::assert_eq; + +const CARTRIDGE_SCHEMA: &str = r#"spaces: + hash_testing: + is_local: false + temporary: false + engine: "memtx" + format: + - name: "identification_number" + type: "integer" + is_nullable: false + - name: "product_code" + type: "string" + is_nullable: false + - name: "product_units" + type: "boolean" + is_nullable: false + - name: "sys_op" + type: "number" + is_nullable: false + - name: "bucket_id" + type: "unsigned" + is_nullable: true + indexes: + - name: "id" + unique: true + type: "TREE" + parts: + - path: "identification_number" + is_nullable: false + type: "integer" + - name: bucket_id + unique: false + parts: + - path: "bucket_id" + is_nullable: true + type: "unsigned" + type: "TREE" + sharding_key: + - identification_number + - product_code + hash_testing_hist: + is_local: false + temporary: false + engine: "memtx" + format: + - name: "identification_number" + type: "integer" + is_nullable: false + - name: "product_code" + type: "string" + is_nullable: false + - name: "product_units" + type: "boolean" + is_nullable: false + - name: "sys_op" + type: "number" + is_nullable: false + - name: "bucket_id" + type: "unsigned" + is_nullable: true + indexes: + - name: "id" + unique: true + type: "TREE" + parts: + - path: "identification_number" + is_nullable: false + type: "integer" + - name: bucket_id + unique: false + parts: + - path: "bucket_id" + is_nullable: true + type: "unsigned" + type: "TREE" + sharding_key: + - identification_number + - product_code"#; + +#[test] +fn simple_query_to_ir() { + let query = r#"SELECT "identification_number", "product_code" FROM "hash_testing" WHERE "identification_number" = 1"#; + + let mut metadata = Metadata::new(); + metadata.load(CARTRIDGE_SCHEMA).unwrap(); + + let path = Path::new("") + .join("tests") + .join("artifactory") + .join("frontend") + .join("sql") + .join("ir") + .join("simple_query.yaml"); + let yml_str = fs::read_to_string(path).unwrap(); + let expected = Plan::from_yaml(&yml_str).unwrap(); + + let ast = AbstractSyntaxTree::new(query).unwrap(); + let actual = ast.to_ir(&metadata).unwrap(); + + assert_eq!(expected, actual); +} + +#[test] +fn complex_cond_query_transform() { + let query = r#"SELECT "identification_number", "product_code" + FROM "hash_testing" + WHERE "identification_number" = 1 AND "product_code" = '1' + OR "identification_number" = 2 AND "product_code" = '2'"#; + + let mut metadata = Metadata::new(); + metadata.load(CARTRIDGE_SCHEMA).unwrap(); + + let path = Path::new("") + .join("tests") + .join("artifactory") + .join("frontend") + .join("sql") + .join("ir") + .join("complex_cond_query.yaml"); + let yml_str = fs::read_to_string(path).unwrap(); + let expected = Plan::from_yaml(&yml_str).unwrap(); + + let ast = AbstractSyntaxTree::new(query).unwrap(); + let actual = ast.to_ir(&metadata).unwrap(); + + assert_eq!(expected, actual); +} + +#[test] +fn simple_union_query_transform() { + let query = r#"SELECT * +FROM + (SELECT "identification_number", "product_code" + FROM "hash_testing" + WHERE "sys_op" = 1 + UNION ALL + SELECT "identification_number", "product_code" + FROM "hash_testing_hist" + WHERE "sys_op" > 1) AS "t3" +WHERE "identification_number" = 1"#; + + let mut metadata = Metadata::new(); + metadata.load(CARTRIDGE_SCHEMA).unwrap(); + + let path = Path::new("") + .join("tests") + .join("artifactory") + .join("frontend") + .join("sql") + .join("ir") + .join("simple_union_query.yaml"); + let yml_str = fs::read_to_string(path).unwrap(); + let expected = Plan::from_yaml(&yml_str).unwrap(); + + let ast = AbstractSyntaxTree::new(query).unwrap(); + let actual = ast.to_ir(&metadata).unwrap(); + + assert_eq!(expected, actual); +} + +#[test] +fn union_complex_cond_query_transform() { + let query = r#"SELECT * +FROM + (SELECT "identification_number", "product_code" + FROM "hash_testing" + WHERE "sys_op" = 1 + UNION ALL + SELECT "identification_number", "product_code" + FROM "hash_testing_hist" + WHERE "sys_op" > 1) AS "t3" +WHERE ("identification_number" = 1 + OR ("identification_number" = 2 + OR "identification_number" = 3)) + AND ("product_code" = '1' + OR "product_code" = '2')"#; + + let mut metadata = Metadata::new(); + metadata.load(CARTRIDGE_SCHEMA).unwrap(); + + let path = Path::new("") + .join("tests") + .join("artifactory") + .join("frontend") + .join("sql") + .join("ir") + .join("complex_union_cond_query.yaml"); + let yml_str = fs::read_to_string(path).unwrap(); + let expected = Plan::from_yaml(&yml_str).unwrap(); + + let ast = AbstractSyntaxTree::new(query).unwrap(); + let actual = ast.to_ir(&metadata).unwrap(); + + assert_eq!(expected, actual); +} diff --git a/src/ir/value.rs b/src/ir/value.rs index 731d494f9b..860de074e4 100644 --- a/src/ir/value.rs +++ b/src/ir/value.rs @@ -52,7 +52,6 @@ impl fmt::Display for Value { } } -#[allow(dead_code)] impl Value { /// Construct a number from the string. /// diff --git a/tests/artifactory/frontend/sql/ir/complex_cond_query.yaml b/tests/artifactory/frontend/sql/ir/complex_cond_query.yaml new file mode 100644 index 0000000000..404048b93e --- /dev/null +++ b/tests/artifactory/frontend/sql/ir/complex_cond_query.yaml @@ -0,0 +1,282 @@ +# +# SELECT "identification_number", "product_code" +# FROM "hash_testing" +# WHERE "identification_number" = 1 AND "product_code" = '1' +# OR "identification_number" = 2 AND "product_code" = '2'; +# +--- +nodes: + arena: + - Expression: + Reference: + targets: ~ + position: 0 + parent: 0 + - Expression: + Alias: + name: identification_number + child: 0 + - Expression: + Reference: + targets: ~ + position: 1 + parent: 0 + - Expression: + Alias: + name: product_code + child: 2 + - Expression: + Reference: + targets: ~ + position: 2 + parent: 0 + - Expression: + Alias: + name: product_units + child: 4 + - Expression: + Reference: + targets: ~ + position: 3 + parent: 0 + - Expression: + Alias: + name: sys_op + child: 6 + - Expression: + Reference: + targets: ~ + position: 4 + parent: 0 + - Expression: + Alias: + name: bucket_id + child: 8 + - Expression: + Row: + list: + - 1 + - 3 + - 5 + - 7 + - 9 + distribution: ~ + - Relational: + ScanRelation: + output: 10 + id: 0 + relation: hash_testing + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 12 + - Expression: + Row: + list: + - 12 + distribution: ~ + - Expression: + Constant: + value: + Number: 1 + - Expression: + Bool: + left: 13 + op: Eq + right: 14 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 12 + - Expression: + Row: + list: + - 16 + distribution: ~ + - Expression: + Constant: + value: + String: "1" + - Expression: + Bool: + left: 17 + op: Eq + right: 18 + - Expression: + Bool: + left: 15 + op: And + right: 19 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 12 + - Expression: + Row: + list: + - 21 + distribution: ~ + - Expression: + Constant: + value: + Number: 2 + - Expression: + Bool: + left: 22 + op: Eq + right: 23 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 12 + - Expression: + Row: + list: + - 25 + distribution: ~ + - Expression: + Constant: + value: + String: "2" + - Expression: + Bool: + left: 26 + op: Eq + right: 27 + - Expression: + Bool: + left: 24 + op: And + right: 28 + - Expression: + Bool: + left: 20 + op: Or + right: 29 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 12 + - Expression: + Alias: + name: identification_number + child: 31 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 12 + - Expression: + Alias: + name: product_code + child: 33 + - Expression: + Reference: + targets: + - 0 + position: 2 + parent: 12 + - Expression: + Alias: + name: product_units + child: 35 + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 12 + - Expression: + Alias: + name: sys_op + child: 37 + - Expression: + Reference: + targets: + - 0 + position: 4 + parent: 12 + - Expression: + Alias: + name: bucket_id + child: 39 + - Expression: + Row: + list: + - 32 + - 34 + - 36 + - 38 + - 40 + distribution: ~ + - Relational: + Selection: + children: + - 11 + filter: 30 + id: 12 + output: 41 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 43 + - Expression: + Alias: + name: identification_number + child: 43 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 43 + - Expression: + Alias: + name: product_code + child: 45 + - Expression: + Row: + list: + - 44 + - 46 + distribution: ~ + - Relational: + Projection: + children: + - 42 + id: 43 + output: 47 +relations: + hash_testing: + Segment: + columns: + - name: identification_number + type: integer + - name: product_code + type: string + - name: product_units + type: boolean + - name: sys_op + type: number + - name: bucket_id + type: unsigned + key: + positions: + - 0 + - 1 + name: hash_testing +slices: ~ +top: 48 diff --git a/tests/artifactory/frontend/sql/ir/complex_union_cond_query.yaml b/tests/artifactory/frontend/sql/ir/complex_union_cond_query.yaml new file mode 100644 index 0000000000..44032674dd --- /dev/null +++ b/tests/artifactory/frontend/sql/ir/complex_union_cond_query.yaml @@ -0,0 +1,667 @@ +# +# SELECT * +# FROM +# ( +# SELECT "identification_number", "product_code" +# FROM "hash_testing" +# WHERE "sys_op" = 1 +# UNION ALL +# SELECT "identification_number", "product_code" +# FROM "hash_testing_hist" +# WHERE "sys_op" > 1 +# ) AS "t3" +# WHERE ("identification_number" = 1 +# OR ("identification_number" = 2 +# OR "identification_number" = 3)) +# AND ("product_code" = '1' +# OR "product_code" = '2') +# +--- +nodes: + arena: + - Expression: + Reference: + targets: ~ + position: 0 + parent: 0 + - Expression: + Alias: + name: identification_number + child: 0 + - Expression: + Reference: + targets: ~ + position: 1 + parent: 0 + - Expression: + Alias: + name: product_code + child: 2 + - Expression: + Reference: + targets: ~ + position: 2 + parent: 0 + - Expression: + Alias: + name: product_units + child: 4 + - Expression: + Reference: + targets: ~ + position: 3 + parent: 0 + - Expression: + Alias: + name: sys_op + child: 6 + - Expression: + Reference: + targets: ~ + position: 4 + parent: 0 + - Expression: + Alias: + name: bucket_id + child: 8 + - Expression: + Row: + list: + - 1 + - 3 + - 5 + - 7 + - 9 + distribution: ~ + - Relational: + ScanRelation: + output: 10 + id: 0 + relation: hash_testing + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 12 + - Expression: + Row: + list: + - 12 + distribution: ~ + - Expression: + Constant: + value: + Number: 1 + - Expression: + Bool: + left: 13 + op: Eq + right: 14 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 12 + - Expression: + Alias: + name: identification_number + child: 16 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 12 + - Expression: + Alias: + name: product_code + child: 18 + - Expression: + Reference: + targets: + - 0 + position: 2 + parent: 12 + - Expression: + Alias: + name: product_units + child: 20 + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 12 + - Expression: + Alias: + name: sys_op + child: 22 + - Expression: + Reference: + targets: + - 0 + position: 4 + parent: 12 + - Expression: + Alias: + name: bucket_id + child: 24 + - Expression: + Row: + list: + - 17 + - 19 + - 21 + - 23 + - 25 + distribution: ~ + - Relational: + Selection: + children: + - 11 + filter: 15 + id: 12 + output: 26 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 28 + - Expression: + Alias: + name: identification_number + child: 28 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 28 + - Expression: + Alias: + name: product_code + child: 30 + - Expression: + Row: + list: + - 29 + - 31 + distribution: ~ + - Relational: + Projection: + children: + - 27 + id: 28 + output: 32 + - Expression: + Reference: + targets: ~ + position: 0 + parent: 34 + - Expression: + Alias: + name: identification_number + child: 34 + - Expression: + Reference: + targets: ~ + position: 1 + parent: 34 + - Expression: + Alias: + name: product_code + child: 36 + - Expression: + Reference: + targets: ~ + position: 2 + parent: 34 + - Expression: + Alias: + name: product_units + child: 38 + - Expression: + Reference: + targets: ~ + position: 3 + parent: 34 + - Expression: + Alias: + name: sys_op + child: 40 + - Expression: + Reference: + targets: ~ + position: 4 + parent: 34 + - Expression: + Alias: + name: bucket_id + child: 42 + - Expression: + Row: + list: + - 35 + - 37 + - 39 + - 41 + - 43 + distribution: ~ + - Relational: + ScanRelation: + output: 44 + id: 34 + relation: hash_testing_hist + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 46 + - Expression: + Row: + list: + - 46 + distribution: ~ + - Expression: + Constant: + value: + Number: 1 + - Expression: + Bool: + left: 47 + op: Gt + right: 48 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 46 + - Expression: + Alias: + name: identification_number + child: 50 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 46 + - Expression: + Alias: + name: product_code + child: 52 + - Expression: + Reference: + targets: + - 0 + position: 2 + parent: 46 + - Expression: + Alias: + name: product_units + child: 54 + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 46 + - Expression: + Alias: + name: sys_op + child: 56 + - Expression: + Reference: + targets: + - 0 + position: 4 + parent: 46 + - Expression: + Alias: + name: bucket_id + child: 58 + - Expression: + Row: + list: + - 51 + - 53 + - 55 + - 57 + - 59 + distribution: ~ + - Relational: + Selection: + children: + - 45 + filter: 49 + id: 46 + output: 60 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 62 + - Expression: + Alias: + name: identification_number + child: 62 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 62 + - Expression: + Alias: + name: product_code + child: 64 + - Expression: + Row: + list: + - 63 + - 65 + distribution: ~ + - Relational: + Projection: + children: + - 61 + id: 62 + output: 66 + - Expression: + Reference: + targets: + - 0 + - 1 + position: 0 + parent: 68 + - Expression: + Alias: + name: identification_number + child: 68 + - Expression: + Reference: + targets: + - 0 + - 1 + position: 1 + parent: 68 + - Expression: + Alias: + name: product_code + child: 70 + - Expression: + Row: + list: + - 69 + - 71 + distribution: ~ + - Relational: + UnionAll: + children: + - 33 + - 67 + id: 68 + output: 72 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 74 + - Expression: + Alias: + name: identification_number + child: 74 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 74 + - Expression: + Alias: + name: product_code + child: 76 + - Expression: + Row: + list: + - 75 + - 77 + distribution: ~ + - Relational: + ScanSubQuery: + alias: t3 + children: + - 73 + id: 74 + output: 78 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 80 + - Expression: + Row: + list: + - 80 + distribution: ~ + - Expression: + Constant: + value: + Number: 1 + - Expression: + Bool: + left: 81 + op: Eq + right: 82 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 80 + - Expression: + Row: + list: + - 84 + distribution: ~ + - Expression: + Constant: + value: + Number: 2 + - Expression: + Bool: + left: 85 + op: Eq + right: 86 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 80 + - Expression: + Row: + list: + - 88 + distribution: ~ + - Expression: + Constant: + value: + Number: 3 + - Expression: + Bool: + left: 89 + op: Eq + right: 90 + - Expression: + Bool: + left: 87 + op: Or + right: 91 + - Expression: + Bool: + left: 83 + op: Or + right: 92 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 80 + - Expression: + Row: + list: + - 94 + distribution: ~ + - Expression: + Constant: + value: + String: "1" + - Expression: + Bool: + left: 95 + op: Eq + right: 96 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 80 + - Expression: + Row: + list: + - 98 + distribution: ~ + - Expression: + Constant: + value: + String: "2" + - Expression: + Bool: + left: 99 + op: Eq + right: 100 + - Expression: + Bool: + left: 97 + op: Or + right: 101 + - Expression: + Bool: + left: 93 + op: And + right: 102 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 80 + - Expression: + Alias: + name: identification_number + child: 104 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 80 + - Expression: + Alias: + name: product_code + child: 106 + - Expression: + Row: + list: + - 105 + - 107 + distribution: ~ + - Relational: + Selection: + children: + - 79 + filter: 103 + id: 80 + output: 108 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 110 + - Expression: + Alias: + name: identification_number + child: 110 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 110 + - Expression: + Alias: + name: product_code + child: 112 + - Expression: + Row: + list: + - 111 + - 113 + distribution: ~ + - Relational: + Projection: + children: + - 109 + id: 110 + output: 114 +relations: + hash_testing: + Segment: + columns: + - name: identification_number + type: integer + - name: product_code + type: string + - name: product_units + type: boolean + - name: sys_op + type: number + - name: bucket_id + type: unsigned + key: + positions: + - 0 + - 1 + name: hash_testing + hash_testing_hist: + Segment: + columns: + - name: identification_number + type: integer + - name: product_code + type: string + - name: product_units + type: boolean + - name: sys_op + type: number + - name: bucket_id + type: unsigned + key: + positions: + - 0 + - 1 + name: hash_testing_hist +slices: ~ +top: 115 diff --git a/tests/artifactory/frontend/sql/ir/simple_query.yaml b/tests/artifactory/frontend/sql/ir/simple_query.yaml new file mode 100644 index 0000000000..3ad5d00263 --- /dev/null +++ b/tests/artifactory/frontend/sql/ir/simple_query.yaml @@ -0,0 +1,205 @@ +# +# SELECT "identification_number", "product_code" FROM "test_space" WHERE "identification_number" = 1; +# + +--- +nodes: + arena: + - Expression: + Reference: + targets: ~ + position: 0 + parent: 0 + - Expression: + Alias: + name: identification_number + child: 0 + - Expression: + Reference: + targets: ~ + position: 1 + parent: 0 + - Expression: + Alias: + name: product_code + child: 2 + - Expression: + Reference: + targets: ~ + position: 2 + parent: 0 + - Expression: + Alias: + name: product_units + child: 4 + - Expression: + Reference: + targets: ~ + position: 3 + parent: 0 + - Expression: + Alias: + name: sys_op + child: 6 + - Expression: + Reference: + targets: ~ + position: 4 + parent: 0 + - Expression: + Alias: + name: bucket_id + child: 8 + - Expression: + Row: + list: + - 1 + - 3 + - 5 + - 7 + - 9 + distribution: ~ + - Relational: + ScanRelation: + output: 10 + id: 0 + relation: hash_testing + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 12 + - Expression: + Row: + list: + - 12 + distribution: ~ + - Expression: + Constant: + value: + Number: 1 + - Expression: + Bool: + left: 13 + op: Eq + right: 14 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 12 + - Expression: + Alias: + name: identification_number + child: 16 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 12 + - Expression: + Alias: + name: product_code + child: 18 + - Expression: + Reference: + targets: + - 0 + position: 2 + parent: 12 + - Expression: + Alias: + name: product_units + child: 20 + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 12 + - Expression: + Alias: + name: sys_op + child: 22 + - Expression: + Reference: + targets: + - 0 + position: 4 + parent: 12 + - Expression: + Alias: + name: bucket_id + child: 24 + - Expression: + Row: + list: + - 17 + - 19 + - 21 + - 23 + - 25 + distribution: ~ + - Relational: + Selection: + children: + - 11 + filter: 15 + id: 12 + output: 26 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 28 + - Expression: + Alias: + name: identification_number + child: 28 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 28 + - Expression: + Alias: + name: product_code + child: 30 + - Expression: + Row: + list: + - 29 + - 31 + distribution: ~ + - Relational: + Projection: + children: + - 27 + id: 28 + output: 32 +relations: + hash_testing: + Segment: + columns: + - name: identification_number + type: integer + - name: product_code + type: string + - name: product_units + type: boolean + - name: sys_op + type: number + - name: bucket_id + type: unsigned + key: + positions: + - 0 + - 1 + name: hash_testing +slices: ~ +top: 33 diff --git a/tests/artifactory/frontend/sql/ir/simple_union_query.yaml b/tests/artifactory/frontend/sql/ir/simple_union_query.yaml new file mode 100644 index 0000000000..c34f93ff15 --- /dev/null +++ b/tests/artifactory/frontend/sql/ir/simple_union_query.yaml @@ -0,0 +1,563 @@ +# +# SELECT * +# FROM +# ( +# SELECT "identification_number", "product_code" +# FROM "hash_testing" +# WHERE "sys_op" = 1 +# UNION ALL +# SELECT "identification_number", "product_code" +# FROM "hash_testing_hist" +# WHERE "sys_op" > 1 +# ) AS "t3" +# WHERE "identification_number" = 1 +# +--- +nodes: + arena: + - Expression: + Reference: + targets: ~ + position: 0 + parent: 0 + - Expression: + Alias: + name: identification_number + child: 0 + - Expression: + Reference: + targets: ~ + position: 1 + parent: 0 + - Expression: + Alias: + name: product_code + child: 2 + - Expression: + Reference: + targets: ~ + position: 2 + parent: 0 + - Expression: + Alias: + name: product_units + child: 4 + - Expression: + Reference: + targets: ~ + position: 3 + parent: 0 + - Expression: + Alias: + name: sys_op + child: 6 + - Expression: + Reference: + targets: ~ + position: 4 + parent: 0 + - Expression: + Alias: + name: bucket_id + child: 8 + - Expression: + Row: + list: + - 1 + - 3 + - 5 + - 7 + - 9 + distribution: ~ + - Relational: + ScanRelation: + output: 10 + id: 0 + relation: hash_testing + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 12 + - Expression: + Row: + list: + - 12 + distribution: ~ + - Expression: + Constant: + value: + Number: 1 + - Expression: + Bool: + left: 13 + op: Eq + right: 14 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 12 + - Expression: + Alias: + name: identification_number + child: 16 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 12 + - Expression: + Alias: + name: product_code + child: 18 + - Expression: + Reference: + targets: + - 0 + position: 2 + parent: 12 + - Expression: + Alias: + name: product_units + child: 20 + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 12 + - Expression: + Alias: + name: sys_op + child: 22 + - Expression: + Reference: + targets: + - 0 + position: 4 + parent: 12 + - Expression: + Alias: + name: bucket_id + child: 24 + - Expression: + Row: + list: + - 17 + - 19 + - 21 + - 23 + - 25 + distribution: ~ + - Relational: + Selection: + children: + - 11 + filter: 15 + id: 12 + output: 26 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 28 + - Expression: + Alias: + name: identification_number + child: 28 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 28 + - Expression: + Alias: + name: product_code + child: 30 + - Expression: + Row: + list: + - 29 + - 31 + distribution: ~ + - Relational: + Projection: + children: + - 27 + id: 28 + output: 32 + - Expression: + Reference: + targets: ~ + position: 0 + parent: 34 + - Expression: + Alias: + name: identification_number + child: 34 + - Expression: + Reference: + targets: ~ + position: 1 + parent: 34 + - Expression: + Alias: + name: product_code + child: 36 + - Expression: + Reference: + targets: ~ + position: 2 + parent: 34 + - Expression: + Alias: + name: product_units + child: 38 + - Expression: + Reference: + targets: ~ + position: 3 + parent: 34 + - Expression: + Alias: + name: sys_op + child: 40 + - Expression: + Reference: + targets: ~ + position: 4 + parent: 34 + - Expression: + Alias: + name: bucket_id + child: 42 + - Expression: + Row: + list: + - 35 + - 37 + - 39 + - 41 + - 43 + distribution: ~ + - Relational: + ScanRelation: + output: 44 + id: 34 + relation: hash_testing_hist + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 46 + - Expression: + Row: + list: + - 46 + distribution: ~ + - Expression: + Constant: + value: + Number: 1 + - Expression: + Bool: + left: 47 + op: Gt + right: 48 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 46 + - Expression: + Alias: + name: identification_number + child: 50 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 46 + - Expression: + Alias: + name: product_code + child: 52 + - Expression: + Reference: + targets: + - 0 + position: 2 + parent: 46 + - Expression: + Alias: + name: product_units + child: 54 + - Expression: + Reference: + targets: + - 0 + position: 3 + parent: 46 + - Expression: + Alias: + name: sys_op + child: 56 + - Expression: + Reference: + targets: + - 0 + position: 4 + parent: 46 + - Expression: + Alias: + name: bucket_id + child: 58 + - Expression: + Row: + list: + - 51 + - 53 + - 55 + - 57 + - 59 + distribution: ~ + - Relational: + Selection: + children: + - 45 + filter: 49 + id: 46 + output: 60 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 62 + - Expression: + Alias: + name: identification_number + child: 62 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 62 + - Expression: + Alias: + name: product_code + child: 64 + - Expression: + Row: + list: + - 63 + - 65 + distribution: ~ + - Relational: + Projection: + children: + - 61 + id: 62 + output: 66 + - Expression: + Reference: + targets: + - 0 + - 1 + position: 0 + parent: 68 + - Expression: + Alias: + name: identification_number + child: 68 + - Expression: + Reference: + targets: + - 0 + - 1 + position: 1 + parent: 68 + - Expression: + Alias: + name: product_code + child: 70 + - Expression: + Row: + list: + - 69 + - 71 + distribution: ~ + - Relational: + UnionAll: + children: + - 33 + - 67 + id: 68 + output: 72 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 74 + - Expression: + Alias: + name: identification_number + child: 74 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 74 + - Expression: + Alias: + name: product_code + child: 76 + - Expression: + Row: + list: + - 75 + - 77 + distribution: ~ + - Relational: + ScanSubQuery: + alias: t3 + children: + - 73 + id: 74 + output: 78 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 80 + - Expression: + Row: + list: + - 80 + distribution: ~ + - Expression: + Constant: + value: + Number: 1 + - Expression: + Bool: + left: 81 + op: Eq + right: 82 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 80 + - Expression: + Alias: + name: identification_number + child: 84 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 80 + - Expression: + Alias: + name: product_code + child: 86 + - Expression: + Row: + list: + - 85 + - 87 + distribution: ~ + - Relational: + Selection: + children: + - 79 + filter: 83 + id: 80 + output: 88 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 90 + - Expression: + Alias: + name: identification_number + child: 90 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 90 + - Expression: + Alias: + name: product_code + child: 92 + - Expression: + Row: + list: + - 91 + - 93 + distribution: ~ + - Relational: + Projection: + children: + - 89 + id: 90 + output: 94 +relations: + hash_testing_hist: + Segment: + columns: + - name: identification_number + type: integer + - name: product_code + type: string + - name: product_units + type: boolean + - name: sys_op + type: number + - name: bucket_id + type: unsigned + key: + positions: + - 0 + - 1 + name: hash_testing_hist + hash_testing: + Segment: + columns: + - name: identification_number + type: integer + - name: product_code + type: string + - name: product_units + type: boolean + - name: sys_op + type: number + - name: bucket_id + type: unsigned + key: + positions: + - 0 + - 1 + name: hash_testing +slices: ~ +top: 95 diff --git a/tests/artifactory/frontend/sql/simple_query.yaml b/tests/artifactory/frontend/sql/simple_query.yaml index d1b0524e4e..ac9962ba0b 100644 --- a/tests/artifactory/frontend/sql/simple_query.yaml +++ b/tests/artifactory/frontend/sql/simple_query.yaml @@ -3,11 +3,10 @@ nodes: arena: - children: - 7 - - 5 - - 1 rule: Select value: ~ - children: + - 5 - 2 rule: Selection value: ~ @@ -20,7 +19,7 @@ nodes: rule: Number value: 1 - children: [] - rule: QuotedName + rule: Name value: "\"identification_number\"" - children: - 6 @@ -30,6 +29,7 @@ nodes: rule: Table value: "\"test_space\"" - children: + - 1 - 10 - 8 rule: Projection @@ -39,13 +39,13 @@ nodes: rule: Column value: ~ - children: [] - rule: QuotedName + rule: ProjectedName value: "\"product_code\"" - children: - 11 rule: Column value: ~ - children: [] - rule: QuotedName + rule: ProjectedName value: "\"identification_number\"" top: 0 \ No newline at end of file diff --git a/tests/artifactory/frontend/sql/transform_select_2.yaml b/tests/artifactory/frontend/sql/transform_select_2.yaml index 4d3ef0e21c..b8704ca94e 100644 --- a/tests/artifactory/frontend/sql/transform_select_2.yaml +++ b/tests/artifactory/frontend/sql/transform_select_2.yaml @@ -22,6 +22,6 @@ nodes: rule: Column value: ~ - children: [] - rule: String + rule: ProjectedName value: a top: 0 diff --git a/tests/artifactory/frontend/sql/transform_select_3.yaml b/tests/artifactory/frontend/sql/transform_select_3.yaml index 31fc36183f..1d90650130 100644 --- a/tests/artifactory/frontend/sql/transform_select_3.yaml +++ b/tests/artifactory/frontend/sql/transform_select_3.yaml @@ -19,7 +19,7 @@ nodes: rule: Number value: 1 - children: [] - rule: String + rule: Name value: a - children: - 6 @@ -38,6 +38,6 @@ nodes: rule: Column value: ~ - children: [] - rule: String + rule: ProjectedName value: a top: 0 diff --git a/tests/artifactory/frontend/sql/transform_select_4.yaml b/tests/artifactory/frontend/sql/transform_select_4.yaml index 89be662949..13acc82cf9 100644 --- a/tests/artifactory/frontend/sql/transform_select_4.yaml +++ b/tests/artifactory/frontend/sql/transform_select_4.yaml @@ -19,10 +19,10 @@ nodes: rule: Eq value: ~ - children: [] - rule: String + rule: Name value: t2.a - children: [] - rule: String + rule: Name value: t1.a - children: - 9 diff --git a/tests/artifactory/frontend/sql/transform_select_5.yaml b/tests/artifactory/frontend/sql/transform_select_5.yaml index c4eb4f4087..bc3ef7ade6 100644 --- a/tests/artifactory/frontend/sql/transform_select_5.yaml +++ b/tests/artifactory/frontend/sql/transform_select_5.yaml @@ -19,7 +19,7 @@ nodes: rule: Number value: 0 - children: [] - rule: String + rule: Name value: t1.a - children: - 6 @@ -35,10 +35,10 @@ nodes: rule: Eq value: ~ - children: [] - rule: String + rule: Name value: t2.a - children: [] - rule: String + rule: Name value: t1.a - children: - 13 -- GitLab