refactor(db): Move DbQueryBuilders to separate namespace
Removes obsolete query builder interface and implementations. Introduces a new namespace for query-related classes to enhance organization. Updates various database managers to use the new query utilities, promoting code reuse and maintainability. Enhances query functionality, ensuring better consistency across the codebase.
This commit is contained in:
parent
0021f9884d
commit
8a75b1fdc5
19 changed files with 434 additions and 403 deletions
|
|
@ -22,6 +22,7 @@ using System.Collections.Generic;
|
|||
using System.Data;
|
||||
using MySql.Data.MySqlClient;
|
||||
using System.Collections.ObjectModel;
|
||||
using TShockAPI.DB.Queries;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Terraria;
|
||||
using TShockAPI.DB.Queries;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ using System.Data;
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
using TShockAPI.DB.Queries;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,401 +0,0 @@
|
|||
/*
|
||||
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 MySql.Data.MySqlClient;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using TShockAPI.Extensions;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for various SQL related utilities.
|
||||
/// </summary>
|
||||
public interface IQueryBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a table from a SqlTable object.
|
||||
/// </summary>
|
||||
/// <param name="table">The SqlTable to create the table from</param>
|
||||
/// <returns>The sql query for the table creation.</returns>
|
||||
string CreateTable(SqlTable table);
|
||||
|
||||
/// <summary>
|
||||
/// Alter a table from source to destination
|
||||
/// </summary>
|
||||
/// <param name="from">Must have name and column names. Column types are not required</param>
|
||||
/// <param name="to">Must have column names and column types.</param>
|
||||
/// <returns>The SQL Query</returns>
|
||||
string AlterTable(SqlTable from, SqlTable to);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the MySqlDbType enum to it's string representation.
|
||||
/// </summary>
|
||||
/// <param name="type">The MySqlDbType type</param>
|
||||
/// <param name="length">The length of the datatype</param>
|
||||
/// <returns>The string representation</returns>
|
||||
string DbTypeToString(MySqlDbType type, int? length);
|
||||
|
||||
/// <summary>
|
||||
/// A UPDATE Query
|
||||
/// </summary>
|
||||
/// <param name="table">The table to update</param>
|
||||
/// <param name="values">The values to change</param>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns>The SQL query</returns>
|
||||
string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres);
|
||||
|
||||
/// <summary>
|
||||
/// A INSERT query
|
||||
/// </summary>
|
||||
/// <param name="table">The table to insert to</param>
|
||||
/// <param name="values"></param>
|
||||
/// <returns>The SQL Query</returns>
|
||||
string InsertValues(string table, List<SqlValue> values);
|
||||
|
||||
/// <summary>
|
||||
/// A SELECT query to get all columns
|
||||
/// </summary>
|
||||
/// <param name="table">The table to select from</param>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns>The SQL query</returns>
|
||||
string ReadColumn(string table, List<SqlValue> wheres);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes row(s).
|
||||
/// </summary>
|
||||
/// <param name="table">The table to delete the row from</param>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns>The SQL query</returns>
|
||||
string DeleteRow(string table, List<SqlValue> wheres);
|
||||
|
||||
/// <summary>
|
||||
/// Renames the given table.
|
||||
/// </summary>
|
||||
/// <param name="from">Old name of the table</param>
|
||||
/// <param name="to">New name of the table</param>
|
||||
/// <returns>The sql query for renaming the table.</returns>
|
||||
string RenameTable(string from, string to);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query Creator for Sqlite
|
||||
/// </summary>
|
||||
public class SqliteQueryCreator : GenericQueryCreator, IQueryBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a table from a SqlTable object.
|
||||
/// </summary>
|
||||
/// <param name="table">The SqlTable to create the table from</param>
|
||||
/// <returns>The sql query for the table creation.</returns>
|
||||
public override string CreateTable(SqlTable table)
|
||||
{
|
||||
ValidateSqlColumnType(table.Columns);
|
||||
var columns =
|
||||
table.Columns.Select(
|
||||
c =>
|
||||
"'{0}' {1} {2} {3} {4} {5}".SFormat(c.Name,
|
||||
DbTypeToString(c.Type, c.Length),
|
||||
c.Primary ? "PRIMARY KEY" : "",
|
||||
c.AutoIncrement ? "AUTOINCREMENT" : "",
|
||||
c.NotNull ? "NOT NULL" : "",
|
||||
c.DefaultCurrentTimestamp ? "DEFAULT CURRENT_TIMESTAMP" : ""));
|
||||
var uniques = table.Columns.Where(c => c.Unique).Select(c => c.Name);
|
||||
return "CREATE TABLE {0} ({1} {2})".SFormat(EscapeTableName(table.Name),
|
||||
string.Join(", ", columns),
|
||||
uniques.Count() > 0 ? ", UNIQUE({0})".SFormat(string.Join(", ", uniques)) : "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames the given table.
|
||||
/// </summary>
|
||||
/// <param name="from">Old name of the table</param>
|
||||
/// <param name="to">New name of the table</param>
|
||||
/// <returns>The sql query for renaming the table.</returns>
|
||||
public override string RenameTable(string from, string to)
|
||||
{
|
||||
return "ALTER TABLE {0} RENAME TO {1}".SFormat(from, to);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new Dictionary<MySqlDbType, string>
|
||||
{
|
||||
{ MySqlDbType.VarChar, "TEXT" },
|
||||
{ MySqlDbType.String, "TEXT" },
|
||||
{ MySqlDbType.Text, "TEXT" },
|
||||
{ MySqlDbType.TinyText, "TEXT" },
|
||||
{ MySqlDbType.MediumText, "TEXT" },
|
||||
{ MySqlDbType.LongText, "TEXT" },
|
||||
{ MySqlDbType.Float, "REAL" },
|
||||
{ MySqlDbType.Double, "REAL" },
|
||||
{ MySqlDbType.Int32, "INTEGER" },
|
||||
{ MySqlDbType.Blob, "BLOB" },
|
||||
{ MySqlDbType.Int64, "BIGINT"},
|
||||
{ MySqlDbType.DateTime, "DATETIME"},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Converts the MySqlDbType enum to it's string representation.
|
||||
/// </summary>
|
||||
/// <param name="type">The MySqlDbType type</param>
|
||||
/// <param name="length">The length of the datatype</param>
|
||||
/// <returns>The string representation</returns>
|
||||
public string DbTypeToString(MySqlDbType type, int? length)
|
||||
{
|
||||
string ret;
|
||||
if (TypesAsStrings.TryGetValue(type, out ret))
|
||||
return ret;
|
||||
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Escapes the table name
|
||||
/// </summary>
|
||||
/// <param name="table">The name of the table to be escaped</param>
|
||||
/// <returns></returns>
|
||||
protected override string EscapeTableName(string table)
|
||||
{
|
||||
return $"\'{table}\'";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query Creator for MySQL
|
||||
/// </summary>
|
||||
public class MysqlQueryCreator : GenericQueryCreator, IQueryBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a table from a SqlTable object.
|
||||
/// </summary>
|
||||
/// <param name="table">The SqlTable to create the table from</param>
|
||||
/// <returns>The sql query for the table creation.</returns>
|
||||
public override string CreateTable(SqlTable table)
|
||||
{
|
||||
ValidateSqlColumnType(table.Columns);
|
||||
var columns =
|
||||
table.Columns.Select(
|
||||
c =>
|
||||
"`{0}` {1} {2} {3} {4} {5}".SFormat(c.Name, DbTypeToString(c.Type, c.Length),
|
||||
c.Primary ? "PRIMARY KEY" : "",
|
||||
c.AutoIncrement ? "AUTO_INCREMENT" : "",
|
||||
c.NotNull ? "NOT NULL" : "",
|
||||
c.DefaultCurrentTimestamp ? "DEFAULT CURRENT_TIMESTAMP" : ""));
|
||||
var uniques = table.Columns.Where(c => c.Unique).Select(c => $"`{c.Name}`");
|
||||
return "CREATE TABLE {0} ({1} {2})".SFormat(EscapeTableName(table.Name), string.Join(", ", columns),
|
||||
uniques.Count() > 0
|
||||
? ", UNIQUE({0})".SFormat(string.Join(", ", uniques))
|
||||
: "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames the given table.
|
||||
/// </summary>
|
||||
/// <param name="from">Old name of the table</param>
|
||||
/// <param name="to">New name of the table</param>
|
||||
/// <returns>The sql query for renaming the table.</returns>
|
||||
public override string RenameTable(string from, string to)
|
||||
{
|
||||
return "RENAME TABLE {0} TO {1}".SFormat(from, to);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new Dictionary<MySqlDbType, string>
|
||||
{
|
||||
{ MySqlDbType.VarChar, "VARCHAR" },
|
||||
{ MySqlDbType.String, "CHAR" },
|
||||
{ MySqlDbType.Text, "TEXT" },
|
||||
{ MySqlDbType.TinyText, "TINYTEXT" },
|
||||
{ MySqlDbType.MediumText, "MEDIUMTEXT" },
|
||||
{ MySqlDbType.LongText, "LONGTEXT" },
|
||||
{ MySqlDbType.Float, "FLOAT" },
|
||||
{ MySqlDbType.Double, "DOUBLE" },
|
||||
{ MySqlDbType.Int32, "INT" },
|
||||
{ MySqlDbType.Int64, "BIGINT"},
|
||||
{ MySqlDbType.DateTime, "DATETIME"},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Converts the MySqlDbType enum to it's string representation.
|
||||
/// </summary>
|
||||
/// <param name="type">The MySqlDbType type</param>
|
||||
/// <param name="length">The length of the datatype</param>
|
||||
/// <returns>The string representation</returns>
|
||||
public string DbTypeToString(MySqlDbType type, int? length)
|
||||
{
|
||||
string ret;
|
||||
if (TypesAsStrings.TryGetValue(type, out ret))
|
||||
return ret + (length != null ? "({0})".SFormat((int)length) : "");
|
||||
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Escapes the table name
|
||||
/// </summary>
|
||||
/// <param name="table">The name of the table to be escaped</param>
|
||||
/// <returns></returns>
|
||||
protected override string EscapeTableName(string table)
|
||||
{
|
||||
return table.SFormat("`{0}`", table);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Generic Query Creator (abstract)
|
||||
/// </summary>
|
||||
public abstract class GenericQueryCreator
|
||||
{
|
||||
protected static Random rand = new Random();
|
||||
|
||||
/// <summary>
|
||||
/// Escapes the table name
|
||||
/// </summary>
|
||||
/// <param name="table">The name of the table to be escaped</param>
|
||||
/// <returns></returns>
|
||||
protected abstract string EscapeTableName(string table);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a table from a SqlTable object.
|
||||
/// </summary>
|
||||
/// <param name="table">The SqlTable to create the table from</param>
|
||||
/// <returns>The sql query for the table creation.</returns>
|
||||
public abstract string CreateTable(SqlTable table);
|
||||
|
||||
/// <summary>
|
||||
/// Renames the given table.
|
||||
/// </summary>
|
||||
/// <param name="from">Old name of the table</param>
|
||||
/// <param name="to">New name of the table</param>
|
||||
/// <returns>The sql query for renaming the table.</returns>
|
||||
public abstract string RenameTable(string from, string to);
|
||||
|
||||
/// <summary>
|
||||
/// Alter a table from source to destination
|
||||
/// </summary>
|
||||
/// <param name="from">Must have name and column names. Column types are not required</param>
|
||||
/// <param name="to">Must have column names and column types.</param>
|
||||
/// <returns>The SQL Query</returns>
|
||||
public string AlterTable(SqlTable from, SqlTable to)
|
||||
{
|
||||
var rstr = rand.NextString(20);
|
||||
var escapedTable = EscapeTableName(from.Name);
|
||||
var tmpTable = EscapeTableName("{0}_{1}".SFormat(rstr, from.Name));
|
||||
var alter = RenameTable(escapedTable, tmpTable);
|
||||
var create = CreateTable(to);
|
||||
// combine all columns in the 'from' variable excluding ones that aren't in the 'to' variable.
|
||||
// exclude the ones that aren't in 'to' variable because if the column is deleted, why try to import the data?
|
||||
var columns = string.Join(", ", from.Columns.Where(c => to.Columns.Any(c2 => c2.Name == c.Name)).Select(c => $"`{c.Name}`"));
|
||||
var insert = "INSERT INTO {0} ({1}) SELECT {1} FROM {2}".SFormat(escapedTable, columns, tmpTable);
|
||||
var drop = "DROP TABLE {0}".SFormat(tmpTable);
|
||||
return "{0}; {1}; {2}; {3};".SFormat(alter, create, insert, drop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for errors in the columns.
|
||||
/// </summary>
|
||||
/// <param name="columns"></param>
|
||||
/// <exception cref="SqlColumnException"></exception>
|
||||
public void ValidateSqlColumnType(List<SqlColumn> columns)
|
||||
{
|
||||
columns.ForEach(x =>
|
||||
{
|
||||
if (x.DefaultCurrentTimestamp && x.Type != MySqlDbType.DateTime)
|
||||
{
|
||||
throw new SqlColumnException(GetString("Can't set to true SqlColumn.DefaultCurrentTimestamp when the MySqlDbType is not DateTime"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes row(s).
|
||||
/// </summary>
|
||||
/// <param name="table">The table to delete the row from</param>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns>The SQL query</returns>
|
||||
public string DeleteRow(string table, List<SqlValue> wheres)
|
||||
{
|
||||
return "DELETE FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(wheres));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A UPDATE Query
|
||||
/// </summary>
|
||||
/// <param name="table">The table to update</param>
|
||||
/// <param name="values">The values to change</param>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns>The SQL query</returns>
|
||||
public string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres)
|
||||
{
|
||||
if (0 == values.Count)
|
||||
throw new ArgumentException(GetString("No values supplied"));
|
||||
|
||||
return "UPDATE {0} SET {1} {2}".SFormat(EscapeTableName(table), string.Join(", ", values.Select(v => v.Name + " = " + v.Value)), BuildWhere(wheres));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A SELECT query to get all columns
|
||||
/// </summary>
|
||||
/// <param name="table">The table to select from</param>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns>The SQL query</returns>
|
||||
public string ReadColumn(string table, List<SqlValue> wheres)
|
||||
{
|
||||
return "SELECT * FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(wheres));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A INSERT query
|
||||
/// </summary>
|
||||
/// <param name="table">The table to insert to</param>
|
||||
/// <param name="values"></param>
|
||||
/// <returns>The SQL Query</returns>
|
||||
public string InsertValues(string table, List<SqlValue> values)
|
||||
{
|
||||
var sbnames = new StringBuilder();
|
||||
var sbvalues = new StringBuilder();
|
||||
int count = 0;
|
||||
foreach (SqlValue value in values)
|
||||
{
|
||||
sbnames.Append(value.Name);
|
||||
sbvalues.Append(value.Value.ToString());
|
||||
|
||||
if (count != values.Count - 1)
|
||||
{
|
||||
sbnames.Append(", ");
|
||||
sbvalues.Append(", ");
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
return "INSERT INTO {0} ({1}) VALUES ({2})".SFormat(EscapeTableName(table), sbnames, sbvalues);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the SQL WHERE clause
|
||||
/// </summary>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns></returns>
|
||||
protected static string BuildWhere(List<SqlValue> wheres)
|
||||
{
|
||||
if (0 == wheres.Count)
|
||||
return string.Empty;
|
||||
|
||||
return "WHERE {0}".SFormat(string.Join(", ", wheres.Select(v => $"{v.Name}" + " = " + v.Value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ using System.Collections.Generic;
|
|||
using System.Data;
|
||||
using System.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
using TShockAPI.DB.Queries;
|
||||
using TShockAPI.Hooks;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ using System.Collections.Generic;
|
|||
using System.Data;
|
||||
using System.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
using TShockAPI.DB.Queries;
|
||||
using TShockAPI.Hooks;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
|
|
|
|||
136
TShockAPI/DB/Queries/GenericQueryCreator.cs
Normal file
136
TShockAPI/DB/Queries/GenericQueryCreator.cs
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
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.Linq;
|
||||
using System.Text;
|
||||
using MySql.Data.MySqlClient;
|
||||
using TShockAPI.Extensions;
|
||||
|
||||
namespace TShockAPI.DB.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// A Generic Query Creator (abstract)
|
||||
/// </summary>
|
||||
public abstract class GenericQueryCreator : IQueryBuilder
|
||||
{
|
||||
protected static Random rand = new Random();
|
||||
|
||||
/// <summary>
|
||||
/// Escapes the table name
|
||||
/// </summary>
|
||||
/// <param name="table">The name of the table to be escaped</param>
|
||||
/// <returns></returns>
|
||||
protected abstract string EscapeTableName(string table);
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string CreateTable(SqlTable table);
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string RenameTable(string from, string to);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string AlterTable(SqlTable from, SqlTable to)
|
||||
{
|
||||
var rstr = rand.NextString(20);
|
||||
var escapedTable = EscapeTableName(from.Name);
|
||||
var tmpTable = EscapeTableName("{0}_{1}".SFormat(rstr, from.Name));
|
||||
var alter = RenameTable(escapedTable, tmpTable);
|
||||
var create = CreateTable(to);
|
||||
// combine all columns in the 'from' variable excluding ones that aren't in the 'to' variable.
|
||||
// exclude the ones that aren't in 'to' variable because if the column is deleted, why try to import the data?
|
||||
var columns = string.Join(", ", from.Columns.Where(c => to.Columns.Any(c2 => c2.Name == c.Name)).Select(c => $"`{c.Name}`"));
|
||||
var insert = "INSERT INTO {0} ({1}) SELECT {1} FROM {2}".SFormat(escapedTable, columns, tmpTable);
|
||||
var drop = "DROP TABLE {0}".SFormat(tmpTable);
|
||||
return "{0}; {1}; {2}; {3};".SFormat(alter, create, insert, drop);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string DbTypeToString(MySqlDbType type, int? length);
|
||||
|
||||
/// <summary>
|
||||
/// Check for errors in the columns.
|
||||
/// </summary>
|
||||
/// <param name="columns"></param>
|
||||
/// <exception cref="SqlColumnException"></exception>
|
||||
protected static void ValidateSqlColumnType(List<SqlColumn> columns)
|
||||
{
|
||||
columns.ForEach(x =>
|
||||
{
|
||||
if (x.DefaultCurrentTimestamp && x.Type != MySqlDbType.DateTime)
|
||||
{
|
||||
throw new SqlColumnException(GetString("Can't set to true SqlColumn.DefaultCurrentTimestamp when the MySqlDbType is not DateTime"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DeleteRow(string table, List<SqlValue> wheres)
|
||||
{
|
||||
return "DELETE FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(wheres));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres)
|
||||
{
|
||||
if (0 == values.Count)
|
||||
throw new ArgumentException(GetString("No values supplied"));
|
||||
|
||||
return "UPDATE {0} SET {1} {2}".SFormat(EscapeTableName(table), string.Join(", ", values.Select(v => v.Name + " = " + v.Value)), BuildWhere(wheres));
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ReadColumn(string table, List<SqlValue> wheres)
|
||||
{
|
||||
return "SELECT * FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(wheres));
|
||||
}
|
||||
|
||||
|
||||
public string InsertValues(string table, List<SqlValue> values)
|
||||
{
|
||||
var sbnames = new StringBuilder();
|
||||
var sbvalues = new StringBuilder();
|
||||
int count = 0;
|
||||
foreach (SqlValue value in values)
|
||||
{
|
||||
sbnames.Append(value.Name);
|
||||
sbvalues.Append(value.Value.ToString());
|
||||
|
||||
if (count != values.Count - 1)
|
||||
{
|
||||
sbnames.Append(", ");
|
||||
sbvalues.Append(", ");
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
return "INSERT INTO {0} ({1}) VALUES ({2})".SFormat(EscapeTableName(table), sbnames, sbvalues);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds the SQL WHERE clause
|
||||
/// </summary>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns></returns>
|
||||
protected static string BuildWhere(List<SqlValue> wheres) => wheres.Count > 0
|
||||
? string.Empty
|
||||
: "WHERE {0}".SFormat(string.Join(", ", wheres.Select(v => $"{v.Name} = {v.Value}")));
|
||||
}
|
||||
92
TShockAPI/DB/Queries/IQueryBuilder.cs
Normal file
92
TShockAPI/DB/Queries/IQueryBuilder.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
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.Collections.Generic;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace TShockAPI.DB.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for various SQL related utilities.
|
||||
/// </summary>
|
||||
public interface IQueryBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a table from a SqlTable object.
|
||||
/// </summary>
|
||||
/// <param name="table">The SqlTable to create the table from</param>
|
||||
/// <returns>The sql query for the table creation.</returns>
|
||||
string CreateTable(SqlTable table);
|
||||
|
||||
/// <summary>
|
||||
/// Alter a table from source to destination
|
||||
/// </summary>
|
||||
/// <param name="from">Must have name and column names. Column types are not required</param>
|
||||
/// <param name="to">Must have column names and column types.</param>
|
||||
/// <returns>The SQL Query</returns>
|
||||
string AlterTable(SqlTable from, SqlTable to);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the MySqlDbType enum to it's string representation.
|
||||
/// </summary>
|
||||
/// <param name="type">The MySqlDbType type</param>
|
||||
/// <param name="length">The length of the datatype</param>
|
||||
/// <returns>The string representation</returns>
|
||||
string DbTypeToString(MySqlDbType type, int? length);
|
||||
|
||||
/// <summary>
|
||||
/// A UPDATE Query
|
||||
/// </summary>
|
||||
/// <param name="table">The table to update</param>
|
||||
/// <param name="values">The values to change</param>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns>The SQL query</returns>
|
||||
string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres);
|
||||
|
||||
/// <summary>
|
||||
/// A INSERT query
|
||||
/// </summary>
|
||||
/// <param name="table">The table to insert to</param>
|
||||
/// <param name="values"></param>
|
||||
/// <returns>The SQL Query</returns>
|
||||
string InsertValues(string table, List<SqlValue> values);
|
||||
|
||||
/// <summary>
|
||||
/// A SELECT query to get all columns
|
||||
/// </summary>
|
||||
/// <param name="table">The table to select from</param>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns>The SQL query</returns>
|
||||
string ReadColumn(string table, List<SqlValue> wheres);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes row(s).
|
||||
/// </summary>
|
||||
/// <param name="table">The table to delete the row from</param>
|
||||
/// <param name="wheres"></param>
|
||||
/// <returns>The SQL query</returns>
|
||||
string DeleteRow(string table, List<SqlValue> wheres);
|
||||
|
||||
/// <summary>
|
||||
/// Renames the given table.
|
||||
/// </summary>
|
||||
/// <param name="from">Old name of the table</param>
|
||||
/// <param name="to">New name of the table</param>
|
||||
/// <returns>The sql query for renaming the table.</returns>
|
||||
string RenameTable(string from, string to);
|
||||
}
|
||||
88
TShockAPI/DB/Queries/MysqlQueryCreator.cs
Normal file
88
TShockAPI/DB/Queries/MysqlQueryCreator.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
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.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace TShockAPI.DB.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// Query Creator for MySQL
|
||||
/// </summary>
|
||||
public class MysqlQueryCreator : GenericQueryCreator, IQueryBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a table from a SqlTable object.
|
||||
/// </summary>
|
||||
/// <param name="table">The SqlTable to create the table from</param>
|
||||
/// <returns>The sql query for the table creation.</returns>
|
||||
public override string CreateTable(SqlTable table)
|
||||
{
|
||||
ValidateSqlColumnType(table.Columns);
|
||||
|
||||
var columns =
|
||||
table.Columns.Select(
|
||||
c =>
|
||||
"`{0}` {1} {2} {3} {4} {5}".SFormat(c.Name, DbTypeToString(c.Type, c.Length),
|
||||
c.Primary ? "PRIMARY KEY" : "",
|
||||
c.AutoIncrement ? "AUTO_INCREMENT" : "",
|
||||
c.NotNull ? "NOT NULL" : "",
|
||||
c.DefaultCurrentTimestamp ? "DEFAULT CURRENT_TIMESTAMP" : ""));
|
||||
|
||||
var uniques = table.Columns.Where(c => c.Unique).Select(c => $"`{c.Name}`");
|
||||
return "CREATE TABLE {0} ({1} {2})".SFormat(EscapeTableName(table.Name), string.Join(", ", columns),
|
||||
uniques.Any()
|
||||
? ", UNIQUE({0})".SFormat(string.Join(", ", uniques))
|
||||
: "");
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string RenameTable(string from, string to) => /*lang=mysql*/"RENAME TABLE {0} TO {1}".SFormat(from, to);
|
||||
|
||||
private static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new()
|
||||
{
|
||||
{ MySqlDbType.VarChar, "VARCHAR" },
|
||||
{ MySqlDbType.String, "CHAR" },
|
||||
{ MySqlDbType.Text, "TEXT" },
|
||||
{ MySqlDbType.TinyText, "TINYTEXT" },
|
||||
{ MySqlDbType.MediumText, "MEDIUMTEXT" },
|
||||
{ MySqlDbType.LongText, "LONGTEXT" },
|
||||
{ MySqlDbType.Float, "FLOAT" },
|
||||
{ MySqlDbType.Double, "DOUBLE" },
|
||||
{ MySqlDbType.Int32, "INT" },
|
||||
{ MySqlDbType.Int64, "BIGINT"},
|
||||
{ MySqlDbType.DateTime, "DATETIME"},
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string DbTypeToString(MySqlDbType type, int? length)
|
||||
{
|
||||
if (TypesAsStrings.TryGetValue(type, out string ret))
|
||||
{
|
||||
return ret + (length is not null ? "({0})".SFormat((int)length) : "");
|
||||
}
|
||||
|
||||
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string EscapeTableName(string table) => table.SFormat("`{0}`", table);
|
||||
}
|
||||
103
TShockAPI/DB/Queries/SqliteQueryCreator.cs
Normal file
103
TShockAPI/DB/Queries/SqliteQueryCreator.cs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
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.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace TShockAPI.DB.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// Query Creator for Sqlite
|
||||
/// </summary>
|
||||
public class SqliteQueryCreator : GenericQueryCreator, IQueryBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a table from a SqlTable object.
|
||||
/// </summary>
|
||||
/// <param name="table">The SqlTable to create the table from</param>
|
||||
/// <returns>The sql query for the table creation.</returns>
|
||||
public override string CreateTable(SqlTable table)
|
||||
{
|
||||
ValidateSqlColumnType(table.Columns);
|
||||
var columns =
|
||||
table.Columns.Select(
|
||||
c =>
|
||||
"'{0}' {1} {2} {3} {4} {5}".SFormat(c.Name,
|
||||
DbTypeToString(c.Type, c.Length),
|
||||
c.Primary ? "PRIMARY KEY" : "",
|
||||
c.AutoIncrement ? "AUTOINCREMENT" : "",
|
||||
c.NotNull ? "NOT NULL" : "",
|
||||
c.DefaultCurrentTimestamp ? "DEFAULT CURRENT_TIMESTAMP" : ""));
|
||||
var uniques = table.Columns.Where(c => c.Unique).Select(c => c.Name);
|
||||
return "CREATE TABLE {0} ({1} {2})".SFormat(EscapeTableName(table.Name),
|
||||
string.Join(", ", columns),
|
||||
uniques.Count() > 0 ? ", UNIQUE({0})".SFormat(string.Join(", ", uniques)) : "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames the given table.
|
||||
/// </summary>
|
||||
/// <param name="from">Old name of the table</param>
|
||||
/// <param name="to">New name of the table</param>
|
||||
/// <returns>The sql query for renaming the table.</returns>
|
||||
public override string RenameTable(string from, string to)
|
||||
{
|
||||
return "ALTER TABLE {0} RENAME TO {1}".SFormat(from, to);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new Dictionary<MySqlDbType, string>
|
||||
{
|
||||
{ MySqlDbType.VarChar, "TEXT" },
|
||||
{ MySqlDbType.String, "TEXT" },
|
||||
{ MySqlDbType.Text, "TEXT" },
|
||||
{ MySqlDbType.TinyText, "TEXT" },
|
||||
{ MySqlDbType.MediumText, "TEXT" },
|
||||
{ MySqlDbType.LongText, "TEXT" },
|
||||
{ MySqlDbType.Float, "REAL" },
|
||||
{ MySqlDbType.Double, "REAL" },
|
||||
{ MySqlDbType.Int32, "INTEGER" },
|
||||
{ MySqlDbType.Blob, "BLOB" },
|
||||
{ MySqlDbType.Int64, "BIGINT"},
|
||||
{ MySqlDbType.DateTime, "DATETIME"},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Converts the MySqlDbType enum to it's string representation.
|
||||
/// </summary>
|
||||
/// <param name="type">The MySqlDbType type</param>
|
||||
/// <param name="length">The length of the datatype</param>
|
||||
/// <returns>The string representation</returns>
|
||||
public override string DbTypeToString(MySqlDbType type, int? length)
|
||||
{
|
||||
if (TypesAsStrings.TryGetValue(type, out string ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Escapes the table name
|
||||
/// </summary>
|
||||
/// <param name="table">The name of the table to be escaped</param>
|
||||
/// <returns></returns>
|
||||
protected override string EscapeTableName(string table) => $"\'{table}\'";
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ using System.Linq;
|
|||
using MySql.Data.MySqlClient;
|
||||
using Terraria;
|
||||
using Microsoft.Xna.Framework;
|
||||
using TShockAPI.DB.Queries;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ using System.Data;
|
|||
using MySql.Data.MySqlClient;
|
||||
using Terraria;
|
||||
using Microsoft.Xna.Framework;
|
||||
using TShockAPI.DB.Queries;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using Terraria;
|
||||
using Terraria.ID;
|
||||
using TShockAPI.DB.Queries;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ using System.Collections.Generic;
|
|||
using System.Data;
|
||||
using System.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
using TShockAPI.DB.Queries;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using TShockAPI.DB.Queries;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ using System.Collections.Generic;
|
|||
using System.Data;
|
||||
using System.Linq;
|
||||
using MySql.Data.MySqlClient;
|
||||
using TShockAPI.DB.Queries;
|
||||
using TShockAPI.Hooks;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ using MySql.Data.MySqlClient;
|
|||
using System.Text.RegularExpressions;
|
||||
using BCrypt.Net;
|
||||
using System.Security.Cryptography;
|
||||
using TShockAPI.DB.Queries;
|
||||
using TShockAPI.Hooks;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ using System.Linq;
|
|||
using MySql.Data.MySqlClient;
|
||||
using Terraria;
|
||||
using Microsoft.Xna.Framework;
|
||||
using TShockAPI.DB.Queries;
|
||||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ namespace TShockAPI
|
|||
public static class StringExt
|
||||
{
|
||||
//Can't name it Format :(
|
||||
public static String SFormat(this String str, params object[] args)
|
||||
public static string SFormat(this string str, params object[] args)
|
||||
{
|
||||
return String.Format(str, args);
|
||||
return string.Format(str, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue