Skip to content

Release 2.1.1: version bump, release notes and changelog (stacked on #474) - #475

Merged
MPCoreDeveloper merged 3 commits into
masterfrom
chore/release-2.1.1
Oct 25, 2026
Merged

MPCoreDeveloper merged 3 commits into
masterfrom
chore/release-2.1.1

Conversation

@MPCoreDeveloper

@MPCoreDeveloper MPCoreDeveloper commented Oct 25, 2026 •

Copy link
Copy Markdown
Owner

What this is

The release commit for 2.1.1: the version bump in the 28 packable projects, the release notes that ship
with them, and a changelog section that closes the [Unreleased] bucket. No code changes beyond #474.

Why a release is needed at all

2.1.0 is published and nuget.org versions are immutable, so the next publish must carry a version that
does not exist yet. The [Unreleased] bucket has also been collecting since the v2.1.0 tag (coverage job,
information_schema, the AOT measurement, the version() fix, the promotion sweep, the vector read-back
fix), so this is the cut where that ships: patch release, no API changes, two SQL vector defects fixed.

What changed

  • Version / FileVersion in the 28 packable src/** projects ├ö├Ñ├å 2.1.1.
  • SharpCoreDBVersion in Directory.Packages.props ├ö├Ñ├å 2.1.1 ├ö├ç├ that property is what the samples and
    providers consume from the published feed; left at 2.1.0 they would point at the release this one
    supersedes.
  • AssemblyVersion stays 2.1.0.0 on purpose: a patch should not change the assembly identity of the
    core library. FileVersion moves so a diagnostic dump still names the build.
  • PackageReleaseNotes gained a 2.1.1 line in all 23 packages that declare one. Without it every package
    would have shipped showing 2.1.0 notes on nuget.org ├ö├ç├ the one place a reader looks for what changed.
  • The EF Core provider's Description asserted Compatible with SharpCoreDB 2.1.0.
  • docs/CHANGELOG.md: [Unreleased] closes into [2.1.1] - 2026-10-25 with a note on what the release is,
    plus the vector-SQL entry from fix(vector): ORDER BY vec_distance_*() LIMIT k reaches the vector index, and CREATE VECTOR INDEX builds one #474 in Fixed, in the evidence-first style the file uses.

The failure this avoids

publish-manual.yml pushes with --skip-duplicate. Running it from a tree that still declares 2.1.0
would have gone green and shipped nothing ├ö├ç├ the same silent no-op shape as the bug in #474.

Stacked on #474

This branch is based on fix/vector-sql-optimizer. Merge #474 first, then this one: the changelog and
the release notes both state that the SQL vector planner is fixed, and once #474 lands this PR diff is just
the version bump.

Verification

Check Result
dotnet build SharpCoreDB.CI.slnf -c Release 0 errors
dotnet pack SharpCoreDB.CI.slnf -c Release 27 nupkgs, all 2.1.1, including the six SharpAgent consumes (core, Search, VectorSearch, Graph, Graph.Advanced, HybridSearch)
SharpCoreDB.Tests 2137 run, 0 failed, 16 skipped
SharpCoreDB.VectorSearch.Tests 255 run, 0 failed
SharpCoreDB.EntityFrameworkCore.Tests 116 run, 0 failed
SharpCoreDB.Functional.Linq2DB.Tests 24 run, 0 failed

After merge: run Manual NuGet Publish with an empty packVersion (so it packs the declared versions),
then tag v2.1.1 at that commit so the tag finally points at a release that contains both fixes.

Second commit: the READMEs that ship inside the packages

  • 21 NuGet.README.md install snippets ÔåÆ --version 2.1.1. These files are embedded in the nupkgs
    (PackageReadmeFile), so publishing 2.1.1 unchanged would have put dotnet add package SharpCoreDB --version 2.1.0 on all 21 package pages ÔÇö the one line a reader copies.
  • src/SharpCoreDB/NuGet.README.md led with SharpCoreDB 2.1.0 / What's New in 2.1.0; it now leads
    with 2.1.1 plus a What's New in 2.1.1 section (the two vector fixes, information_schema, the
    coverage job), keeping the 2.1.0 detail below it.
  • Graph.Advanced README: (v2.1.1) and requires SharpCoreDB 2.1.1+.
  • Five lived docs carry install instructions (analytics, cqrs, graphrag, manual/quickstart,
    scdb/PRODUCTION_GUIDE)  2.1.1. The dated RC.3 record and PROMOTION_TO_MAIN.md keep their
    versions ÔÇö they are history, not current requirements.
  • Verified by packing the core project and reading the README back out of the archive: first line is
    # SharpCoreDB 2.1.1 ÔÇö Performance-First Database Engine, file is SharpCoreDB.2.1.1.nupkg.

How this ships (correcting an earlier note of mine)

Merging this PR is the publish. ci.yml runs pack + publish on every push to master
(if: github.ref == 'refs/heads/master'): it discovers every packable project under src/, packs
them, then pushes in five dependency layers with --skip-duplicate. So no publish-manual.yml
dispatch is needed — that workflow is the fallback (failed or interrupted run, or a core-only
republish via publish-core).

Consequences worth knowing before merging:

  • The run started by fix(vector): ORDER BY vec_distance_*() LIMIT k reaches the vector index, and CREATE VECTOR INDEX builds one #474's merge (40184306018) packs 2.1.0 and has every push skipped as a
    duplicate: green, ships nothing. That is exactly the no-op this version bump exists to break.
  • Tags do not publish. v* triggers ci.yml for build + coverage only; both publish jobs are
    gated on refs/heads/master. Tag v2.1.1 is still a manual step after the merge.
  • v2.1.0 → 58f297e (2026-10-10), and 2.1.0 was published 2026-10-10 18:18 UTC, so neither
    32227696 (float[] binder, committed 10-11) nor 16cb51d5 (the planner wiring) is in the
    published 2.1.0. The tag must not be reused.

…ng in a dead branch

`CREATE VECTOR INDEX` and the `ORDER BY vec_distance_*(col, vector) LIMIT k`
planner branch were both permanently inactive, and restoring the deleted method
alone would have revived neither. `SqlParser.VectorQueryOptimizer` was an
`internal static` that no code in SharpCoreDB ever assigned and no other assembly
could assign (the parser is internal), while SharpCoreDB.VectorSearch registers
the optimizer with the DI container. So `VectorQueryOptimizer?.BuildIndex(...)`
in the DDL path and `VectorQueryOptimizer is not null` in the SELECT path were
no-ops in both directions: nothing built an index and nothing looked for one.

Wiring: Database.GetSharedSqlParser now resolves IVectorQueryOptimizer from the
service provider — the same pattern GRAPH_RAG already used — and attaches it via
SetVectorQueryOptimizer; the property is per parser instance instead of static.
The second SqlParser construction site (the compiled-query fallback) now goes
through GetSharedSqlParser, so falling back cannot produce a parser without the
extensions the first site attaches.

Restored and repaired: TryExecuteVectorOptimized was replaced by a stub returning
null in 997103b, after working in e220461. The restored code is not a snapshot
of it. The old version copied every column and appended a "distance" key whatever
the SELECT list said, and did so for DESC and WHERE queries too, so an optimized
query and an unoptimized one returned different shapes for the same SQL. Rows are
now projected onto the SELECT list (SELECT *, plain columns, aliases, and the
distance expression substituted from the key the optimizer injects), ORDER BY may
name either the alias or the function, and the two shapes an ascending top-k index
cannot answer — DESC and a WHERE clause — fall back to the scan instead of
returning a plausible wrong answer.

Found while testing: an unquoted vector literal (`[1,0,0,0]`, which is exactly
what ParameterBinder produces for a float[] parameter) lost its commas to the
argument splitter, leaving "[1" as the query vector. Brackets and braces now count
as nesting, so a bound float[] parameter works end to end.

Tests: tests/SharpCoreDB.VectorSearch.Tests/SqlVectorQueryTests.cs, seven
end-to-end cases through AddVectorSupport() + Database — the only level at which
the wiring is observable, which is why the existing VectorQueryOptimizer unit
tests stayed green throughout the outage. 255/255 in that project, 2137/2137 in
SharpCoreDB.Tests.

Known limitation, unchanged: an index is a snapshot of the table at CREATE VECTOR
INDEX; rows inserted afterwards are not in it until it is rebuilt.
…tor fixes

2.1.0 is published and nuget.org versions are immutable, so the next publish has to carry a
version that does not exist yet. The Unreleased bucket has also been collecting since the
v2.1.0 tag - the coverage job, information_schema, the AOT measurement, the version() fix, the
promotion sweep, and the vector read-back fix - so a patch release is the honest cut: no API
changes, 27 packages renumbered, the two SQL vector defects fixed (the float[] binder on
master, the optimizer wiring in #474).

Version bumped in the 28 packable projects under src/ (Version and FileVersion), plus
SharpCoreDBVersion in Directory.Packages.props, which is what the samples and providers
consume from the published feed - leaving it at 2.1.0 would have pointed them at the release
this one supersedes. AssemblyVersion stays 2.1.0.0 on purpose: a patch should not change the
assembly identity of the core library.

PackageReleaseNotes gained a 2.1.1 line in all 23 packages that declare one. Without it every
package would have shipped showing 2.1.0 notes on nuget.org, which is the one place a reader
looks for what changed. The EF Core provider's Description also asserted "Compatible with
SharpCoreDB 2.1.0".

docs/CHANGELOG.md closes [Unreleased] into [2.1.1] - 2026-10-25 with a note on what the release
is, and adds the vector-SQL entry (#474) to Fixed, in the evidence-first style the file uses.

Stacked on fix/vector-sql-optimizer: merge #474 first, or this release claims a fix it does
not contain.

The silent failure this avoids: publish-manual.yml pushes with --skip-duplicate, so running it
from a tree still declaring 2.1.0 would have gone green and shipped nothing.

Verified: Release build 0 errors; pack produces 27 nupkgs, all at 2.1.1, including the six
SharpAgent consumes; suites 2137 (16 skipped) / 255 / 116 / 24, all 0 failed.
The install snippets inside the NuGet.README.md files name a version, and every one of those
files ships inside its nupkg (PackageReadmeFile), so publishing 2.1.1 with them unchanged would
have advertised `dotnet add package SharpCoreDB --version 2.1.0` on all 21 package pages - the
one line a reader copies. Same pattern in five docs that carry install instructions (analytics,
cqrs, graphrag, manual/quickstart, scdb/PRODUCTION_GUIDE); the dated RC.3 record and
PROMOTION_TO_MAIN keep their versions, they are history.

src/SharpCoreDB/NuGet.README.md also led with "SharpCoreDB 2.1.0" and "What's New in 2.1.0", so
the package page would have described the previous release. It now leads with 2.1.1, carries a
"What's New in 2.1.1" section for the two vector fixes and the information_schema / coverage work,
and keeps the 2.1.0 detail below it. The Graph.Advanced README says "(v2.1.1)" and requires
"SharpCoreDB 2.1.1+".

Verified by packing the core project and reading the README back out of the nupkg: the first line
is "# SharpCoreDB 2.1.1 - Performance-First Database Engine" and the archive is
SharpCoreDB.2.1.1.nupkg.
@codecov

codecov Bot commented Oct 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.63158% with 34 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/SharpCoreDB/Services/SqlParser.DML.cs 78.98% 12 Missing and 17 partials ⚠️
...arpCoreDB/Database/Execution/Database.Execution.cs 72.72% 2 Missing and 1 partial ⚠️
src/SharpCoreDB/Services/SqlParser.DDL.cs 0.00% 0 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

@sonarqubecloud

Copy link
Copy Markdown

@MPCoreDeveloper
MPCoreDeveloper merged commit 1195434 into master Oct 25, 2026
16 checks passed
@MPCoreDeveloper
MPCoreDeveloper deleted the chore/release-2.1.1 branch October 25, 2026 10:35
MPCoreDeveloper added a commit that referenced this pull request Oct 25, 2026
… them

A master push packs every project and pushes every artifact. `--skip-duplicate` does not avoid the
PUT: a duplicate is still a request, and NuGet.org counts it, so a burst of merges exhausts the push
quota and the run dies with `403 Quota Exceeded` (retry after 822s) long after the release itself
shipped. That is what turned the four dependabot merges after #475 red: 2.1.1 was on the feed, the
publish job was not.

push_layer now reads id and version out of each nupkg nuspec, asks the flatcontainer index, and only
pushes what is missing. Anything already published is skipped without touching the push endpoint, so
an unchanged tree costs one GET per package and zero pushes, and the 30s indexing wait only happens
for a layer that actually pushed something.

The step summary now reports pushed vs skipped and says plainly when a run shipped nothing.
`ls *.nupkg | wc -l` never did: it read "Published 28 package(s)" on runs that pushed none.

The catch-all `push_layer "Remaining packages" "*.nupkg"` also re-pushed the whole set after the
layered passes - 50 already-exists conflicts in a single run - so every release paid for 28 extra
requests. It still catches packages the layers do not name; the feed check makes it free.

The same skip logic goes into publish-manual.yml, so a re-dispatch after a partial publish costs one
request per package instead of a full re-push.

Validated: both workflows parse as YAML; the two helpers run against the live feed (published version
skipped, unpublished pushed, unknown package id pushed, 404 index pushed, nuspec 2.1.0-RC.3 matching
the feed lowercase 2.1.0-rc.3); nuspec extraction returns id/version from a nuspec fragment.
MPCoreDeveloper added a commit that referenced this pull request Oct 25, 2026
… them

A master push packs every project and pushes every artifact. `--skip-duplicate` does not avoid the
PUT: a duplicate is still a request, and NuGet.org counts it, so a burst of merges exhausts the push
quota and the run dies with `403 Quota Exceeded` (retry after 822s) long after the release itself
shipped. That is what turned the four dependabot merges after #475 red: 2.1.1 was on the feed, the
publish job was not.

push_layer now reads id and version out of each nupkg nuspec, asks the flatcontainer index, and only
pushes what is missing. Anything already published is skipped without touching the push endpoint, so
an unchanged tree costs one GET per package and zero pushes, and the 30s indexing wait only happens
for a layer that actually pushed something.

The step summary now reports pushed vs skipped and says plainly when a run shipped nothing.
`ls *.nupkg | wc -l` never did: it read "Published 28 package(s)" on runs that pushed none.

The catch-all `push_layer "Remaining packages" "*.nupkg"` also re-pushed the whole set after the
layered passes - 50 already-exists conflicts in a single run - so every release paid for 28 extra
requests. It still catches packages the layers do not name; the feed check makes it free.

The same skip logic goes into publish-manual.yml, so a re-dispatch after a partial publish costs one
request per package instead of a full re-push.

Validated: both workflows parse as YAML; the two helpers run against the live feed (published version
skipped, unpublished pushed, unknown package id pushed, 404 index pushed, nuspec 2.1.0-RC.3 matching
the feed lowercase 2.1.0-rc.3); nuspec extraction returns id/version from a nuspec fragment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant