Skip to content

bug(graph): three query-shape defects — count(*) after OPTIONAL MATCH, phantom collect() map, and C++ toolkit reading m.alias #1533

Closed

Description

@Shashankss1205

Three query-shape defects found while cross-checking tool queries against writer.py. All reproduced against a live database.

1. count(*) after OPTIONAL MATCH makes injection_count never zero

tools/handlers/analysis_handlers.py:239-240 and tools/query_tool_languages/java_toolkit.py:109-110

OPTIONAL MATCH ()-[:INJECTS]->(c)
WITH c, count(*) AS injection_count

count(*) counts rows, and an unmatched OPTIONAL MATCH still emits one null row. Against a database with 2 INJECTS edges total, find_java_spring_beans reports injection_count: 1 for Dummy, A, B, C and AbstractThing — none of which anything injects. Switching to count(r) over a bound relationship variable returns 0 correctly.

Effect: "which beans are unused" is unanswerable, and every count is off by one.

2. collect() of a map literal yields a phantom all-null entry

tools/handlers/analysis_handlers.py:299

OPTIONAL MATCH (kp:RedisKeyPattern)-[:STORED_IN]->(d)
RETURN ... collect({pattern: kp.pattern, key_type: kp.key_type, count: kp.count})

A map literal is non-null even when every field inside it is null, so collect() does not drop it. find_datasource_nodes returns:

"key_patterns": [{"pattern": null, "key_type": null, "count": null}]

for a Redis datasource with no discovered key patterns, instead of []. A consumer doing len(key_patterns) sees 1.

3. C++ toolkit reads m.alias, which no writer ever sets

tools/query_tool_languages/cpp_toolkit.py:46

The query binds the relationship as i but reads the alias off the node:

MATCH (f:File)-[i:IMPORTS]->(m:Module) RETURN ... m.full_import_name, m.alias

writer.py:580-598 sets r.alias on the relationship; m.alias is never written. Against the live database:

MATCH (m:Module)      RETURN count(m), count(m.alias)  ->  160, 0
MATCH ()-[i:IMPORTS]->() RETURN count(i), count(i.alias) ->  249, 249

All 249 rows return alias: null while the data sits on the relationship. The elisp and solidity toolkits correctly read i.imported_name / i.full_import_name. (Same root cause as the find_importers issue filed separately — worth fixing together.)

Suggested fix

  1. count(r) over a bound relationship variable instead of count(*).
  2. Filter nulls before collecting, or collect() the node and build maps afterwards.
  3. i.alias instead of m.alias.

Environment
Commit c0e0bed (main)
Backend Neo4j (live instance)
Python 3.12.3, Linux

All three reproduced against a live indexed database.

Activity

  1. added
    bugSomething isn't working
    severity: mediumIncorrect results, misleading output, or a broken contract
    area: graphDatabase abstraction, Cypher generation, schema, bundles
    on Aug 1, 2026
  2. github-actions commented on Aug 1, 2026

    @github-actions
    Contributor

    Hi! 👋 Join our CodeGraphContext Discord channel to collaborate: https://discord.gg/dR4QY32uYQ

  3. Shashankss1205 commented on Aug 2, 2026

    @Shashankss1205
    CollaboratorAuthor

    Item 3 is fixed by #1540 (merged) — cpp_toolkit.py:46 now reads i.alias off the IMPORTS relationship instead of m.alias off the Module node. That PR also fixed the sibling call site in find_importers (#1515) and added a regression test asserting "module.alias" not in query.

    Still open here:

    1. count(*) after OPTIONAL MATCH — analysis_handlers.py:239-240 and java_toolkit.py:109-110. An unmatched OPTIONAL MATCH still emits one null row, so injection_count is never 0 and every Spring bean reports at least one injector. Needs count(r) over a bound relationship variable.
    2. Phantom collect() map — analysis_handlers.py:299. A map literal is non-null even when every field inside is null, so key_patterns comes back as [{"pattern": null, "key_type": null, "count": null}] instead of [].

    Both are small and independent — good first issues for anyone looking.

  4. Shashankss1205 commented on Aug 5, 2026

    @Shashankss1205
    CollaboratorAuthor

    All three items now fixed.

  5. moved this from Backlog tasks to Done in CGC Progress Boardon Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: graphDatabase abstraction, Cypher generation, schema, bundlesbugSomething isn't workingseverity: mediumIncorrect results, misleading output, or a broken contract

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions