Query:: COUNT(*) added to logical planning and execution
Reviewers: mislav.bradac, buda, teon.banek Reviewed By: mislav.bradac, teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D353
This commit is contained in:
parent
871b81656b
commit
0866fdcb0c
@ -1059,7 +1059,17 @@ void Aggregate::AggregateCursor::Update(
|
||||
auto agg_elem_it = self_.aggregations_.begin();
|
||||
for (; count_it < agg_value.counts_.end();
|
||||
count_it++, value_it++, agg_elem_it++) {
|
||||
std::get<0>(*agg_elem_it)->Accept(evaluator);
|
||||
|
||||
// COUNT(*) is the only case where input expression is optional
|
||||
// handle it here
|
||||
auto input_expr_ptr = std::get<0>(*agg_elem_it);
|
||||
if (!input_expr_ptr) {
|
||||
*count_it += 1;
|
||||
*value_it = *count_it;
|
||||
continue;
|
||||
}
|
||||
|
||||
input_expr_ptr->Accept(evaluator);
|
||||
TypedValue input_value = evaluator.PopBack();
|
||||
|
||||
// Aggregations skip Null input values.
|
||||
|
@ -310,7 +310,11 @@ class ReturnBodyContext : public TreeVisitorBase {
|
||||
// Aggregation contains a virtual symbol, where the result will be stored.
|
||||
const auto &symbol = symbol_table_.at(aggr);
|
||||
aggregations_.emplace_back(aggr.expression_, aggr.op_, symbol);
|
||||
has_aggregation_.back() = true;
|
||||
// aggregation expression_ is opional in COUNT(*) so it's possible the has_aggregation_ stack is empty
|
||||
if (aggr.expression_)
|
||||
has_aggregation_.back() = true;
|
||||
else
|
||||
has_aggregation_.emplace_back(true);
|
||||
// Possible optimization is to skip remembering symbols inside aggregation.
|
||||
// If and when implementing this, don't forget that Accumulate needs *all*
|
||||
// the symbols, including those inside aggregation.
|
||||
|
@ -152,10 +152,10 @@ TEST(QueryPlan, AggregateOps) {
|
||||
// we will take the sum, avg, min, max and count
|
||||
// we won't group by anything
|
||||
auto prop = dba->property("prop");
|
||||
dba->insert_vertex().PropsSet(prop, 4);
|
||||
dba->insert_vertex().PropsSet(prop, 5);
|
||||
dba->insert_vertex().PropsSet(prop, 7);
|
||||
dba->insert_vertex().PropsSet(prop, 12);
|
||||
// a missing property (null) gets ignored by all aggregations
|
||||
// a missing property (null) gets ignored by all aggregations except COUNT(*)
|
||||
dba->insert_vertex();
|
||||
dba->advance_command();
|
||||
|
||||
@ -167,31 +167,36 @@ TEST(QueryPlan, AggregateOps) {
|
||||
auto n_p = PROPERTY_LOOKUP("n", prop);
|
||||
symbol_table[*n_p->expression_] = n.sym_;
|
||||
|
||||
std::vector<Expression *> aggregation_expressions(6, n_p);
|
||||
aggregation_expressions[0] = nullptr;
|
||||
auto produce = MakeAggregationProduce(
|
||||
n.op_, symbol_table, storage, std::vector<Expression *>(5, n_p),
|
||||
{Aggregation::Op::COUNT, Aggregation::Op::MIN, Aggregation::Op::MAX,
|
||||
Aggregation::Op::SUM, Aggregation::Op::AVG},
|
||||
n.op_, symbol_table, storage, aggregation_expressions,
|
||||
{Aggregation::Op::COUNT, Aggregation::Op::COUNT, Aggregation::Op::MIN,
|
||||
Aggregation::Op::MAX, Aggregation::Op::SUM, Aggregation::Op::AVG},
|
||||
{}, {});
|
||||
|
||||
// checks
|
||||
auto results = CollectProduce(produce, symbol_table, *dba).GetResults();
|
||||
ASSERT_EQ(results.size(), 1);
|
||||
ASSERT_EQ(results[0].size(), 5);
|
||||
// count
|
||||
ASSERT_EQ(results[0].size(), 6);
|
||||
// count(*)
|
||||
ASSERT_EQ(results[0][0].type(), TypedValue::Type::Int);
|
||||
EXPECT_EQ(results[0][0].Value<int64_t>(), 3);
|
||||
// min
|
||||
EXPECT_EQ(results[0][0].Value<int64_t>(), 4);
|
||||
// count
|
||||
ASSERT_EQ(results[0][1].type(), TypedValue::Type::Int);
|
||||
EXPECT_EQ(results[0][1].Value<int64_t>(), 4);
|
||||
// max
|
||||
EXPECT_EQ(results[0][1].Value<int64_t>(), 3);
|
||||
// min
|
||||
ASSERT_EQ(results[0][2].type(), TypedValue::Type::Int);
|
||||
EXPECT_EQ(results[0][2].Value<int64_t>(), 12);
|
||||
// sum
|
||||
EXPECT_EQ(results[0][2].Value<int64_t>(), 5);
|
||||
// max
|
||||
ASSERT_EQ(results[0][3].type(), TypedValue::Type::Int);
|
||||
EXPECT_EQ(results[0][3].Value<int64_t>(), 23);
|
||||
EXPECT_EQ(results[0][3].Value<int64_t>(), 12);
|
||||
// sum
|
||||
ASSERT_EQ(results[0][4].type(), TypedValue::Type::Int);
|
||||
EXPECT_EQ(results[0][4].Value<int64_t>(), 24);
|
||||
// avg
|
||||
ASSERT_EQ(results[0][4].type(), TypedValue::Type::Double);
|
||||
EXPECT_FLOAT_EQ(results[0][4].Value<double>(), 23 / 3.0);
|
||||
ASSERT_EQ(results[0][5].type(), TypedValue::Type::Double);
|
||||
EXPECT_FLOAT_EQ(results[0][5].Value<double>(), 24 / 3.0);
|
||||
}
|
||||
|
||||
TEST(QueryPlan, AggregateGroupByValues) {
|
||||
|
Loading…
Reference in New Issue
Block a user