Skip to content

[Vsintegration] XDatabase: register the collation before the VACUUM - #2132

Merged
RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
hpetriffer:fix/codemodel-vacuum-collation
Oct 28, 2026
Merged

RobertvanderHulst merged 1 commit into
X-Sharp:devfrom
hpetriffer:fix/codemodel-vacuum-collation

Conversation

@hpetriffer

Copy link
Copy Markdown
Contributor

Fixes SQLite Error 11: 'database disk image is malformed' in the code model when the Microsoft.Data.Sqlite engine is used. That engine is used on ARM, or on x64 when "Use the Microsoft.Data.SQLite engine for the intellisense database" is set under Intellisense.

Cause

XDatabase.SetPragmas ran VACUUM before SetCollation().

  • VACUUM rebuilds every index with the collation that is registered on the connection at that moment. The schema only stores the name NOCASE.
  • With Microsoft.Data.Sqlite, SetCollationMicrosoft replaces NOCASE with String.Compare(x, y, ignoreCase: true). That comparison depends on the culture and sorts \, digits, $, _ and umlauts differently from SQLite's built-in NOCASE.
  • Every load of an existing database (OpenFile for ValidateSchema and again for the restore) therefore rebuilt the indexes with the built-in NOCASE. The session then searched, inserted and deleted with the custom one.
  • Effect: index lookups missed rows, unique checks let duplicates in, and deletes failed with SQLITE_CORRUPT. In RadixWfSDK.slnx this produced 19 and 36 errors per load, from DeleteOrphanFiles, DeleteFile, UpdateFileContents, Update(XAssembly) and DeleteProjectsNotInSession.

System.Data.SQLite registers no custom collation and is not affected.

Fix

SetCollation() now runs before the VACUUM. The VACUUM at open stays: with the right order it also re-sorts a file that was written with the other engine.

Test

VS 2022 experimental instance, RadixWfSDK.slnx:

  1. New database, written with System.Data.SQLite. Checked against the custom NOCASE, this file has rows missing from ReferencedGlobals_Name. This is the state that produced the errors before the fix.
  2. The same database loaded with Microsoft.Data.Sqlite: 0 [ERR], 0 × Error 11. The file written at close passes PRAGMA integrity_check with the custom NOCASE and has no duplicate project or file rows.

Not changed

  • CurrentDbVersion is unchanged, so files that already contain duplicates are not rebuilt automatically.
  • With the solution on the devenv command line, the code model database is created before the language package has read EditorSettings.json. That run then uses System.Data.SQLite whatever the option says.

🤖 Generated with Claude Code

…he VACUUM

The VACUUM rebuilds the NOCASE indexes with the collation that is registered on
the connection at that moment. SetCollation() ran after the VACUUM, so with
Microsoft.Data.Sqlite every load of an existing code model database rebuilt the
indexes with SQLite's built-in NOCASE, while the session then searched and
inserted with the custom (culture aware) NOCASE. The two orders differ for
'\' vs digits, '$', '_' and umlauts: lookups missed rows, unique checks let
duplicates in and deletes failed with "database disk image is malformed".

With the collation registered first the VACUUM at open also re-sorts files that
were written with the other SQLite provider. System.Data.SQLite registers no
custom collation and is not affected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RobertvanderHulst

Copy link
Copy Markdown
Member

Thanks. I think I will also add a property to the database to indicate with which version it was created (like the database version). When I detect that the database was created with the other providers then it should be recreated.

Robert

@RobertvanderHulst
RobertvanderHulst merged commit 64916f6 into X-Sharp:dev Oct 28, 2026
1 check passed
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.

2 participants