Skip to content

Commit

Permalink
avoid NotFoundError when trying to unrelate / delete a model with inv…
Browse files Browse the repository at this point in the history
…alid id

`NotFoundError: model (id=x) is not a child of model (id=y). If you want to relate it, use the relate option. If you want to insert it with an id, use the insertMissing option`
- let upsertGraph ignore those errors when `#delete` or `#unrelate` props are used.
  • Loading branch information
falkenhawk committed Mar 28, 2023
1 parent 51cfe27 commit 26733a8
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/queryBuilder/graph/GraphUpsert.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ function checkForNotFoundErrors(graphData, builder) {
for (const node of graph.nodes) {
if (
node.obj.$hasId() &&
!node.toBeUnrelated &&
!node.toBeDeleted &&
!graphOptions.shouldInsertIgnoreDisable(node, graphData) &&
!graphOptions.shouldRelateIgnoreDisable(node, graphData) &&
!currentGraph.nodeForNode(node)
Expand Down
93 changes: 93 additions & 0 deletions tests/integration/upsertGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,99 @@ module.exports = (session) => {
});
});

it('should not fail when trying to #unrelate or #delete a model which either does not exist or is linked elsewhere', () => {
const upsert = {
id: 2,
model1Relation2: [
{
idCol: 1,
model2Relation1: [
// ignore unrelating/deleting models which are linked to a different base model
// id 6&7 are linked to model1Relation2.idCol=2
{ id: 6, '#unrelate': true },
{ id: 7, '#delete': true },
// ignore unrelating/deleting non-existing models
{ id: 900, '#unrelate': true },
{ id: 901, '#delete': true },
// add new model
{ model1Prop1: 'inserted manyToMany' },
],
},
// ignore delete (non-existing) idCol=3 with `#delete: true` special prop
// ignore unrelate (non-existing) idCol=4 with `#unrelate: true` special prop
{ idCol: 3, '#delete': true },
{ idCol: 4, '#unrelate': true },
],
};

return transaction(session.knex, (trx) => {
return Model1.query(trx)
.upsertGraph(upsert, {
fetchStrategy,
relate: true,
noDelete: true,
})
.then((result) => {
// Fetch the graph from the database.
return Model1.query(trx)
.findById(2)
.withGraphFetched('[model1Relation2(orderById).model2Relation1(orderById)]');
})
.then(omitIrrelevantProps)
.then((result) => {
expect(result).to.eql({
id: 2,
model1Id: 3,
model1Prop1: 'root 2',

model1Relation2: [
{
idCol: 1,
model1Id: 2,
model2Prop1: 'hasMany 1',

model2Relation1: [
{
id: 4,
model1Id: null,
model1Prop1: 'manyToMany 1',
},
{
id: 5,
model1Id: null,
model1Prop1: 'manyToMany 2',
},
{
id: 8,
model1Id: null,
model1Prop1: 'inserted manyToMany',
},
],
},
{
idCol: 2,
model1Id: 2,
model2Prop1: 'hasMany 2',

model2Relation1: [
{
id: 6,
model1Id: null,
model1Prop1: 'manyToMany 3',
},
{
id: 7,
model1Id: null,
model1Prop1: 'manyToMany 4',
},
],
},
],
});
});
});
});

it('should relate and unrelate some models if `unrelate` and `relate` are arrays of relation paths', () => {
const upsert = {
// the root gets updated because it has an id
Expand Down

0 comments on commit 26733a8

Please sign in to comment.