TShock/TShockAPI/DB/SqlTable.cs
Sakura Akeno Isayeki 084411f847
refactor(db): Update SqlQueryBuilder references + Various refactors
Consolidates the creation of SQL query builders across multiple classes to ensure a unified approach for database operations.

Replaces manual type checks and specific query creators with a generic method for better maintainability and to prevent errors.

Improves code readability and reduces duplication, facilitating easier updates in the future.
2025-04-28 15:51:26 +02:00

126 lines
3.1 KiB
C#

/*
TShock, a server mod for Terraria
Copyright (C) 2011-2019 Pryaxis & TShock Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using MySql.Data.MySqlClient;
using TShockAPI.DB.Queries;
namespace TShockAPI.DB
{
public class SqlTable
{
public List<SqlColumn> Columns { get; protected set; }
public string Name { get; protected set; }
public SqlTable(string name, params SqlColumn[] columns)
: this(name, new List<SqlColumn>(columns))
{
}
public SqlTable(string name, List<SqlColumn> columns)
{
Name = name;
Columns = columns;
}
}
public class SqlTableCreator
{
private IDbConnection database;
private IQueryBuilder creator;
public SqlTableCreator(IDbConnection db, IQueryBuilder provider)
{
database = db;
creator = provider;
}
// Returns true if the table was created; false if it was not.
public bool EnsureTableStructure(SqlTable table)
{
var columns = GetColumns(table);
if (columns.Count > 0)
{
if (!table.Columns.All(c => columns.Contains(c.Name)) || !columns.All(c => table.Columns.Any(c2 => c2.Name == c)))
{
var from = new SqlTable(table.Name, columns.Select(s => new SqlColumn(s, MySqlDbType.String)).ToList());
database.Query(creator.AlterTable(from, table));
}
}
else
{
database.Query(creator.CreateTable(table));
return true;
}
return false;
}
public List<string> GetColumns(SqlTable table)
{
List<string> ret = new();
switch (database.GetSqlType())
{
case SqlType.Sqlite:
{
using QueryResult reader = database.QueryReader("PRAGMA table_info({0})".SFormat(table.Name));
while (reader.Read())
{
ret.Add(reader.Get<string>("name"));
}
break;
}
case SqlType.Mysql:
{
using QueryResult reader =
database.QueryReader("SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME=@0 AND TABLE_SCHEMA=@1", table.Name, database.Database);
while (reader.Read())
{
ret.Add(reader.Get<string>("COLUMN_NAME"));
}
break;
}
case SqlType.Postgres:
{
using QueryResult reader =
database.QueryReader("SELECT column_name FROM information_schema.columns WHERE table_name=@0", table.Name);
while (reader.Read())
{
ret.Add(reader.Get<string>("column_name"));
}
break;
}
default: throw new NotSupportedException();
}
return ret;
}
public void DeleteRow(string table, List<SqlValue> wheres)
{
database.Query(creator.DeleteRow(table, wheres));
}
}
}