|
|
|
|
@@ -9,7 +9,7 @@ namespace PluginManager.Database;
|
|
|
|
|
|
|
|
|
|
public class SqlDatabase
|
|
|
|
|
{
|
|
|
|
|
private readonly SQLiteConnection Connection;
|
|
|
|
|
private readonly SQLiteConnection _connection;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initialize a SQL connection by specifing its private path
|
|
|
|
|
@@ -22,7 +22,7 @@ public class SqlDatabase
|
|
|
|
|
if (!File.Exists(fileName))
|
|
|
|
|
SQLiteConnection.CreateFile(fileName);
|
|
|
|
|
var connectionString = $"URI=file:{fileName}";
|
|
|
|
|
Connection = new SQLiteConnection(connectionString);
|
|
|
|
|
_connection = new SQLiteConnection(connectionString);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -32,7 +32,7 @@ public class SqlDatabase
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task Open()
|
|
|
|
|
{
|
|
|
|
|
await Connection.OpenAsync();
|
|
|
|
|
await _connection.OpenAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
@@ -55,7 +55,7 @@ public class SqlDatabase
|
|
|
|
|
|
|
|
|
|
query += ")";
|
|
|
|
|
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
await command.ExecuteNonQueryAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -79,7 +79,7 @@ public class SqlDatabase
|
|
|
|
|
|
|
|
|
|
query += ")";
|
|
|
|
|
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
command.ExecuteNonQuery();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -94,7 +94,7 @@ public class SqlDatabase
|
|
|
|
|
{
|
|
|
|
|
var query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
|
|
|
|
|
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
await command.ExecuteNonQueryAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -109,7 +109,7 @@ public class SqlDatabase
|
|
|
|
|
{
|
|
|
|
|
var query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
|
|
|
|
|
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
command.ExecuteNonQuery();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -224,7 +224,7 @@ public class SqlDatabase
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async void Stop()
|
|
|
|
|
{
|
|
|
|
|
await Connection.CloseAsync();
|
|
|
|
|
await _connection.CloseAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
@@ -236,7 +236,7 @@ public class SqlDatabase
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task AddColumnsToTableAsync(string tableName, string[] columns, string TYPE = "TEXT")
|
|
|
|
|
{
|
|
|
|
|
var command = Connection.CreateCommand();
|
|
|
|
|
var command = _connection.CreateCommand();
|
|
|
|
|
command.CommandText = $"SELECT * FROM {tableName}";
|
|
|
|
|
var reader = await command.ExecuteReaderAsync();
|
|
|
|
|
var tableColumns = new List<string>();
|
|
|
|
|
@@ -260,7 +260,7 @@ public class SqlDatabase
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public void AddColumnsToTable(string tableName, string[] columns, string TYPE = "TEXT")
|
|
|
|
|
{
|
|
|
|
|
var command = Connection.CreateCommand();
|
|
|
|
|
var command = _connection.CreateCommand();
|
|
|
|
|
command.CommandText = $"SELECT * FROM {tableName}";
|
|
|
|
|
var reader = command.ExecuteReader();
|
|
|
|
|
var tableColumns = new List<string>();
|
|
|
|
|
@@ -282,7 +282,7 @@ public class SqlDatabase
|
|
|
|
|
/// <returns>True if the table exists, false if not</returns>
|
|
|
|
|
public async Task<bool> TableExistsAsync(string tableName)
|
|
|
|
|
{
|
|
|
|
|
var cmd = Connection.CreateCommand();
|
|
|
|
|
var cmd = _connection.CreateCommand();
|
|
|
|
|
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
|
|
|
|
|
var result = await cmd.ExecuteScalarAsync();
|
|
|
|
|
|
|
|
|
|
@@ -298,7 +298,7 @@ public class SqlDatabase
|
|
|
|
|
/// <returns>True if the table exists, false if not</returns>
|
|
|
|
|
public bool TableExists(string tableName)
|
|
|
|
|
{
|
|
|
|
|
var cmd = Connection.CreateCommand();
|
|
|
|
|
var cmd = _connection.CreateCommand();
|
|
|
|
|
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
|
|
|
|
|
var result = cmd.ExecuteScalar();
|
|
|
|
|
|
|
|
|
|
@@ -315,7 +315,7 @@ public class SqlDatabase
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task CreateTableAsync(string tableName, params string[] columns)
|
|
|
|
|
{
|
|
|
|
|
var cmd = Connection.CreateCommand();
|
|
|
|
|
var cmd = _connection.CreateCommand();
|
|
|
|
|
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
|
|
|
|
|
await cmd.ExecuteNonQueryAsync();
|
|
|
|
|
}
|
|
|
|
|
@@ -328,7 +328,7 @@ public class SqlDatabase
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public void CreateTable(string tableName, params string[] columns)
|
|
|
|
|
{
|
|
|
|
|
var cmd = Connection.CreateCommand();
|
|
|
|
|
var cmd = _connection.CreateCommand();
|
|
|
|
|
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
|
|
|
|
|
cmd.ExecuteNonQuery();
|
|
|
|
|
}
|
|
|
|
|
@@ -340,9 +340,9 @@ public class SqlDatabase
|
|
|
|
|
/// <returns>The number of rows that the query modified</returns>
|
|
|
|
|
public async Task<int> ExecuteAsync(string query)
|
|
|
|
|
{
|
|
|
|
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
await Connection.OpenAsync();
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
if (!_connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
await _connection.OpenAsync();
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
var answer = await command.ExecuteNonQueryAsync();
|
|
|
|
|
return answer;
|
|
|
|
|
}
|
|
|
|
|
@@ -354,9 +354,9 @@ public class SqlDatabase
|
|
|
|
|
/// <returns>The number of rows that the query modified</returns>
|
|
|
|
|
public int Execute(string query)
|
|
|
|
|
{
|
|
|
|
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
Connection.Open();
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
if (!_connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
_connection.Open();
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
var r = command.ExecuteNonQuery();
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
@@ -369,9 +369,9 @@ public class SqlDatabase
|
|
|
|
|
/// <returns>The result is a string that has all values separated by space character</returns>
|
|
|
|
|
public async Task<string?> ReadDataAsync(string query)
|
|
|
|
|
{
|
|
|
|
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
await Connection.OpenAsync();
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
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];
|
|
|
|
|
@@ -391,9 +391,9 @@ public class SqlDatabase
|
|
|
|
|
/// <returns>The result is a string that has all values separated by space character</returns>
|
|
|
|
|
public string? ReadData(string query)
|
|
|
|
|
{
|
|
|
|
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
Connection.Open();
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
if (!_connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
_connection.Open();
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
var reader = command.ExecuteReader();
|
|
|
|
|
|
|
|
|
|
var values = new object[reader.FieldCount];
|
|
|
|
|
@@ -413,9 +413,9 @@ public class SqlDatabase
|
|
|
|
|
/// <returns>The first row as separated items</returns>
|
|
|
|
|
public async Task<object[]?> ReadDataArrayAsync(string query)
|
|
|
|
|
{
|
|
|
|
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
await Connection.OpenAsync();
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
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];
|
|
|
|
|
@@ -436,9 +436,9 @@ public class SqlDatabase
|
|
|
|
|
/// <returns>The first row as separated items</returns>
|
|
|
|
|
public object[]? ReadDataArray(string query)
|
|
|
|
|
{
|
|
|
|
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
Connection.Open();
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
if (!_connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
_connection.Open();
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
var reader = command.ExecuteReader();
|
|
|
|
|
|
|
|
|
|
var values = new object[reader.FieldCount];
|
|
|
|
|
@@ -459,9 +459,9 @@ public class SqlDatabase
|
|
|
|
|
/// <returns>A list of string arrays representing the values that the query returns</returns>
|
|
|
|
|
public async Task<List<string[]>?> ReadAllRowsAsync(string query)
|
|
|
|
|
{
|
|
|
|
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
await Connection.OpenAsync();
|
|
|
|
|
var command = new SQLiteCommand(query, Connection);
|
|
|
|
|
if (!_connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
await _connection.OpenAsync();
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
var reader = await command.ExecuteReaderAsync();
|
|
|
|
|
|
|
|
|
|
if (!reader.HasRows)
|
|
|
|
|
@@ -479,4 +479,163 @@ public class SqlDatabase
|
|
|
|
|
|
|
|
|
|
return rows;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Create a parameter for a query
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="name">The name of the parameter</param>
|
|
|
|
|
/// <param name="value">The value of the parameter</param>
|
|
|
|
|
/// <returns>The SQLiteParameter that has the name, value and DBType set according to your inputs</returns>
|
|
|
|
|
private SQLiteParameter? CreateParameter(string name, object value)
|
|
|
|
|
{
|
|
|
|
|
var parameter = new SQLiteParameter(name);
|
|
|
|
|
parameter.Value = value;
|
|
|
|
|
|
|
|
|
|
if (value is string)
|
|
|
|
|
parameter.DbType = DbType.String;
|
|
|
|
|
else if (value is int)
|
|
|
|
|
parameter.DbType = DbType.Int32;
|
|
|
|
|
else if (value is long)
|
|
|
|
|
parameter.DbType = DbType.Int64;
|
|
|
|
|
else if (value is float)
|
|
|
|
|
parameter.DbType = DbType.Single;
|
|
|
|
|
else if (value is double)
|
|
|
|
|
parameter.DbType = DbType.Double;
|
|
|
|
|
else if (value is bool)
|
|
|
|
|
parameter.DbType = DbType.Boolean;
|
|
|
|
|
else if (value is DateTime)
|
|
|
|
|
parameter.DbType = DbType.DateTime;
|
|
|
|
|
else if (value is byte[])
|
|
|
|
|
parameter.DbType = DbType.Binary;
|
|
|
|
|
else if (value is Guid)
|
|
|
|
|
parameter.DbType = DbType.Guid;
|
|
|
|
|
else if (value is decimal)
|
|
|
|
|
parameter.DbType = DbType.Decimal;
|
|
|
|
|
else if (value is TimeSpan)
|
|
|
|
|
parameter.DbType = DbType.Time;
|
|
|
|
|
else if (value is DateTimeOffset)
|
|
|
|
|
parameter.DbType = DbType.DateTimeOffset;
|
|
|
|
|
else if (value is ushort)
|
|
|
|
|
parameter.DbType = DbType.UInt16;
|
|
|
|
|
else if (value is uint)
|
|
|
|
|
parameter.DbType = DbType.UInt32;
|
|
|
|
|
else if (value is ulong)
|
|
|
|
|
parameter.DbType = DbType.UInt64;
|
|
|
|
|
else if (value is sbyte)
|
|
|
|
|
parameter.DbType = DbType.SByte;
|
|
|
|
|
else if (value is short)
|
|
|
|
|
parameter.DbType = DbType.Int16;
|
|
|
|
|
else if (value is byte)
|
|
|
|
|
parameter.DbType = DbType.Byte;
|
|
|
|
|
else if (value is char)
|
|
|
|
|
parameter.DbType = DbType.StringFixedLength;
|
|
|
|
|
else if (value is char[])
|
|
|
|
|
parameter.DbType = DbType.StringFixedLength;
|
|
|
|
|
else
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
return parameter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Create a parameter for a query. The function automatically detects the type of the value.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="parameterValues">The parameter raw inputs. The Key is name and the Value is the value of the parameter</param>
|
|
|
|
|
/// <returns>The SQLiteParameter that has the name, value and DBType set according to your inputs</returns>
|
|
|
|
|
private SQLiteParameter? CreateParameter(KeyValuePair<string, object> parameterValues) =>
|
|
|
|
|
CreateParameter(parameterValues.Key, parameterValues.Value);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Execute a query with parameters
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query to execute</param>
|
|
|
|
|
/// <param name="parameters">The parameters of the query</param>
|
|
|
|
|
/// <returns>The number of rows that the query modified in the database</returns>
|
|
|
|
|
public async Task<int> ExecuteNonQueryAsync(string query, params KeyValuePair<string, object>[] parameters)
|
|
|
|
|
{
|
|
|
|
|
if (!_connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
await _connection.OpenAsync();
|
|
|
|
|
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
foreach (var parameter in parameters)
|
|
|
|
|
{
|
|
|
|
|
var p = CreateParameter(parameter);
|
|
|
|
|
if (p is not null)
|
|
|
|
|
command.Parameters.Add(p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return await command.ExecuteNonQueryAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Execute a query with parameters that returns a specific type of object. The function will return the first row of the result transformed into the specified type.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query to execute</param>
|
|
|
|
|
/// <param name="convertor">The convertor function that will convert each row of the response into an object of <typeparamref name="T"/></param>
|
|
|
|
|
/// <param name="parameters">The parameters of the query</param>
|
|
|
|
|
/// <typeparam name="T">The return object type</typeparam>
|
|
|
|
|
/// <returns>An object of type T that represents the output of the convertor function based on the array of objects that the first row of the result has</returns>
|
|
|
|
|
public async Task<T?> ReadObjectOfTypeAsync<T> (string query, Func<object[], T> convertor, params KeyValuePair<string, object>[] parameters)
|
|
|
|
|
{
|
|
|
|
|
if (!_connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
await _connection.OpenAsync();
|
|
|
|
|
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
foreach (var parameter in parameters)
|
|
|
|
|
{
|
|
|
|
|
var p = CreateParameter(parameter);
|
|
|
|
|
if (p is not null)
|
|
|
|
|
command.Parameters.Add(p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var reader = await command.ExecuteReaderAsync();
|
|
|
|
|
var values = new object[reader.FieldCount];
|
|
|
|
|
if (reader.Read())
|
|
|
|
|
{
|
|
|
|
|
reader.GetValues(values);
|
|
|
|
|
return convertor(values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return default;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Execute a query with parameters that returns a specific type of object. The function will return a list of objects of the specified type.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="query">The query to execute</param>
|
|
|
|
|
/// <param name="convertor">The convertor from object[] to T</param>
|
|
|
|
|
/// <param name="parameters">The parameters of the query</param>
|
|
|
|
|
/// <typeparam name="T">The expected object type</typeparam>
|
|
|
|
|
/// <returns>A list of objects of type T that represents each line of the output of the specified query, converted to T</returns>
|
|
|
|
|
public async Task<List<T>> ReadListOfTypeAsync<T>(string query, Func<object[], T> convertor,
|
|
|
|
|
params KeyValuePair<string, object>[] parameters)
|
|
|
|
|
{
|
|
|
|
|
if (!_connection.State.HasFlag(ConnectionState.Open))
|
|
|
|
|
await _connection.OpenAsync();
|
|
|
|
|
|
|
|
|
|
var command = new SQLiteCommand(query, _connection);
|
|
|
|
|
foreach (var parameter in parameters)
|
|
|
|
|
{
|
|
|
|
|
var p = CreateParameter(parameter);
|
|
|
|
|
if (p is not null)
|
|
|
|
|
command.Parameters.Add(p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var reader = await command.ExecuteReaderAsync();
|
|
|
|
|
//
|
|
|
|
|
if (!reader.HasRows)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
List<T> rows = new();
|
|
|
|
|
while (await reader.ReadAsync())
|
|
|
|
|
{
|
|
|
|
|
var values = new object[reader.FieldCount];
|
|
|
|
|
reader.GetValues(values);
|
|
|
|
|
rows.Add(convertor(values));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rows;
|
|
|
|
|
}
|
|
|
|
|
}
|