Skip to content

Subqueries in WHERE (IN (SELECT ...), NOT EXISTS) silently return no rows #35

Description

@mp-grind

Summary

A SELECT whose WHERE clause contains a subquery parses, exits 0, and returns
[] regardless of the data. The subquery appears to be accepted and then never
evaluated, so the predicate is effectively always false.

Because [] is a legitimate result shape, there is nothing to distinguish this
from a correct empty answer.

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

Both documents have blocks, so the following must return both paths:

$ mq-db sql -d s.mq-db -F json "SELECT path FROM documents WHERE id IN (SELECT document_id FROM blocks)"
[]

docs/b.md has no Install heading, so this must return docs/b.md:

$ mq-db sql -d s.mq-db -F json \
  "SELECT d.path FROM documents d WHERE NOT EXISTS (SELECT 1 FROM blocks b WHERE b.document_id = d.id AND b.content = 'Install')"
[]

Baseline showing the data is there:

$ mq-db sql -d s.mq-db -F json "SELECT id, path FROM documents"
[{"id":0,"path":"docs/b.md"},{"id":1,"path":"docs/a.md"}]
$ mq-db sql -d s.mq-db -F json "SELECT DISTINCT document_id FROM blocks"
[{"document_id":0},{"document_id":1}]

EXPLAIN shows no subquery step

$ mq-db sql -d s.mq-db "EXPLAIN SELECT path FROM documents WHERE id IN (SELECT document_id FROM blocks)"
│ query:from  │ documents (documents)                          │
│ query:where │ row-by-row (no secondary index for this table) │

No semi-join, no subplan, no scan of blocks.

Note on scope

I'm filing this separately from the dropped-clause issue because the mechanism
looks different — there the clause vanishes from the plan, here the WHERE step
is present but its subquery predicate evaluates to false for every row.

If subqueries in WHERE are simply not implemented yet, that's completely
reasonable — but they should be rejected rather than treated as
always-false, the way UNION already reports unsupported query type. The
README's CTE bullet (line 42) describes CTEs as "usable in FROM, JOIN, and
subqueries", which reads as though subqueries are generally available.

CTEs themselves work well, and are a good workaround for the IN (SELECT ...)
shape:

$ mq-db sql -d s.mq-db -F json \
  "WITH h AS (SELECT document_id FROM blocks WHERE content = 'Install') SELECT d.path FROM documents d JOIN h ON h.document_id = d.id"
[{"path":"docs/a.md"}]

Environment

  • mq-db 0.2.1, installed via cargo install
  • macOS 26.6.2 (build 25G83), arm64

Activity

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions