Files
MrbWebLibre/app/lib/features/bangs/data/database/definitions.drift
T
2026-03-27 19:55:11 +01:00

296 lines
8.2 KiB
Plaintext

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';
import 'package:weblibre/features/bangs/data/models/search_history_entry.dart';
CREATE TABLE bang (
"trigger" TEXT NOT NULL,
"group" ENUM(BangGroup) NOT NULL,
website_name TEXT NOT NULL,
domain TEXT NOT NULL,
url_template TEXT NOT NULL,
category TEXT,
sub_category TEXT,
format TEXT MAPPED BY `const BangFormatConverter()`,
additional_triggers TEXT MAPPED BY `const TriggerListConverter()`,
searxng_api BOOL NOT NULL DEFAULT FALSE,
snap_domain TEXT,
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
);
CREATE TABLE bang_frequency (
"trigger" TEXT NOT NULL,
"group" ENUM(BangGroup) NOT NULL,
frequency INTEGER NOT NULL,
last_used DATETIME NOT NULL,
PRIMARY KEY ("trigger", "group"),
FOREIGN KEY ("trigger", "group") REFERENCES bang ("trigger", "group") ON DELETE CASCADE
);
CREATE TABLE bang_history (
search_query TEXT UNIQUE NOT NULL,
"trigger" TEXT NOT NULL,
"group" ENUM(BangGroup) NOT NULL,
search_date DATETIME NOT NULL,
FOREIGN KEY ("trigger", "group") REFERENCES bang ("trigger", "group") ON DELETE CASCADE
);
CREATE VIRTUAL TABLE bang_fts
USING fts5(
trigger,
website_name,
content=bang,
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.*,
bf.frequency,
bf.last_used
FROM
bang b
LEFT JOIN
bang_frequency bf ON b."trigger" = bf."trigger" AND b."group" = bf."group";
-- Triggers to keep the FTS index up to date.
CREATE TRIGGER bang_after_insert AFTER INSERT ON bang BEGIN
INSERT INTO
bang_fts(rowid, "trigger", website_name)
VALUES (new.rowid, new."trigger", new.website_name);
END;
CREATE TRIGGER bang_after_delete AFTER DELETE ON bang BEGIN
INSERT INTO
bang_fts(bang_fts, rowid, "trigger", website_name)
VALUES('delete', old.rowid, old."trigger", old.website_name);
END;
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;
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
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
*,
MIN(weighted_rank) AS weighted_rank
FROM combined_results
GROUP BY "trigger", "group"
ORDER BY
weighted_rank ASC,
frequency NULLS LAST;
queryBangsBasic WITH BangData:
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 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
*,
MIN(weighted_rank) AS weighted_rank
FROM combined_results
GROUP BY "trigger", "group"
ORDER BY
weighted_rank ASC,
frequency NULLS LAST;
categoriesJson:
WITH categories AS (
SELECT
b.category,
json_group_array(
DISTINCT b.sub_category
ORDER BY b.sub_category
) AS sub_categories
FROM
bang b
WHERE
b.category IS NOT NULL AND
b.sub_category IS NOT NULL
GROUP BY b.category
ORDER BY b.category
)
SELECT
json_group_object(
c.category,
json(c.sub_categories)
) AS categories_json
FROM categories c;
searchHistoryEntries WITH SearchHistoryEntry:
SELECT *
FROM bang_history
ORDER BY search_date DESC
LIMIT :limit;
evictHistoryEntries:
DELETE FROM bang_history
WHERE rowid IN (
SELECT rowid
FROM bang_history
ORDER BY search_date DESC
LIMIT -1 OFFSET :limit
);