From 6749fa87d3d9621b03847584b503c3464e33ff9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=9E=97=E4=BC=9F?= Date: Thu, 1 Feb 2024 16:30:53 +0800 Subject: [PATCH] Add nullable and to_column to ExprTrait --- bustubx/src/expression/alias.rs | 14 +++++++- bustubx/src/expression/binary.rs | 13 +++++++- bustubx/src/expression/cast.rs | 13 +++++++- bustubx/src/expression/column.rs | 20 ++++++++++- bustubx/src/expression/literal.rs | 14 +++++++- bustubx/src/expression/mod.rs | 37 ++++++++++++--------- bustubx/src/planner/logical_plan_v2/util.rs | 2 +- 7 files changed, 92 insertions(+), 21 deletions(-) diff --git a/bustubx/src/expression/alias.rs b/bustubx/src/expression/alias.rs index d2e7c2c..c374661 100644 --- a/bustubx/src/expression/alias.rs +++ b/bustubx/src/expression/alias.rs @@ -1,9 +1,10 @@ -use crate::catalog::DataType; use crate::catalog::Schema; +use crate::catalog::{Column, DataType}; use crate::common::ScalarValue; use crate::error::BustubxResult; use crate::expression::{Expr, ExprTrait}; use crate::storage::Tuple; +use crate::BustubxError; #[derive(Clone, PartialEq, Eq, Debug)] pub struct Alias { @@ -16,7 +17,18 @@ impl ExprTrait for Alias { self.expr.data_type(input_schema) } + fn nullable(&self, input_schema: &Schema) -> BustubxResult { + self.expr.nullable(input_schema) + } + fn evaluate(&self, tuple: &Tuple) -> BustubxResult { self.expr.evaluate(tuple) } + + fn to_column(&self, input_schema: &Schema) -> BustubxResult { + Err(BustubxError::Plan(format!( + "expr {:?} as column not supported", + self + ))) + } } diff --git a/bustubx/src/expression/binary.rs b/bustubx/src/expression/binary.rs index 98a400b..011da43 100644 --- a/bustubx/src/expression/binary.rs +++ b/bustubx/src/expression/binary.rs @@ -1,5 +1,5 @@ -use crate::catalog::DataType; use crate::catalog::Schema; +use crate::catalog::{Column, DataType}; use crate::common::ScalarValue; use crate::error::BustubxResult; use crate::expression::{Expr, ExprTrait}; @@ -37,6 +37,10 @@ impl ExprTrait for BinaryExpr { } } + fn nullable(&self, input_schema: &Schema) -> BustubxResult { + Ok(self.left.nullable(input_schema)? || self.right.nullable(input_schema)?) + } + fn evaluate(&self, tuple: &Tuple) -> BustubxResult { let l = self.left.evaluate(tuple)?; let r = self.right.evaluate(tuple)?; @@ -83,6 +87,13 @@ impl ExprTrait for BinaryExpr { ))), } } + + fn to_column(&self, input_schema: &Schema) -> BustubxResult { + Err(BustubxError::Plan(format!( + "expr {:?} as column not supported", + self + ))) + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Hash)] diff --git a/bustubx/src/expression/cast.rs b/bustubx/src/expression/cast.rs index 07833e1..cbec71a 100644 --- a/bustubx/src/expression/cast.rs +++ b/bustubx/src/expression/cast.rs @@ -1,4 +1,4 @@ -use crate::catalog::{DataType, Schema}; +use crate::catalog::{Column, DataType, Schema}; use crate::common::ScalarValue; use crate::expression::{Expr, ExprTrait}; use crate::{BustubxError, BustubxResult, Tuple}; @@ -17,6 +17,10 @@ impl ExprTrait for Cast { Ok(self.data_type) } + fn nullable(&self, input_schema: &Schema) -> BustubxResult { + self.expr.nullable(input_schema) + } + fn evaluate(&self, tuple: &Tuple) -> BustubxResult { let value = self.expr.evaluate(tuple)?; match value { @@ -66,4 +70,11 @@ impl ExprTrait for Cast { }, } } + + fn to_column(&self, input_schema: &Schema) -> BustubxResult { + Err(BustubxError::Plan(format!( + "expr {:?} as column not supported", + self + ))) + } } diff --git a/bustubx/src/expression/column.rs b/bustubx/src/expression/column.rs index a82e020..f00ea90 100644 --- a/bustubx/src/expression/column.rs +++ b/bustubx/src/expression/column.rs @@ -1,5 +1,5 @@ -use crate::catalog::DataType; use crate::catalog::Schema; +use crate::catalog::{Column, DataType}; use crate::common::table_ref::TableReference; use crate::common::ScalarValue; use crate::error::{BustubxError, BustubxResult}; @@ -23,7 +23,25 @@ impl ExprTrait for ColumnExpr { ) } + fn nullable(&self, input_schema: &Schema) -> BustubxResult { + input_schema.get_col_by_name(&self.name).map_or( + Err(BustubxError::Plan(format!( + "Not found column {} in input schema {:?}", + self.name, input_schema + ))), + |col| Ok(col.nullable), + ) + } + fn evaluate(&self, tuple: &Tuple) -> BustubxResult { Ok(tuple.get_value_by_col_name(&tuple.schema, &self.name)) } + + fn to_column(&self, input_schema: &Schema) -> BustubxResult { + Ok(Column { + name: self.name.clone(), + data_type: self.data_type(input_schema)?, + nullable: self.nullable(input_schema)?, + }) + } } diff --git a/bustubx/src/expression/literal.rs b/bustubx/src/expression/literal.rs index ba8c627..ea08431 100644 --- a/bustubx/src/expression/literal.rs +++ b/bustubx/src/expression/literal.rs @@ -1,9 +1,10 @@ -use crate::catalog::DataType; use crate::catalog::Schema; +use crate::catalog::{Column, DataType}; use crate::common::ScalarValue; use crate::error::BustubxResult; use crate::expression::ExprTrait; use crate::storage::Tuple; +use crate::BustubxError; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Literal { @@ -15,7 +16,18 @@ impl ExprTrait for Literal { Ok(self.value.data_type()) } + fn nullable(&self, _input_schema: &Schema) -> BustubxResult { + Ok(self.value.is_null()) + } + fn evaluate(&self, _tuple: &Tuple) -> BustubxResult { Ok(self.value.clone()) } + + fn to_column(&self, _input_schema: &Schema) -> BustubxResult { + Err(BustubxError::Plan(format!( + "expr {:?} as column not supported", + self + ))) + } } diff --git a/bustubx/src/expression/mod.rs b/bustubx/src/expression/mod.rs index c45f62d..ed119ee 100644 --- a/bustubx/src/expression/mod.rs +++ b/bustubx/src/expression/mod.rs @@ -20,8 +20,14 @@ pub trait ExprTrait { /// Get the data type of this expression, given the schema of the input fn data_type(&self, input_schema: &Schema) -> BustubxResult; + /// Determine whether this expression is nullable, given the schema of the input + fn nullable(&self, input_schema: &Schema) -> BustubxResult; + /// Evaluate an expression against a Tuple fn evaluate(&self, tuple: &Tuple) -> BustubxResult; + + /// convert to a column with respect to a schema + fn to_column(&self, input_schema: &Schema) -> BustubxResult; } #[derive(Clone, PartialEq, Eq, Debug)] @@ -50,6 +56,16 @@ impl ExprTrait for Expr { } } + fn nullable(&self, input_schema: &Schema) -> BustubxResult { + match self { + Expr::Alias(alias) => alias.nullable(input_schema), + Expr::Column(column) => column.nullable(input_schema), + Expr::Literal(literal) => literal.nullable(input_schema), + Expr::BinaryExpr(binary) => binary.nullable(input_schema), + Expr::Cast(cast) => cast.nullable(input_schema), + } + } + fn evaluate(&self, tuple: &Tuple) -> BustubxResult { match self { Expr::Alias(alias) => alias.evaluate(tuple), @@ -59,23 +75,14 @@ impl ExprTrait for Expr { Expr::Cast(cast) => cast.evaluate(tuple), } } -} -impl Expr { - pub fn to_column(&self, input_schema: &Schema) -> BustubxResult { + fn to_column(&self, input_schema: &Schema) -> BustubxResult { match self { - Expr::Column(ColumnExpr { relation, name }) => Ok(Column { - name: name.clone(), - data_type: self.data_type(input_schema)?, - // TODO fix - nullable: false, - }), - _ => { - return Err(BustubxError::Plan(format!( - "expr {:?} as column not supported", - self - ))) - } + Expr::Alias(alias) => alias.to_column(input_schema), + Expr::Column(column) => column.to_column(input_schema), + Expr::Literal(literal) => literal.to_column(input_schema), + Expr::BinaryExpr(binary) => binary.to_column(input_schema), + Expr::Cast(cast) => cast.to_column(input_schema), } } } diff --git a/bustubx/src/planner/logical_plan_v2/util.rs b/bustubx/src/planner/logical_plan_v2/util.rs index 396e1d5..4fb2d37 100644 --- a/bustubx/src/planner/logical_plan_v2/util.rs +++ b/bustubx/src/planner/logical_plan_v2/util.rs @@ -1,5 +1,5 @@ use crate::catalog::{ColumnRef, Schema}; -use crate::expression::{ColumnExpr, Expr}; +use crate::expression::{ColumnExpr, Expr, ExprTrait}; use crate::planner::logical_plan_v2::LogicalPlanV2; use crate::planner::table_ref::join::JoinType; use crate::{BustubxError, BustubxResult};