diff --git a/ChaosBot/Database/Controller.cs b/ChaosBot/Database/Controller.cs index f99aceb..50d4c6e 100644 --- a/ChaosBot/Database/Controller.cs +++ b/ChaosBot/Database/Controller.cs @@ -14,6 +14,17 @@ namespace ChaosBot.Database static SqliteConnection _conn = new SqliteConnection($"Data Source={System.IO.Directory.GetCurrentDirectory()}/{Program.Cfg.GetValue("Bot:Database")}"); private static Logger _logger = Program._logger; + /// + /// Run a raw query on the database + /// + /// + /// string query = "TRUNCATE SomeTable"; + /// Controller.RawQuery(query); + /// + /// Raw query to execute + /// Whether to read the output and return it as a DataFrame + /// Whether to throw any exceptions or to log and shrug. + /// public static DataTable RawQuery(string query, bool readOutput = true, bool throwError = false) { DataTable dt = new DataTable(); @@ -22,21 +33,26 @@ namespace ChaosBot.Database { using (_conn) { + // Open the SQLite connection _conn.Open(); + // Start creating the command and assign the query given SqliteCommand cmd = _conn.CreateCommand(); cmd.CommandText = query; - + if (readOutput) { + // output needs to be read, make a reader and fill the datatable with the data SqliteDataReader executeReader = cmd.ExecuteReader(CommandBehavior.SingleResult); dt.Load(executeReader); } else { + // output does not need to be read, just run the query without reading cmd.ExecuteNonQuery(); } + // Clean up after ourselves _conn.Close(); } } @@ -44,24 +60,47 @@ namespace ChaosBot.Database { if (throwError) { + // If we throw any exception, just throw it so other code can handle it throw; } + // We handle the exception, log it and be done _logger.Fatal($"Database.Controller.RawQuery: Exception [{ex}] thrown, <[{ex.Message}]>."); } return dt; } + /// + /// Insert a list of parameters into a table in the database + /// + /// + /// string table = "SomeTable"; + /// Dictionary<string, object> parameters = new Dictionary<string, object> + /// { + /// { "someInt", 123 }, + /// { "someString", "asdf" }, + /// { "someChar", 'x' } + /// } + /// + /// Controller.InsertQuery(table, parameters); + /// + /// Table to insert into + /// List of parameters to insert to the row. Every type is a key public static void InsertQuery(string table, Dictionary parameters) { try { using (_conn) { + // Open the SQLite connection _conn.Open(); + // Start the command creation SqliteCommand cmd = _conn.CreateCommand(); + + // Build the command bit by bit + // INSERT INTO {table} (key1, key2, key3) VALUES (@key1,@key2,@key3) StringBuilder commandText = new StringBuilder(); commandText.Append("INSERT INTO "); commandText.Append(table); @@ -77,20 +116,27 @@ namespace ChaosBot.Database foreach (string key in parameters.Keys) { + // We use @key to indicate the parameter placeholder commandText.Append($"@{key},"); } + // Remove the trailing comma commandText.Remove(commandText.Length - 1, 1); commandText.Append(")"); + // Assign onto QueryCommand cmd.CommandText = commandText.ToString(); + // Replace all the parameters to the query foreach (string key in parameters.Keys) { cmd.Parameters.AddWithValue($"@{key}", parameters.GetValueOrDefault(key)); } + // Prepare the parameters cmd.Prepare(); + + // Execute, do not return anything cmd.ExecuteNonQuery(); _conn.Close(); @@ -102,20 +148,44 @@ namespace ChaosBot.Database } } + /// + /// Update rows in the database + /// + /// + /// string table = "SomeTable"; + /// Dictionary<string, object> values = new Dictionary<string, object> + /// { + /// {"key", "newValue"} + /// }; + /// Dictionary<string, object> parameters = new Dictionary<string, object> + /// { + /// {"key", "oldValue"} + /// }; + /// Controller.UpdateQuery(table, values, parameters); + /// + /// Table to update data in + /// List of keys to set. Equivalent of SQL: SET {key} = {value} + /// List of filters to apply in the SQL WHERE condition public static void UpdateQuery(string table, Dictionary values, Dictionary parameters) { try { using (_conn) { + // Open SQLite connection _conn.Open(); + // Create the command SqliteCommand cmd = _conn.CreateCommand(); + + // Build the commandtext + // UPDATE {table} SET {key}=@val_{key} WHERE {key}=@fil_{key} StringBuilder commandText = new StringBuilder(); commandText.Append("UPDATE "); commandText.Append(table); commandText.Append(" SET "); + // Build the list of values List updateList = new List(); foreach (string key in values.Keys) { @@ -123,26 +193,35 @@ namespace ChaosBot.Database cmd.Parameters.AddWithValue($@"val_{key}", values.GetValueOrDefault(key)); } + // Append the list of values, comma-separated commandText.Append(string.Join(", ", updateList)); + // Build the list of filters List filterList = new List(); foreach (string key in parameters.Keys) { filterList.Add($"{key}=@fil_{key} "); cmd.Parameters.AddWithValue($"@fil_{key}", parameters.GetValueOrDefault(key)); } - + if (filterList.Count > 0) { + // Prepend with WHERE if there are parameters commandText.Append("WHERE "); + // Append the list of filters AND separated commandText.Append(string.Join("AND ", filterList)); } + // Assign the command cmd.CommandText = commandText.ToString(); - Console.WriteLine(commandText.ToString()); + + // Prepare the parameters cmd.Prepare(); + + // Execute, do not return cmd.ExecuteNonQuery(); + // Close connection _conn.Close(); } } diff --git a/ChaosBot/Database/Repository/RaffleRepository.cs b/ChaosBot/Database/Repository/RaffleRepository.cs index b7c3204..5cc87f1 100644 --- a/ChaosBot/Database/Repository/RaffleRepository.cs +++ b/ChaosBot/Database/Repository/RaffleRepository.cs @@ -11,6 +11,10 @@ namespace ChaosBot.Database.Repository { private static readonly string Table = "RaffleTable"; + /// + /// Fetch all Raffles + /// + /// List of raffles public static Raffle[] All() { DataTable dataTable = Controller.SelectQuery(Table); @@ -28,6 +32,11 @@ namespace ChaosBot.Database.Repository return raffles.ToArray(); } + /// + /// Fetch all Raffles filtered by guildId + /// + /// + /// List of raffles public static Raffle[] All(string guildId) { Dictionary filterDict = new Dictionary(); @@ -48,6 +57,10 @@ namespace ChaosBot.Database.Repository return raffles.ToArray(); } + /// + /// Count amount of Raffles + /// + /// Amount of raffles public static int Count() { DataTable dataTable = Controller.SelectQuery(Table, "COUNT(*)"); @@ -55,6 +68,11 @@ namespace ChaosBot.Database.Repository return Convert.ToInt32(dataTable.Rows[0]["COUNT(*)"]); } + /// + /// Count amount of Raffles filtered by guildId + /// + /// + /// Amount of raffles public static int Count(string guildId) { Dictionary filterDict = new Dictionary(); @@ -64,7 +82,13 @@ namespace ChaosBot.Database.Repository return Convert.ToInt32(dataTable.Rows[0]["COUNT(*)"]); } - + + /// + /// Count amount of Raffles filtered by guildId + /// + /// + /// + /// Amount of raffles public static int Count(string userId, string guildId) { Dictionary filterDict = new Dictionary(); @@ -76,6 +100,11 @@ namespace ChaosBot.Database.Repository return Convert.ToInt32(dataTable.Rows[0]["COUNT(*)"]); } + /// + /// Get all Raffles from a user + /// + /// + /// List of raffles public static Raffle[] SelectUser(string userId) { Dictionary filterDict = new Dictionary(); @@ -96,6 +125,12 @@ namespace ChaosBot.Database.Repository return raffles.ToArray(); } + /// + /// Get all Raffles from a user filtered by guild + /// + /// + /// + /// List of raffles public static Raffle[] SelectUser(string userId, string guildId) { Dictionary filterDict = new Dictionary(); @@ -117,6 +152,10 @@ namespace ChaosBot.Database.Repository return raffles.ToArray(); } + /// + /// Insert a Raffle into the database + /// + /// public static void Insert(Raffle raffle) { Dictionary dict = new Dictionary(); @@ -127,6 +166,10 @@ namespace ChaosBot.Database.Repository Controller.InsertQuery(Table, dict); } + /// + /// Insert a List of Raffles into the database + /// + /// public static void MassInsert(List raffles) { foreach (var raf in raffles) @@ -140,6 +183,11 @@ namespace ChaosBot.Database.Repository } } + /// + /// Pick a random raffle from the database filtered to a guild + /// + /// + /// Random raffle public static Raffle PickRandom(string guildId) { Dictionary filterDict = new Dictionary(); @@ -155,6 +203,10 @@ namespace ChaosBot.Database.Repository return new Raffle(idFetch, userIdFetch, guildIdFetch); } + /// + /// Clear all Raffles for a given guild + /// + /// public static void ClearRaffle(string guildId) { Dictionary filterDict = new Dictionary(); @@ -164,6 +216,10 @@ namespace ChaosBot.Database.Repository Controller.DeleteQuery(Table, filterDict); } + /// + /// Delete a Raffle by id + /// + /// public static void Delete(int id) { Dictionary filterDict = new Dictionary();