From 3f339d07d38d2886869dff5a4a22dfd49e5d082e Mon Sep 17 00:00:00 2001 From: mazchew Date: Tue, 9 Jul 2024 02:43:36 +0800 Subject: [PATCH] add max aggregate function --- core/translate.rs | 16 ++++++++++++++-- core/types.rs | 3 +++ core/vdbe.rs | 40 ++++++++++++++++++++++++++++++++++++++++ testing/all.test | 4 ++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/core/translate.rs b/core/translate.rs index 4e869dac6..f371c0c64 100644 --- a/core/translate.rs +++ b/core/translate.rs @@ -471,9 +471,21 @@ fn translate_aggregation( }); target_register } - AggFunc::GroupConcat => todo!(), - AggFunc::Max => todo!(), + AggFunc::Max => { + if args.len() != 1 { + anyhow::bail!("Parse error: max bad number of arguments"); + } + let expr = &args[0]; + let expr_reg = program.alloc_register(); + let _ = translate_expr(program, cursor_id, table, expr, expr_reg); + program.emit_insn(Insn::AggStep { + acc_reg: target_register, + col: expr_reg, + func: AggFunc::Max, + }); + target_register + } AggFunc::Min => todo!(), AggFunc::StringAgg => todo!(), AggFunc::Sum => { diff --git a/core/types.rs b/core/types.rs index 2e3ed32fa..bad398d7e 100644 --- a/core/types.rs +++ b/core/types.rs @@ -47,6 +47,7 @@ impl Display for OwnedValue { AggContext::Avg(acc, _count) => write!(f, "{}", acc), AggContext::Sum(acc) => write!(f, "{}", acc), AggContext::Count(count) => write!(f, "{}", count), + AggContext::Max(max) => write!(f, "{}", max), }, OwnedValue::Record(r) => write!(f, "{:?}", r), } @@ -58,6 +59,7 @@ pub enum AggContext { Avg(OwnedValue, OwnedValue), // acc and count Sum(OwnedValue), Count(OwnedValue), + Max(OwnedValue), } impl std::ops::Add for OwnedValue { @@ -163,6 +165,7 @@ pub fn to_value(value: &OwnedValue) -> Value<'_> { AggContext::Avg(acc, _count) => to_value(acc), // we assume aggfinal was called AggContext::Sum(acc) => to_value(acc), AggContext::Count(count) => to_value(count), + AggContext::Max(max) => to_value(max), }, OwnedValue::Record(_) => todo!(), } diff --git a/core/vdbe.rs b/core/vdbe.rs index e3067a858..f787902c1 100644 --- a/core/vdbe.rs +++ b/core/vdbe.rs @@ -433,6 +433,20 @@ impl Program { AggFunc::Count => { OwnedValue::Agg(Box::new(AggContext::Count(OwnedValue::Integer(0)))) } + AggFunc::Max => { + let col = state.registers[*col].clone(); + match col { + OwnedValue::Integer(_) => { + OwnedValue::Agg(Box::new(AggContext::Max(OwnedValue::Integer(i64::MIN)))) + } + OwnedValue::Float(_) => { + OwnedValue::Agg(Box::new(AggContext::Max(OwnedValue::Float(f64::NEG_INFINITY)))) + } + _ => { + unreachable!(); + } + } + } _ => { todo!(); } @@ -472,6 +486,31 @@ impl Program { }; *count += 1; } + AggFunc::Max => { + let col = state.registers[*col].clone(); + let OwnedValue::Agg(agg) = state.registers[*acc_reg].borrow_mut() else { + unreachable!(); + }; + let AggContext::Max(acc) = agg.borrow_mut() else { + unreachable!(); + }; + + match (acc, col) { + (OwnedValue::Integer(ref mut current_max), OwnedValue::Integer(value)) => { + if value > *current_max { + *current_max = value; + } + } + (OwnedValue::Float(ref mut current_max), OwnedValue::Float(value)) => { + if value > *current_max { + *current_max = value; + } + } + _ => { + eprintln!("Unexpected types in max aggregation"); + } + } + } _ => { todo!(); } @@ -492,6 +531,7 @@ impl Program { } AggFunc::Sum => {} AggFunc::Count => {} + AggFunc::Max => {} _ => { todo!(); } diff --git a/testing/all.test b/testing/all.test index b1fd6cb95..70f311292 100755 --- a/testing/all.test +++ b/testing/all.test @@ -47,6 +47,10 @@ do_execsql_test select-count { SELECT count(id) FROM users; } {10000} +do_execsql_test select-max { + SELECT max(age) FROM users; +} {100} + do_execsql_test select-limit-0 { SELECT id FROM users LIMIT 0; } {}