|
| 1 | +# CockroachDB Adapter Improvements (Phase 2) |
| 2 | + |
| 3 | +**Issues**: #1972, #1974 |
| 4 | +**Goal**: Fix CockroachDB test failures and remove from SOFT_FAIL_DBS in CI |
| 5 | + |
| 6 | +## Context |
| 7 | + |
| 8 | +CockroachDB is marked as soft-fail in CI (`SOFT_FAIL_DBS="cockroachdb"` in `.github/workflows/tests.yml`). Tests run but failures don't block the build. Current results on Lucee 6: **2217 pass, 31 fail, 38 error** out of 507 suites. |
| 9 | + |
| 10 | +Phase 1 (already merged) established the CockroachDB adapter: `CockroachDBModel.cfc` (type mapping, RETURNING clause identity select) and `CockroachDBMigrator.cfc` (native sqlTypes, unique_rowid() PK generation), plus unit and integration tests. |
| 11 | + |
| 12 | +Phase 2 fixes the remaining test failures so CockroachDB becomes a first-class CI target. |
| 13 | + |
| 14 | +## Root Causes |
| 15 | + |
| 16 | +### 1. Missing CockroachDB in adapter name checks (9 SQL errors + ~20 cascading failures) |
| 17 | + |
| 18 | +The SQL generation layer in `model/update.cfc` and `model/sql.cfc` uses hardcoded adapter name lists like `ListFind('PostgreSQL,H2,Oracle,SQLite', adapterName())`. CockroachDB returns `"CockroachDB"` for `adapterName()` and matches **none** of these branches. |
| 19 | + |
| 20 | +The critical failure: `update.cfc:108` — the `UPDATE table SET` prefix is never generated for CockroachDB, producing SQL like `"authorid" = ` (no table, no SET keyword). This causes 9 direct SQL syntax errors and cascading failures in tests that depend on UPDATE operations. |
| 21 | + |
| 22 | +**Locations to fix** (add `CockroachDB` alongside `PostgreSQL`): |
| 23 | + |
| 24 | +| File | Line | Current List | |
| 25 | +|------|------|-------------| |
| 26 | +| `vendor/wheels/model/update.cfc` | 108 | `PostgreSQL,H2,Oracle,SQLite` | |
| 27 | +| `vendor/wheels/model/sql.cfc` | 653 | `PostgreSQL,H2,MicrosoftSQLServer,Oracle,SQLite` | |
| 28 | +| `vendor/wheels/model/sql.cfc` | 664 | `PostgreSQL` | |
| 29 | +| `vendor/wheels/model/sql.cfc` | 701 | `PostgreSQL,H2` | |
| 30 | + |
| 31 | +### 2. unique_rowid() generates large INT8 IDs (3-5 test failures) |
| 32 | + |
| 33 | +CockroachDB's SERIAL uses `unique_rowid()` producing large non-sequential INT8 values (e.g., `1161774559250219009`). Core tests that hardcode `Expected [1]` or `Expected [5]` fail. |
| 34 | + |
| 35 | +Affected tests: |
| 36 | +- `readSpec > findfirst > works` — expects id=1 |
| 37 | +- `readSpec > findLastOne > works` — expects id=5 |
| 38 | +- `crudSpec > order > is working with maxrows and calculated property` — ID in expected string |
| 39 | +- `sqlSpec > works with numeric operators` — expects cf_sql_integer (gets cf_sql_bigint) |
| 40 | +- `migrationSpec > is changing column` — expects limit 50 (gets 2147483647) |
| 41 | + |
| 42 | +### 3. Transaction behavior differences (12 failures in transactionsSpec) |
| 43 | + |
| 44 | +CockroachDB uses SERIALIZABLE isolation by default and has different SAVEPOINT semantics. Several transaction tests assume READ COMMITTED behavior or specific savepoint rollback mechanics. |
| 45 | + |
| 46 | +## Design |
| 47 | + |
| 48 | +### Part 1: Fix adapter name checks |
| 49 | + |
| 50 | +Mechanical change: add `CockroachDB` to each `ListFind()` call that currently includes `PostgreSQL` in `update.cfc` and `sql.cfc`. CockroachDB uses the PostgreSQL wire protocol and should receive identical SQL generation treatment. |
| 51 | + |
| 52 | +### Part 2: Adapter-specific test suites |
| 53 | + |
| 54 | +**Strategy**: Guard core tests that have CockroachDB-incompatible assumptions, then provide equivalent coverage through CockroachDB-specific test specs. |
| 55 | + |
| 56 | +**Guard pattern** (in core spec files): |
| 57 | +```cfm |
| 58 | +it("expects sequential IDs", () => { |
| 59 | + if ($isCockroachDB()) return; // covered by CockroachDBCrudSpec |
| 60 | + // ... test with hardcoded IDs |
| 61 | +}); |
| 62 | +``` |
| 63 | + |
| 64 | +The `$isCockroachDB()` helper checks the current adapter name. This is the pattern already used in `CockroachDBIntegrationSpec.cfc`. |
| 65 | + |
| 66 | +**New test files** (in `vendor/wheels/tests/specs/database/`): |
| 67 | + |
| 68 | +1. **CockroachDBCrudSpec.cfc** — CRUD lifecycle with non-sequential ID assertions: |
| 69 | + - Create returns numeric key > 0 |
| 70 | + - Sequential creates produce unique increasing keys |
| 71 | + - findFirst/findLast work without assuming specific ID values |
| 72 | + - findAll with maxrows works with large IDs |
| 73 | + |
| 74 | +2. **CockroachDBTransactionSpec.cfc** — Transaction behavior under SERIALIZABLE isolation: |
| 75 | + - Basic transaction commit/rollback |
| 76 | + - invokeWithTransaction callback behavior |
| 77 | + - Nested transaction semantics |
| 78 | + - deleteAll/updateAll within transactions |
| 79 | + |
| 80 | +3. **CockroachDBTypeSpec.cfc** — Type introspection for CockroachDB-specific types: |
| 81 | + - SERIAL columns report as cf_sql_bigint (INT8) |
| 82 | + - STRING type maps correctly |
| 83 | + - Column metadata returns expected limits |
| 84 | + |
| 85 | +### Part 3: Remove from SOFT_FAIL_DBS |
| 86 | + |
| 87 | +After all fixes verified locally on Lucee 6 + Adobe 2025: |
| 88 | +- Remove `cockroachdb` from `SOFT_FAIL_DBS` on lines 390 and 520 of `.github/workflows/tests.yml` |
| 89 | + |
| 90 | +## Files to modify |
| 91 | + |
| 92 | +| File | Change | |
| 93 | +|------|--------| |
| 94 | +| `vendor/wheels/model/update.cfc` | Add CockroachDB to adapter name list (line 108) | |
| 95 | +| `vendor/wheels/model/sql.cfc` | Add CockroachDB to adapter name lists (lines 653, 664, 701) | |
| 96 | +| `vendor/wheels/tests/specs/model/readSpec.cfc` | Guard CockroachDB-incompatible ID tests | |
| 97 | +| `vendor/wheels/tests/specs/model/crudSpec.cfc` | Guard CockroachDB-incompatible ID/order tests | |
| 98 | +| `vendor/wheels/tests/specs/model/sqlSpec.cfc` | Guard CockroachDB type expectation test | |
| 99 | +| `vendor/wheels/tests/specs/migrator/migrationSpec.cfc` | Guard CockroachDB column limit test | |
| 100 | +| `vendor/wheels/tests/specs/model/transactionsSpec.cfc` | Guard CockroachDB-incompatible transaction tests | |
| 101 | +| `vendor/wheels/tests/specs/database/CockroachDBCrudSpec.cfc` | **New** — CRUD with non-sequential IDs | |
| 102 | +| `vendor/wheels/tests/specs/database/CockroachDBTransactionSpec.cfc` | **New** — SERIALIZABLE transaction tests | |
| 103 | +| `vendor/wheels/tests/specs/database/CockroachDBTypeSpec.cfc` | **New** — Type introspection tests | |
| 104 | +| `.github/workflows/tests.yml` | Remove cockroachdb from SOFT_FAIL_DBS | |
| 105 | + |
| 106 | +## Verification |
| 107 | + |
| 108 | +1. Run Lucee 6 + CockroachDB locally: `curl "http://localhost:60006/wheels/core/tests?db=cockroachdb&format=json"` |
| 109 | +2. Run Adobe 2025 + CockroachDB locally: `curl "http://localhost:62025/wheels/core/tests?db=cockroachdb&format=json"` |
| 110 | +3. Confirm 0 fail, 0 error for CockroachDB across both engines |
| 111 | +4. Run Lucee 6 + H2 to verify no regressions: `curl "http://localhost:60006/wheels/core/tests?db=h2&format=json"` |
| 112 | +5. Push and verify CI passes with CockroachDB as a blocking database |
| 113 | + |
| 114 | +## Open questions |
| 115 | + |
| 116 | +- Some transaction failures may be fixable in the framework (not just test expectations) — investigate after fixing SQL generation to see which persist |
| 117 | +- IN clause failures (`works with IN operator with spaces`) may be a separate SQL generation or CockroachDB dialect issue — investigate after main fix |
| 118 | +- Guard pattern: use inline `adapterName() != "CockroachDB"` check (matches existing pattern in CockroachDBIntegrationSpec.cfc) rather than adding a new base class helper — keeps change minimal |
0 commit comments