also looking at this
fix: a multi-row insert names every column any row carries (#1189)
#1190
3 files
+384
-11
| @@ -611,6 +611,33 @@ Two consequences worth knowing: | ||
| 611 | 611 | |
| 612 | 612 | If you want the server to enforce the instant and your dates stay before 2038, declare the column `TIMESTAMP` in a hand-written migration rather than through a model. |
| 613 | 613 | |
| 614 | ### A multi-row insert with uneven rows loses column defaults on SQLite | |
| 615 | ||
| 616 | A multi-row insert names the union of every row's keys, so a column only some rows set is still written for the rows that set it: | |
| 617 | ||
| 618 | ```ts | |
| 619 | await db.insertInto('timeline_entries').values([ | |
| 620 | { kind: 'labeled', subject_text: 'first' }, | |
| 621 | { kind: 'renamed', subject_text: 'second', previous_text: 'kept' }, | |
| 622 | ]).execute() | |
| 623 | ``` | |
| 624 | ||
| 625 | A row that lacks one of those columns has to put *something* in its tuple, and that is where the dialects differ: | |
| 626 | ||
| 627 | | dialect | emitted for the gap | effect | | |
| 628 | | --- | --- | --- | | |
| 629 | | Postgres, MySQL | `DEFAULT` | the column's own default applies | | |
| 630 | | SQLite | `NULL` | the column default is **bypassed** | | |
| 631 | ||
| 632 | SQLite has no `DEFAULT` keyword inside a `VALUES` list — it answers `near "DEFAULT": syntax error` — so there is nothing to emit that means "use the default". A column with a non-null default therefore stores `NULL` for the rows that omitted it, and a `NOT NULL` column with a default fails the insert. | |
| 633 | ||
| 634 | This only bites when the rows are uneven *and* the missing column has a default. Two ways out, both explicit: | |
| 635 | ||
| 636 | - set the key on every row, so the batch is uniform and nothing has to be filled in | |
| 637 | - group the rows by shape and insert each group separately, so a column no row sets is simply not named | |
| 638 | ||
| 639 | Uniform batches are unaffected on every dialect, and so is the single-row form. | |
| 640 | ||
| 614 | 641 | ## Performance Tips Per Dialect |
| 615 | 642 | |
| 616 | 643 | - Postgres: leverage `EXPLAIN (ANALYZE, BUFFERS)` during tuning; create appropriate indexes for JSON paths if needed |