using System;
using System.Collections.Generic;
using System.Data;
using Microsoft.Data.Sqlite;
using System.IO;
using System.Threading.Tasks;
namespace DiscordBotCore.Database;
public class SqlDatabase
{
private readonly SqliteConnection _Connection;
///
/// Initialize a SQL connection by specifying its private path
///
/// The path to the database (it is starting from ./Data/Resources/)
public SqlDatabase(string fileName)
{
var connectionString = $"Data Source={fileName}";
_Connection = new SqliteConnection(connectionString);
}
///
/// Open the SQL Connection. To close use the Stop() method
///
///
public async Task Open()
{
await _Connection.OpenAsync();
}
///
///
/// Insert into a specified table some values
///
///
/// The table name
/// The values to be inserted (in the correct order and number)
///
public async Task InsertAsync(string tableName, params string[] values)
{
var query = $"INSERT INTO {tableName} VALUES (";
for (var i = 0; i < values.Length; i++)
{
query += $"'{values[i]}'";
if (i != values.Length - 1)
query += ", ";
}
query += ")";
var command = new SqliteCommand(query, _Connection);
await command.ExecuteNonQueryAsync();
}
///
///
/// Insert into a specified table some values
///
///
/// The table name
/// The values to be inserted (in the correct order and number)
///
public void Insert(string tableName, params string[] values)
{
var query = $"INSERT INTO {tableName} VALUES (";
for (var i = 0; i < values.Length; i++)
{
query += $"'{values[i]}'";
if (i != values.Length - 1)
query += ", ";
}
query += ")";
var command = new SqliteCommand(query, _Connection);
command.ExecuteNonQuery();
}
///
/// Remove every row in a table that has a certain propery
///
/// The table name
/// The column name that the search is made by
/// The value that is searched in the specified column
///
public async Task RemoveKeyAsync(string tableName, string KeyName, string KeyValue)
{
var query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
var command = new SqliteCommand(query, _Connection);
await command.ExecuteNonQueryAsync();
}
///
/// Remove every row in a table that has a certain propery
///
/// The table name
/// The column name that the search is made by
/// The value that is searched in the specified column
///
public void RemoveKey(string tableName, string KeyName, string KeyValue)
{
var query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
var command = new SqliteCommand(query, _Connection);
command.ExecuteNonQuery();
}
///
/// Check if the key exists in the table
///
/// The table name
/// The column that the search is made by
/// The value that is searched in the specified column
///
public async Task KeyExistsAsync(string tableName, string keyName, string KeyValue)
{
var query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
if (await ReadDataAsync(query) is not null)
return true;
return false;
}
///
/// Check if the key exists in the table
///
/// The table name
/// The column that the search is made by
/// The value that is searched in the specified column
///
public bool KeyExists(string tableName, string keyName, string KeyValue)
{
var query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
if (ReadData(query) is not null)
return true;
return false;
}
///
/// Set value of a column in a table
///
/// The table name
/// The column that the search is made by
/// The value that is searched in the column specified
/// The column that has to be modified
/// The new value that will replace the old value from the column specified
public async Task SetValueAsync(
string tableName, string keyName, string KeyValue, string ResultColumnName,
string ResultColumnValue)
{
if (!await TableExistsAsync(tableName))
throw new Exception($"Table {tableName} does not exist");
await ExecuteAsync(
$"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'"
);
}
///
/// Set value of a column in a table
///
/// The table name
/// The column that the search is made by
/// The value that is searched in the column specified
/// The column that has to be modified
/// The new value that will replace the old value from the column specified
public void SetValue(
string tableName, string keyName, string KeyValue, string ResultColumnName,
string ResultColumnValue)
{
if (!TableExists(tableName))
throw new Exception($"Table {tableName} does not exist");
Execute($"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
}
///
/// Get value from a column in a table
///
/// The table name
/// The column that the search is made by
/// The value that is searched in the specified column
/// The column that has the result
/// A string that has the requested value (can be null if nothing found)
public async Task GetValueAsync(
string tableName, string keyName, string KeyValue,
string ResultColumnName)
{
if (!await TableExistsAsync(tableName))
throw new Exception($"Table {tableName} does not exist");
return await ReadDataAsync($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
}
///
/// Get value from a column in a table
///
/// The table name
/// The column that the search is made by
/// The value that is searched in the specified column
/// The column that has the result
/// A string that has the requested value (can be null if nothing found)
public string? GetValue(string tableName, string keyName, string KeyValue, string ResultColumnName)
{
if (!TableExists(tableName))
throw new Exception($"Table {tableName} does not exist");
return ReadData($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
}
///
/// Stop the connection to the SQL Database
///
///
public async void Stop()
{
await _Connection.CloseAsync();
}
///
/// Change the structure of a table by adding new columns
///
/// The table name
/// The columns to be added
/// The type of the columns (TEXT, INTEGER, FLOAT, etc)
///
public async Task AddColumnsToTableAsync(string tableName, string[] columns, string TYPE = "TEXT")
{
var command = _Connection.CreateCommand();
command.CommandText = $"SELECT * FROM {tableName}";
var reader = await command.ExecuteReaderAsync();
var tableColumns = new List();
for (var i = 0; i < reader.FieldCount; i++)
tableColumns.Add(reader.GetName(i));
foreach (var column in columns)
if (!tableColumns.Contains(column))
{
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} {TYPE}";
await command.ExecuteNonQueryAsync();
}
}
///
/// Change the structure of a table by adding new columns
///
/// The table name
/// The columns to be added
/// The type of the columns (TEXT, INTEGER, FLOAT, etc)
///
public void AddColumnsToTable(string tableName, string[] columns, string TYPE = "TEXT")
{
var command = _Connection.CreateCommand();
command.CommandText = $"SELECT * FROM {tableName}";
var reader = command.ExecuteReader();
var tableColumns = new List();
for (var i = 0; i < reader.FieldCount; i++)
tableColumns.Add(reader.GetName(i));
foreach (var column in columns)
if (!tableColumns.Contains(column))
{
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} {TYPE}";
command.ExecuteNonQuery();
}
}
///
/// Check if a table exists
///
/// The table name
/// True if the table exists, false if not
public async Task TableExistsAsync(string tableName)
{
var cmd = _Connection.CreateCommand();
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
var result = await cmd.ExecuteScalarAsync();
if (result == null)
return false;
return true;
}
///
/// Check if a table exists
///
/// The table name
/// True if the table exists, false if not
public bool TableExists(string tableName)
{
var cmd = _Connection.CreateCommand();
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
var result = cmd.ExecuteScalar();
if (result == null)
return false;
return true;
}
///
/// Create a table
///
/// The table name
/// The columns of the table
///
public async Task CreateTableAsync(string tableName, params string[] columns)
{
var cmd = _Connection.CreateCommand();
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
await cmd.ExecuteNonQueryAsync();
}
///
/// Create a table
///
/// The table name
/// The columns of the table
///
public void CreateTable(string tableName, params string[] columns)
{
var cmd = _Connection.CreateCommand();
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
cmd.ExecuteNonQuery();
}
///
/// Execute a custom query
///
/// The query
/// The number of rows that the query modified
public async Task ExecuteAsync(string query)
{
if (!_Connection.State.HasFlag(ConnectionState.Open))
await _Connection.OpenAsync();
var command = new SqliteCommand(query, _Connection);
var answer = await command.ExecuteNonQueryAsync();
return answer;
}
///
/// Execute a custom query
///
/// The query
/// The number of rows that the query modified
public int Execute(string query)
{
if (!_Connection.State.HasFlag(ConnectionState.Open))
_Connection.Open();
var command = new SqliteCommand(query, _Connection);
var r = command.ExecuteNonQuery();
return r;
}
///
/// Read data from the result table and return the first row
///
/// The query
/// The result is a string that has all values separated by space character
public async Task ReadDataAsync(string query)
{
if (!_Connection.State.HasFlag(ConnectionState.Open))
await _Connection.OpenAsync();
var command = new SqliteCommand(query, _Connection);
var reader = await command.ExecuteReaderAsync();
var values = new object[reader.FieldCount];
if (reader.Read())
{
reader.GetValues(values);
return string.Join