fix(sqlite,mysql): implement the non-generic Weasel.Core.ICommandBuilder - #424
Merged
Merged
Conversation
…der (weasel#423)
Weasel.Sqlite.CommandBuilder and Weasel.MySql.CommandBuilder derived from
CommandBuilderBase<,,> but never declared the non-generic
Weasel.Core.ICommandBuilder, so nothing targeting the neutral contract could be
handed one.
That contract is what every Weasel.Storage closed-shape operation configures
itself against:
void ConfigureCommand(ICommandBuilder builder, IStorageSession session);
so the practical effect was that no Weasel.Storage document or event operation
could execute against SQLite at all -- there was no way to construct the builder
argument. Found while building Fisher, the SQLite event store, on
Weasel.Storage. Postgresql, SqlServer and Oracle already carry the interface;
Sqlite and MySql were the two outliers left behind by #327.
Four members were missing on each: TenantId, AppendParameters(params object[]),
a DbParameter-returning AppendParameter(object) (the inherited overloads all
return void, so none satisfied the interface), and
CreateGroupedParameterBuilder. Everything else the interface needs was already
inherited.
AppendParameter and AppendParameters are implemented explicitly, following
Weasel.Oracle rather than Weasel.SqlServer: the base class already exposes
void-returning AppendParameter overloads, and a public member here would hide
them and silently change which overload existing call sites bind to.
StartNewCommand is deliberately not overridden. The base is already a no-op,
which is correct for both providers, so an override would be pure noise that
implies a difference that does not exist.
Adds a contract test to each provider's suite so the set cannot drift again.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DLKYzKRqfvk2vS88kfcvqc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #423.
Weasel.Sqlite.CommandBuilderandWeasel.MySql.CommandBuilderderive fromCommandBuilderBase<,,>but never declared the non-genericWeasel.Core.ICommandBuilder, so nothing targeting the neutral contract could be handed one.That contract is what every
Weasel.Storageclosed-shape operation configures itself against:so the practical effect was that no Weasel.Storage document or event operation could execute against SQLite at all — there was no way to construct the builder argument. Found while building Fisher on Weasel.Storage.
Postgresql, SqlServer and Oracle already carry the interface; Sqlite and MySql were the two left behind by #327. Only SQLite was blocking a consumer today, but MySql had the identical gap and would hit it the moment a Weasel.Storage consumer targeted it, so both are fixed here.
Missing members
Four on each provider — everything else the interface needs was already inherited from
CommandBuilderBase:string TenantId { get; set; }void AppendParameters(params object[])DbParameter AppendParameter(object)void, so none satisfied the interfaceIGroupedParameterBuilder CreateGroupedParameterBuilder(char?)Two deliberate choices
AppendParameter/AppendParametersare implemented explicitly, followingWeasel.Oraclerather thanWeasel.SqlServer. The base class already exposes void-returningAppendParameteroverloads; a public member would hide them and silently change which overload existing call sites bind to. Explicit implementation adds the interface without touching the public surface, so this is additive for existing users.StartNewCommandis not overridden.Weasel.SqlServeroverrides it to a no-op, but the base is already a no-op ("multi-statement providers just keep appending"), which is correct for both of these —Microsoft.Data.Sqliteand MySqlConnector both execute several semicolon-separated statements from one command. An override would be noise implying a difference that does not exist.Tests
A contract test per provider covering the interface itself plus each of the four members, so the set cannot drift again:
src/Weasel.Sqlite.Tests/CommandBuilderTests.cs—CommandBuilderNeutralContractTestssrc/Weasel.MySql.Tests/CommandBuilderNeutralContractTests.csBoth are pure type/behaviour tests needing no database server.
Verification
Weasel.slnxbuilds clean.Weasel.Sqlite.Tests: 393 passed, 0 failed, on net9.0 and net10.0.Weasel.MySql.TestsCommandBuilderNeutralContractTests: 6 passed (the rest of that suite needs a MySQL server and was not run).Fisher currently carries a local
FisherCommandBuildershim and will delete it once this ships.