Skip to content

Separate dry-run row-operation estimates from final persisted row counts #5236

Description

@Widthdom

Summary

For an unchanged rebuild fixture, dry-run table-mutation estimates are exactly twice the row counts reported by the real rebuild:

Metric Dry-run Persisted after rebuild
chunks 18 9
symbols 110 55
symbol references 322 161
reference lines 198 99

The preview is summing replacement deletes and inserts, while the execution response reports final persisted cardinality. The output does not distinguish those meanings, so the values appear to be a 2x overestimate.

Reproduced with an isolated fixture using locally built cdidx v1.45.1 at 81861a14c9396cd74190edc91392ab11abfa86f8.

Reproduction

dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll index <project> \
  --db <existing.db> --rebuild --dry-run --json

dotnet ./src/CodeIndex/bin/Debug/net8.0/cdidx.dll index <project> \
  --db <existing.db> --rebuild --yes --json --notify none

Both commands exit 0 and produce the values above.

Expected behavior

Expose unambiguous, mathematically comparable dimensions:

  • projected rows deleted;
  • projected rows inserted/upserted;
  • total row operations, if useful;
  • projected final row count or delta where it can be computed.

Do not use the same apparent metric for an operation count in preview and a final/persisted count in execution.

Existing issue relationship

Related history:

No existing issue covers this delete-plus-insert versus persisted-cardinality mismatch.

Root-cause pointers

  • src/CodeIndex/Cli/IndexCommandRunner.DryRun.cs:420-450 adds existing-row and parsed-row estimates to one accumulator.
  • AddEstimatedExistingUpdateMutations, AddExistingChildRows, BuildDryRunParsedMutationEstimate, and DryRunMutationEstimateAccumulator in that file own the two sides.

PR scope and implementation guidance

  • Define explicit operation and projected-state dimensions in the dry-run result model.
  • Prefer additive structured fields; if legacy fields remain, document their exact semantics and deprecation path.
  • Keep human and JSON definitions identical.
  • Preserve confidence/source/unknown reasons independently for each dimension.
  • Ensure arithmetic remains bounded and does not require materializing all rows.
  • Do not combine this PR with C# target-expansion or unrelated indexing planner changes.

Acceptance criteria

  • The fixture explains 9 deletes plus 9 inserts rather than presenting an unexplained 18-versus-9 mismatch.
  • New-database, unchanged rebuild, changed update, delete, purge, skipped, and parse-unavailable fixtures have consistent estimates.
  • Unknown values remain explicit rather than zero.
  • Existing path/file/truncation budgets remain intact.
  • Dry-run remains non-mutating.

Tests, documentation, and changelog

  • Add arithmetic fixtures for empty/new DB, unchanged rebuild, changed content, deletes, and parse-unavailable cases.
  • Verify JSON and human metric names/definitions.
  • Run the complete net8.0 and net9.0 test suites.
  • Update dry-run schema/help documentation.
  • Add the required bilingual changelog.d/unreleased/ fragment referencing the prior estimate work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETPull requests that update .NET codebugSomething isn't workingdocumentationImprovements or additions to documentationtests

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions