fix(mssql,oracle): omit unknown overview size bytes - #579
Conversation
getOverview() in both providers initialised databaseSizeBytes to 0 beside a databaseSize of "0 bytes", ran the size statement inside a try whose catch was empty, and returned the field unconditionally - so a statement that never answered published a measured-looking zero. StorageTab.tsx keys its whole breakdown off `databaseSizeBytes !== undefined`, so that fabricated 0 drew the breakdown over a database it never measured, against per-table bytes from getTableStats(), a separate read that does not share the failure. The field is now spread only when the statement answered, mirroring the activeConnections line two lines above it, and databaseSize moves with it - "N/A" while the bytes are unknown, as in the merged libSQL (libredb#569) and search (libredb#517) shapes, since both monitoring tabs render that string as the headline size. A genuine reading of 0 stays 0: the `|| 0` fold inside the try is deliberate, because an Oracle SUM over a schema that owns no segment is a measured zero rather than an unknown, so only the catch path leaves the field absent. Both provider test files pin the absence and the measured zero, and docs/providers/{mssql,oracle}.md gain a "7.3 When the database size is not measurable" section beside 7.1 and 7.2. Fixes libredb#565 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Merging. Gates green, the triad moves together, and the One residual, in the line you deliberately kept: Your comment says a Filed as #585, and offered to you first if you want it. |
Description
getOverview()in both providers initialiseddatabaseSizeBytesto0beside adatabaseSizeof"0 bytes", ran the size statement inside atrywhosecatchwas empty, and returned the field unconditionally — so a statement that never answered published a measured-looking zero.DatabaseOverview.databaseSizeBytesis optional precisely so that cannot happen (src/lib/db/types.ts: "absence and zero are different facts"), and both files already get this right foractiveConnections, spread conditionally two lines above the defect in the same return.What the fabrication bought on screen:
StorageTab.tsxkeys its whole breakdown offdatabaseSizeBytes !== undefined, so the0drew that breakdown instead of "No storage size information available." — and drew it against per-table bytes fromgetTableStats(), a separate read that does not share the size statement's failure. Every share is gated ontotalSize > 0, so all three bars stayed empty and0 - tables - indexeswent negative, which the remainder row refuses asN/A. The tab presented, as a measurement, a breakdown whose every element either disagreed with the total or declined to answer.@cevheri — I took your correction from the issue: the
databaseSizestring moves with the bytes. It is now initialised to"N/A"rather than"0 bytes", which is the pairing merged in #569 (libSQL) and #517 (the search provider), and whatgetHealth()in both of these same files already does.Type of Change
Related Issue
Closes #565
Changes Made
src/lib/db/providers/sql/mssql.ts,src/lib/db/providers/sql/oracle.ts—let databaseSizeBytes: number | undefinedand...(databaseSizeBytes === undefined ? {} : { databaseSizeBytes })in the return, mirroring theactiveConnectionsline above it;let databaseSize = "N/A".0still reports0. TheNumber(... || 0)fold inside thetryis deliberately unchanged, andmeasuredNumberis deliberately not used here: an OracleSUM(BYTES)over a schema that owns no segment answersNULL, and that is a measurement, not an unknown. Only thecatchpath leaves the field absent. Both arms are pinned by tests.tests/integration/db/oracle-provider.test.ts— "degrades to defaults when every statistics query fails" assertedexpect(overview.databaseSizeBytes).toBe(0), i.e. the suite pinned the fabrication; it now asserts the key is absent and the string is"N/A". New case: "a schema that owns no segment keeps its measured zero size".tests/integration/db/mssql-provider.test.ts— the mirror pair, next to the existingactiveConnectionspair.docs/providers/mssql.md,docs/providers/oracle.md— a new 7.3 When the database size is not measurable beside 7.1 and 7.2, plus thegetOverview()row in the §8 table. Provider triad moves together.Two things I deliberately did not do
maxConnectionsis untouched. Its docblock says0there means "no limit published", so0and absence are the same fact for the ceiling and different facts for the size.sys.database_filesis database-scoped andUSER_SEGMENTSdescribes the caller's own objects, so neither is gated by the server-level /V_$grants that §7.1 and §7.2 measured refusals against — and I have not measured a failure of either statement on a live instance. That is the argument for the guard rather than a gap in it: a request timeout, a pool fault mid-overview and a missing view all reach the samecatchin the same shape, so it must not publish a figure for any of them.Testing
I wrote the failing tests first. Before the fix:
After the fix:
The whole provider suite, run on this branch and on
mainfor comparison. Same three pre-existing failures either way — all of them induckdb-provider.test.ts, where the native addon does not open on my machine (openDuckDBClientatsrc/lib/db/providers/sql/duckdb/client.ts:180) — and my three new tests are the only difference:tests/apigives423 pass / 6 failon both, and the two logs are byte-identical apart from timestamps — so the failure set is provably unchanged. The consumer components are green:Coverage of the two changed files, measured from their own suites (lcov,
DA:lines):The rest of the local gate:
The caveat, stated plainly: I could not get a clean full
bun run teston this machine (Windows), and I am not going to claim one.helm,zipandbashare not on myPATH, so the Helm chart, packaging and shell-script suites error out before they assert anything — the sameExecutable not found in $PATH: "helm"that #569's author reported — and runningtests/unitas one process reproduces themock.module()cross-contaminationCLAUDE.mdwarns about (tests/unit/db/factory.test.tsthen hangs inpool-manager.test.ts; that file passes 53/53 in isolation). None of those files importmssql.tsororacle.ts. What I did run is above, including the A/B against unmodifiedmain, so CI is the authority on the full gate and the 100% coverage merge.Test Environment
main@a59fb8b)Checklist
Additional Notes
Scope is MSSQL and Oracle only, per the issue — SQLite and LibreDB are #546.
🤖 Generated with Claude Code