|
| 1 | +--- |
| 2 | +'@objectstack/driver-sql': minor |
| 3 | +'@objectstack/spec': patch |
| 4 | +'@objectstack/platform-objects': patch |
| 5 | +'@objectstack/lint': patch |
| 6 | +--- |
| 7 | + |
| 8 | +fix(driver-sql): a declared index that can never be built is logged at `error` and reported in drift |
| 9 | + |
| 10 | +**Clause-②: yes (widening)**: the exported `DriftOp` union gains one member, `unbuildable_index`. |
| 11 | +No accept set changes. Nothing an author could write before is refused now. |
| 12 | + |
| 13 | +A declared index names a column that no declaration will ever create when: |
| 14 | + |
| 15 | +- the name is not a field of the object, for example a misspelling that the Studio save door |
| 16 | + admits (`os validate` / `os build` already refuse it); or |
| 17 | +- the name is a virtual `formula` field, which is computed on read and has no column. The same |
| 18 | + applies to a field-level `unique` on a formula field. |
| 19 | + |
| 20 | +The SQL driver skips such an index at every sync. It used to say so at `warn`, and the drift |
| 21 | +report dropped the index from the expected set, so `os migrate plan` showed nothing. For a |
| 22 | +`unique` index, the declared constraint was not enforced and duplicate rows were accepted, |
| 23 | +while everything looked normal. |
| 24 | + |
| 25 | +- **The sync logs the skip at `error`**, on the same durability channel as the duplicate-row |
| 26 | + refusals in the same loop. One line per skipped index per sync names the object, the index, |
| 27 | + each missing column with its reason (not a field of the object, or a formula field), and |
| 28 | + whether the index is `UNIQUE`. The structured meta carries `index`, `missing` and `unique`. |
| 29 | +- **Drift reports it** as a report-only entry: `kind: 'index_mismatch'`, `actual: '(absent)'`, |
| 30 | + `category: 'needs_confirm'`, `severity: 'error'` for a unique index and `'warning'` otherwise. |
| 31 | + Its op is the new member: |
| 32 | + |
| 33 | + ```ts |
| 34 | + { type: 'unbuildable_index'; table: string; column?: string; indexName: string; |
| 35 | + unique: boolean; missingColumns: string[] } |
| 36 | + ``` |
| 37 | + |
| 38 | + `missingColumns` lists only the columns that will never materialize. A declared column that |
| 39 | + is merely not added yet is pending additive work, not this finding. |
| 40 | + |
| 41 | +**What a consumer that reads `op.type` now sees.** A new value, `'unbuildable_index'`. It has |
| 42 | +no reconciler arm, and none can exist, because there is no column to build over. The remedy is |
| 43 | +a metadata edit. It is in `INDEX_DRIFT_OPS`, so `isIndexDriftOp` answers `true` and it never |
| 44 | +triggers a SQLite table rebuild. `applyMigrationEntries` reports it `skipped` on every dialect. |
| 45 | +`os migrate plan` lists it under "Needs confirmation", addressed by its index name. `os migrate |
| 46 | +apply` counts it like any `needs_confirm` entry (so it asks for `--yes`), and then reports it |
| 47 | +skipped. The artifact-pinned boot warns about it and still starts, because |
| 48 | +only `destructive` entries refuse a boot. A `switch` over `op.type` that treats unknown values |
| 49 | +as "not applied" needs no change. An exhaustive `switch` with a `never` check gets one more case |
| 50 | +to handle. |
| 51 | + |
| 52 | +**The object form's help text follows.** The `indexes` → Fields help in the Studio object form |
| 53 | +said the skip left "a warning in the server log". It now says an error, in English and in the |
| 54 | +zh-CN, ja-JP and es-ES translations. Nothing else in the text changes. |
| 55 | + |
| 56 | +**The lint message follows too.** `object-field-ref-unknown`, on a misspelt `indexes[].fields` |
| 57 | +name, said the SQL driver skips the index "with only a warning, and drift drops it too". It now |
| 58 | +says the skip is logged at error and `os migrate plan` reports the index as unbuildable. The rule, |
| 59 | +its severity and its prescription are unchanged. |
| 60 | + |
| 61 | +**Upgrade note:** on a database that already carries such an index, `os migrate plan` now |
| 62 | +reports one entry per index, and so does the boot's drift warning. That entry clears only when |
| 63 | +the metadata names stored fields or drops the index. |
0 commit comments