TShock/TShockAPI/DB/DbBuilder.cs
Sakura Akeno Isayeki 69b98980f1
feat(db): add Postgres support to configuration
Extends database configuration to support Postgres in addition to existing SQLite and MySQL options.

Includes new settings for Postgres host, database name, username, and password.

Implements a connection builder for Postgres, ensuring proper error handling when connecting.

Updates dependency to include Npgsql for Postgres connectivity.
2025-04-28 15:51:27 +02:00

115 lines
3.2 KiB
C#

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;
/// <summary>
/// Provides logic to build a DB connection.
/// </summary>
public sealed class DbBuilder
{
private readonly TShock _caller;
private readonly TShockConfig _config;
private readonly string _savePath;
/// <summary>
/// Initializes a new instance of the <see cref="DbBuilder"/> class.
/// </summary>
/// <param name="caller">The TShock instance calling this DbBuilder.</param>
/// <param name="config">The TShock configuration, supplied by <see cref="TShock.Config" /> at init.</param>
/// <param name="savePath">The savePath registered by TShock. See <see cref="TShock.SavePath" />.</param>
public DbBuilder(TShock caller, TShockConfig config, string savePath)
{
_caller = caller;
_config = config;
_savePath = savePath;
}
/// <summary>
/// Builds a DB connection based on the provided configuration.
/// </summary>
/// <param name="config">The TShock configuration.</param>
/// <remarks>
/// Default settings will result in a local sqlite database file named "tshock.db" in the current directory to be used as server DB.
/// </remarks>
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);
}
}
}