using System.Data;
using System.Diagnostics;
using System.IO;
using Microsoft.Data.Sqlite;
using MySql.Data.MySqlClient;
using Npgsql;
using TerrariaApi.Server;
using TShockAPI.Configuration;
namespace TShockAPI.DB;
///
/// Provides logic to build a DB connection.
///
public sealed class DbBuilder
{
private readonly TShock _caller;
private readonly TShockConfig _config;
private readonly string _savePath;
///
/// Initializes a new instance of the class.
///
/// The TShock instance calling this DbBuilder.
/// The TShock configuration, supplied by at init.
/// The savePath registered by TShock. See .
public DbBuilder(TShock caller, TShockConfig config, string savePath)
{
_caller = caller;
_config = config;
_savePath = savePath;
}
///
/// Builds a DB connection based on the provided configuration.
///
/// The TShock configuration.
///
/// Default settings will result in a local sqlite database file named "tshock.db" in the current directory to be used as server DB.
///
public IDbConnection BuildDbConnection()
{
string dbType = _config.Settings.StorageType.ToLowerInvariant();
return dbType switch
{
"sqlite" => BuildSqliteConnection(),
"mysql" => BuildMySqlConnection(),
"postgres" => BuildPostgresConnection(),
_ => throw new("Invalid storage type")
};
}
private SqliteConnection BuildSqliteConnection()
{
string dbFilePath = Path.Combine(_savePath, _config.Settings.SqliteDBPath);
if (Path.GetDirectoryName(dbFilePath) is not { } dbDirPath)
{
throw new DirectoryNotFoundException($"The SQLite database path '{dbFilePath}' could not be found.");
}
Directory.CreateDirectory(dbDirPath);
return new($"Data Source={dbFilePath}");
}
private MySqlConnection BuildMySqlConnection()
{
try
{
string[] hostport = _config.Settings.MySqlHost.Split(':');
MySqlConnectionStringBuilder connStrBuilder = new()
{
Server = hostport[0],
Port = hostport.Length > 1 ? uint.Parse(hostport[1]) : 3306,
Database = _config.Settings.MySqlDbName,
UserID = _config.Settings.MySqlUsername,
Password = _config.Settings.MySqlPassword
};
return new(connStrBuilder.ToString());
}
catch (MySqlException e)
{
ServerApi.LogWriter.PluginWriteLine(_caller, e.ToString(), TraceLevel.Error);
throw new("MySql not setup correctly", e);
}
}
private NpgsqlConnection BuildPostgresConnection()
{
try
{
string[] hostport = _config.Settings.PostgresHost.Split(':');
NpgsqlConnectionStringBuilder connStrBuilder = new()
{
Host = hostport[0],
Port = hostport.Length > 1 ? int.Parse(hostport[1]) : 5432,
Database = _config.Settings.PostgresDbName,
Username = _config.Settings.PostgresUsername,
Password = _config.Settings.PostgresPassword
};
return new(connStrBuilder.ToString());
}
catch (NpgsqlException e)
{
ServerApi.LogWriter.PluginWriteLine(_caller, e.ToString(), TraceLevel.Error);
throw new("Postgres not setup correctly", e);
}
}
}