part of 'database.dart'; @DataClassName('RawRule') class Rules extends Table { @override String get tableName => 'rules'; IntColumn get id => integer()(); TextColumn get value => text()(); @override Set get primaryKey => {id}; } @DriftAccessor(tables: [Rules, ProfileRuleLinks]) class RulesDao extends DatabaseAccessor with _$RulesDaoMixin { RulesDao(super.attachedDatabase); Selectable allGlobalAddedRules() { return _get(); } Selectable allProfileAddedRules(int profileId) { return _get(profileId: profileId, scene: RuleScene.added); } Selectable allProfileDisabledRules(int profileId) { return _get(profileId: profileId, scene: RuleScene.disabled); } Selectable allAddedRules(int profileId) { final disabledIdsQuery = selectOnly(profileRuleLinks) ..addColumns([profileRuleLinks.ruleId]) ..where( profileRuleLinks.profileId.equals(profileId) & profileRuleLinks.scene.equalsValue(RuleScene.disabled), ); final query = select(rules).join([ innerJoin(profileRuleLinks, profileRuleLinks.ruleId.equalsExp(rules.id)), ]); query.where( (profileRuleLinks.profileId.isNull() | (profileRuleLinks.profileId.equals(profileId) & profileRuleLinks.scene.equalsValue(RuleScene.added))) & profileRuleLinks.ruleId.isNotInQuery(disabledIdsQuery), ); query.orderBy([ OrderingTerm.desc( profileRuleLinks.profileId.isNull().caseMatch( when: {const Constant(true): const Constant(1)}, orElse: const Constant(0), ), ), OrderingTerm.desc(profileRuleLinks.order), ]); return query.map((row) { final ruleData = row.readTable(rules); final order = row.read(profileRuleLinks.order); return ruleData.toRule(order); }); } void restoreWithBatch( Batch batch, Iterable rules, Iterable links, ) { batch.insertAllOnConflictUpdate( this.rules, rules.map((item) => item.toCompanion()), ); final ruleIds = rules.map((item) => item.id); batch.deleteWhere(this.rules, (t) => t.id.isNotIn(ruleIds)); batch.insertAllOnConflictUpdate( profileRuleLinks, links.map((item) => item.toCompanion()), ); final linkKeys = links.map((item) => item.key); batch.deleteWhere(profileRuleLinks, (t) => t.id.isNotIn(linkKeys)); } Future delRules(Iterable ruleIds) { return _delAll(ruleIds); } Future putGlobalRule(Rule rule) { return _put(rule); } Future putProfileAddedRule(int profileId, Rule rule) { return _put(rule, profileId: profileId, scene: RuleScene.added); } Future putProfileDisabledRule(int profileId, Rule rule) { return _put(rule, profileId: profileId, scene: RuleScene.added); } Future putGlobalRules(Iterable rules) { return _putAll(rules); } Future setGlobalRules(Iterable rules) { return _set(rules); } Future putDisabledLink(int profileId, int ruleId) async { return await profileRuleLinks.insertOnConflictUpdate( ProfileRuleLink( ruleId: ruleId, profileId: profileId, scene: RuleScene.disabled, ).toCompanion(), ); } Future delDisabledLink(int profileId, int ruleId) async { return await profileRuleLinks.deleteOne( ProfileRuleLink( profileId: profileId, ruleId: ruleId, scene: RuleScene.disabled, ).toCompanion(), ); } Future orderGlobalRule({ required int ruleId, required String order, }) async { return await _order(ruleId: ruleId, order: order); } Future orderProfileAddedRule( int profileId, { required int ruleId, required String order, }) async { return await _order( ruleId: ruleId, order: order, profileId: profileId, scene: RuleScene.added, ); } Selectable _get({int? profileId, RuleScene? scene}) { final query = select(rules).join([ innerJoin(profileRuleLinks, profileRuleLinks.ruleId.equalsExp(rules.id)), ]); query.where( profileId == null ? profileRuleLinks.profileId.isNull() : profileRuleLinks.profileId.equals(profileId) & profileRuleLinks.scene.equalsValue(scene), ); query.orderBy([ OrderingTerm.desc(profileRuleLinks.order), OrderingTerm.desc(profileRuleLinks.id), ]); return query.map((row) { return row.readTable(rules).toRule(row.read(profileRuleLinks.order)); }); } Future _order({ required int ruleId, required String order, int? profileId, RuleScene? scene, }) async { final stmt = profileRuleLinks.update(); stmt.where((t) { return (profileId == null ? t.profileId.isNull() : t.profileId.equals(profileId)) & t.ruleId.equals(ruleId) & t.scene.equalsValue(scene); }); return await stmt.write(ProfileRuleLinksCompanion(order: Value(order))); } Future _put(Rule rule, {int? profileId, RuleScene? scene}) async { return transaction(() async { final row = await rules.insertOnConflictUpdate(rule.toCompanion()); if (row == 0) { return 0; } return await profileRuleLinks.insertOnConflictUpdate( ProfileRuleLink( ruleId: rule.id, profileId: profileId, scene: scene, ).toCompanion(), ); }); } Future _delAll(Iterable ruleIds) async { await rules.deleteWhere((t) => t.id.isIn(ruleIds)); } Future _putAll( Iterable rules, { int? profileId, RuleScene? scene, }) async { await batch((b) { b.insertAllOnConflictUpdate( this.rules, rules.map((item) => item.toCompanion()), ); b.insertAllOnConflictUpdate( profileRuleLinks, rules.map( (item) => ProfileRuleLink( ruleId: item.id, profileId: profileId, scene: scene, ).toCompanion(), ), ); }); } Future _set( Iterable rules, { int? profileId, RuleScene? scene, }) async { await batch((b) { b.insertAllOnConflictUpdate( this.rules, rules.map((item) => item.toCompanion()), ); b.deleteWhere( profileRuleLinks, (t) => (profileId == null ? t.profileId.isNull() : t.profileId.equals(profileId)) & (scene == null ? const Constant(true) : t.scene.equalsValue(scene)), ); b.insertAllOnConflictUpdate( profileRuleLinks, rules.map( (item) => ProfileRuleLink( ruleId: item.id, profileId: profileId, scene: scene, ).toCompanion(), ), ); b.deleteWhere(this.rules, (r) { final linkedIds = selectOnly(profileRuleLinks); linkedIds.addColumns([profileRuleLinks.ruleId]); return r.id.isNotInQuery(linkedIds); }); }); } } extension RawRuleExt on RawRule { Rule toRule([String? order]) { return Rule(id: id, value: value, order: order); } } extension RulesCompanionExt on Rule { RulesCompanion toCompanion() { return RulesCompanion.insert(id: Value(id), value: value); } }