Version: v0.9.1-rc.1 (built from the tag, 560ad40, macOS arm64)
Tool: query_graph
Summary
A LIMIT is silently ignored when the query has an ORDER BY with more than one sort key. Single-key ORDER BY … LIMIT works; adding a second key makes the whole result set come back.
This is a token-safety problem rather than a cosmetic one: on a 24k-node graph my first natural hot-path query returned 6339 rows / ~587 KB (~147k tokens) into an agent's context instead of the 8 rows I asked for. On a bigger graph that is a context-window wipeout from a query that looks completely ordinary.
Reproduction
Same project, same binary, same DB — only the ORDER BY arity changes.
P=my-project
# A) single-key ORDER BY + LIMIT 5 -> correct
cbm cli query_graph --project $P \
--query 'MATCH (f:Method) WHERE f.file_path STARTS WITH "src/" RETURN f.name ORDER BY f.complexity DESC LIMIT 5'
# rows: 5 (113 bytes)
# B) two-key ORDER BY + LIMIT 5 -> LIMIT DROPPED
cbm cli query_graph --project $P \
--query 'MATCH (f:Method) WHERE f.file_path STARTS WITH "src/" RETURN f.name ORDER BY f.complexity DESC, f.name DESC LIMIT 5'
# rows: 6326 (117277 bytes) <-- expected 5
# C) LIMIT 5, no ORDER BY -> correct
cbm cli query_graph --project $P \
--query 'MATCH (f:Method) WHERE f.file_path STARTS WITH "src/" RETURN f.name LIMIT 5'
# rows: 5 (113 bytes)
# D) two-key ORDER BY + LIMIT 5, plus the MCP-level guard -> correct
cbm cli query_graph --project $P --max-rows 5 \
--query 'MATCH (f:Method) WHERE f.file_path STARTS WITH "src/" RETURN f.name ORDER BY f.complexity DESC, f.name DESC LIMIT 5'
# rows: 5 (113 bytes)
| case |
ORDER BY keys |
LIMIT |
rows returned |
bytes |
| A |
1 |
5 |
5 |
113 |
| B |
2 |
5 |
6326 |
117277 |
| C |
0 |
5 |
5 |
113 |
| D |
2 |
5 + max_rows:5 |
5 |
113 |
The original query that surfaced it (six projected columns, two sort keys, LIMIT 8) returned 6339 rows / 586541 bytes.
Notes
Secondary, same call surface
toFloat() is rejected inside WHERE, though the README lists it under supported functions:
$ cbm cli query_graph --project $P \
--query 'MATCH (a)-[r:CALLS]->(b) WHERE toFloat(r.confidence) < 0.4 RETURN count(r)'
unsupported function 'toFloat' in WHERE (supported: coalesce, substring, replace, left, right)
It does work in RETURN. Same shape as the closed #874 (coalesce() in WHERE), so the WHERE evaluator seems to support a much narrower function set than RETURN — worth either widening it or narrowing the documented list, because numeric comparison on edge properties like r.confidence (stored as a string) is otherwise impossible in WHERE.
Version:
v0.9.1-rc.1(built from the tag,560ad40, macOS arm64)Tool:
query_graphSummary
A
LIMITis silently ignored when the query has anORDER BYwith more than one sort key. Single-keyORDER BY … LIMITworks; adding a second key makes the whole result set come back.This is a token-safety problem rather than a cosmetic one: on a 24k-node graph my first natural hot-path query returned 6339 rows / ~587 KB (~147k tokens) into an agent's context instead of the 8 rows I asked for. On a bigger graph that is a context-window wipeout from a query that looks completely ordinary.
Reproduction
Same project, same binary, same DB — only the
ORDER BYarity changes.ORDER BYkeysLIMITmax_rows:5The original query that surfaced it (six projected columns, two sort keys,
LIMIT 8) returned 6339 rows / 586541 bytes.Notes
max_rowsis an effective workaround, which suggests the row cap is applied at the MCP layer and the planner simply loses theLIMITnode when theORDER BYkey list has length > 1.max_rowsis optional andLIMITis the documented, idiomatic way to bound a Cypher result, the failure mode is "agent writes a textbook query, gets a context flood".DISTINCTvsORDER BY … LIMIT), but this one needs noDISTINCTand over-returns rather than under-returns.query_graphfall back to a defaultmax_rowswhen the query text contains aLIMITthat the planner did not honour, or log acypher.limit.droppedwarning.Secondary, same call surface
toFloat()is rejected insideWHERE, though the README lists it under supported functions:It does work in
RETURN. Same shape as the closed #874 (coalesce()inWHERE), so theWHEREevaluator seems to support a much narrower function set thanRETURN— worth either widening it or narrowing the documented list, because numeric comparison on edge properties liker.confidence(stored as a string) is otherwise impossible inWHERE.