Summary
Three of the SQL features listed in one README bullet do not take effect. None of
them raise an error — the query succeeds and returns a wrong result, which makes
them easy to build on without noticing.
README (line 49) claims:
GROUP BY ... HAVING, LIMIT ... OFFSET, UNION/UNION ALL/INTERSECT/EXCEPT: standard aggregate filtering, pagination, and set operations across SELECTs
Observed on mq-db 0.2.1: HAVING is ignored, OFFSET is ignored, ORDER BY
after a GROUP BY is ignored, and the set operators error out.
Reproduction
mkdir -p /tmp/mqbug/docs && cd /tmp/mqbug
printf '# Alpha\n\nIntro paragraph.\n\n## Install\n\nRun the installer.\n' > docs/a.md
printf '# Beta\n\nAnother paragraph.\n\n## Usage\n\nUse it well.\n' > docs/b.md
mq-db index docs -o s.mq-db
That yields 2 documents and 8 blocks, 4 per document (blocks.id = 0..7).
1. HAVING is ignored
$ mq-db sql -d s.mq-db -F json \
"SELECT document_id, COUNT(*) AS n FROM blocks GROUP BY document_id HAVING COUNT(*) > 100"
[{"document_id":0,"n":4},{"document_id":1,"n":4}]
Expected: zero rows (no group has more than 100 blocks). Actual: every group,
identical to the same query without the HAVING.
2. OFFSET is ignored
$ mq-db sql -d s.mq-db -F json "SELECT id FROM blocks ORDER BY id LIMIT 2 OFFSET 4"
[{"id":0},{"id":1}]
Expected: [{"id":4},{"id":5}]. Actual: the same rows as LIMIT 2 with no
offset.
3. ORDER BY after GROUP BY is ignored
$ mq-db sql -d s.mq-db -F json \
"SELECT document_id, COUNT(*) AS n FROM blocks GROUP BY document_id ORDER BY document_id DESC"
[{"document_id":0,"n":4},{"document_id":1,"n":4}]
Expected document_id 1 then 0. ORDER BY works correctly on an ungrouped
query, so this is specific to the aggregate path.
4. Set operators error (loud, but contradicts the README)
$ mq-db sql -d s.mq-db "SELECT path FROM documents UNION ALL SELECT path FROM documents"
Error: SQL execution error: unsupported query type
$ mq-db sql -d s.mq-db "SELECT path FROM documents EXCEPT SELECT path FROM documents"
Error: SQL execution error: unsupported query type
This one fails safely, so it's much less of a problem than 1–3 — but since it is
in the same README bullet, either the implementation or the bullet needs a
change.
EXPLAIN confirms the clauses are dropped, not mis-evaluated
$ mq-db sql -d s.mq-db "EXPLAIN SELECT document_id, COUNT(*) AS n FROM blocks GROUP BY document_id HAVING COUNT(*) > 100"
│ query:from │ blocks (blocks) │
│ query:where │ none — full scan │
│ query:group-by │ 1 key(s) │
$ mq-db sql -d s.mq-db "EXPLAIN SELECT id FROM blocks ORDER BY id LIMIT 2 OFFSET 4"
│ query:from │ blocks (blocks) │
│ query:where │ none — full scan │
│ query:order-by │ id ASC │
│ query:limit │ 2 │
There is no having step and no offset step. The parser accepts the clauses;
the planner never emits them.
The underlying machinery already works
Doing the same filtering and sorting one level out, over a CTE, gives the right
answers — including the negative case:
$ mq-db sql -d s.mq-db -F json "WITH c AS (SELECT document_id, COUNT(*) AS n FROM blocks GROUP BY document_id) SELECT * FROM c WHERE n > 2"
[{"document_id":0,"n":4},{"document_id":1,"n":4}]
$ mq-db sql -d s.mq-db -F json "WITH c AS (...same...) SELECT * FROM c WHERE n > 4"
[]
$ mq-db sql -d s.mq-db -F json "WITH c AS (...same...) SELECT * FROM c ORDER BY document_id DESC"
[{"document_id":1,"n":4},{"document_id":0,"n":4}]
So aggregation, post-aggregate filtering, and post-aggregate sorting are all
correct. Only the inline HAVING / post-GROUP BY ORDER BY clauses are not
routed into them. That also gives users a workaround in the meantime.
Suggested resolution
Whatever the fix timeline, rejecting an unsupported clause is much better than
ignoring it. A HAVING that returns unfiltered rows is a wrong answer a caller
will act on; Error: HAVING is not supported is one they can see. The set
operators already behave this way, and that's the right behavior.
Environment
mq-db 0.2.1, installed via cargo install
- macOS 26.6.2 (build 25G83), arm64
Summary
Three of the SQL features listed in one README bullet do not take effect. None of
them raise an error — the query succeeds and returns a wrong result, which makes
them easy to build on without noticing.
README (line 49) claims:
Observed on
mq-db 0.2.1:HAVINGis ignored,OFFSETis ignored,ORDER BYafter a
GROUP BYis ignored, and the set operators error out.Reproduction
That yields 2 documents and 8 blocks, 4 per document (
blocks.id= 0..7).1.
HAVINGis ignoredExpected: zero rows (no group has more than 100 blocks). Actual: every group,
identical to the same query without the
HAVING.2.
OFFSETis ignoredExpected:
[{"id":4},{"id":5}]. Actual: the same rows asLIMIT 2with nooffset.
3.
ORDER BYafterGROUP BYis ignoredExpected
document_id1 then 0.ORDER BYworks correctly on an ungroupedquery, so this is specific to the aggregate path.
4. Set operators error (loud, but contradicts the README)
This one fails safely, so it's much less of a problem than 1–3 — but since it is
in the same README bullet, either the implementation or the bullet needs a
change.
EXPLAINconfirms the clauses are dropped, not mis-evaluatedThere is no
havingstep and nooffsetstep. The parser accepts the clauses;the planner never emits them.
The underlying machinery already works
Doing the same filtering and sorting one level out, over a CTE, gives the right
answers — including the negative case:
So aggregation, post-aggregate filtering, and post-aggregate sorting are all
correct. Only the inline
HAVING/ post-GROUP BYORDER BYclauses are notrouted into them. That also gives users a workaround in the meantime.
Suggested resolution
Whatever the fix timeline, rejecting an unsupported clause is much better than
ignoring it. A
HAVINGthat returns unfiltered rows is a wrong answer a callerwill act on;
Error: HAVING is not supportedis one they can see. The setoperators already behave this way, and that's the right behavior.
Environment
mq-db 0.2.1, installed viacargo install