Skip to content

Commit f2f6ed0

Browse files
authored
fix: don't process delete PKs if norows were affected (#621)
1 parent 52fb570 commit f2f6ed0

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

packages/mysql/src/mysql-adapter.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,12 @@ export class MySQLQueryResolver<T extends OrmEntity> extends SQLQueryResolver<T>
427427
`;
428428

429429
const rows = await connection.execAndReturnAll(sql, select.params);
430-
const returning = rows[1];
431-
const pk = returning[0]['@_pk'];
432-
if (pk) deleteResult.primaryKeys = JSON.parse(pk).map(primaryKeyConverted);
430+
const affectedRows = rows[0].affectedRows;
431+
if (affectedRows) {
432+
const returning = rows[1];
433+
const pk = returning[0]['@_pk'];
434+
deleteResult.primaryKeys = JSON.parse(pk).map(primaryKeyConverted);
435+
}
433436
deleteResult.modified = deleteResult.primaryKeys.length;
434437
} catch (error: any) {
435438
error = new DatabaseDeleteError(this.classSchema, 'Could not delete in database', { cause: error });

packages/mysql/tests/mysql.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,43 @@ test('non-object null unions should not render as JSON', async () => {
344344
{name: 'Thomas', nickName: 'Tom', birthdate: new Date('1960-02-10T00:00:00Z')},
345345
]);
346346
});
347+
348+
test('updates & deletes should ignore previous @_pk session variable if no rows were affected', async () => {
349+
@entity.name('model7')
350+
class Model {
351+
id: number & PrimaryKey & AutoIncrement = 0;
352+
353+
constructor(public name: string) {}
354+
}
355+
356+
const database = await databaseFactory([Model]);
357+
const model = new Model('Peter');
358+
await database.persist(model);
359+
expect(model.id).toEqual(expect.any(Number));
360+
361+
// perform update & delete in single database connection to ensure @_pk session variable is shared
362+
// between multiple queries. outside a transaction, this is luck of the draw based on connection pooling.
363+
await database.transaction(async txn => {
364+
{
365+
const result = await txn.query(Model).filter({id: model.id}).patchMany({name: 'Paul'});
366+
expect(result.primaryKeys[0]).toEqual({ id: model.id });
367+
}
368+
369+
{
370+
const result = await txn.query(Model).filter({id: model.id}).deleteMany();
371+
expect(result.primaryKeys[0]).toEqual({ id: model.id });
372+
}
373+
374+
// there should be no ID returned if we try to update a non-existent record
375+
{
376+
const result = await txn.query(Model).filter({id: model.id}).patchMany({name: 'Simon'});
377+
expect(result.primaryKeys[0]).toBeUndefined();
378+
}
379+
380+
// there should be no ID returned if we try to delete a non-existent record
381+
{
382+
const result = await txn.query(Model).filter({id: model.id}).deleteMany();
383+
expect(result.primaryKeys[0]).toBeUndefined();
384+
}
385+
});
386+
});

0 commit comments

Comments
 (0)