diff --git a/Directory.Build.props b/Directory.Build.props
index d0caaa21ff..832f672a72 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -9,6 +9,13 @@
true
$(MSBuildThisFileDirectory)
+
+ bin\sts2-sqlite\
+ obj\sts2-sqlite\
+ $(DefaultItemExcludes);bin\**;obj\**
+
net10.0
net8.0
diff --git a/docs/sts2/CLIENT.md b/docs/sts2/CLIENT.md
index 9cede78ce6..3a89707885 100644
--- a/docs/sts2/CLIENT.md
+++ b/docs/sts2/CLIENT.md
@@ -29,6 +29,10 @@ table and `docs/sts2/TRACE-SCHEMA.md` for the envelope/trace format.
This is a copy-pasteable reference; it is documented rather than run in CI (no Node
toolchain is assumed in this repo). The wire shapes match `docs/sts2/CONTRACT.md`.
+The sample uses the non-production SQLite test driver. Production/default publishes
+contain only the SQL Client driver; build locally with
+`-p:IncludeSts2SqliteDriver=true` to make the `sqlite` driver available.
+
```typescript
import { spawn } from "node:child_process";
import {
diff --git a/docs/sts2/COMPONENTS.md b/docs/sts2/COMPONENTS.md
index 6ee62a4ada..1fac2e88dc 100644
--- a/docs/sts2/COMPONENTS.md
+++ b/docs/sts2/COMPONENTS.md
@@ -1,7 +1,7 @@
# STS2 Components
-Roles come from each project's COMPONENT.md; references are read from the csproj files on disk. The allowed matrix is SPEC §4; DependencyMatrixTests enforces it (I11).
+Roles come from each project's COMPONENT.md; references are read from the csproj files on disk. Conditional references include their MSBuild condition. The allowed matrix is SPEC §4; DependencyMatrixTests enforces it (I11).
## Microsoft.SqlTools.Sts2.Abstractions
@@ -14,7 +14,7 @@ Driver port (IDbDriver/IDbSession), clock and id abstractions.
Composition root invoked by legacy Program.cs; owns --enable-sts2 / STS_ENABLE_STS2 activation and process wiring.
-- Project references: Microsoft.SqlTools.Sts2.Contracts, Microsoft.SqlTools.Sts2.Drivers.SqlClient, Microsoft.SqlTools.Sts2.Drivers.Sqlite, Microsoft.SqlTools.Sts2.Hosting, Microsoft.SqlTools.Sts2.Multiplexer, Microsoft.SqlTools.Sts2.Runtime
+- Project references: Microsoft.SqlTools.Sts2.Contracts, Microsoft.SqlTools.Sts2.Drivers.SqlClient, Microsoft.SqlTools.Sts2.Drivers.Sqlite (condition: `'$(IncludeSts2SqliteDriver)' == 'true'`), Microsoft.SqlTools.Sts2.Hosting, Microsoft.SqlTools.Sts2.Multiplexer, Microsoft.SqlTools.Sts2.Runtime
- Package references: none (BCL only)
## Microsoft.SqlTools.Sts2.Contracts
@@ -40,7 +40,7 @@ Production driver adapter over Microsoft.Data.SqlClient.
## Microsoft.SqlTools.Sts2.Drivers.Sqlite
-Portable real-I/O driver adapter over Microsoft.Data.Sqlite.
+Non-production real-I/O test driver adapter over Microsoft.Data.Sqlite.
- Project references: Microsoft.SqlTools.Sts2.Abstractions, Microsoft.SqlTools.Sts2.Contracts
- Package references: Microsoft.Data.Sqlite, SQLitePCLRaw.lib.e_sqlite3
diff --git a/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/COMPONENT.md b/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/COMPONENT.md
index eac3ec1230..7c0da69507 100644
--- a/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/COMPONENT.md
+++ b/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/COMPONENT.md
@@ -2,8 +2,10 @@
**Role:** Composition root invoked by legacy Program.cs; owns --enable-sts2 / STS_ENABLE_STS2 activation and process wiring.
-**Allowed dependencies:** Hosting, Runtime, Multiplexer, Drivers.SqlClient, Drivers.Sqlite, Contracts
+**Allowed dependencies:** Hosting, Runtime, Multiplexer, Drivers.SqlClient, Contracts; Drivers.Sqlite only when `IncludeSts2SqliteDriver=true`
**Forbidden:** legacy namespaces
See docs/sts2/SPEC.md SS4 for the authoritative dependency matrix.
+
+The default and production publish graph excludes Drivers.Sqlite. Local and E2E builds may opt in with `-p:IncludeSts2SqliteDriver=true`.
diff --git a/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/Microsoft.SqlTools.Sts2.Bootstrap.csproj b/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/Microsoft.SqlTools.Sts2.Bootstrap.csproj
index 8c9204b926..71477a17fa 100644
--- a/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/Microsoft.SqlTools.Sts2.Bootstrap.csproj
+++ b/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/Microsoft.SqlTools.Sts2.Bootstrap.csproj
@@ -1,13 +1,18 @@
STS2 composition root called by legacy Program.cs. Owns activation flags and process-level wiring.
+
+ false
+ $(DefineConstants);STS2_INCLUDE_SQLITE_DRIVER
-
+
diff --git a/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/Sts2Bootstrap.cs b/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/Sts2Bootstrap.cs
index 4b63cf9ed6..19bba7f47d 100644
--- a/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/Sts2Bootstrap.cs
+++ b/src/sts2/Microsoft.SqlTools.Sts2.Bootstrap/Sts2Bootstrap.cs
@@ -10,7 +10,9 @@
using System.Text;
using System.Threading.Tasks;
using Microsoft.SqlTools.Sts2.Abstractions;
+#if STS2_INCLUDE_SQLITE_DRIVER
using Microsoft.SqlTools.Sts2.Drivers.Sqlite;
+#endif
using Microsoft.SqlTools.Sts2.Hosting;
using Microsoft.SqlTools.Sts2.Multiplexer;
@@ -118,11 +120,7 @@ public static Sts2BootstrapHandle TryStart(string[] args, string? logFilePath)
// never conflate this run with an earlier one in the shared log directory.
JournalDirectory = Path.Combine(logDirectory, "sts2", runId),
ServiceVersion = typeof(Sts2Bootstrap).Assembly.GetName().Version?.ToString() ?? "0.0.0.0",
- Drivers = new Dictionary
- {
- ["sqlclient"] = new Drivers.SqlClient.SqlClientDriver(), // production (M5)
- ["sqlite"] = new SqliteDriver(), // portable (M4)
- },
+ Drivers = CreateDrivers(),
CommandLine = SanitizeCommandLine(args),
},
multiplexer.Sts2OutputWriter,
@@ -138,6 +136,20 @@ public static Sts2BootstrapHandle TryStart(string[] args, string? logFilePath)
return new Sts2BootstrapHandle(multiplexer.LegacyInput, multiplexer.LegacyOutput, multiplexer, session, diagnosticsLog);
}
+ private static Dictionary CreateDrivers()
+ {
+ var drivers = new Dictionary
+ {
+ ["sqlclient"] = new Drivers.SqlClient.SqlClientDriver(), // production (M5)
+ };
+#if STS2_INCLUDE_SQLITE_DRIVER
+ // Non-production real-I/O test driver. The conditional project reference
+ // keeps Microsoft.Data.Sqlite and every native SQLite RID out of release builds.
+ drivers["sqlite"] = new SqliteDriver();
+#endif
+ return drivers;
+ }
+
///
/// Records the command line for the journal manifest by SHAPE, not by blocklist
/// (R033): flag NAMES are kept verbatim (they aren't secret and are useful forensics),
diff --git a/src/sts2/Microsoft.SqlTools.Sts2.Drivers.Sqlite/COMPONENT.md b/src/sts2/Microsoft.SqlTools.Sts2.Drivers.Sqlite/COMPONENT.md
index f5b1826d9d..b5ab8fe305 100644
--- a/src/sts2/Microsoft.SqlTools.Sts2.Drivers.Sqlite/COMPONENT.md
+++ b/src/sts2/Microsoft.SqlTools.Sts2.Drivers.Sqlite/COMPONENT.md
@@ -1,9 +1,11 @@
# Microsoft.SqlTools.Sts2.Drivers.Sqlite
-**Role:** Portable real-I/O driver adapter over Microsoft.Data.Sqlite.
+**Role:** Non-production real-I/O test driver adapter over Microsoft.Data.Sqlite.
**Allowed dependencies:** Abstractions, Contracts, Microsoft.Data.Sqlite, SQLitePCLRaw.lib.e_sqlite3
**Forbidden:** Core, Runtime, Hosting, legacy namespaces
The enforced dependency matrix is in [DependencyMatrixTests](../../../test/sts2/Microsoft.SqlTools.Sts2.UnitTests/Architecture/DependencyMatrixTests.cs) (I11); see the generated [component graph](../../../docs/sts2/COMPONENTS.md) for the references on disk.
+
+This project is tested directly. It enters the ServiceLayer graph only when a local or test build sets `IncludeSts2SqliteDriver=true`.
diff --git a/src/sts2/Microsoft.SqlTools.Sts2.Drivers.Sqlite/Microsoft.SqlTools.Sts2.Drivers.Sqlite.csproj b/src/sts2/Microsoft.SqlTools.Sts2.Drivers.Sqlite/Microsoft.SqlTools.Sts2.Drivers.Sqlite.csproj
index 6f159de3cf..75910e2667 100644
--- a/src/sts2/Microsoft.SqlTools.Sts2.Drivers.Sqlite/Microsoft.SqlTools.Sts2.Drivers.Sqlite.csproj
+++ b/src/sts2/Microsoft.SqlTools.Sts2.Drivers.Sqlite/Microsoft.SqlTools.Sts2.Drivers.Sqlite.csproj
@@ -1,6 +1,6 @@
- STS2 portable real-I/O driver adapter over Microsoft.Data.Sqlite. Quick-CI honesty check for the port.
+ STS2 non-production real-I/O test driver over Microsoft.Data.Sqlite. Quick-CI honesty check for the port.
@@ -8,7 +8,7 @@
+ every opted-in consumer and the direct test references. Version in Packages.props. -->
diff --git a/src/sts2/Microsoft.SqlTools.Sts2.Testing/GeneratedDocs.cs b/src/sts2/Microsoft.SqlTools.Sts2.Testing/GeneratedDocs.cs
index d0d7e7fc60..6159a131e8 100644
--- a/src/sts2/Microsoft.SqlTools.Sts2.Testing/GeneratedDocs.cs
+++ b/src/sts2/Microsoft.SqlTools.Sts2.Testing/GeneratedDocs.cs
@@ -230,7 +230,7 @@ public static string Components(string sts2SourceDir)
{
var sb = new StringBuilder(Header);
sb.Append("# STS2 Components\n\n");
- sb.Append("Roles come from each project's COMPONENT.md; references are read from the csproj files on disk. The allowed matrix is SPEC §4; DependencyMatrixTests enforces it (I11).\n\n");
+ sb.Append("Roles come from each project's COMPONENT.md; references are read from the csproj files on disk. Conditional references include their MSBuild condition. The allowed matrix is SPEC §4; DependencyMatrixTests enforces it (I11).\n\n");
foreach (string projectDir in Directory.EnumerateDirectories(sts2SourceDir).Order(StringComparer.Ordinal))
{
@@ -252,7 +252,14 @@ public static string Components(string sts2SourceDir)
XDocument csproj = XDocument.Load(csprojPath);
string[] projectRefs = csproj.Descendants("ProjectReference")
- .Select(r => Path.GetFileNameWithoutExtension(r.Attribute("Include")!.Value.Replace('\\', '/')))
+ .Select(r =>
+ {
+ string name = Path.GetFileNameWithoutExtension(r.Attribute("Include")!.Value.Replace('\\', '/'));
+ string? condition = r.Attribute("Condition")?.Value;
+ return string.IsNullOrWhiteSpace(condition)
+ ? name
+ : $"{name} (condition: `{condition}`)";
+ })
.Order(StringComparer.Ordinal).ToArray();
string[] packageRefs = csproj.Descendants("PackageReference")
.Select(r => (r.Attribute("Include") ?? r.Attribute("Update"))!.Value)
diff --git a/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/Microsoft.SqlTools.Sts2.E2ETests.csproj b/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/Microsoft.SqlTools.Sts2.E2ETests.csproj
index a0b9bfd28d..af34cf3df6 100644
--- a/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/Microsoft.SqlTools.Sts2.E2ETests.csproj
+++ b/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/Microsoft.SqlTools.Sts2.E2ETests.csproj
@@ -10,10 +10,31 @@
+
+
+ $(MSBuildThisFileDirectory)..\..\..\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj
+ Configuration=$(Configuration);IncludeSts2SqliteDriver=true;Sts2IsolatedSqliteBuild=true
+
-
-
+
+
+
+
+
diff --git a/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/ServiceProcessClient.cs b/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/ServiceProcessClient.cs
index 8418e745a4..f118e534ff 100644
--- a/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/ServiceProcessClient.cs
+++ b/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/ServiceProcessClient.cs
@@ -45,7 +45,7 @@ private ServiceProcessClient(Process process)
/// Queue of notifications received from the service, by method name.
public ConcurrentQueue<(string Method, JsonElement Params)> Notifications { get; } = new();
- public static string LocateServiceDll()
+ public static string LocateServiceDll(bool includeSqlite = false)
{
string? dir = AppContext.BaseDirectory;
while (dir != null && !File.Exists(Path.Combine(dir, "sqltoolsservice.sln")))
@@ -60,11 +60,17 @@ public static string LocateServiceDll()
DirectoryInfo testOutputDirectory = new(AppContext.BaseDirectory);
string currentTfm = testOutputDirectory.Name;
string currentConfiguration = testOutputDirectory.Parent?.Name ?? "Debug";
- string candidate = Path.Combine(
+ string serviceOutputRoot = Path.Combine(
dir,
"src",
"Microsoft.SqlTools.ServiceLayer",
- "bin",
+ "bin");
+ if (includeSqlite)
+ {
+ serviceOutputRoot = Path.Combine(serviceOutputRoot, "sts2-sqlite");
+ }
+ string candidate = Path.Combine(
+ serviceOutputRoot,
currentConfiguration,
currentTfm,
"MicrosoftSqlToolsServiceLayer.dll");
@@ -77,10 +83,10 @@ public static string LocateServiceDll()
". The E2E project reference must build ServiceLayer for the current configuration and TFM.");
}
- public static ServiceProcessClient Start(bool enableSts2, string logDirectory)
+ public static ServiceProcessClient Start(bool enableSts2, string logDirectory, bool includeSqlite = false)
{
Directory.CreateDirectory(logDirectory);
- string args = "\"" + LocateServiceDll() + "\" --log-file \"" + Path.Combine(logDirectory, "sqltools.log") + "\"";
+ string args = "\"" + LocateServiceDll(includeSqlite) + "\" --log-file \"" + Path.Combine(logDirectory, "sqltools.log") + "\"";
if (enableSts2)
{
args += " --enable-sts2";
diff --git a/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/StdioE2ETests.cs b/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/StdioE2ETests.cs
index e753b27805..9e4d07ca51 100644
--- a/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/StdioE2ETests.cs
+++ b/test/sts2/Microsoft.SqlTools.Sts2.E2ETests/StdioE2ETests.cs
@@ -56,6 +56,13 @@ public void SpawnedSubjectMatchesCurrentTestBuild()
Assert.True(File.Exists(serviceDll));
}
+ [Fact]
+ public void DefaultSubjectExcludesSqliteAssets()
+ {
+ string serviceDirectory = Path.GetDirectoryName(ServiceProcessClient.LocateServiceDll())!;
+ Assert.Empty(Directory.EnumerateFiles(serviceDirectory, "*sqlite*", SearchOption.AllDirectories));
+ }
+
[Fact]
public async Task DisabledMode_V1VersionWorks_AndNoSts2ArtifactsAreCreated()
{
@@ -119,7 +126,10 @@ public async Task EnabledMode_InitializeWorksAndJournalIsWritten()
[Fact]
public async Task EnabledMode_SqliteQueryExercisesPagedLifecycleOverRealStdio()
{
- await using var client = ServiceProcessClient.Start(enableSts2: true, logDirectory: logDirectory);
+ await using var client = ServiceProcessClient.Start(
+ enableSts2: true,
+ logDirectory: logDirectory,
+ includeSqlite: true);
await client.RequestAsync("v2/initialize", new { clientName = "e2e" }, TestTimeout);
JsonElement open = await client.RequestAsync("v2/connection.open",
diff --git a/test/sts2/Microsoft.SqlTools.Sts2.UnitTests/Architecture/DependencyMatrixTests.cs b/test/sts2/Microsoft.SqlTools.Sts2.UnitTests/Architecture/DependencyMatrixTests.cs
index 226fdefe74..4b453b1c9c 100644
--- a/test/sts2/Microsoft.SqlTools.Sts2.UnitTests/Architecture/DependencyMatrixTests.cs
+++ b/test/sts2/Microsoft.SqlTools.Sts2.UnitTests/Architecture/DependencyMatrixTests.cs
@@ -97,6 +97,31 @@ public void AllMatrixProjectsExistOnDisk()
}
}
+ [Fact]
+ public void SqliteIsOptInAtProductCompositionRoot()
+ {
+ string bootstrapProjectPath = Path.Combine(
+ RepoRoot.Sts2SourceDir,
+ "Microsoft.SqlTools.Sts2.Bootstrap",
+ "Microsoft.SqlTools.Sts2.Bootstrap.csproj");
+ XDocument bootstrapProject = XDocument.Load(bootstrapProjectPath);
+
+ XElement includeProperty = Assert.Single(
+ bootstrapProject.Descendants("IncludeSts2SqliteDriver"));
+ Assert.Equal("false", includeProperty.Value);
+ Assert.Contains("IncludeSts2SqliteDriver", includeProperty.Attribute("Condition")?.Value);
+
+ XElement sqliteReference = Assert.Single(
+ bootstrapProject.Descendants("ProjectReference").Where(reference =>
+ string.Equals(
+ Path.GetFileNameWithoutExtension(reference.Attribute("Include")!.Value.Replace('\\', '/')),
+ "Microsoft.SqlTools.Sts2.Drivers.Sqlite",
+ StringComparison.OrdinalIgnoreCase)));
+ string? condition = sqliteReference.Attribute("Condition")?.Value;
+ Assert.Contains("IncludeSts2SqliteDriver", condition);
+ Assert.Contains("true", condition);
+ }
+
[Fact]
public void Sts2SourcesNeverUseLegacyServiceLayerNamespaces()
{