using Microsoft.Data.Sqlite; using YKanBan.Storage; using YKanBan.Storage.Workspace; namespace YKanBan.Tests.TestUtilities; /// /// Shared helpers for the storage tests: small SQL conveniences plus opening a /// workspace database with the real migration list. /// public static class SqliteTestHelper { /// /// Executes a non-query SQL statement and returns the affected row count. /// /// An open database connection. /// The statement to execute. /// Name/value pairs bound as SQL parameters. /// The number of affected rows. public static int Exec(SqliteConnection connection, string sql, params (string Name, object? Value)[] parameters) { using var command = connection.CreateCommand(); command.CommandText = sql; foreach ((string name, object? value) in parameters) { command.Parameters.AddWithValue(name, value); } return command.ExecuteNonQuery(); } /// /// Returns the scalar result of a SQL query as a string. /// /// An open database connection. /// The query to execute. /// The scalar result cast to a string. public static string ScalarString(SqliteConnection connection, string sql) { using var command = connection.CreateCommand(); command.CommandText = sql; return (string)command.ExecuteScalar()!; } /// /// Returns the scalar result of a SQL query as a long. /// /// An open database connection. /// The query to execute. /// The scalar result cast to a long. public static long ScalarLong(SqliteConnection connection, string sql) { using var command = connection.CreateCommand(); command.CommandText = sql; return (long)command.ExecuteScalar()!; } /// /// Returns whether a table with the given name exists in the database. /// /// An open database connection. /// The table name to look for. /// when the table exists. public static bool TableExists(SqliteConnection connection, string tableName) { using var command = connection.CreateCommand(); command.CommandText = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=$name;"; command.Parameters.AddWithValue("$name", tableName); return (long)command.ExecuteScalar()! == 1; } /// /// Returns the titles of all columns, ordered by id ascending. /// /// An open database connection. /// The column titles in id order. public static List GetColumnTitles(SqliteConnection connection) { using var command = connection.CreateCommand(); command.CommandText = "SELECT title FROM columns ORDER BY id ASC;"; using var reader = command.ExecuteReader(); var titles = new List(); while (reader.Read()) { titles.Add(reader.GetString(0)); } return titles; } /// /// Returns the descriptions of all columns, ordered by id ascending. /// /// An open database connection. /// The column descriptions in id order. public static List GetColumnDescriptions(SqliteConnection connection) { using var command = connection.CreateCommand(); command.CommandText = "SELECT description FROM columns ORDER BY id ASC;"; using var reader = command.ExecuteReader(); var descriptions = new List(); while (reader.Read()) { descriptions.Add(reader.GetString(0)); } return descriptions; } /// /// Returns all tags as name/color/description tuples, ordered by id ascending. /// /// An open database connection. /// The tags in id order. public static List<(string Name, string Color, string Description)> GetTags(SqliteConnection connection) { using var command = connection.CreateCommand(); command.CommandText = "SELECT name, color, description FROM tags ORDER BY id ASC;"; using var reader = command.ExecuteReader(); var tags = new List<(string, string, string)>(); while (reader.Read()) { tags.Add((reader.GetString(0), reader.GetString(1), reader.GetString(2))); } return tags; } /// /// Opens a workspace database with the real workspace migration list. /// /// The workspace folder path. /// An open, migrated connection. public static SqliteConnection OpenWorkspace(string folderPath) { return SqliteDatabase.Open(WorkspacePaths.Database(folderPath), WorkspaceSchema.Migrations); } }