Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/release-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
- `upsertGraph()` treats a row that lists itself in a relation on its own key, e.g. in its own `siblings`, as giving that relation no key, so the listing no longer conflicts with the key that the row's other places give: where 3.x threw a `ValidationError` of type `InvalidGraph`, such a graph is written, or throws the `NotFoundError` that asks for the `relate` option when a row it moves isn't related. A row that such a relation leaves out of its own list, e.g. a pet whose `siblings` name only the other pets, is removed from it, as in 3.x, also where the graph relates or moves the row. [#427](https://github.com/ditojs/objection/pull/427)
- `upsertGraph()` patches a key that the graph gives a row, where it changes the key or the row isn't loaded, before it writes the rows that it relates by that key, at the same place or another one, so a foreign key with `ON UPDATE CASCADE` on that column holds, where 3.x wrote these rows with the old key and relied on the cascade. For these graphs, the patch and its `$beforeUpdate` run before the inserts and `$beforeInsert` of these rows, and before the relates and patches of the rows that read the key. A patch that also waits for a key or `#ref{}` value of these rows throws a `ValidationError` of type `InvalidGraph` before anything is written. [#428](https://github.com/ditojs/objection/issues/428)
- `upsertGraph()` writes the keys that it changes under `noUpdate` with `patch()` instead of `update()`, so `$beforeUpdate()` and `$afterUpdate()` get `patch: true` in their options for them, as for the patches of other models. They were already validated as patches. [#415](https://github.com/ditojs/objection/issues/415)
- `insertGraph()` and `upsertGraph()` write in fewer queries: rows are deleted with one query per relation instead of one per owner, with all owners as `items` in the static hooks. On SQLite, rows are inserted in batches too, where 3.x inserted one row per query there, so the static `beforeInsert` and `afterInsert` hooks run once per batch with several models. See [migration](/release-notes/migration.md#insertgraph-and-upsertgraph-write-in-fewer-queries)
- `insertGraph()` and `upsertGraph()` write in fewer queries: rows are deleted with one query per relation instead of one per owner, with all owners as `items` in the static hooks. On SQLite, rows are inserted in batches too, where 3.x inserted one row per query there, so the static `beforeInsert` and `afterInsert` hooks run once per batch with several models. These batches use the query builder's `insert()`, so a custom `insert()` that sends arrays to `insertGraph()`, a 3.x workaround on SQLite, now recurses until it runs out of memory and needs to go. See [migration](/release-notes/migration.md#insertgraph-and-upsertgraph-write-in-fewer-queries)
- Custom relation classes that extend `Relation` directly declare where their keys are stored with a `keySide` getter (`'owner'`, `'related'` or `'join'`) to be used in `insertGraph()` and `upsertGraph()`. Relations that extend the built-in relation classes inherit it. See [migration](/release-notes/migration.md#custom-relations-that-extend-relation-declare-keyside)
- The deprecated `allowMarkers` option is removed from the `InsertGraphOptions` typings. It has no effect since 3.8.0, where `insertGraph()` rejects `#unrelate` and `#delete` markers. See [migration](/release-notes/migration.md#typescript-insertgraph-has-no-allowmarkers-option)
- The type parameter of `RelateQueryBuilder` is the number query builder, e.g. `RelateQueryBuilder<NumberQueryBuilder<this>>` in custom query builders that override `relate()`. See [migration](/release-notes/migration.md#typescript-relatequerybuilder-takes-the-number-query-builder)
Expand Down
16 changes: 16 additions & 0 deletions doc/release-notes/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,22 @@ Rows that the graph deletes are deleted with one query per relation instead of o

On SQLite, rows that the graph inserts are inserted in batches, where 3.x inserted one row per query, so the static `beforeInsert` and `afterInsert` hooks get several models at once.

These batches go through the query builder's `insert()` with an array of rows. A custom `QueryBuilder` that sends arrays from `insert()` to `insertGraph()`, the usual 3.x way to insert several rows on SQLite, now calls itself until the process runs out of memory, without an error:

```js
class MyQueryBuilder extends QueryBuilder {
insert(data) {
// Remove this override: `insert()` inserts arrays on SQLite itself.
if (Array.isArray(data) && data.length > 1) {
return this.insertGraph(data);
}
return super.insert(data);
}
}
```

Remove such overrides, as `insert()` inserts several rows on SQLite itself now.

## Custom relations that extend Relation declare keySide

`insertGraph()` and `upsertGraph()` read where the keys of a relation are stored from its `keySide` getter: `'owner'` for keys in the owner rows, like `BelongsToOneRelation`, `'related'` for keys in the related rows, like `HasManyRelation`, and `'join'` for keys in the rows of a join table, like `ManyToManyRelation`. Relation classes that extend the built-in relations inherit it. Classes that extend `Relation` directly need to declare it, or graph writes through them throw `not implemented`:
Expand Down
Loading