ADR-0017 implementation: per-cell type-change with override flags
Replaces the placeholder "trust STRICT" body of do_change_column_type
with the per-cell transformer matrix from ADR-0017. Adds:
- src/type_change.rs: CellOutcome { Clean / Lossy / Incompatible }
+ transform_cell + static_refusal covering every matrix pair
from §3 (54 unit tests).
- --force-conversion and --dont-convert flags on `change column`
(mutually exclusive at parse time per §5).
- Refined PK rule (§4.1): refused only when the column has an
inbound FK and fk_target_type would change. Outbound-FK columns
still refused outright (§4.2). PK / shortid uniqueness checked
post-transformation (§4.3).
- Bordered diagnostic tables (lossy / incompatible / collision)
via the pretty-table renderer (§7) — uses ADR-0016's primitives.
- [client-side] success note (§6) when any cell was rewritten.
- Friendly wrapper for engine-level errors under --dont-convert
so no engine vocabulary leaks (ADR-0002 user-facing posture).
ADR-0017 §3 + §7 amended in place (with user sign-off): serial->int
added explicitly to the always-clean matrix, and diagnostic rows
identify themselves by PK value(s) rather than positional indices
(SQLite returns rows unordered without ORDER BY, so positional
"row 5" is unaddressable).
Tests: 449 -> 517 (+68). Clippy clean with nursery lints.
This commit is contained in:
@@ -108,6 +108,7 @@ statically refused (carried over from B2/C2). Anything ↔
|
||||
| `int` / `serial` | `real` | widening; precision caveat for ¦v¦ > 2⁵³ noted in docs but not policed |
|
||||
| `int` / `serial` | `decimal` | exact decimal representation |
|
||||
| `int` / `serial` | `text` | stringify |
|
||||
| `serial` | `int` | identity at the storage class level (both store as INTEGER); drops the auto-increment metadata. The canonical PK conversion enabled by §4.1's `fk_target_type`-aware refinement. |
|
||||
| `bool` | `int` | 0/1 |
|
||||
| `bool` | `real` | 0.0/1.0 |
|
||||
| `bool` | `decimal` | "0"/"1" |
|
||||
@@ -359,14 +360,14 @@ and these conversion diagnostics.
|
||||
Cannot change `T.col` from real to int: 50 row(s) would
|
||||
discard information.
|
||||
|
||||
┌─────┬───────┬─────┬───────────────────────────────────┐
|
||||
│ Row │ From │ To │ Reason │
|
||||
├─────┼───────┼─────┼───────────────────────────────────┤
|
||||
│ 5 │ 3.14 │ 3 │ truncated; would discard 0.14 │
|
||||
│ 12 │ 2.71 │ 2 │ truncated; would discard 0.71 │
|
||||
│ 18 │ 1.5 │ 1 │ truncated; would discard 0.5 │
|
||||
│ … │ … │ … │ … and 47 more │
|
||||
└─────┴───────┴─────┴───────────────────────────────────┘
|
||||
┌─────────┬───────┬─────┬───────────────────────────────────┐
|
||||
│ id (PK) │ From │ To │ Reason │
|
||||
├─────────┼───────┼─────┼───────────────────────────────────┤
|
||||
│ 5 │ 3.14 │ 3 │ truncated; would discard 0.14 │
|
||||
│ 12 │ 2.71 │ 2 │ truncated; would discard 0.71 │
|
||||
│ 18 │ 1.5 │ 1 │ truncated; would discard 0.5 │
|
||||
│ … │ … │ … │ … and 47 more │
|
||||
└─────────┴───────┴─────┴───────────────────────────────────┘
|
||||
|
||||
if you want to execute this conversion in spite of the
|
||||
problems, re-run with `--force-conversion`.
|
||||
@@ -378,13 +379,13 @@ problems, re-run with `--force-conversion`.
|
||||
Cannot change `T.col` from text to int: 3 row(s) cannot
|
||||
be converted.
|
||||
|
||||
┌─────┬───────┬───────────────────────┐
|
||||
│ Row │ Value │ Reason │
|
||||
├─────┼───────┼───────────────────────┤
|
||||
│ 3 │ abc │ not a valid int │
|
||||
│ 7 │ x42 │ not a valid int │
|
||||
│ 12 │ │ not a valid int │
|
||||
└─────┴───────┴───────────────────────┘
|
||||
┌─────────┬───────┬───────────────────────┐
|
||||
│ id (PK) │ Value │ Reason │
|
||||
├─────────┼───────┼───────────────────────┤
|
||||
│ 3 │ abc │ not a valid int │
|
||||
│ 7 │ x42 │ not a valid int │
|
||||
│ 12 │ │ not a valid int │
|
||||
└─────────┴───────┴───────────────────────┘
|
||||
```
|
||||
|
||||
The trailing `--force-conversion` hint is omitted for
|
||||
@@ -397,11 +398,11 @@ forward-look — would re-introduce one).
|
||||
Cannot change `T.col` from real to int: 1 collision(s)
|
||||
would violate uniqueness.
|
||||
|
||||
┌─────────┬─────────────────┬──────────────────┐
|
||||
│ Becomes │ Source rows │ Source values │
|
||||
├─────────┼─────────────────┼──────────────────┤
|
||||
│ 3 │ row 5, row 12 │ 3.14, 3.7 │
|
||||
└─────────┴─────────────────┴──────────────────┘
|
||||
┌─────────┬──────────────────┬──────────────────┐
|
||||
│ Becomes │ Source rows (id) │ Source values │
|
||||
├─────────┼──────────────────┼──────────────────┤
|
||||
│ 3 │ 5, 12 │ 3.14, 3.7 │
|
||||
└─────────┴──────────────────┴──────────────────┘
|
||||
```
|
||||
|
||||
#### Common rules
|
||||
@@ -411,9 +412,33 @@ would violate uniqueness.
|
||||
literal text "and N more" inside the row is rendered
|
||||
inside the table — not as a footer line. Keeps the
|
||||
bordered shape intact.
|
||||
- Row indices are 1-based to match how learners count
|
||||
rows; the tool counts internally from 0.
|
||||
- Numeric "Row" / "Becomes" columns inherit numeric
|
||||
- Rows are identified by their **primary-key value(s)**, not
|
||||
by positional indices. SQLite returns rows in unspecified
|
||||
order without `ORDER BY`, so a positional "row 5" would
|
||||
not be reproducible or addressable by the user. The PK is
|
||||
the natural row identifier in a relational setting and is
|
||||
what the user would type in a `where` clause to find or
|
||||
fix the offending cell.
|
||||
- Single PK: rendered as one column whose header is the
|
||||
PK column name with a trailing `(PK)` marker
|
||||
(e.g. `id (PK)`); cells carry the raw PK value with no
|
||||
`column=` prefix. The marker appears once per table, in
|
||||
the header.
|
||||
- Compound PK: one column per PK component, each header
|
||||
annotated `(PK)` (e.g. `a (PK)`, `b (PK)`); cells carry
|
||||
the raw component values.
|
||||
- Uniqueness-collision tables list the colliding rows'
|
||||
PK values comma-separated inside a single `Source rows`
|
||||
cell whose header carries the PK column name(s) in
|
||||
parentheses (e.g. `Source rows (id)` or `Source rows
|
||||
(a, b)`). Compound-PK source rows render as tuples:
|
||||
`(1,2), (1,3)`.
|
||||
- The change-column command always operates on a table
|
||||
with at least one PK column (every `create table` in v1
|
||||
produces a PK; the AST permits PK-less tables, but no
|
||||
grammar produces one today). If a PK-less surface ever
|
||||
lands, this section will be revisited.
|
||||
- Numeric PK and "Becomes" columns inherit numeric
|
||||
right-alignment from ADR-0016 §2.
|
||||
- Cells that would render multi-line content (for `text →`
|
||||
conversions where source values contain newlines) honour
|
||||
|
||||
Reference in New Issue
Block a user