diff --git a/app/lib/features/bangs/data/database/database.drift.dart b/app/lib/features/bangs/data/database/database.drift.dart index edf8d938..639c8312 100644 --- a/app/lib/features/bangs/data/database/database.drift.dart +++ b/app/lib/features/bangs/data/database/database.drift.dart @@ -13,10 +13,12 @@ abstract class $BangDatabase extends i0.GeneratedDatabase { $BangDatabase(i0.QueryExecutor e) : super(e); $BangDatabaseManager get managers => $BangDatabaseManager(this); late final i1.BangTable bang = i1.BangTable(this); + late final i1.BangTriggers bangTriggers = i1.BangTriggers(this); late final i1.BangSync bangSync = i1.BangSync(this); late final i1.BangFrequency bangFrequency = i1.BangFrequency(this); late final i1.BangHistory bangHistory = i1.BangHistory(this); late final i1.BangFts bangFts = i1.BangFts(this); + late final i1.BangTriggersFts bangTriggersFts = i1.BangTriggersFts(this); late final i1.BangDataView bangDataView = i1.BangDataView(this); late final i2.BangDao bangDao = i2.BangDao(this as i3.BangDatabase); late final i4.SyncDao syncDao = i4.SyncDao(this as i3.BangDatabase); @@ -29,49 +31,100 @@ abstract class $BangDatabase extends i0.GeneratedDatabase { @override List get allSchemaEntities => [ bang, + bangTriggers, + i1.idxBangTriggersLookup, + i1.bangTriggersAfterInsert, + i1.bangTriggersAfterUpdate, bangSync, bangFrequency, bangHistory, bangFts, + bangTriggersFts, bangDataView, i1.bangAfterInsert, i1.bangAfterDelete, i1.bangAfterUpdate, + i1.bangTriggersAfterInsertFts, + i1.bangTriggersAfterDeleteFts, + i1.bangTriggersAfterUpdateFts, ]; @override - i0.StreamQueryUpdateRules get streamUpdateRules => - const i0.StreamQueryUpdateRules([ - i0.WritePropagation( - on: i0.TableUpdateQuery.onTableName( - 'bang', - limitUpdateKind: i0.UpdateKind.delete, - ), - result: [ - i0.TableUpdate('bang_frequency', kind: i0.UpdateKind.delete), - ], - ), - i0.WritePropagation( - on: i0.TableUpdateQuery.onTableName( - 'bang', - limitUpdateKind: i0.UpdateKind.insert, - ), - result: [i0.TableUpdate('bang_fts', kind: i0.UpdateKind.insert)], - ), - i0.WritePropagation( - on: i0.TableUpdateQuery.onTableName( - 'bang', - limitUpdateKind: i0.UpdateKind.delete, - ), - result: [i0.TableUpdate('bang_fts', kind: i0.UpdateKind.insert)], - ), - i0.WritePropagation( - on: i0.TableUpdateQuery.onTableName( - 'bang', - limitUpdateKind: i0.UpdateKind.update, - ), - result: [i0.TableUpdate('bang_fts', kind: i0.UpdateKind.insert)], - ), - ]); + i0.StreamQueryUpdateRules + get streamUpdateRules => const i0.StreamQueryUpdateRules([ + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang', + limitUpdateKind: i0.UpdateKind.delete, + ), + result: [i0.TableUpdate('bang_triggers', kind: i0.UpdateKind.delete)], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang', + limitUpdateKind: i0.UpdateKind.insert, + ), + result: [i0.TableUpdate('bang_triggers', kind: i0.UpdateKind.insert)], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang', + limitUpdateKind: i0.UpdateKind.update, + ), + result: [ + i0.TableUpdate('bang_triggers', kind: i0.UpdateKind.delete), + i0.TableUpdate('bang_triggers', kind: i0.UpdateKind.insert), + ], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang', + limitUpdateKind: i0.UpdateKind.delete, + ), + result: [i0.TableUpdate('bang_frequency', kind: i0.UpdateKind.delete)], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang', + limitUpdateKind: i0.UpdateKind.insert, + ), + result: [i0.TableUpdate('bang_fts', kind: i0.UpdateKind.insert)], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang', + limitUpdateKind: i0.UpdateKind.delete, + ), + result: [i0.TableUpdate('bang_fts', kind: i0.UpdateKind.insert)], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang', + limitUpdateKind: i0.UpdateKind.update, + ), + result: [i0.TableUpdate('bang_fts', kind: i0.UpdateKind.insert)], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang_triggers', + limitUpdateKind: i0.UpdateKind.insert, + ), + result: [i0.TableUpdate('bang_triggers_fts', kind: i0.UpdateKind.insert)], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang_triggers', + limitUpdateKind: i0.UpdateKind.delete, + ), + result: [i0.TableUpdate('bang_triggers_fts', kind: i0.UpdateKind.insert)], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName( + 'bang_triggers', + limitUpdateKind: i0.UpdateKind.update, + ), + result: [i0.TableUpdate('bang_triggers_fts', kind: i0.UpdateKind.insert)], + ), + ]); } class $BangDatabaseManager { @@ -79,6 +132,8 @@ class $BangDatabaseManager { $BangDatabaseManager(this._db); i1.$BangTableTableManager get bang => i1.$BangTableTableManager(_db, _db.bang); + i1.$BangTriggersTableManager get bangTriggers => + i1.$BangTriggersTableManager(_db, _db.bangTriggers); i1.$BangSyncTableManager get bangSync => i1.$BangSyncTableManager(_db, _db.bangSync); i1.$BangFrequencyTableManager get bangFrequency => @@ -87,6 +142,8 @@ class $BangDatabaseManager { i1.$BangHistoryTableManager(_db, _db.bangHistory); i1.$BangFtsTableManager get bangFts => i1.$BangFtsTableManager(_db, _db.bangFts); + i1.$BangTriggersFtsTableManager get bangTriggersFts => + i1.$BangTriggersFtsTableManager(_db, _db.bangTriggersFts); } extension DefineFunctions on i6.CommonDatabase { diff --git a/app/lib/features/bangs/data/database/definitions.drift b/app/lib/features/bangs/data/database/definitions.drift index 658a3f05..0b0d20fe 100644 --- a/app/lib/features/bangs/data/database/definitions.drift +++ b/app/lib/features/bangs/data/database/definitions.drift @@ -1,4 +1,5 @@ import 'package:weblibre/features/bangs/data/database/drift/converters/bang_format.dart'; +import 'package:weblibre/features/bangs/data/database/drift/converters/trigger_list.dart'; import 'package:weblibre/features/bangs/data/models/bang_data.dart'; import 'package:weblibre/features/bangs/data/models/bang_group.dart'; import 'package:weblibre/features/bangs/data/models/bang.dart'; @@ -13,9 +14,47 @@ CREATE TABLE bang ( category TEXT, sub_category TEXT, format TEXT MAPPED BY `const BangFormatConverter()`, + additional_triggers TEXT MAPPED BY `const TriggerListConverter()`, PRIMARY KEY ("trigger", "group") ) WITH Bang; +CREATE TABLE bang_triggers ( + "trigger" TEXT NOT NULL, + "group" ENUM(BangGroup) NOT NULL, + additional_trigger TEXT NOT NULL, + PRIMARY KEY ("trigger", "group", additional_trigger), + FOREIGN KEY ("trigger", "group") REFERENCES bang ("trigger", "group") ON DELETE CASCADE +); +CREATE INDEX idx_bang_triggers_lookup ON bang_triggers (additional_trigger, "group"); + +-- Trigger to populate bang_triggers when inserting a new bang +CREATE TRIGGER bang_triggers_after_insert AFTER INSERT ON bang +WHEN new.additional_triggers IS NOT NULL +BEGIN + INSERT INTO bang_triggers("trigger", "group", additional_trigger) + SELECT + new."trigger", + new."group", + json_each.value + FROM json_each(new.additional_triggers); +END; + +-- Trigger to update bang_triggers when updating a bang +CREATE TRIGGER bang_triggers_after_update AFTER UPDATE ON bang BEGIN + -- Delete old additional triggers + DELETE FROM bang_triggers + WHERE "trigger" = old."trigger" AND "group" = old."group"; + + -- Insert new additional triggers if they exist + INSERT INTO bang_triggers("trigger", "group", additional_trigger) + SELECT + new."trigger", + new."group", + json_each.value + FROM json_each(new.additional_triggers) + WHERE new.additional_triggers IS NOT NULL; +END; + CREATE TABLE bang_sync ( "group" ENUM(BangGroup) PRIMARY KEY NOT NULL, last_sync DATETIME NOT NULL @@ -46,6 +85,13 @@ CREATE VIRTUAL TABLE bang_fts prefix='2 3' ); +CREATE VIRTUAL TABLE bang_triggers_fts + USING fts5( + additional_trigger, + content=bang_triggers, + prefix='2 3' + ); + CREATE VIEW bang_data_view WITH BangData AS SELECT b.*, @@ -76,59 +122,137 @@ CREATE TRIGGER bang_after_update AFTER UPDATE ON bang BEGIN VALUES (new.rowid, new."trigger", new.website_name); END; -optimizeFtsIndex: +CREATE TRIGGER bang_triggers_after_insert_fts AFTER INSERT ON bang_triggers BEGIN + INSERT INTO + bang_triggers_fts(rowid, additional_trigger) + VALUES (new.rowid, new.additional_trigger); +END; +CREATE TRIGGER bang_triggers_after_delete_fts AFTER DELETE ON bang_triggers BEGIN + INSERT INTO + bang_triggers_fts(bang_triggers_fts, rowid, additional_trigger) + VALUES('delete', old.rowid, old.additional_trigger); +END; +CREATE TRIGGER bang_triggers_after_update_fts AFTER UPDATE ON bang_triggers BEGIN + INSERT INTO + bang_triggers_fts(bang_triggers_fts, rowid, additional_trigger) + VALUES('delete', old.rowid, old.additional_trigger); + INSERT INTO + bang_triggers_fts(rowid, additional_trigger) + VALUES (new.rowid, new.additional_trigger); +END; + +optimizeBangFtsIndex: INSERT INTO bang_fts(bang_fts) VALUES ('optimize'); +optimizeTriggerFtsIndex: + INSERT INTO bang_triggers_fts(bang_triggers_fts) VALUES ('optimize'); + queryBangs WITH BangData: WITH weights AS ( SELECT - -- Customize these weights (higher = more important) - 10.0 AS "trigger", -- Title matches are most important - 5.0 AS website_name -- URL matches are quite important + 10.0 AS "trigger", + 8.0 AS additional_trigger, + 5.0 AS website_name + ), + bang_results AS ( + SELECT + b.*, + bf.frequency, + bf.last_used, + bm25(bang_fts, weights."trigger", weights.website_name) AS weighted_rank + FROM + bang_fts(:query) fts + INNER JOIN + bang b ON b.rowid = fts.rowid + LEFT JOIN + bang_frequency bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" + CROSS JOIN weights + ), + trigger_results AS ( + SELECT + b.*, + bf.frequency, + bf.last_used, + bm25(bang_triggers_fts, weights.additional_trigger) AS weighted_rank + FROM + bang_triggers_fts(:query) tfts + INNER JOIN + bang_triggers bt ON bt.rowid = tfts.rowid + INNER JOIN + bang b ON b."trigger" = bt."trigger" AND b."group" = bt."group" + LEFT JOIN + bang_frequency bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" + CROSS JOIN weights + ), + combined_results AS ( + SELECT * FROM bang_results + UNION ALL + SELECT * FROM trigger_results ) SELECT - b.*, - bf.frequency, - bf.last_used, - bm25(bang_fts, weights."trigger", weights.website_name) AS weighted_rank - FROM - bang_fts(:query) fts - INNER JOIN - bang b ON b.rowid = fts.rowid - LEFT JOIN - bang_frequency bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" - CROSS JOIN - weights + *, + MIN(weighted_rank) AS weighted_rank + FROM combined_results + GROUP BY "trigger", "group" ORDER BY - weighted_rank ASC, - bf.frequency NULLS LAST; + weighted_rank ASC, + frequency NULLS LAST; queryBangsBasic WITH BangData: WITH weights AS ( SELECT - -- Customize these weights (higher = more important) - 10.0 AS "trigger", -- Title matches are most important - 5.0 AS website_name -- URL matches are quite important + 10.0 AS "trigger", + 8.0 AS additional_trigger, + 5.0 AS website_name + ), + bang_results AS ( + SELECT + b.*, + bf.frequency, + bf.last_used, + bm25(bang_fts, weights."trigger", weights.website_name) AS weighted_rank + FROM + bang_fts fts + INNER JOIN + bang b ON b.rowid = fts.rowid + LEFT JOIN + bang_frequency bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" + CROSS JOIN weights + WHERE + fts."trigger" LIKE :query OR + fts.website_name LIKE :query + ), + trigger_results AS ( + SELECT + b.*, + bf.frequency, + bf.last_used, + bm25(bang_triggers_fts, weights.additional_trigger) AS weighted_rank + FROM + bang_triggers_fts tfts + INNER JOIN + bang_triggers bt ON bt.rowid = tfts.rowid + INNER JOIN + bang b ON b."trigger" = bt."trigger" AND b."group" = bt."group" + LEFT JOIN + bang_frequency bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" + CROSS JOIN weights + WHERE + tfts.additional_trigger LIKE :query + ), + combined_results AS ( + SELECT * FROM bang_results + UNION ALL + SELECT * FROM trigger_results ) SELECT - b.*, - bf.frequency, - bf.last_used, - bm25(bang_fts, weights."trigger", weights.website_name) AS weighted_rank - FROM - bang_fts fts - INNER JOIN - bang b ON b.rowid = fts.rowid - LEFT JOIN - bang_frequency bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" - CROSS JOIN - weights - WHERE - fts."trigger" LIKE :query OR - fts.website_name LIKE :query + *, + MIN(weighted_rank) AS weighted_rank + FROM combined_results + GROUP BY "trigger", "group" ORDER BY - weighted_rank ASC, - bf.frequency NULLS LAST; + weighted_rank ASC, + frequency NULLS LAST; categoriesJson: WITH categories AS ( diff --git a/app/lib/features/bangs/data/database/definitions.drift.dart b/app/lib/features/bangs/data/database/definitions.drift.dart index 9dd043bc..a5858154 100644 --- a/app/lib/features/bangs/data/database/definitions.drift.dart +++ b/app/lib/features/bangs/data/database/definitions.drift.dart @@ -7,10 +7,12 @@ import 'package:weblibre/features/bangs/data/database/definitions.drift.dart' as i3; import 'package:weblibre/features/bangs/data/database/drift/converters/bang_format.dart' as i4; -import 'package:weblibre/features/bangs/data/models/bang_data.dart' as i5; -import 'package:drift/internal/modular.dart' as i6; +import 'package:weblibre/features/bangs/data/database/drift/converters/trigger_list.dart' + as i5; +import 'package:weblibre/features/bangs/data/models/bang_data.dart' as i6; +import 'package:drift/internal/modular.dart' as i7; import 'package:weblibre/features/bangs/data/models/search_history_entry.dart' - as i7; + as i8; typedef $BangTableCreateCompanionBuilder = i3.BangCompanion Function({ @@ -22,6 +24,7 @@ typedef $BangTableCreateCompanionBuilder = i0.Value category, i0.Value subCategory, i0.Value?> format, + i0.Value?> additionalTriggers, i0.Value rowid, }); typedef $BangTableUpdateCompanionBuilder = @@ -34,6 +37,7 @@ typedef $BangTableUpdateCompanionBuilder = i0.Value category, i0.Value subCategory, i0.Value?> format, + i0.Value?> additionalTriggers, i0.Value rowid, }); @@ -91,6 +95,12 @@ class $BangTableFilterComposer column: $table.format, builder: (column) => i0.ColumnWithTypeConverterFilters(column), ); + + i0.ColumnWithTypeConverterFilters?, Set, String> + get additionalTriggers => $composableBuilder( + column: $table.additionalTriggers, + builder: (column) => i0.ColumnWithTypeConverterFilters(column), + ); } class $BangTableOrderingComposer @@ -141,6 +151,11 @@ class $BangTableOrderingComposer column: $table.format, builder: (column) => i0.ColumnOrderings(column), ); + + i0.ColumnOrderings get additionalTriggers => $composableBuilder( + column: $table.additionalTriggers, + builder: (column) => i0.ColumnOrderings(column), + ); } class $BangTableAnnotationComposer @@ -181,6 +196,12 @@ class $BangTableAnnotationComposer i0.GeneratedColumnWithTypeConverter?, String> get format => $composableBuilder(column: $table.format, builder: (column) => column); + + i0.GeneratedColumnWithTypeConverter?, String> + get additionalTriggers => $composableBuilder( + column: $table.additionalTriggers, + builder: (column) => column, + ); } class $BangTableTableManager @@ -222,6 +243,8 @@ class $BangTableTableManager i0.Value category = const i0.Value.absent(), i0.Value subCategory = const i0.Value.absent(), i0.Value?> format = const i0.Value.absent(), + i0.Value?> additionalTriggers = + const i0.Value.absent(), i0.Value rowid = const i0.Value.absent(), }) => i3.BangCompanion( trigger: trigger, @@ -232,6 +255,7 @@ class $BangTableTableManager category: category, subCategory: subCategory, format: format, + additionalTriggers: additionalTriggers, rowid: rowid, ), createCompanionCallback: @@ -244,6 +268,8 @@ class $BangTableTableManager i0.Value category = const i0.Value.absent(), i0.Value subCategory = const i0.Value.absent(), i0.Value?> format = const i0.Value.absent(), + i0.Value?> additionalTriggers = + const i0.Value.absent(), i0.Value rowid = const i0.Value.absent(), }) => i3.BangCompanion.insert( trigger: trigger, @@ -254,6 +280,7 @@ class $BangTableTableManager category: category, subCategory: subCategory, format: format, + additionalTriggers: additionalTriggers, rowid: rowid, ), withReferenceMapper: (p0) => p0 @@ -278,6 +305,179 @@ typedef $BangTableProcessedTableManager = i1.Bang, i0.PrefetchHooks Function() >; +typedef $BangTriggersCreateCompanionBuilder = + i3.BangTriggersCompanion Function({ + required String trigger, + required i2.BangGroup group, + required String additionalTrigger, + i0.Value rowid, + }); +typedef $BangTriggersUpdateCompanionBuilder = + i3.BangTriggersCompanion Function({ + i0.Value trigger, + i0.Value group, + i0.Value additionalTrigger, + i0.Value rowid, + }); + +class $BangTriggersFilterComposer + extends i0.Composer { + $BangTriggersFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.ColumnFilters get trigger => $composableBuilder( + column: $table.trigger, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnWithTypeConverterFilters + get group => $composableBuilder( + column: $table.group, + builder: (column) => i0.ColumnWithTypeConverterFilters(column), + ); + + i0.ColumnFilters get additionalTrigger => $composableBuilder( + column: $table.additionalTrigger, + builder: (column) => i0.ColumnFilters(column), + ); +} + +class $BangTriggersOrderingComposer + extends i0.Composer { + $BangTriggersOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.ColumnOrderings get trigger => $composableBuilder( + column: $table.trigger, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get group => $composableBuilder( + column: $table.group, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get additionalTrigger => $composableBuilder( + column: $table.additionalTrigger, + builder: (column) => i0.ColumnOrderings(column), + ); +} + +class $BangTriggersAnnotationComposer + extends i0.Composer { + $BangTriggersAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.GeneratedColumn get trigger => + $composableBuilder(column: $table.trigger, builder: (column) => column); + + i0.GeneratedColumnWithTypeConverter get group => + $composableBuilder(column: $table.group, builder: (column) => column); + + i0.GeneratedColumn get additionalTrigger => $composableBuilder( + column: $table.additionalTrigger, + builder: (column) => column, + ); +} + +class $BangTriggersTableManager + extends + i0.RootTableManager< + i0.GeneratedDatabase, + i3.BangTriggers, + i3.BangTrigger, + i3.$BangTriggersFilterComposer, + i3.$BangTriggersOrderingComposer, + i3.$BangTriggersAnnotationComposer, + $BangTriggersCreateCompanionBuilder, + $BangTriggersUpdateCompanionBuilder, + ( + i3.BangTrigger, + i0.BaseReferences< + i0.GeneratedDatabase, + i3.BangTriggers, + i3.BangTrigger + >, + ), + i3.BangTrigger, + i0.PrefetchHooks Function() + > { + $BangTriggersTableManager(i0.GeneratedDatabase db, i3.BangTriggers table) + : super( + i0.TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + i3.$BangTriggersFilterComposer($db: db, $table: table), + createOrderingComposer: () => + i3.$BangTriggersOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + i3.$BangTriggersAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + i0.Value trigger = const i0.Value.absent(), + i0.Value group = const i0.Value.absent(), + i0.Value additionalTrigger = const i0.Value.absent(), + i0.Value rowid = const i0.Value.absent(), + }) => i3.BangTriggersCompanion( + trigger: trigger, + group: group, + additionalTrigger: additionalTrigger, + rowid: rowid, + ), + createCompanionCallback: + ({ + required String trigger, + required i2.BangGroup group, + required String additionalTrigger, + i0.Value rowid = const i0.Value.absent(), + }) => i3.BangTriggersCompanion.insert( + trigger: trigger, + group: group, + additionalTrigger: additionalTrigger, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), i0.BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + ), + ); +} + +typedef $BangTriggersProcessedTableManager = + i0.ProcessedTableManager< + i0.GeneratedDatabase, + i3.BangTriggers, + i3.BangTrigger, + i3.$BangTriggersFilterComposer, + i3.$BangTriggersOrderingComposer, + i3.$BangTriggersAnnotationComposer, + $BangTriggersCreateCompanionBuilder, + $BangTriggersUpdateCompanionBuilder, + ( + i3.BangTrigger, + i0.BaseReferences< + i0.GeneratedDatabase, + i3.BangTriggers, + i3.BangTrigger + >, + ), + i3.BangTrigger, + i0.PrefetchHooks Function() + >; typedef $BangSyncCreateCompanionBuilder = i3.BangSyncCompanion Function({ i0.Value group, @@ -944,6 +1144,142 @@ typedef $BangFtsProcessedTableManager = i3.BangFt, i0.PrefetchHooks Function() >; +typedef $BangTriggersFtsCreateCompanionBuilder = + i3.BangTriggersFtsCompanion Function({ + required String additionalTrigger, + i0.Value rowid, + }); +typedef $BangTriggersFtsUpdateCompanionBuilder = + i3.BangTriggersFtsCompanion Function({ + i0.Value additionalTrigger, + i0.Value rowid, + }); + +class $BangTriggersFtsFilterComposer + extends i0.Composer { + $BangTriggersFtsFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.ColumnFilters get additionalTrigger => $composableBuilder( + column: $table.additionalTrigger, + builder: (column) => i0.ColumnFilters(column), + ); +} + +class $BangTriggersFtsOrderingComposer + extends i0.Composer { + $BangTriggersFtsOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.ColumnOrderings get additionalTrigger => $composableBuilder( + column: $table.additionalTrigger, + builder: (column) => i0.ColumnOrderings(column), + ); +} + +class $BangTriggersFtsAnnotationComposer + extends i0.Composer { + $BangTriggersFtsAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.GeneratedColumn get additionalTrigger => $composableBuilder( + column: $table.additionalTrigger, + builder: (column) => column, + ); +} + +class $BangTriggersFtsTableManager + extends + i0.RootTableManager< + i0.GeneratedDatabase, + i3.BangTriggersFts, + i3.BangTriggersFt, + i3.$BangTriggersFtsFilterComposer, + i3.$BangTriggersFtsOrderingComposer, + i3.$BangTriggersFtsAnnotationComposer, + $BangTriggersFtsCreateCompanionBuilder, + $BangTriggersFtsUpdateCompanionBuilder, + ( + i3.BangTriggersFt, + i0.BaseReferences< + i0.GeneratedDatabase, + i3.BangTriggersFts, + i3.BangTriggersFt + >, + ), + i3.BangTriggersFt, + i0.PrefetchHooks Function() + > { + $BangTriggersFtsTableManager( + i0.GeneratedDatabase db, + i3.BangTriggersFts table, + ) : super( + i0.TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + i3.$BangTriggersFtsFilterComposer($db: db, $table: table), + createOrderingComposer: () => + i3.$BangTriggersFtsOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + i3.$BangTriggersFtsAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + i0.Value additionalTrigger = const i0.Value.absent(), + i0.Value rowid = const i0.Value.absent(), + }) => i3.BangTriggersFtsCompanion( + additionalTrigger: additionalTrigger, + rowid: rowid, + ), + createCompanionCallback: + ({ + required String additionalTrigger, + i0.Value rowid = const i0.Value.absent(), + }) => i3.BangTriggersFtsCompanion.insert( + additionalTrigger: additionalTrigger, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), i0.BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + ), + ); +} + +typedef $BangTriggersFtsProcessedTableManager = + i0.ProcessedTableManager< + i0.GeneratedDatabase, + i3.BangTriggersFts, + i3.BangTriggersFt, + i3.$BangTriggersFtsFilterComposer, + i3.$BangTriggersFtsOrderingComposer, + i3.$BangTriggersFtsAnnotationComposer, + $BangTriggersFtsCreateCompanionBuilder, + $BangTriggersFtsUpdateCompanionBuilder, + ( + i3.BangTriggersFt, + i0.BaseReferences< + i0.GeneratedDatabase, + i3.BangTriggersFts, + i3.BangTriggersFt + >, + ), + i3.BangTriggersFt, + i0.PrefetchHooks Function() + >; class BangTable extends i0.Table with i0.TableInfo { @override @@ -1019,6 +1355,15 @@ class BangTable extends i0.Table with i0.TableInfo { requiredDuringInsert: false, $customConstraints: '', ).withConverter?>(i3.BangTable.$converterformat); + late final i0.GeneratedColumnWithTypeConverter?, String> + additionalTriggers = i0.GeneratedColumn( + 'additional_triggers', + aliasedName, + true, + type: i0.DriftSqlType.string, + requiredDuringInsert: false, + $customConstraints: '', + ).withConverter?>(i3.BangTable.$converteradditionalTriggers); @override List get $columns => [ trigger, @@ -1029,6 +1374,7 @@ class BangTable extends i0.Table with i0.TableInfo { category, subCategory, format, + additionalTriggers, ]; @override String get aliasedName => _alias ?? actualTableName; @@ -1077,6 +1423,12 @@ class BangTable extends i0.Table with i0.TableInfo { data['${effectivePrefix}format'], ), ), + additionalTriggers: i3.BangTable.$converteradditionalTriggers.fromSql( + attachedDatabase.typeMapping.read( + i0.DriftSqlType.string, + data['${effectivePrefix}additional_triggers'], + ), + ), ); } @@ -1089,6 +1441,8 @@ class BangTable extends i0.Table with i0.TableInfo { const i0.EnumIndexConverter(i2.BangGroup.values); static i0.TypeConverter?, String?> $converterformat = const i4.BangFormatConverter(); + static i0.TypeConverter?, String?> $converteradditionalTriggers = + const i5.TriggerListConverter(); @override List get customConstraints => const [ 'PRIMARY KEY("trigger", "group")', @@ -1106,6 +1460,7 @@ class BangCompanion extends i0.UpdateCompanion { final i0.Value category; final i0.Value subCategory; final i0.Value?> format; + final i0.Value?> additionalTriggers; final i0.Value rowid; const BangCompanion({ this.trigger = const i0.Value.absent(), @@ -1116,6 +1471,7 @@ class BangCompanion extends i0.UpdateCompanion { this.category = const i0.Value.absent(), this.subCategory = const i0.Value.absent(), this.format = const i0.Value.absent(), + this.additionalTriggers = const i0.Value.absent(), this.rowid = const i0.Value.absent(), }); BangCompanion.insert({ @@ -1127,6 +1483,7 @@ class BangCompanion extends i0.UpdateCompanion { this.category = const i0.Value.absent(), this.subCategory = const i0.Value.absent(), this.format = const i0.Value.absent(), + this.additionalTriggers = const i0.Value.absent(), this.rowid = const i0.Value.absent(), }) : trigger = i0.Value(trigger), group = i0.Value(group), @@ -1142,6 +1499,7 @@ class BangCompanion extends i0.UpdateCompanion { i0.Expression? category, i0.Expression? subCategory, i0.Expression? format, + i0.Expression? additionalTriggers, i0.Expression? rowid, }) { return i0.RawValuesInsertable({ @@ -1153,6 +1511,7 @@ class BangCompanion extends i0.UpdateCompanion { if (category != null) 'category': category, if (subCategory != null) 'sub_category': subCategory, if (format != null) 'format': format, + if (additionalTriggers != null) 'additional_triggers': additionalTriggers, if (rowid != null) 'rowid': rowid, }); } @@ -1166,6 +1525,7 @@ class BangCompanion extends i0.UpdateCompanion { i0.Value? category, i0.Value? subCategory, i0.Value?>? format, + i0.Value?>? additionalTriggers, i0.Value? rowid, }) { return i3.BangCompanion( @@ -1177,6 +1537,7 @@ class BangCompanion extends i0.UpdateCompanion { category: category ?? this.category, subCategory: subCategory ?? this.subCategory, format: format ?? this.format, + additionalTriggers: additionalTriggers ?? this.additionalTriggers, rowid: rowid ?? this.rowid, ); } @@ -1212,6 +1573,13 @@ class BangCompanion extends i0.UpdateCompanion { i3.BangTable.$converterformat.toSql(format.value), ); } + if (additionalTriggers.present) { + map['additional_triggers'] = i0.Variable( + i3.BangTable.$converteradditionalTriggers.toSql( + additionalTriggers.value, + ), + ); + } if (rowid.present) { map['rowid'] = i0.Variable(rowid.value); } @@ -1229,12 +1597,277 @@ class BangCompanion extends i0.UpdateCompanion { ..write('category: $category, ') ..write('subCategory: $subCategory, ') ..write('format: $format, ') + ..write('additionalTriggers: $additionalTriggers, ') ..write('rowid: $rowid') ..write(')')) .toString(); } } +class BangTriggers extends i0.Table + with i0.TableInfo { + @override + final i0.GeneratedDatabase attachedDatabase; + final String? _alias; + BangTriggers(this.attachedDatabase, [this._alias]); + late final i0.GeneratedColumn trigger = i0.GeneratedColumn( + 'trigger', + aliasedName, + false, + type: i0.DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + late final i0.GeneratedColumnWithTypeConverter group = + i0.GeneratedColumn( + 'group', + aliasedName, + false, + type: i0.DriftSqlType.int, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ).withConverter(i3.BangTriggers.$convertergroup); + late final i0.GeneratedColumn additionalTrigger = + i0.GeneratedColumn( + 'additional_trigger', + aliasedName, + false, + type: i0.DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: 'NOT NULL', + ); + @override + List get $columns => [trigger, group, additionalTrigger]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'bang_triggers'; + @override + Set get $primaryKey => { + trigger, + group, + additionalTrigger, + }; + @override + i3.BangTrigger map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return i3.BangTrigger( + trigger: attachedDatabase.typeMapping.read( + i0.DriftSqlType.string, + data['${effectivePrefix}trigger'], + )!, + group: i3.BangTriggers.$convertergroup.fromSql( + attachedDatabase.typeMapping.read( + i0.DriftSqlType.int, + data['${effectivePrefix}group'], + )!, + ), + additionalTrigger: attachedDatabase.typeMapping.read( + i0.DriftSqlType.string, + data['${effectivePrefix}additional_trigger'], + )!, + ); + } + + @override + BangTriggers createAlias(String alias) { + return BangTriggers(attachedDatabase, alias); + } + + static i0.JsonTypeConverter2 $convertergroup = + const i0.EnumIndexConverter(i2.BangGroup.values); + @override + List get customConstraints => const [ + 'PRIMARY KEY("trigger", "group", additional_trigger)', + 'FOREIGN KEY("trigger", "group")REFERENCES bang("trigger", "group")ON DELETE CASCADE', + ]; + @override + bool get dontWriteConstraints => true; +} + +class BangTrigger extends i0.DataClass + implements i0.Insertable { + final String trigger; + final i2.BangGroup group; + final String additionalTrigger; + const BangTrigger({ + required this.trigger, + required this.group, + required this.additionalTrigger, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['trigger'] = i0.Variable(trigger); + { + map['group'] = i0.Variable( + i3.BangTriggers.$convertergroup.toSql(group), + ); + } + map['additional_trigger'] = i0.Variable(additionalTrigger); + return map; + } + + factory BangTrigger.fromJson( + Map json, { + i0.ValueSerializer? serializer, + }) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return BangTrigger( + trigger: serializer.fromJson(json['trigger']), + group: i3.BangTriggers.$convertergroup.fromJson( + serializer.fromJson(json['group']), + ), + additionalTrigger: serializer.fromJson( + json['additional_trigger'], + ), + ); + } + @override + Map toJson({i0.ValueSerializer? serializer}) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return { + 'trigger': serializer.toJson(trigger), + 'group': serializer.toJson( + i3.BangTriggers.$convertergroup.toJson(group), + ), + 'additional_trigger': serializer.toJson(additionalTrigger), + }; + } + + i3.BangTrigger copyWith({ + String? trigger, + i2.BangGroup? group, + String? additionalTrigger, + }) => i3.BangTrigger( + trigger: trigger ?? this.trigger, + group: group ?? this.group, + additionalTrigger: additionalTrigger ?? this.additionalTrigger, + ); + BangTrigger copyWithCompanion(i3.BangTriggersCompanion data) { + return BangTrigger( + trigger: data.trigger.present ? data.trigger.value : this.trigger, + group: data.group.present ? data.group.value : this.group, + additionalTrigger: data.additionalTrigger.present + ? data.additionalTrigger.value + : this.additionalTrigger, + ); + } + + @override + String toString() { + return (StringBuffer('BangTrigger(') + ..write('trigger: $trigger, ') + ..write('group: $group, ') + ..write('additionalTrigger: $additionalTrigger') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(trigger, group, additionalTrigger); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is i3.BangTrigger && + other.trigger == this.trigger && + other.group == this.group && + other.additionalTrigger == this.additionalTrigger); +} + +class BangTriggersCompanion extends i0.UpdateCompanion { + final i0.Value trigger; + final i0.Value group; + final i0.Value additionalTrigger; + final i0.Value rowid; + const BangTriggersCompanion({ + this.trigger = const i0.Value.absent(), + this.group = const i0.Value.absent(), + this.additionalTrigger = const i0.Value.absent(), + this.rowid = const i0.Value.absent(), + }); + BangTriggersCompanion.insert({ + required String trigger, + required i2.BangGroup group, + required String additionalTrigger, + this.rowid = const i0.Value.absent(), + }) : trigger = i0.Value(trigger), + group = i0.Value(group), + additionalTrigger = i0.Value(additionalTrigger); + static i0.Insertable custom({ + i0.Expression? trigger, + i0.Expression? group, + i0.Expression? additionalTrigger, + i0.Expression? rowid, + }) { + return i0.RawValuesInsertable({ + if (trigger != null) 'trigger': trigger, + if (group != null) 'group': group, + if (additionalTrigger != null) 'additional_trigger': additionalTrigger, + if (rowid != null) 'rowid': rowid, + }); + } + + i3.BangTriggersCompanion copyWith({ + i0.Value? trigger, + i0.Value? group, + i0.Value? additionalTrigger, + i0.Value? rowid, + }) { + return i3.BangTriggersCompanion( + trigger: trigger ?? this.trigger, + group: group ?? this.group, + additionalTrigger: additionalTrigger ?? this.additionalTrigger, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (trigger.present) { + map['trigger'] = i0.Variable(trigger.value); + } + if (group.present) { + map['group'] = i0.Variable( + i3.BangTriggers.$convertergroup.toSql(group.value), + ); + } + if (additionalTrigger.present) { + map['additional_trigger'] = i0.Variable(additionalTrigger.value); + } + if (rowid.present) { + map['rowid'] = i0.Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('BangTriggersCompanion(') + ..write('trigger: $trigger, ') + ..write('group: $group, ') + ..write('additionalTrigger: $additionalTrigger, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +i0.Index get idxBangTriggersLookup => i0.Index( + 'idx_bang_triggers_lookup', + 'CREATE INDEX idx_bang_triggers_lookup ON bang_triggers (additional_trigger, "group")', +); +i0.Trigger get bangTriggersAfterInsert => i0.Trigger( + 'CREATE TRIGGER bang_triggers_after_insert AFTER INSERT ON bang WHEN new.additional_triggers IS NOT NULL BEGIN INSERT INTO bang_triggers ("trigger", "group", additional_trigger) SELECT new."trigger", new."group", json_each.value FROM json_each(new.additional_triggers);END', + 'bang_triggers_after_insert', +); +i0.Trigger get bangTriggersAfterUpdate => i0.Trigger( + 'CREATE TRIGGER bang_triggers_after_update AFTER UPDATE ON bang BEGIN DELETE FROM bang_triggers WHERE "trigger" = old."trigger" AND "group" = old."group";INSERT INTO bang_triggers ("trigger", "group", additional_trigger) SELECT new."trigger", new."group", json_each.value FROM json_each(new.additional_triggers)WHERE new.additional_triggers IS NOT NULL;END', + 'bang_triggers_after_update', +); + class BangSync extends i0.Table with i0.TableInfo { @override final i0.GeneratedDatabase attachedDatabase; @@ -2176,7 +2809,167 @@ class BangFtsCompanion extends i0.UpdateCompanion { } } -class BangDataView extends i0.ViewInfo +class BangTriggersFts extends i0.Table + with + i0.TableInfo, + i0.VirtualTableInfo { + @override + final i0.GeneratedDatabase attachedDatabase; + final String? _alias; + BangTriggersFts(this.attachedDatabase, [this._alias]); + late final i0.GeneratedColumn additionalTrigger = + i0.GeneratedColumn( + 'additional_trigger', + aliasedName, + false, + type: i0.DriftSqlType.string, + requiredDuringInsert: true, + $customConstraints: '', + ); + @override + List get $columns => [additionalTrigger]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'bang_triggers_fts'; + @override + Set get $primaryKey => const {}; + @override + i3.BangTriggersFt map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return i3.BangTriggersFt( + additionalTrigger: attachedDatabase.typeMapping.read( + i0.DriftSqlType.string, + data['${effectivePrefix}additional_trigger'], + )!, + ); + } + + @override + BangTriggersFts createAlias(String alias) { + return BangTriggersFts(attachedDatabase, alias); + } + + @override + bool get dontWriteConstraints => true; + @override + String get moduleAndArgs => + 'fts5(additional_trigger, content=bang_triggers, prefix=\'2 3\')'; +} + +class BangTriggersFt extends i0.DataClass + implements i0.Insertable { + final String additionalTrigger; + const BangTriggersFt({required this.additionalTrigger}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['additional_trigger'] = i0.Variable(additionalTrigger); + return map; + } + + factory BangTriggersFt.fromJson( + Map json, { + i0.ValueSerializer? serializer, + }) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return BangTriggersFt( + additionalTrigger: serializer.fromJson( + json['additional_trigger'], + ), + ); + } + @override + Map toJson({i0.ValueSerializer? serializer}) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return { + 'additional_trigger': serializer.toJson(additionalTrigger), + }; + } + + i3.BangTriggersFt copyWith({String? additionalTrigger}) => i3.BangTriggersFt( + additionalTrigger: additionalTrigger ?? this.additionalTrigger, + ); + BangTriggersFt copyWithCompanion(i3.BangTriggersFtsCompanion data) { + return BangTriggersFt( + additionalTrigger: data.additionalTrigger.present + ? data.additionalTrigger.value + : this.additionalTrigger, + ); + } + + @override + String toString() { + return (StringBuffer('BangTriggersFt(') + ..write('additionalTrigger: $additionalTrigger') + ..write(')')) + .toString(); + } + + @override + int get hashCode => additionalTrigger.hashCode; + @override + bool operator ==(Object other) => + identical(this, other) || + (other is i3.BangTriggersFt && + other.additionalTrigger == this.additionalTrigger); +} + +class BangTriggersFtsCompanion extends i0.UpdateCompanion { + final i0.Value additionalTrigger; + final i0.Value rowid; + const BangTriggersFtsCompanion({ + this.additionalTrigger = const i0.Value.absent(), + this.rowid = const i0.Value.absent(), + }); + BangTriggersFtsCompanion.insert({ + required String additionalTrigger, + this.rowid = const i0.Value.absent(), + }) : additionalTrigger = i0.Value(additionalTrigger); + static i0.Insertable custom({ + i0.Expression? additionalTrigger, + i0.Expression? rowid, + }) { + return i0.RawValuesInsertable({ + if (additionalTrigger != null) 'additional_trigger': additionalTrigger, + if (rowid != null) 'rowid': rowid, + }); + } + + i3.BangTriggersFtsCompanion copyWith({ + i0.Value? additionalTrigger, + i0.Value? rowid, + }) { + return i3.BangTriggersFtsCompanion( + additionalTrigger: additionalTrigger ?? this.additionalTrigger, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (additionalTrigger.present) { + map['additional_trigger'] = i0.Variable(additionalTrigger.value); + } + if (rowid.present) { + map['rowid'] = i0.Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('BangTriggersFtsCompanion(') + ..write('additionalTrigger: $additionalTrigger, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class BangDataView extends i0.ViewInfo implements i0.HasResultSet { final String? _alias; @override @@ -2192,6 +2985,7 @@ class BangDataView extends i0.ViewInfo category, subCategory, format, + additionalTriggers, frequency, lastUsed, ]; @@ -2207,9 +3001,9 @@ class BangDataView extends i0.ViewInfo @override BangDataView get asDslTable => this; @override - i5.BangData map(Map data, {String? tablePrefix}) { + i6.BangData map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return i5.BangData( + return i6.BangData( websiteName: attachedDatabase.typeMapping.read( i0.DriftSqlType.string, data['${effectivePrefix}website_name'], @@ -2246,6 +3040,12 @@ class BangDataView extends i0.ViewInfo data['${effectivePrefix}format'], ), ), + additionalTriggers: i3.BangTable.$converteradditionalTriggers.fromSql( + attachedDatabase.typeMapping.read( + i0.DriftSqlType.string, + data['${effectivePrefix}additional_triggers'], + ), + ), frequency: attachedDatabase.typeMapping.read( i0.DriftSqlType.int, data['${effectivePrefix}frequency'], @@ -2310,6 +3110,13 @@ class BangDataView extends i0.ViewInfo true, type: i0.DriftSqlType.string, ).withConverter?>(i3.BangTable.$converterformat); + late final i0.GeneratedColumnWithTypeConverter?, String> + additionalTriggers = i0.GeneratedColumn( + 'additional_triggers', + aliasedName, + true, + type: i0.DriftSqlType.string, + ).withConverter?>(i3.BangTable.$converteradditionalTriggers); late final i0.GeneratedColumn frequency = i0.GeneratedColumn( 'frequency', aliasedName, @@ -2346,10 +3153,22 @@ i0.Trigger get bangAfterUpdate => i0.Trigger( 'CREATE TRIGGER bang_after_update AFTER UPDATE ON bang BEGIN INSERT INTO bang_fts (bang_fts, "rowid", "trigger", website_name) VALUES (\'delete\', old."rowid", old."trigger", old.website_name);INSERT INTO bang_fts ("rowid", "trigger", website_name) VALUES (new."rowid", new."trigger", new.website_name);END', 'bang_after_update', ); +i0.Trigger get bangTriggersAfterInsertFts => i0.Trigger( + 'CREATE TRIGGER bang_triggers_after_insert_fts AFTER INSERT ON bang_triggers BEGIN INSERT INTO bang_triggers_fts ("rowid", additional_trigger) VALUES (new."rowid", new.additional_trigger);END', + 'bang_triggers_after_insert_fts', +); +i0.Trigger get bangTriggersAfterDeleteFts => i0.Trigger( + 'CREATE TRIGGER bang_triggers_after_delete_fts AFTER DELETE ON bang_triggers BEGIN INSERT INTO bang_triggers_fts (bang_triggers_fts, "rowid", additional_trigger) VALUES (\'delete\', old."rowid", old.additional_trigger);END', + 'bang_triggers_after_delete_fts', +); +i0.Trigger get bangTriggersAfterUpdateFts => i0.Trigger( + 'CREATE TRIGGER bang_triggers_after_update_fts AFTER UPDATE ON bang_triggers BEGIN INSERT INTO bang_triggers_fts (bang_triggers_fts, "rowid", additional_trigger) VALUES (\'delete\', old."rowid", old.additional_trigger);INSERT INTO bang_triggers_fts ("rowid", additional_trigger) VALUES (new."rowid", new.additional_trigger);END', + 'bang_triggers_after_update_fts', +); -class DefinitionsDrift extends i6.ModularAccessor { +class DefinitionsDrift extends i7.ModularAccessor { DefinitionsDrift(i0.GeneratedDatabase db) : super(db); - Future optimizeFtsIndex() { + Future optimizeBangFtsIndex() { return customInsert( 'INSERT INTO bang_fts (bang_fts) VALUES (\'optimize\')', variables: [], @@ -2357,13 +3176,21 @@ class DefinitionsDrift extends i6.ModularAccessor { ); } - i0.Selectable queryBangs({required String query}) { + Future optimizeTriggerFtsIndex() { + return customInsert( + 'INSERT INTO bang_triggers_fts (bang_triggers_fts) VALUES (\'optimize\')', + variables: [], + updates: {bangTriggersFts}, + ); + } + + i0.Selectable queryBangs({required String query}) { return customSelect( - 'WITH weights AS (SELECT 10.0 AS "trigger", 5.0 AS website_name) SELECT b.*, bf.frequency, bf.last_used, bm25(bang_fts, weights."trigger", weights.website_name) AS weighted_rank FROM bang_fts(?1)AS fts INNER JOIN bang AS b ON b."rowid" = fts."rowid" LEFT JOIN bang_frequency AS bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" CROSS JOIN weights ORDER BY weighted_rank ASC, bf.frequency NULLS LAST', + 'WITH weights AS (SELECT 10.0 AS "trigger", 8.0 AS additional_trigger, 5.0 AS website_name), bang_results AS (SELECT b.*, bf.frequency, bf.last_used, bm25(bang_fts, weights."trigger", weights.website_name) AS weighted_rank FROM bang_fts(?1)AS fts INNER JOIN bang AS b ON b."rowid" = fts."rowid" LEFT JOIN bang_frequency AS bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" CROSS JOIN weights), trigger_results AS (SELECT b.*, bf.frequency, bf.last_used, bm25(bang_triggers_fts, weights.additional_trigger) AS weighted_rank FROM bang_triggers_fts(?1)AS tfts INNER JOIN bang_triggers AS bt ON bt."rowid" = tfts."rowid" INNER JOIN bang AS b ON b."trigger" = bt."trigger" AND b."group" = bt."group" LEFT JOIN bang_frequency AS bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" CROSS JOIN weights), combined_results AS (SELECT * FROM bang_results UNION ALL SELECT * FROM trigger_results) SELECT *, MIN(weighted_rank) AS weighted_rank FROM combined_results GROUP BY "trigger", "group" ORDER BY weighted_rank ASC, frequency NULLS LAST', variables: [i0.Variable(query)], - readsFrom: {bangFrequency, bangFts, bang}, + readsFrom: {bangFrequency, bangFts, bang, bangTriggersFts, bangTriggers}, ).map( - (i0.QueryRow row) => i5.BangData( + (i0.QueryRow row) => i6.BangData( websiteName: row.read('website_name'), domain: row.read('domain'), trigger: row.read('trigger'), @@ -2374,19 +3201,22 @@ class DefinitionsDrift extends i6.ModularAccessor { format: i3.BangTable.$converterformat.fromSql( row.readNullable('format'), ), + additionalTriggers: i3.BangTable.$converteradditionalTriggers.fromSql( + row.readNullable('additional_triggers'), + ), frequency: row.readNullable('frequency'), lastUsed: row.readNullable('last_used'), ), ); } - i0.Selectable queryBangsBasic({required String query}) { + i0.Selectable queryBangsBasic({required String query}) { return customSelect( - 'WITH weights AS (SELECT 10.0 AS "trigger", 5.0 AS website_name) SELECT b.*, bf.frequency, bf.last_used, bm25(bang_fts, weights."trigger", weights.website_name) AS weighted_rank FROM bang_fts AS fts INNER JOIN bang AS b ON b."rowid" = fts."rowid" LEFT JOIN bang_frequency AS bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" CROSS JOIN weights WHERE fts."trigger" LIKE ?1 OR fts.website_name LIKE ?1 ORDER BY weighted_rank ASC, bf.frequency NULLS LAST', + 'WITH weights AS (SELECT 10.0 AS "trigger", 8.0 AS additional_trigger, 5.0 AS website_name), bang_results AS (SELECT b.*, bf.frequency, bf.last_used, bm25(bang_fts, weights."trigger", weights.website_name) AS weighted_rank FROM bang_fts AS fts INNER JOIN bang AS b ON b."rowid" = fts."rowid" LEFT JOIN bang_frequency AS bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" CROSS JOIN weights WHERE fts."trigger" LIKE ?1 OR fts.website_name LIKE ?1), trigger_results AS (SELECT b.*, bf.frequency, bf.last_used, bm25(bang_triggers_fts, weights.additional_trigger) AS weighted_rank FROM bang_triggers_fts AS tfts INNER JOIN bang_triggers AS bt ON bt."rowid" = tfts."rowid" INNER JOIN bang AS b ON b."trigger" = bt."trigger" AND b."group" = bt."group" LEFT JOIN bang_frequency AS bf ON b."trigger" = bf."trigger" AND b."group" = bf."group" CROSS JOIN weights WHERE tfts.additional_trigger LIKE ?1), combined_results AS (SELECT * FROM bang_results UNION ALL SELECT * FROM trigger_results) SELECT *, MIN(weighted_rank) AS weighted_rank FROM combined_results GROUP BY "trigger", "group" ORDER BY weighted_rank ASC, frequency NULLS LAST', variables: [i0.Variable(query)], - readsFrom: {bangFrequency, bangFts, bang}, + readsFrom: {bangFrequency, bangFts, bang, bangTriggersFts, bangTriggers}, ).map( - (i0.QueryRow row) => i5.BangData( + (i0.QueryRow row) => i6.BangData( websiteName: row.read('website_name'), domain: row.read('domain'), trigger: row.read('trigger'), @@ -2397,6 +3227,9 @@ class DefinitionsDrift extends i6.ModularAccessor { format: i3.BangTable.$converterformat.fromSql( row.readNullable('format'), ), + additionalTriggers: i3.BangTable.$converteradditionalTriggers.fromSql( + row.readNullable('additional_triggers'), + ), frequency: row.readNullable('frequency'), lastUsed: row.readNullable('last_used'), ), @@ -2411,7 +3244,7 @@ class DefinitionsDrift extends i6.ModularAccessor { ).map((i0.QueryRow row) => row.read('categories_json')); } - i0.Selectable searchHistoryEntries({ + i0.Selectable searchHistoryEntries({ required int limit, }) { return customSelect( @@ -2419,7 +3252,7 @@ class DefinitionsDrift extends i6.ModularAccessor { variables: [i0.Variable(limit)], readsFrom: {bangHistory}, ).map( - (i0.QueryRow row) => i7.SearchHistoryEntry( + (i0.QueryRow row) => i8.SearchHistoryEntry( searchQuery: row.read('search_query'), trigger: row.read('trigger'), searchDate: row.read('search_date'), @@ -2436,16 +3269,22 @@ class DefinitionsDrift extends i6.ModularAccessor { ); } - i3.BangFts get bangFts => i6.ReadDatabaseContainer( + i3.BangFts get bangFts => i7.ReadDatabaseContainer( attachedDatabase, ).resultSet('bang_fts'); - i3.BangTable get bang => i6.ReadDatabaseContainer( + i3.BangTriggersFts get bangTriggersFts => i7.ReadDatabaseContainer( + attachedDatabase, + ).resultSet('bang_triggers_fts'); + i3.BangTable get bang => i7.ReadDatabaseContainer( attachedDatabase, ).resultSet('bang'); - i3.BangFrequency get bangFrequency => i6.ReadDatabaseContainer( + i3.BangFrequency get bangFrequency => i7.ReadDatabaseContainer( attachedDatabase, ).resultSet('bang_frequency'); - i3.BangHistory get bangHistory => i6.ReadDatabaseContainer( + i3.BangTriggers get bangTriggers => i7.ReadDatabaseContainer( + attachedDatabase, + ).resultSet('bang_triggers'); + i3.BangHistory get bangHistory => i7.ReadDatabaseContainer( attachedDatabase, ).resultSet('bang_history'); } diff --git a/app/lib/features/bangs/data/database/drift/converters/trigger_list.dart b/app/lib/features/bangs/data/database/drift/converters/trigger_list.dart new file mode 100644 index 00000000..3509507d --- /dev/null +++ b/app/lib/features/bangs/data/database/drift/converters/trigger_list.dart @@ -0,0 +1,20 @@ +import 'dart:convert'; + +import 'package:drift/drift.dart'; +import 'package:nullability/nullability.dart'; + +class TriggerListConverter extends TypeConverter?, String?> { + const TriggerListConverter(); + + @override + Set? fromSql(String? fromDb) { + return fromDb.mapNotNull( + (value) => (jsonDecode(value) as List).cast().toSet(), + ); + } + + @override + String? toSql(Set? value) { + return value.mapNotNull((value) => jsonEncode(value.toList())); + } +} diff --git a/app/lib/features/bangs/data/models/bang.dart b/app/lib/features/bangs/data/models/bang.dart index a295a239..d767949a 100644 --- a/app/lib/features/bangs/data/models/bang.dart +++ b/app/lib/features/bangs/data/models/bang.dart @@ -79,6 +79,10 @@ class Bang with FastEquatable implements Insertable { @JsonKey(name: 'fmt') final Set? format; + ///Additional triggers that invoke this bang + @JsonKey(name: 'ts') + final Set? additionalTriggers; + String formatQuery(String input) { return (format == null || format!.contains(BangFormat.urlEncodePlaceholder) == true) @@ -121,6 +125,7 @@ class Bang with FastEquatable implements Insertable { this.category, this.subCategory, this.format, + this.additionalTriggers, }); factory Bang.fromJson(Map json) => _$BangFromJson(json); @@ -137,6 +142,7 @@ class Bang with FastEquatable implements Insertable { category, subCategory, format, + additionalTriggers, ]; @override @@ -150,6 +156,7 @@ class Bang with FastEquatable implements Insertable { category: Value.absentIfNull(category), subCategory: Value.absentIfNull(subCategory), format: Value.absentIfNull(format), + additionalTriggers: Value.absentIfNull(additionalTriggers), ).toColumns(nullToAbsent); } } diff --git a/app/lib/features/bangs/data/models/bang.g.dart b/app/lib/features/bangs/data/models/bang.g.dart index 5bd00599..f61da16c 100644 --- a/app/lib/features/bangs/data/models/bang.g.dart +++ b/app/lib/features/bangs/data/models/bang.g.dart @@ -23,6 +23,8 @@ abstract class _$BangCWProxy { Bang format(Set? format); + Bang additionalTriggers(Set? additionalTriggers); + /// Creates a new instance with the provided field values. /// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `Bang(...).copyWith.fieldName(value)`. /// @@ -39,6 +41,7 @@ abstract class _$BangCWProxy { String? category, String? subCategory, Set? format, + Set? additionalTriggers, }); } @@ -73,6 +76,10 @@ class _$BangCWProxyImpl implements _$BangCWProxy { @override Bang format(Set? format) => call(format: format); + @override + Bang additionalTriggers(Set? additionalTriggers) => + call(additionalTriggers: additionalTriggers); + @override /// Creates a new instance with the provided field values. /// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `Bang(...).copyWith.fieldName(value)`. @@ -90,6 +97,7 @@ class _$BangCWProxyImpl implements _$BangCWProxy { Object? category = const $CopyWithPlaceholder(), Object? subCategory = const $CopyWithPlaceholder(), Object? format = const $CopyWithPlaceholder(), + Object? additionalTriggers = const $CopyWithPlaceholder(), }) { return Bang( websiteName: @@ -126,6 +134,10 @@ class _$BangCWProxyImpl implements _$BangCWProxy { ? _value.format // ignore: cast_nullable_to_non_nullable : format as Set?, + additionalTriggers: additionalTriggers == const $CopyWithPlaceholder() + ? _value.additionalTriggers + // ignore: cast_nullable_to_non_nullable + : additionalTriggers as Set?, ); } } @@ -151,6 +163,9 @@ Bang _$BangFromJson(Map json) => Bang( format: (json['fmt'] as List?) ?.map((e) => $enumDecode(_$BangFormatEnumMap, e)) .toSet(), + additionalTriggers: (json['ts'] as List?) + ?.map((e) => e as String) + .toSet(), ); Map _$BangToJson(Bang instance) => { @@ -161,6 +176,7 @@ Map _$BangToJson(Bang instance) => { 'c': instance.category, 'sc': instance.subCategory, 'fmt': instance.format?.map((e) => _$BangFormatEnumMap[e]!).toList(), + 'ts': instance.additionalTriggers?.toList(), }; const _$BangFormatEnumMap = { diff --git a/app/lib/features/bangs/data/models/bang_data.dart b/app/lib/features/bangs/data/models/bang_data.dart index 3829781c..1ed32b52 100644 --- a/app/lib/features/bangs/data/models/bang_data.dart +++ b/app/lib/features/bangs/data/models/bang_data.dart @@ -44,6 +44,7 @@ class BangData extends Bang { super.category, super.subCategory, super.format, + super.additionalTriggers, int? frequency, this.lastUsed, this.icon, @@ -58,6 +59,7 @@ class BangData extends Bang { super.category, super.subCategory, super.format, + super.additionalTriggers, int? frequency, this.lastUsed, this.icon, diff --git a/app/lib/features/bangs/data/models/bang_data.g.dart b/app/lib/features/bangs/data/models/bang_data.g.dart index 300dd29b..d842d561 100644 --- a/app/lib/features/bangs/data/models/bang_data.g.dart +++ b/app/lib/features/bangs/data/models/bang_data.g.dart @@ -21,6 +21,8 @@ abstract class _$BangDataCWProxy { BangData format(Set? format); + BangData additionalTriggers(Set? additionalTriggers); + BangData frequency(int? frequency); BangData lastUsed(DateTime? lastUsed); @@ -42,6 +44,7 @@ abstract class _$BangDataCWProxy { String? category, String? subCategory, Set? format, + Set? additionalTriggers, int? frequency, DateTime? lastUsed, BrowserIcon? icon, @@ -76,6 +79,10 @@ class _$BangDataCWProxyImpl implements _$BangDataCWProxy { @override BangData format(Set? format) => call(format: format); + @override + BangData additionalTriggers(Set? additionalTriggers) => + call(additionalTriggers: additionalTriggers); + @override BangData frequency(int? frequency) => call(frequency: frequency); @@ -101,6 +108,7 @@ class _$BangDataCWProxyImpl implements _$BangDataCWProxy { Object? category = const $CopyWithPlaceholder(), Object? subCategory = const $CopyWithPlaceholder(), Object? format = const $CopyWithPlaceholder(), + Object? additionalTriggers = const $CopyWithPlaceholder(), Object? frequency = const $CopyWithPlaceholder(), Object? lastUsed = const $CopyWithPlaceholder(), Object? icon = const $CopyWithPlaceholder(), @@ -136,6 +144,10 @@ class _$BangDataCWProxyImpl implements _$BangDataCWProxy { ? _value.format // ignore: cast_nullable_to_non_nullable : format as Set?, + additionalTriggers: additionalTriggers == const $CopyWithPlaceholder() + ? _value.additionalTriggers + // ignore: cast_nullable_to_non_nullable + : additionalTriggers as Set?, frequency: frequency == const $CopyWithPlaceholder() ? _value.frequency // ignore: cast_nullable_to_non_nullable diff --git a/app/lib/features/bangs/data/providers.dart b/app/lib/features/bangs/data/providers.dart index 7fafc82d..4f925dd4 100644 --- a/app/lib/features/bangs/data/providers.dart +++ b/app/lib/features/bangs/data/providers.dart @@ -36,7 +36,7 @@ BangDatabase bangDatabase(Ref ref) { // put the database file, called db.sqlite here, into the documents folder // for your app. final dbFolder = await path_provider.getApplicationDocumentsDirectory(); - final file = File(p.join(dbFolder.path, 'bang2.db')); + final file = File(p.join(dbFolder.path, 'bang3.db')); // Also work around limitations on old Android versions if (Platform.isAndroid) { diff --git a/app/lib/features/bangs/data/providers.g.dart b/app/lib/features/bangs/data/providers.g.dart index f7f9d761..89b2f3b5 100644 --- a/app/lib/features/bangs/data/providers.g.dart +++ b/app/lib/features/bangs/data/providers.g.dart @@ -48,4 +48,4 @@ final class BangDatabaseProvider } } -String _$bangDatabaseHash() => r'35142ef6c747e7c65c3417a2b6fc1c6f41d0411b'; +String _$bangDatabaseHash() => r'e46ec1582f1a21337a302bef1b7963c2e11468d9'; diff --git a/app/lib/features/bangs/domain/repositories/sync.dart b/app/lib/features/bangs/domain/repositories/sync.dart index 021a69d2..60097d0a 100644 --- a/app/lib/features/bangs/domain/repositories/sync.dart +++ b/app/lib/features/bangs/domain/repositories/sync.dart @@ -54,7 +54,8 @@ class BangSyncRepository extends _$BangSyncRepository { remoteBangs: remoteBangs, syncTime: DateTime.now(), ); - await db.definitionsDrift.optimizeFtsIndex(); + await db.definitionsDrift.optimizeBangFtsIndex(); + await db.definitionsDrift.optimizeTriggerFtsIndex(); }); } @@ -84,7 +85,8 @@ class BangSyncRepository extends _$BangSyncRepository { remoteBangs: remoteBangs, syncTime: sourceDate, ); - await db.definitionsDrift.optimizeFtsIndex(); + await db.definitionsDrift.optimizeBangFtsIndex(); + await db.definitionsDrift.optimizeTriggerFtsIndex(); }); } diff --git a/app/lib/features/bangs/domain/repositories/sync.g.dart b/app/lib/features/bangs/domain/repositories/sync.g.dart index cf304c91..f9cc3f84 100644 --- a/app/lib/features/bangs/domain/repositories/sync.g.dart +++ b/app/lib/features/bangs/domain/repositories/sync.g.dart @@ -42,7 +42,7 @@ final class BangSyncRepositoryProvider } String _$bangSyncRepositoryHash() => - r'bb977652087d2ff2cb75b093adcfc45dafa21d2a'; + r'e3ce355e5332ff1fe7ac8ecaa277a431b74f2da0'; abstract class _$BangSyncRepository extends $Notifier { void build(); diff --git a/app/lib/features/bangs/presentation/widgets/bang_details.dart b/app/lib/features/bangs/presentation/widgets/bang_details.dart index 0ea5c28d..f1edc3df 100644 --- a/app/lib/features/bangs/presentation/widgets/bang_details.dart +++ b/app/lib/features/bangs/presentation/widgets/bang_details.dart @@ -19,6 +19,7 @@ */ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:nullability/nullability.dart'; import 'package:weblibre/core/routing/routes.dart'; import 'package:weblibre/features/bangs/data/models/bang_data.dart'; import 'package:weblibre/features/geckoview/domain/repositories/tab.dart'; @@ -106,12 +107,16 @@ class BangDetails extends HookConsumerWidget { ), const SizedBox(width: 8), Expanded( - child: Text( - '!${bangData.trigger}', - style: theme.textTheme.titleSmall, - textAlign: TextAlign.right, - maxLines: 2, - overflow: TextOverflow.ellipsis, + child: Tooltip( + message: + 'Triggers: ${bangData.trigger}${bangData.additionalTriggers.mapNotNull((triggers) => ', ${triggers.map((trigger) => '!$trigger').join(', ')}') ?? ''}', + child: Text( + '!${bangData.trigger}', + style: theme.textTheme.titleSmall, + textAlign: TextAlign.right, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), ), ), ],