feat(sql): Odbc provider — ANSI SQL:2008 profile over System.Data.Odbc (lmxopcua#753)
SqlProvider.Odbc is now constructed; every enum member is a working backend. - OdbcDialect: System.Data.Odbc 10.0.14 (no vulnerable packages), ANSI double- quote quoting, positional `?` markers, INFORMATION_SCHEMA catalog (system schemas of the common backends excluded by name — the live gate caught psqlODBC listing pg_catalog), FETCH FIRST n ROWS ONLY limits, a conservative 1000-parameter chunk. Positional binding is safe because every caller adds parameters in marker order (planner IN list, catalog schema-then-table). - Named queries on a positional provider are checked by `?` count against the declared params (literals/comments ignored), since there is no name to match. - Supported backends are those whose SQL accepts that profile (PostgreSQL via psqlODBC proven, Snowflake-like); SQL Server/MySQL/DB2 should use their native provider. The host needs the ODBC driver manager + vendor driver. - Reserved-provider controls in factory/probe/browser tests now use an undeclared ordinal (99); the AdminUI form offers Odbc and a test pins the dropdown theory to SqlDialects.Supported. - Tests: OdbcDialectTests (unit, any host). OdbcReadTests + Docker/odbc/ run-odbc-gate.sh run the built suite in a throwaway Linux SDK container with unixODBC + psqlODBC against a throwaway seeded PostgreSQL: KV IN-list positional binding, where-pair, topByTimestamp via FETCH FIRST, a two- parameter named query, and the browse walk. macOS has no vendor ODBC driver, so there the suite skips. (lmxopcua#753) Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -102,6 +102,7 @@ public sealed class SqlDriverFormContractTests
|
||||
[InlineData(SqlProvider.Postgres, "Postgres")]
|
||||
[InlineData(SqlProvider.Oracle, "Oracle")]
|
||||
[InlineData(SqlProvider.MySql, "MySql")]
|
||||
[InlineData(SqlProvider.Odbc, "Odbc")]
|
||||
public void Every_dropdown_provider_round_trips_through_the_form_model(SqlProvider provider, string name)
|
||||
{
|
||||
var form = new SqlDriverForm.FormModel { Provider = provider, ConnectionStringRef = "MesStaging" };
|
||||
@@ -117,18 +118,16 @@ public sealed class SqlDriverFormContractTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Odbc stays reserved-and-rejected in this build, so the dropdown deliberately does not offer it. Nothing in the form model blocks the value — this records the intent so a later "the enum has
|
||||
/// five members, the dropdown should too" edit has to argue with a test.
|
||||
/// The dropdown offers every provider the build constructs (lmxopcua#753 made all five enum members real),
|
||||
/// so the form-model theory above must cover exactly <see cref="SqlDialects.Supported"/> — a provider added
|
||||
/// to the map without a dropdown option (or the reverse) has to argue with this test.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData(SqlProvider.Odbc)]
|
||||
public void Reserved_providers_are_not_offered_but_still_serialize_by_name(SqlProvider reserved)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(
|
||||
new SqlDriverForm.FormModel { Provider = reserved, ConnectionStringRef = "R" }.ToDto(), FormOptions);
|
||||
[Fact]
|
||||
public void Every_constructed_provider_is_covered_by_the_dropdown_theory()
|
||||
=> SqlDialects.Supported.ShouldBe(
|
||||
[SqlProvider.SqlServer, SqlProvider.Postgres, SqlProvider.MySql, SqlProvider.Odbc, SqlProvider.Oracle],
|
||||
ignoreOrder: true);
|
||||
|
||||
json.ShouldContain($"\"provider\":\"{reserved}\"");
|
||||
}
|
||||
// ---- named queries (lmxopcua#753): the form refuses exactly what the factory refuses ----
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user