Skip to content

Commit

Permalink
Implement binary and unary operator.
Browse files Browse the repository at this point in the history
  • Loading branch information
gtnao committed Jan 17, 2024
1 parent e7d074d commit 5805b2c
Show file tree
Hide file tree
Showing 12 changed files with 479 additions and 155 deletions.
42 changes: 29 additions & 13 deletions src/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
UnaryOperator, UpdateStatementAST, AGGREGATE_FUNCTION_NAMES,
},
tuple::Tuple,
value::{boolean::BooleanValue, Value},
value::Value,
};

#[derive(Debug, PartialEq, Eq, Clone)]
Expand Down Expand Up @@ -719,26 +719,42 @@ impl Binder {
}

impl BoundExpressionAST {
pub fn eval(&self, tuples: &Vec<&Tuple>, schemas: &Vec<&Schema>) -> Value {
pub fn eval(&self, tuples: &Vec<&Tuple>, schemas: &Vec<&Schema>) -> Result<Value> {
match self {
BoundExpressionAST::Path(path_expression) => {
let tuple = &tuples[path_expression.table_index];
let values = tuple.values(schemas[path_expression.table_index]);
values[path_expression.column_index].clone()
Ok(values[path_expression.column_index].clone())
}
BoundExpressionAST::Literal(literal_expression) => literal_expression.value.clone(),
BoundExpressionAST::Unary(_) => {
// let operand = unary_expression.operand.eval(tuples, schemas);
// TODO:
unimplemented!()
BoundExpressionAST::Literal(literal_expression) => Ok(literal_expression.value.clone()),
BoundExpressionAST::Unary(unary_expression) => {
let operand = unary_expression.operand.eval(tuples, schemas)?;
match unary_expression.operator {
UnaryOperator::Negate => operand.perform_negate(),
UnaryOperator::Not => operand.perform_not(),
UnaryOperator::IsNull => operand.perform_is_null(),
UnaryOperator::IsNotNull => operand.perform_is_not_null(),
}
}
BoundExpressionAST::Binary(binary_expression) => {
let left = binary_expression.left.eval(tuples, schemas);
let right = binary_expression.right.eval(tuples, schemas);
let left = binary_expression.left.eval(tuples, schemas)?;
let right = binary_expression.right.eval(tuples, schemas)?;
match binary_expression.operator {
BinaryOperator::Equal => Value::Boolean(BooleanValue(left.perform_eq(&right))),
// TODO: implement other operators
_ => unimplemented!(),
BinaryOperator::Equal => left.perform_equal(&right),
BinaryOperator::NotEqual => left.perform_not_equal(&right),
BinaryOperator::LessThan => left.perform_less_than(&right),
BinaryOperator::LessThanOrEqual => left.perform_less_than_or_equal(&right),
BinaryOperator::GreaterThan => left.perform_greater_than(&right),
BinaryOperator::GreaterThanOrEqual => {
left.perform_greater_than_or_equal(&right)
}
BinaryOperator::Add => left.perform_add(&right),
BinaryOperator::Subtract => left.perform_subtract(&right),
BinaryOperator::Multiply => left.perform_multiply(&right),
BinaryOperator::Divide => left.perform_divide(&right),
BinaryOperator::Modulo => left.perform_modulo(&right),
BinaryOperator::And => left.perform_and(&right),
BinaryOperator::Or => left.perform_or(&right),
}
}
// TODO: function call
Expand Down
115 changes: 100 additions & 15 deletions src/executor/aggregate_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use std::collections::HashMap;
use anyhow::Result;

use crate::{
catalog::DataType,
plan::AggregatePlan,
tuple::Tuple,
value::{integer::IntegerValue, Value},
value::{boolean::BooleanValue, integer::IntegerValue, Value},
};

use super::{Executor, ExecutorContext};
Expand All @@ -25,12 +26,16 @@ impl AggregateExecutor<'_> {
while let Some(tuple) = self.child.next()? {
let mut keys = vec![];
for expression in &self.plan.group_by {
keys.push(expression.eval(&vec![&tuple], &vec![&self.plan.child.schema()]));
keys.push(expression.eval(&vec![&tuple], &vec![&self.plan.child.schema()])?);
}
for (i, expression) in self.plan.aggregate_functions.iter().enumerate() {
let value = match &*expression.function_name {
"COUNT" => Value::Integer(IntegerValue(1)),
_ => unimplemented!(),
_ => expression
.arguments
.first()
.ok_or(anyhow::anyhow!("SUM argument error"))?
.eval(&vec![&tuple], &vec![&self.plan.child.schema()])?,
};
self.aggregate_table.add(
keys.clone(),
Expand All @@ -40,7 +45,14 @@ impl AggregateExecutor<'_> {
);
}
}
self.result = self.aggregate_table.aggregate();
self.result = self.aggregate_table.aggregate(
self.plan
.aggregate_functions
.clone()
.into_iter()
.map(|f| f.function_name)
.collect(),
)?;
Ok(())
}
pub fn next(&mut self) -> Result<Option<Tuple>> {
Expand Down Expand Up @@ -89,12 +101,12 @@ impl AggregateTable {
}
}

fn aggregate(&self) -> Vec<Vec<Value>> {
fn aggregate(&self, function_names: Vec<String>) -> Result<Vec<Vec<Value>>> {
let mut result = vec![];
for (key, value) in self.map.iter() {
match value {
AggregateTableValue::Table(table) => {
let mut rows = table.aggregate();
let mut rows = table.aggregate(function_names.clone())?;
for row in &mut rows {
row.insert(0, key.clone());
}
Expand All @@ -103,22 +115,95 @@ impl AggregateTable {
AggregateTableValue::Value(values_list) => {
let mut row = vec![];
row.push(key.clone());
for values in values_list {
let mut sum = 0;
for value in values {
match value {
Value::Integer(v) => {
sum += v.0;
for (i, values) in values_list.iter().enumerate() {
match &*function_names[i] {
"COUNT" => {
let mut sum = 0;
for value in values {
if value.is_null_value() {
continue;
}
sum += 1;
}
_ => unimplemented!(),
row.push(Value::Integer(IntegerValue(sum)));
}
"SUM" => {
let mut sum = 0;
for value in values {
if value.is_null_value() {
continue;
}
match value.convert_to(&DataType::Integer)? {
Value::Integer(v) => {
sum += v.0;
}
_ => unimplemented!(),
}
}
row.push(Value::Integer(IntegerValue(sum)));
}
"MAX" => {
let mut max = Value::Integer(IntegerValue(i64::MIN));
for value in values {
if value.is_null_value() {
continue;
}
match value.convert_to(&DataType::Integer)? {
Value::Integer(v) => {
if value.perform_greater_than(&max)?
== Value::Boolean(BooleanValue(true))
{
max = Value::Integer(v);
}
}
_ => unimplemented!(),
}
}
row.push(max);
}
"MIN" => {
let mut min = Value::Integer(IntegerValue(i64::MAX));
for value in values {
if value.is_null_value() {
continue;
}
match value.convert_to(&DataType::Integer)? {
Value::Integer(v) => {
if value.perform_less_than(&min)?
== Value::Boolean(BooleanValue(true))
{
min = Value::Integer(v);
}
}
_ => unimplemented!(),
}
}
row.push(min);
}
"AVG" => {
let mut sum = 0;
let mut count = 0;
for value in values {
if value.is_null_value() {
continue;
}
match value.convert_to(&DataType::Integer)? {
Value::Integer(v) => {
sum += v.0;
count += 1;
}
_ => unimplemented!(),
}
}
row.push(Value::Integer(IntegerValue(sum / count)));
}
_ => Err(anyhow::anyhow!("unknown aggregate function error"))?,
}
row.push(Value::Integer(IntegerValue(sum)));
}
result.push(row);
}
}
}
result
Ok(result)
}
}
2 changes: 1 addition & 1 deletion src/executor/filter_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl FilterExecutor<'_> {
if self
.plan
.condition
.eval(&tuples, &vec![&self.plan.child.schema()])
.eval(&tuples, &vec![&self.plan.child.schema()])?
== Value::Boolean(BooleanValue(true))
{
return Ok(Some(row));
Expand Down
2 changes: 1 addition & 1 deletion src/executor/insert_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl InsertExecutor<'_> {
let raw_value = self.plan.values[i].eval(
&vec![&Tuple::new(None, &vec![])],
&vec![&Schema { columns: vec![] }],
);
)?;
raw_value.convert_to(&c.data_type)
})
.collect::<Result<Vec<_>>>()?;
Expand Down
16 changes: 10 additions & 6 deletions src/executor/nested_loop_join_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl NestedLoopJoinExecutor<'_> {

// condition check
let condition_result = self.plan.conditions[depth - 1].as_ref().map_or_else(
|| true,
|| Ok(true),
|condition| {
let tuples = self
.tuples
Expand All @@ -73,9 +73,11 @@ impl NestedLoopJoinExecutor<'_> {
.iter()
.map(|child| child.schema())
.collect::<Vec<_>>();
condition.eval(&tuples, &schemas) == Value::Boolean(BooleanValue(true))
condition
.eval(&tuples, &schemas)
.map(|v| v == Value::Boolean(BooleanValue(true)))
},
);
)?;
if !condition_result {
self.tuples[depth] = self.children[depth].next()?;

Expand Down Expand Up @@ -133,7 +135,7 @@ impl NestedLoopJoinExecutor<'_> {
}

let condition_result = self.plan.conditions[depth - 1].as_ref().map_or_else(
|| true,
|| Ok(true),
|condition| {
// for left join dummy tuple
let dummy = Tuple::temp_tuple(&vec![]);
Expand All @@ -148,9 +150,11 @@ impl NestedLoopJoinExecutor<'_> {
.iter()
.map(|child| child.schema())
.collect::<Vec<_>>();
condition.eval(&tuples, &schemas) == Value::Boolean(BooleanValue(true))
condition
.eval(&tuples, &schemas)
.map(|v| v == Value::Boolean(BooleanValue(true)))
},
);
)?;
if !condition_result {
self.tuples[depth] = self.children[depth].next()?;

Expand Down
4 changes: 2 additions & 2 deletions src/executor/project_executor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::Result;

use crate::{plan::ProjectPlan, tuple::Tuple, value::Value};
use crate::{plan::ProjectPlan, tuple::Tuple};

use super::{Executor, ExecutorContext};

Expand Down Expand Up @@ -28,7 +28,7 @@ impl ProjectExecutor<'_> {
.expression
.eval(&tuples, &vec![&self.plan.child.schema()])
})
.collect::<Vec<Value>>();
.collect::<Result<Vec<_>>>()?;
return Ok(Some(Tuple::temp_tuple(&values)));
}
Ok(None)
Expand Down
2 changes: 1 addition & 1 deletion src/executor/update_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl UpdateExecutor<'_> {
for assignment in self.plan.assignments.iter() {
new_values[assignment.column_index] = assignment
.value
.eval(&vec![&row], &vec![&self.plan.child.schema()]);
.eval(&vec![&row], &vec![&self.plan.child.schema()])?;
}
self.table_heap.delete(rid)?;
self.table_heap.insert(&new_values)?;
Expand Down
Loading

0 comments on commit 5805b2c

Please sign in to comment.