|
| 1 | +--- |
| 2 | +"@objectstack/cli": patch |
| 3 | +--- |
| 4 | + |
| 5 | +fix(cli): a generated migration carries the column DEFAULT `driver-sql` puts on the same field (#16294) |
| 6 | + |
| 7 | +## What was wrong |
| 8 | + |
| 9 | +Neither `os generate migration` format read a field's `defaultValue`, so a table |
| 10 | +created from a generated migration had no column DEFAULT where the platform's |
| 11 | +own table has one. A row inserted out of band — by a database client, a seed |
| 12 | +script, anything that does not go through the engine — got NULL where the |
| 13 | +declared value belonged. |
| 14 | + |
| 15 | +Driven on live PostgreSQL 16.13: one object, three schemas, one producer each |
| 16 | +(`driver-sql` through `initObjects`, `--format sql` through `db.raw`, |
| 17 | +`--format ts` by importing the emitted module and calling `up(db)`), with |
| 18 | +`information_schema.columns` read back per schema. |
| 19 | + |
| 20 | +``` |
| 21 | +field driver sqlgen verdict |
| 22 | +f_default null=YES default='hello'::text null=YES default=- DIVERGED |
| 23 | +f_default_required null=YES default='hello'::text null=YES default=- DIVERGED |
| 24 | +``` |
| 25 | + |
| 26 | +After: `diverged: 0 of 6` on the card's probe, and 22 of 23 on a wider one |
| 27 | +covering every `defaultValue` shape. |
| 28 | + |
| 29 | +## What changed |
| 30 | + |
| 31 | +Both formats now render one shared verdict, taken from |
| 32 | +`SqlDriver.applyDeclaredColumnDefault` — the single place a `defaultValue` |
| 33 | +becomes DDL on the platform side: |
| 34 | + |
| 35 | +- a **literal** is emitted, quoted the way knex binds it (`DEFAULT '42'`, not |
| 36 | + `DEFAULT 42` — PostgreSQL keeps those two textually apart forever in |
| 37 | + `column_default`, and the driver's column carries the quoted form); |
| 38 | +- **`'NOW()'`** becomes the driver's own translation, which is type-branched: |
| 39 | + `CURRENT_TIMESTAMP` on a timestamp column, and a UTC-pinned expression on |
| 40 | + `date` / `time`, because a bare `CURRENT_TIMESTAMP` resolves those in the |
| 41 | + server's timezone; |
| 42 | +- **any other runtime token** (`current_user`), an **Expression envelope** and |
| 43 | + an **option-level `default: true`** emit nothing, each because the driver |
| 44 | + emits nothing — the engine owns those, and a column DEFAULT would override a |
| 45 | + decision it makes deliberately; |
| 46 | +- a **`multiple: true`** field gets neither, because `createColumn` returns |
| 47 | + before both questions. |
| 48 | + |
| 49 | +No authorable key, export or accepted-input set changes: `defaultValue` was |
| 50 | +already declared, already parsed and already honoured by the driver. The |
| 51 | +generators simply now read it. |
0 commit comments