From 4e4619514ce42cd9d4592f3b85fbd2e74ea6af43 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 5 Aug 2026 07:55:12 -0400 Subject: [PATCH] docs(sql): chrome/AdminUI gate PASSED; records the Test-Connect provider-gate defect it found Also adds the two fixture connection strings to both docker-dev centrals, so the rig can author + browse the Postgres and Oracle fixtures on 10.100.0.35. --- docker-dev/docker-compose.yml | 10 +++++ .../2026-08-05-sql-postgres-oracle-design.md | 38 +++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/docker-dev/docker-compose.yml b/docker-dev/docker-compose.yml index d24e64a6..d0f9f89b 100644 --- a/docker-dev/docker-compose.yml +++ b/docker-dev/docker-compose.yml @@ -286,6 +286,12 @@ services: # the rig's own `sql` container, a SEPARATE `DevSql` database seeded with dbo.TagValues (KeyValue) # + dbo.LatestStatus (WideRow). Committed-dev-secret exception, same as ConfigDb above. Sql__ConnectionStrings__DevSql: "Server=sql,1433;Database=DevSql;User Id=sa;Password=OtOpcUa!Dev123;TrustServerCertificate=True;" + # The Postgres + Oracle counterparts, pointing at the two DISPOSABLE fixture containers on the + # shared docker host (tests/.../Driver.Sql.IntegrationTests/Docker/{postgres,oracle}/). Same + # committed-dev-secret exception; the passwords are each fixture compose's documented default. + # Unlike DevSql these are NOT on the rig's own network, so they carry the host's IP. + Sql__ConnectionStrings__FixturePg: "Host=10.100.0.35;Port=15432;Database=sqlpollfixture;Username=otopcua;Password=OtOpcUaPg2026x" + Sql__ConnectionStrings__FixtureOracle: "User Id=otopcua;Password=OtOpcUaOra2026x;Data Source=10.100.0.35:11521/FREEPDB1" Cluster__Hostname: "0.0.0.0" Cluster__Port: "4053" Cluster__PublicHostname: "central-1" @@ -426,6 +432,10 @@ services: # the rig's own `sql` container, a SEPARATE `DevSql` database seeded with dbo.TagValues (KeyValue) # + dbo.LatestStatus (WideRow). Committed-dev-secret exception, same as ConfigDb above. Sql__ConnectionStrings__DevSql: "Server=sql,1433;Database=DevSql;User Id=sa;Password=OtOpcUa!Dev123;TrustServerCertificate=True;" + # Postgres + Oracle fixture connection strings — see central-1. Both centrals must carry them: + # :9200 round-robins, so the AdminUI browse can land on either node. + Sql__ConnectionStrings__FixturePg: "Host=10.100.0.35;Port=15432;Database=sqlpollfixture;Username=otopcua;Password=OtOpcUaPg2026x" + Sql__ConnectionStrings__FixtureOracle: "User Id=otopcua;Password=OtOpcUaOra2026x;Data Source=10.100.0.35:11521/FREEPDB1" Cluster__Hostname: "0.0.0.0" Cluster__Port: "4053" Cluster__PublicHostname: "central-2" diff --git a/docs/plans/2026-08-05-sql-postgres-oracle-design.md b/docs/plans/2026-08-05-sql-postgres-oracle-design.md index 476236ab..ef97fc22 100644 --- a/docs/plans/2026-08-05-sql-postgres-oracle-design.md +++ b/docs/plans/2026-08-05-sql-postgres-oracle-design.md @@ -17,9 +17,41 @@ WideRow `topByTimestamp`, catalog case-folding, browse walk). Env recipe used: `SQL_ORACLE_ENDPOINT=10.100.0.35:11521 SQL_ORACLE_USER=otopcua SQL_ORACLE_PASSWORD=` (service defaults `FREEPDB1`). -**§4.3's chrome/AdminUI gate remains with the operator** — provider dropdown authoring, -Test-connect, `/raw` browse + browse-commit against both fixtures at `http://localhost:9200`. The -docker-dev rig must be rebuilt from a master image at/after `d54f3c83` first. +**§4.3's chrome/AdminUI gate PASSED (2026-08-05) — and it found a real defect.** Run against a +docker-dev rig rebuilt from master (both centrals on one image, provider assemblies confirmed +present in `/app`) with `Sql__ConnectionStrings__FixturePg` / `__FixtureOracle` added to central-1 +**and** central-2 (`:9200` round-robins, so a browse can land on either node). + +⚠️ **The gate's first finding: Test Connect was broken for BOTH new providers.** +`SqlDriverProbe.DefaultDialectFor` was never widened — it still constructed `SqlServerDialect` +only and threw `InvalidOperationException` for Postgres/Oracle, so a config that **deployed and +browsed fine failed Test Connect**. There are *three* dialect-selection sites and Task 4's `Files:` +block named two (`SqlDriverFactoryExtensions`, `SqlDriverBrowser`) plus the enum. No test caught +it because **every case in `SqlDriverProbeTests` builds its probe through `ForTest(...)`**, which +injects `_ => dialect` and never reaches the production switch — the parameterless constructor had +zero coverage. Fixed in `75a057f2`: switch widened arm-for-arm with the factory, plus an internal +seam covering the gate directly, a reserved-provider (MySql/Odbc) falsification control, and an +end-to-end production-constructor case. Red-first confirmed (3 failures) before the widening; +Driver.Sql.Tests then 361/361. + +Legs, after the fix: + +1. **Provider dropdown authoring ✅** — dropdown offers SqlServer/Postgres/Oracle; both saved and + persisted as `{"provider":"Postgres",…}` / `{"provider":"Oracle",…}`, i.e. serialized by **name**, + not ordinal (the driver-enum-serialization defect class does not recur here). +2. **Test-connect ✅** — Postgres `OK · 174 ms`, Oracle `OK · 386 ms`. **Negative control:** the + Oracle driver cross-wired to the Postgres connection string returns + `FAILED · … (ARGUMENTEXCEPTION)` — the provider itself rejecting the string, and *not* + `InvalidOperationException`, which proves the dialect was constructed and the green came from a + real round trip rather than an unconditional OK. +3. **`/raw` browse + browse-commit ✅** — Postgres browse discovered schema `sqlpoll` → `tag_values` + / `latest_status` → per-column LEAFs; **the schema is owned by `sqlpoll_owner` while the poller + connects as `otopcua`**, so this is the live confirmation that `PostgresDialect.ListSchemasSql` + sources from `information_schema.tables` rather than `.schemata`. Oracle browse listed the PDB's + schemas → `OTOPCUA` → `TAG_VALUES`/`LATEST_STATUS` → LEAFs. One leaf committed per provider, + both persisting schema-qualified with the right type: + `{"model":"WideRow","table":"sqlpoll.tag_values","columnName":"num_value"}` [Double] and + `{"model":"WideRow","table":"OTOPCUA.TAG_VALUES","columnName":"NUM_VALUE"}` [Double]. ## 1. Problem