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 @@ -42,7 +42,7 @@
- `insertGraph()`, `upsertGraph()` and their `*AndFetch()` variants throw an error when combined with `onConflict()`, `ignore()` or `merge()`, instead of ignoring the clause with a warning. See [migration](/release-notes/migration.md#onconflict-with-insertgraph-and-upsertgraph-throws) [#2156](https://github.com/Vincit/objection.js/issues/2156)
- `insertGraph()`, `upsertGraph()` and their `*AndFetch()` variants throw an error for unknown graph options like `noInset` instead of ignoring them with a warning, and `insertGraph()` also for the options of `upsertGraph()` that have no effect on an insert, like `noDelete` or `allowMarkers`. See [migration](/release-notes/migration.md#unknown-graph-options-throw) [#84](https://github.com/ditojs/objection/issues/84)
- `insertGraph()` throws a `ValidationError` of type `InvalidGraph` for new models below related models, instead of ignoring them with a warning. Models with ids below related models are still ignored. See [migration](/release-notes/migration.md#insertgraph-throws-for-new-models-below-related-models) [#217](https://github.com/ditojs/objection/issues/217)
- `insertGraph()` and `upsertGraph()` throw a `ValidationError` of type `InvalidGraph` for graphs that give one row two different values for the same column, or the slot of a `HasOneRelation` two rows. Examples are a row under two owners through the same foreign key, a row under an owner while its own `BelongsToOneRelation` names another model, and a model related twice through a many-to-many relation with different join table extras. This holds for any two places of a row, also for the values that places read through the rows they relate, e.g. two rows that list each other as siblings at different owners. It also holds for a place that clears a key that another place places rows by, e.g. a row that its owner's list leaves out while its own `siblings` are placed at that owner. 3.x wrote these graphs in an undefined order that could delete rows the graph names, and wrote the rows placed by a cleared key with `null`. A model related twice with the same extras gets one join row. See [migration](/release-notes/migration.md#insertgraph-and-upsertgraph-reject-rows-placed-in-conflicting-ways)
- `insertGraph()` and `upsertGraph()` throw a `ValidationError` of type `InvalidGraph` for graphs that give one row two different values for the same column, or the slot of a `HasOneRelation` two rows. Examples are a row under two owners through the same foreign key, a row under an owner while its own `BelongsToOneRelation` names another model, and a model related twice through a many-to-many relation with different join table extras. This holds for any two places of a row, also for the values that places read through the rows they relate, e.g. two rows that list each other as siblings at different owners. It also holds for a place that clears a key that another place places rows by, e.g. a row that its owner's list leaves out while its own `siblings` are placed at that owner. 3.x wrote these graphs in an undefined order that could delete rows the graph names, and wrote the rows placed by a cleared key with `null`. A model related twice with the same extras gets one join row, where 3.x wrote one for each listing. See [migration](/release-notes/migration.md#insertgraph-and-upsertgraph-reject-rows-placed-in-conflicting-ways)
- `upsertGraph()` upserts the models below related models in the same graph, instead of in nested `upsertGraph()` calls after all other writes: their rows are fetched together, their writes run in the same steps as the rest of the graph, and `#ref` can point between them. A related model with relations whose row doesn't exist throws a `NotFoundError` before anything is written, where 3.x wrote the rest of the graph first. The relations of rows that the graph moves to another owner are read where the rows end up, whether a row moves through a relate into a new owner, its own `BelongsToOneRelation` or a key that another place writes. The siblings that a moved row lists anywhere in the graph apply at its new owner: its old siblings stay where they are, and `siblings: []` unrelates all other rows at the new owner. Rows keep their related rows when a key changes with them instead, e.g. through a `#ref{}`. All errors are thrown before anything is written. A moved row is written once, so its update hooks run once, in the order of the other writes of their kind. 3.x upserted the models below moved rows in a later pass, and wrote a moved row twice if they changed its keys. See [migration](/release-notes/migration.md#upsertgraph-upserts-below-related-models-in-the-same-graph) [#427](https://github.com/ditojs/objection/pull/427)
- `upsertGraph()` relates the rows that move to existing owners of a `HasManyRelation` or `HasOneRelation` before it deletes the removed rows. Rows moved out of a deleted parent, up a level or to a sibling are kept, where `ON DELETE CASCADE` deleted them and foreign keys without `ON DELETE` action failed. The update hooks of these relates run before the delete hooks. Rows that wait for the keys or references of models that the graph inserts are related after the inserts, as in 3.x. A relate into a `HasOneRelation` still waits for the removal of the current model, or for the relate that moves it to another owner, also a new one or one whose slot is freed first. A row related from another owner that takes the unique key of a row that the graph removes in its new place, e.g. with `unique(ownerId, name)`, fails with a `UniqueViolationError`, where 3.x removed the other row first. So does a new row that takes the unique key of a row that moves to a new owner, where 3.x cleared the moved row's key first. Swapping the rows of two `HasOneRelation` slots with a unique foreign key, e.g. two people's `pet`, fails with a `UniqueViolationError` too, where 3.x with `unrelate` unrelated both rows first. See [migration](/release-notes/migration.md#upsertgraph-relates-moved-rows-before-it-deletes) [#214](https://github.com/ditojs/objection/issues/214)
- `upsertGraph()` checks that the models it relates exist, also through `#dbRef`, and throws a `NotFoundError` "model (id=N) does not exist" before anything is written if one doesn't and the graph doesn't insert it elsewhere, for all relation types. 3.9.0 only checked related models with relations of their own: it patched no row for a missing `HasManyRelation` or `HasOneRelation` model, and wrote the foreign key or join row of a missing `BelongsToOneRelation` or `ManyToManyRelation` model. The graph fetches the ids of the related models without relations in one query per model class. See [migration](/release-notes/migration.md#upsertgraph-checks-that-related-models-exist) [#372](https://github.com/ditojs/objection/issues/372)
Expand Down
4 changes: 2 additions & 2 deletions doc/release-notes/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ A graph that gives one row two different values for the same column in any two o
- the row is marked with `#delete` in one place and kept in another, or marked with `#unrelate`, which clears its key, while another place puts it under an owner;
- one place clears a key that another place places rows by, e.g. `[{ id: 1, pets: [{ id: 10 }] }, { id: 3, favoritePet: { id: 12, siblings: [{ name: 's' }] } }]` with `unrelate`, where person 1's pets unrelate pet 12 while its siblings are placed at its owner, or a pet whose `siblings` leave out the pet that lists it among its own;
- a many-to-many pair is marked with `#unrelate` in one place and related or kept in another, e.g. `{ id: 1, movies: [{ id: 3, '#id': 'm', '#unrelate': true }, { '#ref': 'm' }] }`, as the pair has one join row;
- a model is related twice through a many-to-many relation with different join table extras, e.g. `{ id: 1, movies: [{ id: 2, role: 'director' }, { id: 2, role: 'producer' }] }`. A pair of models has one join row, as in 3.x, which wrote the last extras to it. To relate a pair more than once, model the join table with an id column of its own and relate its rows instead, e.g. as a `credits` relation from the person to a `Credit` model that belongs to the movie.
- a model is related twice through a many-to-many relation with different join table extras, e.g. `{ id: 1, movies: [{ id: 2, role: 'director' }, { id: 2, role: 'producer' }] }`. A pair of models has one join row in 4.0, where 3.x wrote a join row for each listing. To relate a pair more than once, model the join table with an id column of its own and relate its rows instead, e.g. as a `credits` relation from the person to a `Credit` model that belongs to the movie.

3.x wrote these graphs in an order that the graph doesn't define, and often deleted rows that the graph names, like the root. A graph that places a row the same way more than once stays valid, e.g. `{ id: 1, pets: [{ id: 4, owner: { id: 1 } }] }`, and so does a row in places that write different columns, e.g. as a `child` and as a `boss`. A foreign key prop that a model gives next to its own relation, e.g. an old `parentId` next to a new `parent`, still follows the relation, and so does the key of a model that a relation places, e.g. a fetched pet with its old `ownerId` moved into the `pets` of another person. A row that one place of an owner lists and another place of the same owner leaves out is kept, as the graph keeps it in the first place.
3.x wrote these graphs in an order that the graph doesn't define, and often deleted rows that the graph names, like the root. A graph that places a row the same way more than once stays valid, e.g. `{ id: 1, pets: [{ id: 4, owner: { id: 1 } }] }`, and so does a row in places that write different columns, e.g. as a `child` and as a `boss`. A model related twice through the same many-to-many relation with the same extras, e.g. `{ title: 'T', genres: [{ '#id': 'f', name: 'Fantasy' }, { '#ref': 'f' }] }` or the same `{ id: 2 }` listed twice, gets one join row, where 3.x wrote one for each listing. A foreign key prop that a model gives next to its own relation, e.g. an old `parentId` next to a new `parent`, still follows the relation, and so does the key of a model that a relation places, e.g. a fetched pet with its old `ownerId` moved into the `pets` of another person. A row that one place of an owner lists and another place of the same owner leaves out is kept, as the graph keeps it in the first place.

## upsertGraph() checks that related models exist

Expand Down
Loading