-- Seed for the Sql driver's Oracle live gate (OracleReadTests), applied once by the compose -- `oracle-seed` one-shot AS THE APPLICATION USER (otopcua) against the OWNED `otopcua-sql-oracle` -- container. Oracle equates a schema with a user, so everything below lands in the OTOPCUA schema. -- -- The table shapes mirror the SQL Server fixture (SqlPollServerFixture) row for row — a present -- value, a present row with a NULL cell, and a wide-row table whose NEWEST row is deliberately not -- its first — so the same assertions can be made against both backends and a divergence between -- the two provider paths shows up as a failing assertion rather than as two suites that quietly -- test different things. -- -- ⚠️ EVERY IDENTIFIER HERE IS UNQUOTED, AND THAT IS THE POINT. Oracle upper-cases an unquoted -- identifier, so the catalog stores OTOPCUA / TAG_VALUES / TAG_NAME while an operator authoring a -- tag in the AdminUI naturally types lower case. The suite's case-folding leg authors the lower-case -- spelling and expects `SqlCatalogGate` to resolve it through `SqlCatalog.TryMatch` (exact-ordinal -- first, then a UNIQUE case-insensitive match) and substitute the catalog's own UPPER-case spelling -- before `OracleDialect.QuoteIdentifier` double-quotes it — which is load-bearing, because a quoted -- "tag_values" and a quoted "TAG_VALUES" are DIFFERENT objects to Oracle. Quoting a name here would -- make that leg meaningless. WHENEVER SQLERROR EXIT SQL.SQLCODE SET FEEDBACK OFF SET DEFINE OFF -- Drop-and-recreate rather than merge-or-insert: the seed is an assertion contract, and a leftover -- row from an older revision of this file would make a passing test meaningless. ORA-00942 (table -- does not exist) is the expected outcome on a first run and is the only error swallowed. BEGIN EXECUTE IMMEDIATE 'DROP TABLE tag_values PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END; / BEGIN EXECUTE IMMEDIATE 'DROP TABLE latest_status PURGE'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END; / -- Key-value (EAV) source: tag_name → num_value, with a source timestamp. -- num_value is NUMBER, Oracle's one numeric family — which OracleDialect.MapColumnType folds to -- Float64 (the documented under-specification; see that method's remarks). CREATE TABLE tag_values ( tag_name VARCHAR2(128) NOT NULL, num_value NUMBER, sample_ts TIMESTAMP(3) NOT NULL ); INSERT INTO tag_values (tag_name, num_value, sample_ts) VALUES ('Line1.Speed', 42, TIMESTAMP '2026-07-24 10:00:00'); INSERT INTO tag_values (tag_name, num_value, sample_ts) VALUES ('Line1.Temp', NULL, TIMESTAMP '2026-07-24 10:00:01'); INSERT INTO tag_values (tag_name, num_value, sample_ts) VALUES ('Line1.Pressure', 3.5, TIMESTAMP '2026-07-24 10:00:02'); -- Wide-row source: one row per station, several value columns. Station 8 is inserted LAST and is -- also the newest sample, while station 7 is first — so a topByTimestamp plan that lost its -- ORDER BY … DESC (or its FETCH FIRST 1 ROWS ONLY) returns a different, wrong value rather than a -- coincidentally right one. CREATE TABLE latest_status ( station_id NUMBER(10) NOT NULL, oven_temp NUMBER, pressure NUMBER, sample_ts TIMESTAMP(3) NOT NULL ); INSERT INTO latest_status (station_id, oven_temp, pressure, sample_ts) VALUES (7, 180.5, 1.2, TIMESTAMP '2026-07-24 10:00:00'); INSERT INTO latest_status (station_id, oven_temp, pressure, sample_ts) VALUES (9, NULL, 1.6, TIMESTAMP '2026-07-24 10:00:01'); INSERT INTO latest_status (station_id, oven_temp, pressure, sample_ts) VALUES (8, 210.25, 1.4, TIMESTAMP '2026-07-24 10:00:02'); COMMIT; EXIT;