Commit 80d28a7
Two defects in the PostgreSQL schema reader, both found during #389 and deferred
there with in-place comments. Landed together because they share a file, a test
surface and a verification cost.
#414 — the `columns` aggregate is `quote_ident(name) || ' ' || format_type(...)`
and the reader split it on `" "`, so an identifier CONTAINING a space was torn in
half before anything else saw it: `"Parent Id" bigint` yielded the phantom name
`"Parent` (the leading quote survives — `_unquote_ident` correctly refuses to strip
a lone unbalanced one), the non-type `Id"` so the column degraded to TextField, and
a LOST relation, because `fk_map`/`pk_set`/`index_map` all key on names that survive
a space. makemigrations then proposed adding the phantom and dropping the real
column on every run, forever. SQLite was never affected.
Fixed in the PARSER, not the aggregate: `quote_ident` output is self-delimiting, so
scanning to the closing quote recovers every name that reaches the function whole.
The flag/type scans move onto the post-name remainder in the same change, which
closes the sibling class where a column NAMED like a marker marked itself.
#415 — the `foreign_keys` CTE derived an FK's referenced column from the parent's
PRIMARY KEY INDEX; `con.confkey` was not selected anywhere in the file. An FK
pointing at a non-PK UNIQUE column reported the wrong column, and a composite
parent key fanned every aggregate out once per parent key column, so the last entry
silently won the `fk_map` assignment and the delete_rules alignment #292
established broke with it.
Now correlated through `unnest(con.conkey, con.confkey)` — bound-agnostic, so unlike
a `conkey[1]` subscript it carries none of #347's lower-bound hazard. Adds no
version floor: the `indexes` CTE in the same statement already requires PG 11+.
Three behavior changes fall out, all deliberate and documented:
* a genuine MULTI-column FK is skipped rather than guessed at, on BOTH engines
(PG by `array_length(con.conkey, 1) = 1`, SQLite by grouping PRAGMA
foreign_key_list on `id`, which used to split one constraint into N relations).
PormG has no composite-FK field type; reading one approximately would
regenerate a different schema.
* an FK referencing a non-PK UNIQUE column reads that column.
* an FK whose parent has NO primary key is visible at all — the dropped
`pg_index` join was INNER, so such a key vanished from the PG read entirely
while SQLite reported it.
Also restores `db_column = "driver ref"` on the Odd_identifier_scratch fixture,
which #394 had to leave out precisely because of #414 — the global no-drift
assertion in test_db_table_db.jl is now the live gate for this parse. And
test_importers_introspection.jl gains the standalone guard it uniquely lacked, so
it no longer forces the full runtests.jl prologue to see one assertion.
Verification: unit 8874/8874; full SQLite integration suite 2172 pass / 1
pre-existing broken / 0 fail; db_sl introspection slice 78/78; docs build clean.
Mutation-checked — reverting the parser fails 13 assertions, removing the SQLite
skip fails 4.
NOT verified: the PostgreSQL behavior of #415. A read-only probe confirms the new
CTE parses and executes against db_2 and that none of its 28 existing FK tables
regress, but measured side by side the old and new CTE agree on all 28 — db_2
carries neither affected shape today, so that probe is a no-regression check, not
a gate. Sections 3f/3g/3h and the spaced-db_column no-drift assertion need a full
db_2 run.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 26b9a70 commit 80d28a7
9 files changed
Lines changed: 857 additions & 51 deletions
File tree
- docs/src
- src/migrations
- test
- integration
- db_2
- db_sl
- unit
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
48 | 164 | | |
49 | 165 | | |
50 | 166 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
488 | 488 | | |
489 | 489 | | |
490 | 490 | | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
491 | 518 | | |
492 | 519 | | |
493 | 520 | | |
| |||
0 commit comments