Merge remote-tracking branch 'origin/general-devel' into fragments
This commit is contained in:
commit
e8a3f87e23
4 changed files with 319 additions and 99 deletions
|
|
@ -27,6 +27,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
|
||||||
* Update OTAPI to 2.0.0.31, which also updates Newtonsoft.Json to 10.0.3 (@Ryozuki)
|
* Update OTAPI to 2.0.0.31, which also updates Newtonsoft.Json to 10.0.3 (@Ryozuki)
|
||||||
* Fixed DumpItems() from trying to dump older versions of certain items (negative item IDs). (@Zaicon)
|
* Fixed DumpItems() from trying to dump older versions of certain items (negative item IDs). (@Zaicon)
|
||||||
* Added the `/dump-reference-data` command, which when run, runs Utils.Dump() and outputs Terraria reference data to the server folder. (@hakusaro)
|
* Added the `/dump-reference-data` command, which when run, runs Utils.Dump() and outputs Terraria reference data to the server folder. (@hakusaro)
|
||||||
|
* Added DateTime datatype support for both MySQL and SQLite. (@Ryozuki)
|
||||||
* Fixed builds to not require a specific version of OTAPI and to not fail when in Release mode (@bartico6)
|
* Fixed builds to not require a specific version of OTAPI and to not fail when in Release mode (@bartico6)
|
||||||
* Update Assembly Company to Pryaxis (@Ryozuki)
|
* Update Assembly Company to Pryaxis (@Ryozuki)
|
||||||
* Removed `/restart` command. (@hakusaro)
|
* Removed `/restart` command. (@hakusaro)
|
||||||
|
|
|
||||||
|
|
@ -16,45 +16,120 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using MySql.Data.MySqlClient;
|
|
||||||
using TShockAPI.Extensions;
|
using TShockAPI.Extensions;
|
||||||
|
|
||||||
namespace TShockAPI.DB
|
namespace TShockAPI.DB
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for various SQL related utilities.
|
||||||
|
/// </summary>
|
||||||
public interface IQueryBuilder
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
string RenameTable(string from, string to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Query Creator for Sqlite
|
||||||
|
/// </summary>
|
||||||
public class SqliteQueryCreator : GenericQueryCreator, IQueryBuilder
|
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)
|
public override string CreateTable(SqlTable table)
|
||||||
{
|
{
|
||||||
|
ValidateSqlColumnType(table.Columns);
|
||||||
var columns =
|
var columns =
|
||||||
table.Columns.Select(
|
table.Columns.Select(
|
||||||
c =>
|
c =>
|
||||||
"'{0}' {1} {2} {3} {4}".SFormat(c.Name,
|
"'{0}' {1} {2} {3} {4} {5}".SFormat(c.Name,
|
||||||
DbTypeToString(c.Type, c.Length),
|
DbTypeToString(c.Type, c.Length),
|
||||||
c.Primary ? "PRIMARY KEY" : "",
|
c.Primary ? "PRIMARY KEY" : "",
|
||||||
c.AutoIncrement ? "AUTOINCREMENT" : "",
|
c.AutoIncrement ? "AUTOINCREMENT" : "",
|
||||||
c.NotNull ? "NOT NULL" : ""));
|
c.NotNull ? "NOT NULL" : "",
|
||||||
|
c.DefaultCurrentTimestamp ? "DEFAULT CURRENT_TIMESTAMP" : ""));
|
||||||
var uniques = table.Columns.Where(c => c.Unique).Select(c => c.Name);
|
var uniques = table.Columns.Where(c => c.Unique).Select(c => c.Name);
|
||||||
return "CREATE TABLE {0} ({1} {2})".SFormat(EscapeTableName(table.Name),
|
return "CREATE TABLE {0} ({1} {2})".SFormat(EscapeTableName(table.Name),
|
||||||
string.Join(", ", columns),
|
string.Join(", ", columns),
|
||||||
uniques.Count() > 0 ? ", UNIQUE({0})".SFormat(string.Join(", ", uniques)) : "");
|
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)
|
public override string RenameTable(string from, string to)
|
||||||
{
|
{
|
||||||
return "ALTER TABLE {0} RENAME TO {1}".SFormat(from, to);
|
return "ALTER TABLE {0} RENAME TO {1}".SFormat(from, to);
|
||||||
|
|
@ -72,9 +147,16 @@ namespace TShockAPI.DB
|
||||||
{ MySqlDbType.Double, "REAL" },
|
{ MySqlDbType.Double, "REAL" },
|
||||||
{ MySqlDbType.Int32, "INTEGER" },
|
{ MySqlDbType.Int32, "INTEGER" },
|
||||||
{ MySqlDbType.Blob, "BLOB" },
|
{ MySqlDbType.Blob, "BLOB" },
|
||||||
{ MySqlDbType.Int64, "BIGINT"},
|
{ 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)
|
public string DbTypeToString(MySqlDbType type, int? length)
|
||||||
{
|
{
|
||||||
string ret;
|
string ret;
|
||||||
|
|
@ -83,21 +165,38 @@ namespace TShockAPI.DB
|
||||||
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
|
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)
|
protected override string EscapeTableName(string table)
|
||||||
{
|
{
|
||||||
return table.SFormat("'{0}'", table);
|
return table.SFormat("'{0}'", table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Query Creator for MySQL
|
||||||
|
/// </summary>
|
||||||
public class MysqlQueryCreator : GenericQueryCreator, IQueryBuilder
|
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)
|
public override string CreateTable(SqlTable table)
|
||||||
{
|
{
|
||||||
|
ValidateSqlColumnType(table.Columns);
|
||||||
var columns =
|
var columns =
|
||||||
table.Columns.Select(
|
table.Columns.Select(
|
||||||
c =>
|
c =>
|
||||||
"{0} {1} {2} {3} {4}".SFormat(c.Name, DbTypeToString(c.Type, c.Length), c.Primary ? "PRIMARY KEY" : "",
|
"{0} {1} {2} {3} {4} {5}".SFormat(c.Name, DbTypeToString(c.Type, c.Length),
|
||||||
c.AutoIncrement ? "AUTO_INCREMENT" : "", c.NotNull ? "NOT NULL" : ""));
|
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);
|
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),
|
return "CREATE TABLE {0} ({1} {2})".SFormat(EscapeTableName(table.Name), string.Join(", ", columns),
|
||||||
uniques.Count() > 0
|
uniques.Count() > 0
|
||||||
|
|
@ -105,6 +204,12 @@ namespace TShockAPI.DB
|
||||||
: "");
|
: "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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)
|
public override string RenameTable(string from, string to)
|
||||||
{
|
{
|
||||||
return "RENAME TABLE {0} TO {1}".SFormat(from, to);
|
return "RENAME TABLE {0} TO {1}".SFormat(from, to);
|
||||||
|
|
@ -121,9 +226,16 @@ namespace TShockAPI.DB
|
||||||
{ MySqlDbType.Float, "FLOAT" },
|
{ MySqlDbType.Float, "FLOAT" },
|
||||||
{ MySqlDbType.Double, "DOUBLE" },
|
{ MySqlDbType.Double, "DOUBLE" },
|
||||||
{ MySqlDbType.Int32, "INT" },
|
{ MySqlDbType.Int32, "INT" },
|
||||||
{ MySqlDbType.Int64, "BIGINT"},
|
{ 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)
|
public string DbTypeToString(MySqlDbType type, int? length)
|
||||||
{
|
{
|
||||||
string ret;
|
string ret;
|
||||||
|
|
@ -132,17 +244,44 @@ namespace TShockAPI.DB
|
||||||
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
|
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)
|
protected override string EscapeTableName(string table)
|
||||||
{
|
{
|
||||||
return table.SFormat("`{0}`", table);
|
return table.SFormat("`{0}`", table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A Generic Query Creator (abstract)
|
||||||
|
/// </summary>
|
||||||
public abstract class GenericQueryCreator
|
public abstract class GenericQueryCreator
|
||||||
{
|
{
|
||||||
protected static Random rand = new Random();
|
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);
|
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);
|
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);
|
public abstract string RenameTable(string from, string to);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -150,18 +289,9 @@ namespace TShockAPI.DB
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="from">Must have name and column names. Column types are not required</param>
|
/// <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>
|
/// <param name="to">Must have column names and column types.</param>
|
||||||
/// <returns></returns>
|
/// <returns>The SQL Query</returns>
|
||||||
public string AlterTable(SqlTable from, SqlTable to)
|
public string AlterTable(SqlTable from, SqlTable to)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Any example outpuf from this looks like:-
|
|
||||||
ALTER TABLE "main"."Bans" RENAME TO "oXHFcGcd04oXHFcGcd04_Bans"
|
|
||||||
CREATE TABLE "main"."Bans" ("IP" TEXT PRIMARY KEY ,"Name" TEXT)
|
|
||||||
INSERT INTO "main"."Bans" SELECT "IP","Name" FROM "main"."oXHFcGcd04oXHFcGcd04_Bans"
|
|
||||||
DROP TABLE "main"."oXHFcGcd04oXHFcGcd04_Bans"
|
|
||||||
*
|
|
||||||
* Twitchy - Oh. I get it!
|
|
||||||
*/
|
|
||||||
var rstr = rand.NextString(20);
|
var rstr = rand.NextString(20);
|
||||||
var escapedTable = EscapeTableName(from.Name);
|
var escapedTable = EscapeTableName(from.Name);
|
||||||
var tmpTable = EscapeTableName("{0}_{1}".SFormat(rstr, from.Name));
|
var tmpTable = EscapeTableName("{0}_{1}".SFormat(rstr, from.Name));
|
||||||
|
|
@ -175,11 +305,41 @@ namespace TShockAPI.DB
|
||||||
return "{0}; {1}; {2}; {3};".SFormat(alter, create, insert, drop);
|
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("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)
|
public string DeleteRow(string table, List<SqlValue> wheres)
|
||||||
{
|
{
|
||||||
return "DELETE FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(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)
|
public string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres)
|
||||||
{
|
{
|
||||||
if (0 == values.Count)
|
if (0 == values.Count)
|
||||||
|
|
@ -188,11 +348,23 @@ namespace TShockAPI.DB
|
||||||
return "UPDATE {0} SET {1} {2}".SFormat(EscapeTableName(table), string.Join(", ", values.Select(v => v.Name + " = " + v.Value)), BuildWhere(wheres));
|
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)
|
public string ReadColumn(string table, List<SqlValue> wheres)
|
||||||
{
|
{
|
||||||
return "SELECT * FROM {0} {1}".SFormat(EscapeTableName(table), BuildWhere(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)
|
public string InsertValues(string table, List<SqlValue> values)
|
||||||
{
|
{
|
||||||
var sbnames = new StringBuilder();
|
var sbnames = new StringBuilder();
|
||||||
|
|
@ -214,6 +386,11 @@ namespace TShockAPI.DB
|
||||||
return "INSERT INTO {0} ({1}) VALUES ({2})".SFormat(EscapeTableName(table), sbnames, sbvalues);
|
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)
|
protected static string BuildWhere(List<SqlValue> wheres)
|
||||||
{
|
{
|
||||||
if (0 == wheres.Count)
|
if (0 == wheres.Count)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace TShockAPI.DB
|
namespace TShockAPI.DB
|
||||||
{
|
{
|
||||||
|
|
@ -28,11 +29,30 @@ namespace TShockAPI.DB
|
||||||
|
|
||||||
|
|
||||||
//Optional
|
//Optional
|
||||||
|
/// <summary>
|
||||||
|
/// Sets/Gets if it's unique
|
||||||
|
/// </summary>
|
||||||
public bool Unique { get; set; }
|
public bool Unique { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Sets/Gets if it's primary key
|
||||||
|
/// </summary>
|
||||||
public bool Primary { get; set; }
|
public bool Primary { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Sets/Gets if it autoincrements
|
||||||
|
/// </summary>
|
||||||
public bool AutoIncrement { get; set; }
|
public bool AutoIncrement { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Sets/Gets if it can be or not null
|
||||||
|
/// </summary>
|
||||||
public bool NotNull { get; set; }
|
public bool NotNull { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the default value
|
||||||
|
/// </summary>
|
||||||
public string DefaultValue { get; set; }
|
public string DefaultValue { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Use on DateTime only, if true, sets the default value to the current date when creating the row.
|
||||||
|
/// </summary>
|
||||||
|
public bool DefaultCurrentTimestamp { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Length of the data type, null = default
|
/// Length of the data type, null = default
|
||||||
|
|
@ -51,4 +71,19 @@ namespace TShockAPI.DB
|
||||||
Length = length;
|
Length = length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used when a SqlColumn has validation errors.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class SqlColumnException : Exception
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new SqlColumnException with the given message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
public SqlColumnException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
namespace TShockAPI.DB
|
namespace TShockAPI.DB
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Database extensions
|
||||||
|
/// </summary>
|
||||||
public static class DbExt
|
public static class DbExt
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -103,7 +106,7 @@ namespace TShockAPI.DB
|
||||||
|
|
||||||
public static IDbConnection CloneEx(this IDbConnection conn)
|
public static IDbConnection CloneEx(this IDbConnection conn)
|
||||||
{
|
{
|
||||||
var clone = (IDbConnection) Activator.CreateInstance(conn.GetType());
|
var clone = (IDbConnection)Activator.CreateInstance(conn.GetType());
|
||||||
clone.ConnectionString = conn.ConnectionString;
|
clone.ConnectionString = conn.ConnectionString;
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
@ -120,80 +123,84 @@ namespace TShockAPI.DB
|
||||||
|
|
||||||
private static readonly Dictionary<Type, Func<IDataReader, int, object>> ReadFuncs = new Dictionary
|
private static readonly Dictionary<Type, Func<IDataReader, int, object>> ReadFuncs = new Dictionary
|
||||||
<Type, Func<IDataReader, int, object>>
|
<Type, Func<IDataReader, int, object>>
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
typeof (bool),
|
typeof (bool),
|
||||||
(s, i) => s.GetBoolean(i)
|
(s, i) => s.GetBoolean(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (bool?),
|
typeof (bool?),
|
||||||
(s, i) => s.IsDBNull(i) ? null : (object)s.GetBoolean(i)
|
(s, i) => s.IsDBNull(i) ? null : (object)s.GetBoolean(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (byte),
|
typeof (byte),
|
||||||
(s, i) => s.GetByte(i)
|
(s, i) => s.GetByte(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (byte?),
|
typeof (byte?),
|
||||||
(s, i) => s.IsDBNull(i) ? null : (object)s.GetByte(i)
|
(s, i) => s.IsDBNull(i) ? null : (object)s.GetByte(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (Int16),
|
typeof (Int16),
|
||||||
(s, i) => s.GetInt16(i)
|
(s, i) => s.GetInt16(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (Int16?),
|
typeof (Int16?),
|
||||||
(s, i) => s.IsDBNull(i) ? null : (object)s.GetInt16(i)
|
(s, i) => s.IsDBNull(i) ? null : (object)s.GetInt16(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (Int32),
|
typeof (Int32),
|
||||||
(s, i) => s.GetInt32(i)
|
(s, i) => s.GetInt32(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (Int32?),
|
typeof (Int32?),
|
||||||
(s, i) => s.IsDBNull(i) ? null : (object)s.GetInt32(i)
|
(s, i) => s.IsDBNull(i) ? null : (object)s.GetInt32(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (Int64),
|
typeof (Int64),
|
||||||
(s, i) => s.GetInt64(i)
|
(s, i) => s.GetInt64(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (Int64?),
|
typeof (Int64?),
|
||||||
(s, i) => s.IsDBNull(i) ? null : (object)s.GetInt64(i)
|
(s, i) => s.IsDBNull(i) ? null : (object)s.GetInt64(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (string),
|
typeof (string),
|
||||||
(s, i) => s.GetString(i)
|
(s, i) => s.GetString(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (decimal),
|
typeof (decimal),
|
||||||
(s, i) => s.GetDecimal(i)
|
(s, i) => s.GetDecimal(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (decimal?),
|
typeof (decimal?),
|
||||||
(s, i) => s.IsDBNull(i) ? null : (object)s.GetDecimal(i)
|
(s, i) => s.IsDBNull(i) ? null : (object)s.GetDecimal(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (float),
|
typeof (float),
|
||||||
(s, i) => s.GetFloat(i)
|
(s, i) => s.GetFloat(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (float?),
|
typeof (float?),
|
||||||
(s, i) => s.IsDBNull(i) ? null : (object)s.GetFloat(i)
|
(s, i) => s.IsDBNull(i) ? null : (object)s.GetFloat(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (double),
|
typeof (double),
|
||||||
(s, i) => s.GetDouble(i)
|
(s, i) => s.GetDouble(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (double?),
|
typeof (double?),
|
||||||
(s, i) => s.IsDBNull(i) ? null : (object)s.GetDouble(i)
|
(s, i) => s.IsDBNull(i) ? null : (object)s.GetDouble(i)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
typeof (object),
|
typeof (DateTime),
|
||||||
(s, i) => s.GetValue(i)
|
(s, i) => s.IsDBNull(i) ? null : (object)s.GetDateTime(i)
|
||||||
},
|
},
|
||||||
};
|
{
|
||||||
|
typeof (object),
|
||||||
|
(s, i) => s.GetValue(i)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
public static T Get<T>(this IDataReader reader, string column)
|
public static T Get<T>(this IDataReader reader, string column)
|
||||||
{
|
{
|
||||||
|
|
@ -205,8 +212,8 @@ namespace TShockAPI.DB
|
||||||
if (reader.IsDBNull(column))
|
if (reader.IsDBNull(column))
|
||||||
return default(T);
|
return default(T);
|
||||||
|
|
||||||
if (ReadFuncs.ContainsKey(typeof (T)))
|
if (ReadFuncs.ContainsKey(typeof(T)))
|
||||||
return (T) ReadFuncs[typeof (T)](reader, column);
|
return (T)ReadFuncs[typeof(T)](reader, column);
|
||||||
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
@ -272,4 +279,4 @@ namespace TShockAPI.DB
|
||||||
return Reader.Get<T>(Reader.GetOrdinal(column));
|
return Reader.Get<T>(Reader.GetOrdinal(column));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue