From fff942cdd954b682ed901f9226a16c3888342f9e Mon Sep 17 00:00:00 2001 From: guthubrx Date: Thu, 9 Jul 2026 04:52:59 +0200 Subject: [PATCH] fix(db): create SQLite indexes for [Indexed] columns --- .../Database/DatabaseConnection.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Grayjay.ClientServer/Database/DatabaseConnection.cs b/Grayjay.ClientServer/Database/DatabaseConnection.cs index 1fca0d27..26f8801c 100644 --- a/Grayjay.ClientServer/Database/DatabaseConnection.cs +++ b/Grayjay.ClientServer/Database/DatabaseConnection.cs @@ -117,6 +117,26 @@ public void EnsureTable(string table, string primaryKey = "ID", bool autoIncr string tableQuery = $"CREATE TABLE {tq}\n({string.Join(",\n", definitions)})"; SQL((x) => x.Execute(tableQuery)); } + + // Create an index for every property marked [Indexed]. Uses + // IF NOT EXISTS so it also repairs existing databases whose table + // predates this: the [Indexed] attribute was declared on columns + // like subscriptionCache.Url/ChannelUrl but never actually created, + // leaving large tables unindexed and forcing a full table scan on + // every lookup (very slow startup for users with big caches). + var indexedProperties = properties + .Where(x => x.GetCustomAttribute() != null); + foreach (var prop in indexedProperties) + { + var ordering = prop.GetCustomAttribute()!.Ordering switch + { + Ordering.Ascending => " ASC", + Ordering.Descending => " DESC", + _ => "" + }; + var indexName = Quote($"idx_{table}_{prop.Name}"); + SQL((x) => x.Execute($"CREATE INDEX IF NOT EXISTS {indexName} ON {tq} ({Quote(prop.Name)}{ordering})")); + } } private string GetSQLType(Type type) {