Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Bug: a grouped count/avg over a variable-length pattern with a relationship predicate ignores the predicate since #1080

Closed Beginner friendly
#1,127 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

A pull request for this has already been merged.

  • #1133 by @adsharma — merged

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
74/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
databases

Research direction

Start at tryRewriteGroupedReachableCount, where the gate already rejects recursiveExtend->hasNodePredicate(); check RecursiveInfo::relPredicate and reject the rewrite when it is set, alongside the self-loop and negative-shape guards the issue mentions. Locate the C++ optimizer source (the gate lives in the query planner/optimizer code) and the existing tests in OptimizerTest.GroupedReachableCount, adding a case with (r, n | WHERE r.w > 2). Done means the Python repro from the issue returns [(True, 6, 2.0)], EXPLAIN no longer shows GROUPED_REACHABLE_COUNT for the predicate query, and the new optimizer test passes.

Written by the indexing model from the issue text.

Description

Since #1080 the grouped count and avg rewrite (GROUPED_REACHABLE_COUNT) is also applied to a variable-length pattern that has a relationship predicate, and it ignores the predicate. The same query returns correct rows without the aggregate and with the aggregate before #1080.

Builds, both from source (Release, make python equivalent, g++ 15.2, Python 3.12.13, Ubuntu 26.04): the merge of #1080 at 99ae4efe9578226f48396e0ecfe6da5ffca18b30, against its base 95dbf5ed180f625993a49a64b92f4d968401e90e. The published 0.21.2 wheel behaves like the base.

Repro, self-contained (three nodes, edges 0 to 1 with w=1, 1 to 2 with w=5, 2 to 2 with w=5):

import ladybug

db = ladybug.Database("db.lbug")
c = ladybug.Connection(db)
c.execute("CREATE NODE TABLE N(id INT64 PRIMARY KEY, active BOOLEAN)")
c.execute("CREATE REL TABLE E(FROM N TO N, w INT64)")
for i, a in [(0, True), (1, False), (2, True)]:
    c.execute(f"CREATE (:N {{id: {i}, active: {str(a).lower()}}})")
for a, b, w in [(0, 1, 1), (1, 2, 5), (2, 2, 5)]:
    c.execute(f"MATCH (x:N {{id: {a}}}), (y:N {{id: {b}}}) CREATE (x)-[:E {{w: {w}}}]->(y)")

q = "MATCH (a:N)-[r:E*1..3 (r, n | WHERE r.w > 2)]->(b:N) RETURN b.active, count(b), avg(b.id)"
print(sorted(map(tuple, c.execute(q).get_all()), key=str))

Only the edges with w > 2 may be used, so the walks are 1 to 2, 2 to 2, and 2 to 2 to 2 repeated up to three hops, all ending on active = true. Expected: [(True, 6, 2.0)].

At the base commit and on 0.21.2: [(True, 6, 2.0)]. At 99ae4efe95: [(False, 1, 1.0), (True, 8, 2.0)], which is exactly the answer of the same pattern with no predicate (MATCH (a:N)-[r:E*1..3]->(b:N) ...). Row by row, RETURN a.id, b.id, count(*) on the same predicate pattern is still right at 99ae4efe95 ([(1, 2, 3), (2, 2, 3)]), so only the rewritten aggregate is wrong.

EXPLAIN at 99ae4efe95 shows GROUPED_REACHABLE_COUNT for the predicate query. The gate in tryRewriteGroupedReachableCount rejects recursiveExtend->hasNodePredicate(), which is !children.empty(), but I could not find anything that rejects a relationship predicate (RecursiveInfo::relPredicate), so the walk counts are taken over the full table.

How it was found: a differential run against a brute-force walk enumeration, 120 random graphs with self-loops, parallel edges and cycles, three hop ranges (*0..3, *1..3, *2..4), shape RETURN b.active, count(b), avg(b.score) with (r, n | WHERE r.w > 2). At the base commit every mismatch is at *0..3 and is the known length-0 duplication that #1080 fixes. At 99ae4efe95 356 of the 360 cells for this shape differ from the enumeration, in all three ranges. The other shapes in the matrix (count, count DISTINCT, avg, min, max, sums, one and two group keys, a WHERE on the endpoint or the start, trail, backward, undirected) have no mismatch at 99ae4efe95.

Suggested fix: reject the rewrite when the recursive info carries a relationship predicate, and add that case next to the self-loop and negative shapes in OptimizerTest.GroupedReachableCount.

Dominant language
C++
Stars
1.8k
Forks
148
Avg merge
14h 57m
Merged PRs (30d)
124

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from LadybugDB/ladybug

All issues in LadybugDB/ladybug

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.