Skip to content

[feature] Add a statement-scoped orm_call_in_loop signal (so N+1 detection doesn't false-positive on pre-materialized lists) #600

Description

@ecosuper2025

Version: codebase-memory-mcp v0.8.1

Problem

There is no statement-level signal for "an ORM/query call happens inside a loop". The only in-loop signals on Function/Method are linear_scan_in_loop, alloc_in_loop, recursion_in_loop. So any N+1 detection has to be done at function granularity: "this function has a loop AND somewhere calls .filter()". That cannot distinguish:

rows = list(qs.filter(active=True))   # materialized ONCE, outside the loop  ✅ fine
for r in rows:                        # iterating an in-memory list — NOT N+1
    do(r)

from the real N+1:

for pk in pks:
    obj = Model.objects.get(pk=pk)    # query INSIDE the loop  ❌ N+1

Both look identical to a function-level query (loop_count>=1 + CALLS → get/filter), so the first is a false positive.

Repro

There is no property to query; get_graph_schema() shows Function props include
loop_count, loop_depth, linear_scan_in_loop, alloc_in_loop, recursion_in_loop
but no orm_call_in_loop / query_in_loop. A user N+1 query (loop + ORM call) therefore mis-flags list(qs.filter())-outside-loop patterns.

Requested

  • Add a statement-scoped signal analogous to linear_scan_in_loop, e.g. orm_call_in_loop (count of ORM/DB-query calls whose call-site is lexically inside a loop body), and/or
  • A query_in_loop boolean. ORM call recognition can mirror whatever powers route/HTTP extraction (Django objects.*, SQLAlchemy session.*, Sequelize, etc.).
  • Bonus: don't count calls whose result is assigned via list(...)/tuple(...) before the loop (materialization).

Why

linear_scan_in_loop already proves the analyzer can attribute calls to loop scope; extending it to ORM calls would make N+1 detection precise instead of heuristic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions