Delete tag when the last note using it is deleted
This commit is contained in:
parent
efbd5d034a
commit
e51c191ae5
|
@ -0,0 +1,21 @@
|
||||||
|
import type { Kysely, Migration } from 'kysely';
|
||||||
|
import { sql } from 'kysely';
|
||||||
|
|
||||||
|
export const Migration20230930: Migration = {
|
||||||
|
async up(db: Kysely<any>) {
|
||||||
|
await db
|
||||||
|
.deleteFrom('tag')
|
||||||
|
.where('id', 'not in', ({ selectFrom }: any) => selectFrom('noteTag').select('tagId'))
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
await sql`
|
||||||
|
CREATE TRIGGER noteTagDeleteUnusedTagTrigger AFTER DELETE ON noteTag
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM tag WHERE id = old.tagId AND (SELECT COUNT(*) FROM noteTag WHERE tagId = old.tagId) = 0;
|
||||||
|
END;
|
||||||
|
`.execute(db);
|
||||||
|
},
|
||||||
|
async down(db: Kysely<any>) {
|
||||||
|
await sql`DROP TRIGGER noteTagDeleteUnusedTagTrigger`.execute(db);
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,6 +1,8 @@
|
||||||
import type { Migration } from 'kysely';
|
import type { Migration } from 'kysely';
|
||||||
import { Migration20230830 } from './2023-08-30';
|
import { Migration20230830 } from './2023-08-30';
|
||||||
|
import { Migration20230930 } from './2023-09-30';
|
||||||
|
|
||||||
export const migrations: Record<string, Migration> = {
|
export const migrations: Record<string, Migration> = {
|
||||||
'2023-08-30': Migration20230830,
|
'2023-08-30': Migration20230830,
|
||||||
|
'2023-09-30': Migration20230930,
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,28 +54,18 @@ export class NoteTagsStore implements Readable<Tag[]> {
|
||||||
};
|
};
|
||||||
|
|
||||||
remove = async (tagId: Tag['id']) => {
|
remove = async (tagId: Tag['id']) => {
|
||||||
const noteId = this.noteId;
|
const [deletedNoteTag] = await db
|
||||||
|
|
||||||
await db.transaction().execute(async (trx) => {
|
|
||||||
await trx
|
|
||||||
.deleteFrom('noteTag')
|
.deleteFrom('noteTag')
|
||||||
.where('noteId', '=', noteId)
|
.where('noteId', '=', this.noteId)
|
||||||
.where('tagId', '=', tagId)
|
.where('tagId', '=', tagId)
|
||||||
.executeTakeFirstOrThrow();
|
.returningAll()
|
||||||
const remainingTagUsage = await trx
|
.execute();
|
||||||
.selectFrom('noteTag')
|
|
||||||
.where('tagId', '=', tagId)
|
|
||||||
.select('tagId')
|
|
||||||
.executeTakeFirst();
|
|
||||||
|
|
||||||
if (!remainingTagUsage) {
|
|
||||||
await trx.deleteFrom('tag').where('id', '=', tagId).executeTakeFirstOrThrow();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.refreshTags();
|
this.refreshTags();
|
||||||
this.notes.refreshNotes();
|
this.notes.refreshNotes();
|
||||||
this.tags.refreshTags();
|
this.tags.refreshTags();
|
||||||
|
|
||||||
|
return deletedNoteTag;
|
||||||
};
|
};
|
||||||
|
|
||||||
search = async (searchString: string): Promise<string[]> => {
|
search = async (searchString: string): Promise<string[]> => {
|
||||||
|
|
Loading…
Reference in New Issue