libredb / libredb/libredb-studio
[BUG] MongoDB: a collection outside the session database silently returns 0 rows
- Dominant language
- TypeScript
- Stars
- 726
- Forks
- 119
- Avg merge
- 7h 47m
- Merged PRs (30d)
- 265
Description
## Description
The object tree lists every database the connection is authorized to see, but the query path is still bound to the one database named at connect.
Clicking a collection in any other database runs the find against the session database instead, and MongoDB answers an absent collection with an empty result rather than an error.
The user gets 0 rows and no indication that the wrong database was read.
This is the half of #765's shape that MongoDB did not get: the container level was added, the query binding was not.
## Steps to Reproduce
Fixture:
```
docker run -d --name mongo-repro -p 27842:27017 \
-e MONGO_INITDB_ROOT_USERNAME=probeadmin -e MONGO_INITDB_ROOT_PASSWORD=probepass842 mongo:8
docker exec mongo-repro mongosh -u probeadmin -p probepass842 --authenticationDatabase admin --quiet --eval '
db.getSiblingDB("appdata").orders.insertOne({n:1});
db.getSiblingDB("analytics").events.insertOne({n:1});'
```
1. Add a MongoDB connection: host `localhost`, port `27842`, user `probeadmin`, password `probepass842`, Authentication Database `admin`, Database Name `appdata`.
2. Connect. The left panel lists `analytics` and `appdata`.
3. Expand `appdata` > Collections and click `orders`. The result footer reads `1 rows`. This is the control.
4. Expand `analytics` > Collections and click `events`. The result footer reads `0 rows`.
`analytics.events` holds exactly one document, so step 4 must also read `1 rows`.
## Expected Behavior
A collection is read from the database it is listed under.
Where that cannot be honoured, the read raises rather than answering an empty result.
## Actual Behavior
| Clicked | Documents present | Rows returned |
|---|---|---|
| `appdata.orders` (control) | 1 | 1 |
| `analytics.events` | 1 | 0 |
## Root Cause
Two places, one missing fact.
- `src/lib/query-generators.ts:420` - the `queryLanguage === "json"` branch emits `{ collection: tableName, operation: "find", ... }` and discards `path`. Every SQL dialect below it qualifies the object with `quoteObjectPath(path, capabilities)`, so MongoDB is the only generator that drops the container segment.
- `src/lib/db/providers/document/mongodb.ts:863` - `query()` resolves the collection as `this.db!.collection(query.collection)`, and `this.db` is pinned once at connect to `client.db(getDatabaseName())` (`mongodb.ts:739-740`, `getDatabaseName()` at `:822`). There is no per-statement database.
The command grammar itself has no database key: it is documented at `mongodb.ts:685` and `mongodb.ts:848`, offered as a completion at `src/lib/editor/mongodb-completions.ts:85`, and parsed at `mongodb.ts:1013`.
So this cannot be fixed in the generator alone; the grammar has to carry the database.
## Scope
Fixing the binding also removes the reason the `database` field is mandatory.
`validate()` rejects an empty Database Name in field mode (`mongodb.ts:709`, message `Database name is required for MongoDB`), while connection-string mode has no such check and the same box is labelled "Database Name (optional override)" in `ConnectionModal.tsx`.
Measured: connected by URI with no database path at all, the tree still lists both databases and expands them correctly, so the requirement is not load-bearing for reading the tree.
It is load-bearing for queries only because of the defect above: with no database bound, `getDatabaseName()` falls back to `"test"` and every find reads `test`.
So the order is: bind the query to the object's own database first, then make the field optional. Making the field optional on its own would send every query to `test`.
## Acceptance Criteria
1. Clicking a collection in any listed database returns that collection's documents. The repro above reads `1 rows` at both step 3 and step 4.
2. The command grammar carries the database, and a command naming a database the connection cannot reach raises with the server's own sentence rather than answering an empty result.
3. A command with no database key keeps today's meaning, the session database, so saved queries and the editor's own snippets do not change behaviour.
4. The Database Name field is optional in field mode as well, and a connection with no database still lists, expands and queries every authorized database.
5. The triad stays in lockstep in the same PR: `src/lib/db/providers/document/mongodb.ts`, `docs/providers/mongodb.md` and `tests/integration/db/mongodb-provider.test.ts`. The grammar is written in three places (`mongodb.ts:685`, `mongodb.ts:848`, `mongodb-completions.ts:85`) and all three have to agree.
## Test Requirement
Write the failing tests first.
- A provider test that a find naming a second database reads that database, and that today's unqualified find still reads the session database.
- A provider test that an unreachable database in the command raises rather than returning an empty result.
- A generator test in `tests/` covering `src/lib/query-generators.ts` that the JSON branch qualifies the collection with its container path, mirroring what the SQL branches already assert.
- A `validate()` test that an absent database is accepted in field mode.
100% line coverage is a required check, so every new line lands with its test in the same PR.
## Environment
Measured on `main` at 7b59efc7 (v0.16.0, unreleased), `mongo:8`, Linux, driven through the browser rather than the API.
Contributor guide
Research direction
Start with src/lib/query-generators.ts:420 and the MongoDB grammar and query paths in src/lib/db/providers/document/mongodb.ts, then inspect the completion entry at src/lib/editor/mongodb-completions.ts:85. Run the MongoDB provider, generator, and validate tests in tests/ while adding the requested cases. Done means qualified database reads work, unqualified reads retain session behavior, unreachable databases raise, and the field, docs, grammar, and tests agree.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- mongodb, typescript
- Domain
- backend-api-design, databases, documentation, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 64/100