diff --git a/TShockAPI/DB/BanManager.cs b/TShockAPI/DB/BanManager.cs index 3e93a3b7..be05b45c 100644 --- a/TShockAPI/DB/BanManager.cs +++ b/TShockAPI/DB/BanManager.cs @@ -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 { diff --git a/TShockAPI/DB/CharacterManager.cs b/TShockAPI/DB/CharacterManager.cs index c0551b65..be09da1d 100644 --- a/TShockAPI/DB/CharacterManager.cs +++ b/TShockAPI/DB/CharacterManager.cs @@ -23,6 +23,7 @@ using System.Linq; using System.Text; using MySql.Data.MySqlClient; using Terraria; +using TShockAPI.DB.Queries; namespace TShockAPI.DB { diff --git a/TShockAPI/DB/GroupManager.cs b/TShockAPI/DB/GroupManager.cs index 4a9f8afb..5d32419e 100644 --- a/TShockAPI/DB/GroupManager.cs +++ b/TShockAPI/DB/GroupManager.cs @@ -23,6 +23,7 @@ using System.Data; using System.Diagnostics; using System.Linq; using MySql.Data.MySqlClient; +using TShockAPI.DB.Queries; namespace TShockAPI.DB { diff --git a/TShockAPI/DB/IQueryBuilder.cs b/TShockAPI/DB/IQueryBuilder.cs deleted file mode 100644 index c2be131d..00000000 --- a/TShockAPI/DB/IQueryBuilder.cs +++ /dev/null @@ -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 . -*/ - -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 -{ - /// - /// Interface for various SQL related utilities. - /// - public interface IQueryBuilder - { - /// - /// Creates a table from a SqlTable object. - /// - /// The SqlTable to create the table from - /// The sql query for the table creation. - string CreateTable(SqlTable table); - - /// - /// Alter a table from source to destination - /// - /// Must have name and column names. Column types are not required - /// Must have column names and column types. - /// The SQL Query - string AlterTable(SqlTable from, SqlTable to); - - /// - /// Converts the MySqlDbType enum to it's string representation. - /// - /// The MySqlDbType type - /// The length of the datatype - /// The string representation - string DbTypeToString(MySqlDbType type, int? length); - - /// - /// A UPDATE Query - /// - /// The table to update - /// The values to change - /// - /// The SQL query - string UpdateValue(string table, List values, List wheres); - - /// - /// A INSERT query - /// - /// The table to insert to - /// - /// The SQL Query - string InsertValues(string table, List values); - - /// - /// A SELECT query to get all columns - /// - /// The table to select from - /// - /// The SQL query - string ReadColumn(string table, List wheres); - - /// - /// Deletes row(s). - /// - /// The table to delete the row from - /// - /// The SQL query - string DeleteRow(string table, List wheres); - - /// - /// Renames the given table. - /// - /// Old name of the table - /// New name of the table - /// The sql query for renaming the table. - string RenameTable(string from, string to); - } - - /// - /// Query Creator for Sqlite - /// - public class SqliteQueryCreator : GenericQueryCreator, IQueryBuilder - { - /// - /// Creates a table from a SqlTable object. - /// - /// The SqlTable to create the table from - /// The sql query for the table creation. - 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)) : ""); - } - - /// - /// Renames the given table. - /// - /// Old name of the table - /// New name of the table - /// The sql query for renaming the table. - public override string RenameTable(string from, string to) - { - return "ALTER TABLE {0} RENAME TO {1}".SFormat(from, to); - } - - private static readonly Dictionary TypesAsStrings = new Dictionary - { - { 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"}, - }; - - /// - /// Converts the MySqlDbType enum to it's string representation. - /// - /// The MySqlDbType type - /// The length of the datatype - /// The string representation - 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)); - } - - /// - /// Escapes the table name - /// - /// The name of the table to be escaped - /// - protected override string EscapeTableName(string table) - { - return $"\'{table}\'"; - } - } - - /// - /// Query Creator for MySQL - /// - public class MysqlQueryCreator : GenericQueryCreator, IQueryBuilder - { - /// - /// Creates a table from a SqlTable object. - /// - /// The SqlTable to create the table from - /// The sql query for the table creation. - 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)) - : ""); - } - - /// - /// Renames the given table. - /// - /// Old name of the table - /// New name of the table - /// The sql query for renaming the table. - public override string RenameTable(string from, string to) - { - return "RENAME TABLE {0} TO {1}".SFormat(from, to); - } - - private static readonly Dictionary TypesAsStrings = new Dictionary - { - { 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"}, - }; - - /// - /// Converts the MySqlDbType enum to it's string representation. - /// - /// The MySqlDbType type - /// The length of the datatype - /// The string representation - 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)); - } - - /// - /// Escapes the table name - /// - /// The name of the table to be escaped - /// - protected override string EscapeTableName(string table) - { - return table.SFormat("`{0}`", table); - } - } - - /// - /// A Generic Query Creator (abstract) - /// - public abstract class GenericQueryCreator - { - protected static Random rand = new Random(); - - /// - /// Escapes the table name - /// - /// The name of the table to be escaped - /// - protected abstract string EscapeTableName(string table); - - /// - /// Creates a table from a SqlTable object. - /// - /// The SqlTable to create the table from - /// The sql query for the table creation. - public abstract string CreateTable(SqlTable table); - - /// - /// Renames the given table. - /// - /// Old name of the table - /// New name of the table - /// The sql query for renaming the table. - public abstract string RenameTable(string from, string to); - - /// - /// Alter a table from source to destination - /// - /// Must have name and column names. Column types are not required - /// Must have column names and column types. - /// The SQL Query - 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); - } - - /// - /// Check for errors in the columns. - /// - /// - /// - public void ValidateSqlColumnType(List 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")); - } - }); - } - - /// - /// Deletes row(s). - /// - /// The table to delete the row from - /// - /// The SQL query - public string DeleteRow(string table, List wheres) - { - return "DELETE FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(wheres)); - } - - /// - /// A UPDATE Query - /// - /// The table to update - /// The values to change - /// - /// The SQL query - public string UpdateValue(string table, List values, List 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)); - } - - /// - /// A SELECT query to get all columns - /// - /// The table to select from - /// - /// The SQL query - public string ReadColumn(string table, List wheres) - { - return "SELECT * FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(wheres)); - } - - /// - /// A INSERT query - /// - /// The table to insert to - /// - /// The SQL Query - public string InsertValues(string table, List 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); - } - - /// - /// Builds the SQL WHERE clause - /// - /// - /// - protected static string BuildWhere(List wheres) - { - if (0 == wheres.Count) - return string.Empty; - - return "WHERE {0}".SFormat(string.Join(", ", wheres.Select(v => $"{v.Name}" + " = " + v.Value))); - } - } -} diff --git a/TShockAPI/DB/ItemManager.cs b/TShockAPI/DB/ItemManager.cs index 012132dc..e707406c 100644 --- a/TShockAPI/DB/ItemManager.cs +++ b/TShockAPI/DB/ItemManager.cs @@ -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 diff --git a/TShockAPI/DB/ProjectileManager.cs b/TShockAPI/DB/ProjectileManager.cs index 0e6cabe0..f07280b5 100644 --- a/TShockAPI/DB/ProjectileManager.cs +++ b/TShockAPI/DB/ProjectileManager.cs @@ -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 diff --git a/TShockAPI/DB/Queries/GenericQueryCreator.cs b/TShockAPI/DB/Queries/GenericQueryCreator.cs new file mode 100644 index 00000000..f9fc2038 --- /dev/null +++ b/TShockAPI/DB/Queries/GenericQueryCreator.cs @@ -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 . +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MySql.Data.MySqlClient; +using TShockAPI.Extensions; + +namespace TShockAPI.DB.Queries; + +/// +/// A Generic Query Creator (abstract) +/// +public abstract class GenericQueryCreator : IQueryBuilder +{ + protected static Random rand = new Random(); + + /// + /// Escapes the table name + /// + /// The name of the table to be escaped + /// + protected abstract string EscapeTableName(string table); + + /// + public abstract string CreateTable(SqlTable table); + + /// + public abstract string RenameTable(string from, string to); + + /// + 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); + } + + /// + public abstract string DbTypeToString(MySqlDbType type, int? length); + + /// + /// Check for errors in the columns. + /// + /// + /// + protected static void ValidateSqlColumnType(List 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")); + } + }); + } + + + /// + public string DeleteRow(string table, List wheres) + { + return "DELETE FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(wheres)); + } + + /// + public string UpdateValue(string table, List values, List 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)); + } + + + /// + public string ReadColumn(string table, List wheres) + { + return "SELECT * FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(wheres)); + } + + + public string InsertValues(string table, List 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); + } + + /// + /// Builds the SQL WHERE clause + /// + /// + /// + protected static string BuildWhere(List wheres) => wheres.Count > 0 + ? string.Empty + : "WHERE {0}".SFormat(string.Join(", ", wheres.Select(v => $"{v.Name} = {v.Value}"))); +} diff --git a/TShockAPI/DB/Queries/IQueryBuilder.cs b/TShockAPI/DB/Queries/IQueryBuilder.cs new file mode 100644 index 00000000..dc61370f --- /dev/null +++ b/TShockAPI/DB/Queries/IQueryBuilder.cs @@ -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 . +*/ + +using System.Collections.Generic; +using MySql.Data.MySqlClient; + +namespace TShockAPI.DB.Queries; + +/// +/// Interface for various SQL related utilities. +/// +public interface IQueryBuilder +{ + /// + /// Creates a table from a SqlTable object. + /// + /// The SqlTable to create the table from + /// The sql query for the table creation. + string CreateTable(SqlTable table); + + /// + /// Alter a table from source to destination + /// + /// Must have name and column names. Column types are not required + /// Must have column names and column types. + /// The SQL Query + string AlterTable(SqlTable from, SqlTable to); + + /// + /// Converts the MySqlDbType enum to it's string representation. + /// + /// The MySqlDbType type + /// The length of the datatype + /// The string representation + string DbTypeToString(MySqlDbType type, int? length); + + /// + /// A UPDATE Query + /// + /// The table to update + /// The values to change + /// + /// The SQL query + string UpdateValue(string table, List values, List wheres); + + /// + /// A INSERT query + /// + /// The table to insert to + /// + /// The SQL Query + string InsertValues(string table, List values); + + /// + /// A SELECT query to get all columns + /// + /// The table to select from + /// + /// The SQL query + string ReadColumn(string table, List wheres); + + /// + /// Deletes row(s). + /// + /// The table to delete the row from + /// + /// The SQL query + string DeleteRow(string table, List wheres); + + /// + /// Renames the given table. + /// + /// Old name of the table + /// New name of the table + /// The sql query for renaming the table. + string RenameTable(string from, string to); +} diff --git a/TShockAPI/DB/Queries/MysqlQueryCreator.cs b/TShockAPI/DB/Queries/MysqlQueryCreator.cs new file mode 100644 index 00000000..1c0ec24f --- /dev/null +++ b/TShockAPI/DB/Queries/MysqlQueryCreator.cs @@ -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 . +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using MySql.Data.MySqlClient; + +namespace TShockAPI.DB.Queries; + +/// +/// Query Creator for MySQL +/// +public class MysqlQueryCreator : GenericQueryCreator, IQueryBuilder +{ + /// + /// Creates a table from a SqlTable object. + /// + /// The SqlTable to create the table from + /// The sql query for the table creation. + 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)) + : ""); + } + + + /// + public override string RenameTable(string from, string to) => /*lang=mysql*/"RENAME TABLE {0} TO {1}".SFormat(from, to); + + private static readonly Dictionary 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"}, + }; + + /// + 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)); + } + + /// + protected override string EscapeTableName(string table) => table.SFormat("`{0}`", table); +} diff --git a/TShockAPI/DB/Queries/SqliteQueryCreator.cs b/TShockAPI/DB/Queries/SqliteQueryCreator.cs new file mode 100644 index 00000000..229ba49b --- /dev/null +++ b/TShockAPI/DB/Queries/SqliteQueryCreator.cs @@ -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 . +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using MySql.Data.MySqlClient; + +namespace TShockAPI.DB.Queries; + +/// +/// Query Creator for Sqlite +/// +public class SqliteQueryCreator : GenericQueryCreator, IQueryBuilder +{ + /// + /// Creates a table from a SqlTable object. + /// + /// The SqlTable to create the table from + /// The sql query for the table creation. + 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)) : ""); + } + + /// + /// Renames the given table. + /// + /// Old name of the table + /// New name of the table + /// The sql query for renaming the table. + public override string RenameTable(string from, string to) + { + return "ALTER TABLE {0} RENAME TO {1}".SFormat(from, to); + } + + private static readonly Dictionary TypesAsStrings = new Dictionary + { + { 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"}, + }; + + /// + /// Converts the MySqlDbType enum to it's string representation. + /// + /// The MySqlDbType type + /// The length of the datatype + /// The string representation + 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)); + } + + /// + /// Escapes the table name + /// + /// The name of the table to be escaped + /// + protected override string EscapeTableName(string table) => $"\'{table}\'"; +} diff --git a/TShockAPI/DB/RegionManager.cs b/TShockAPI/DB/RegionManager.cs index 1a284ff3..0950f92f 100644 --- a/TShockAPI/DB/RegionManager.cs +++ b/TShockAPI/DB/RegionManager.cs @@ -23,6 +23,7 @@ using System.Linq; using MySql.Data.MySqlClient; using Terraria; using Microsoft.Xna.Framework; +using TShockAPI.DB.Queries; namespace TShockAPI.DB { diff --git a/TShockAPI/DB/RememberedPosManager.cs b/TShockAPI/DB/RememberedPosManager.cs index c49c5912..297877f7 100644 --- a/TShockAPI/DB/RememberedPosManager.cs +++ b/TShockAPI/DB/RememberedPosManager.cs @@ -21,6 +21,7 @@ using System.Data; using MySql.Data.MySqlClient; using Terraria; using Microsoft.Xna.Framework; +using TShockAPI.DB.Queries; namespace TShockAPI.DB { diff --git a/TShockAPI/DB/ResearchDatastore.cs b/TShockAPI/DB/ResearchDatastore.cs index 0d2429d7..cb51ab18 100644 --- a/TShockAPI/DB/ResearchDatastore.cs +++ b/TShockAPI/DB/ResearchDatastore.cs @@ -7,6 +7,7 @@ using System.Text; using System.Threading.Tasks; using Terraria; using Terraria.ID; +using TShockAPI.DB.Queries; namespace TShockAPI.DB { diff --git a/TShockAPI/DB/SqlTable.cs b/TShockAPI/DB/SqlTable.cs index 1f0c4593..299ac851 100644 --- a/TShockAPI/DB/SqlTable.cs +++ b/TShockAPI/DB/SqlTable.cs @@ -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 { diff --git a/TShockAPI/DB/SqlValue.cs b/TShockAPI/DB/SqlValue.cs index aa70e2d6..3df5d995 100644 --- a/TShockAPI/DB/SqlValue.cs +++ b/TShockAPI/DB/SqlValue.cs @@ -18,6 +18,7 @@ along with this program. If not, see . using System.Collections.Generic; using System.Data; +using TShockAPI.DB.Queries; namespace TShockAPI.DB { diff --git a/TShockAPI/DB/TileManager.cs b/TShockAPI/DB/TileManager.cs index bd918e73..61903186 100644 --- a/TShockAPI/DB/TileManager.cs +++ b/TShockAPI/DB/TileManager.cs @@ -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 diff --git a/TShockAPI/DB/UserManager.cs b/TShockAPI/DB/UserManager.cs index 6fc50d98..a3e050f7 100644 --- a/TShockAPI/DB/UserManager.cs +++ b/TShockAPI/DB/UserManager.cs @@ -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 diff --git a/TShockAPI/DB/WarpsManager.cs b/TShockAPI/DB/WarpsManager.cs index bd13ce4d..f3287441 100644 --- a/TShockAPI/DB/WarpsManager.cs +++ b/TShockAPI/DB/WarpsManager.cs @@ -24,6 +24,7 @@ using System.Linq; using MySql.Data.MySqlClient; using Terraria; using Microsoft.Xna.Framework; +using TShockAPI.DB.Queries; namespace TShockAPI.DB { diff --git a/TShockAPI/Extensions/StringExt.cs b/TShockAPI/Extensions/StringExt.cs index 56f46215..8f886031 100644 --- a/TShockAPI/Extensions/StringExt.cs +++ b/TShockAPI/Extensions/StringExt.cs @@ -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); } ///