diff --git a/src/errors.rs b/src/errors.rs index 43d2f1ed2aa34782d2f2a31c33af97d53b7cc7f5..41b2dcfe1079535d068e1dcafc5a225cf075a9ce 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -5,6 +5,7 @@ use serde::Serialize; const BUCKET_ID_ERROR: &str = "field doesn't contains sharding key value"; const DUPLICATE_COLUMN_ERROR: &str = "duplicate column"; const INVALID_BOOL_ERROR: &str = "invalid boolean"; +const INVALID_NAME_ERROR: &str = "invalid name"; const INVALID_NUMBER_ERROR: &str = "invalid number"; const INVALID_PLAN_ERROR: &str = "invalid plan"; const INVALID_RELATION_ERROR: &str = "invalid relation"; @@ -23,6 +24,7 @@ pub enum QueryPlannerError { BucketIdError, DuplicateColumn, InvalidBool, + InvalidName, InvalidNumber, InvalidPlan, InvalidRelation, @@ -43,6 +45,7 @@ impl fmt::Display for QueryPlannerError { QueryPlannerError::BucketIdError => BUCKET_ID_ERROR, QueryPlannerError::DuplicateColumn => DUPLICATE_COLUMN_ERROR, QueryPlannerError::InvalidBool => INVALID_BOOL_ERROR, + QueryPlannerError::InvalidName => INVALID_NAME_ERROR, QueryPlannerError::InvalidNumber => INVALID_NUMBER_ERROR, QueryPlannerError::InvalidPlan => INVALID_PLAN_ERROR, QueryPlannerError::InvalidRelation => INVALID_RELATION_ERROR, diff --git a/src/ir/operator.rs b/src/ir/operator.rs index bc6d59de7bcd71627e7af8507850ead81bf9f9b5..2bb4e66a999adb36581139ab6640ed7d5400299e 100644 --- a/src/ir/operator.rs +++ b/src/ir/operator.rs @@ -67,6 +67,8 @@ pub enum Relational { relation: String, }, ScanSubQuery { + /// SubQuery name + alias: String, /// Child tuple node index in the plan node arena (left branch). child: usize, /// Output tuple node index in the plan node arena. @@ -404,13 +406,21 @@ impl Relational { /// /// # Errors /// Returns `QueryPlannerError` when the child node is invalid. - pub fn new_sub_query(plan: &mut Plan, child: usize) -> Result<Self, QueryPlannerError> { + pub fn new_sub_query( + plan: &mut Plan, + child: usize, + alias: &str, + ) -> Result<Self, QueryPlannerError> { let names: Vec<String> = if let Node::Relational(rel_op) = plan.get_node(child)? { rel_op.output_alias_names(&plan.nodes)? } else { return Err(QueryPlannerError::InvalidRow); }; + if alias.is_empty() { + return Err(QueryPlannerError::InvalidName); + } + let col_names: Vec<&str> = names.iter().map(|s| s as &str).collect(); let aliases = new_alias_nodes(plan, child, &col_names, &Branch::Both)?; @@ -430,7 +440,11 @@ impl Relational { Node::Expression(Expression::new_row(aliases, dist)), ); - Ok(Relational::ScanSubQuery { child, output }) + Ok(Relational::ScanSubQuery { + alias: String::from(alias), + child, + output, + }) } } diff --git a/src/ir/operator/tests.rs b/src/ir/operator/tests.rs index 14c90cd01d9e764afad9de54232bc125531d1e82..b501170b402cf1ce11927da0a4a54c988f8cf9b0 100644 --- a/src/ir/operator/tests.rs +++ b/src/ir/operator/tests.rs @@ -336,13 +336,19 @@ fn sub_query() { let scan = Relational::new_scan("t", &mut plan).unwrap(); let scan_id = vec_alloc(&mut plan.nodes, Node::Relational(scan)); - Relational::new_sub_query(&mut plan, scan_id).unwrap(); + Relational::new_sub_query(&mut plan, scan_id, "sq").unwrap(); - // Check non-relational child node error + // Non-relational child node let a = 1; assert_eq!( QueryPlannerError::InvalidRow, - Relational::new_sub_query(&mut plan, a).unwrap_err() + Relational::new_sub_query(&mut plan, a, "sq").unwrap_err() + ); + + // Invalid name + assert_eq!( + QueryPlannerError::InvalidName, + Relational::new_sub_query(&mut plan, scan_id, "").unwrap_err() ); } diff --git a/tests/artifactory/ir/operator/sub_query.yaml b/tests/artifactory/ir/operator/sub_query.yaml index 60752578c0f3a5812588c274872c137c1890b57a..9ebf065926d45df5d09f435d954e93adea72b4c4 100644 --- a/tests/artifactory/ir/operator/sub_query.yaml +++ b/tests/artifactory/ir/operator/sub_query.yaml @@ -56,6 +56,7 @@ nodes: - 0 - Relational: ScanSubQuery: + alias: sq child: 5 output: 10 relations: