diff --git a/TShockAPI/DB/Queries/PostgresQueryCreator.cs b/TShockAPI/DB/Queries/PostgresQueryCreator.cs new file mode 100644 index 00000000..779e38b0 --- /dev/null +++ b/TShockAPI/DB/Queries/PostgresQueryCreator.cs @@ -0,0 +1,89 @@ +/* +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 PostgreSQL +/// +public class PostgresQueryCreator : GenericQueryCreator +{ + /// + public override string DbTypeToString(MySqlDbType type, int? length) => type switch + { + MySqlDbType.VarChar when length is not null => "VARCHAR({0})".SFormat(length), + MySqlDbType.String when length is not null => "CHAR({0})".SFormat(length), + MySqlDbType.Text => "TEXT", + MySqlDbType.TinyText => "TEXT", + MySqlDbType.MediumText => "TEXT", + MySqlDbType.LongText => "TEXT", + MySqlDbType.Float => "REAL", + MySqlDbType.Double => "DOUBLE PRECISION", + MySqlDbType.Int32 => "INT", + MySqlDbType.Int64 => "BIGINT", + MySqlDbType.DateTime => "TIMESTAMP", + + _ => throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type)) + }; + + /// + protected override string EscapeTableName(string table) => table.SFormat("\"{0}\"", table); + + /// + public override string CreateTable(SqlTable table) + { + ValidateSqlColumnType(table.Columns); + + IEnumerable columns = table.Columns.Select(c => + { + // Handle PostgreSQL-specific auto-increment using SERIAL/BIGSERIAL + string dataType; + + if (c.AutoIncrement) + { + dataType = c.Type is MySqlDbType.Int32 ? "SERIAL" : "BIGSERIAL"; + } + else + { + dataType = DbTypeToString(c.Type, c.Length); + } + + return "\"{0}\" {1} {2} {3} {4}".SFormat(c.Name, + dataType, + c.Primary ? "PRIMARY KEY" : "", + c.NotNull && !c.AutoIncrement ? "NOT NULL" : "", // SERIAL implies NOT NULL + c.DefaultCurrentTimestamp ? "DEFAULT CURRENT_TIMESTAMP" : ""); + }); + + string[] uniques = table.Columns + .Where(c => c.Unique).Select(c => $"\"{c.Name}\"") + .ToArray(); // No re-enumeration + + 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=postgresql*/"ALTER TABLE {0} RENAME TO {1}".SFormat(from, to); +} diff --git a/TShockAPI/SqlLog.cs b/TShockAPI/SqlLog.cs index 3e79aaab..2e5a55e3 100644 --- a/TShockAPI/SqlLog.cs +++ b/TShockAPI/SqlLog.cs @@ -24,6 +24,7 @@ using System.Globalization; using System.Linq; using MySql.Data.MySqlClient; using TShockAPI.DB; +using TShockAPI.DB.Queries; namespace TShockAPI { diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj index a01bb022..a152bd03 100644 --- a/TShockAPI/TShockAPI.csproj +++ b/TShockAPI/TShockAPI.csproj @@ -36,6 +36,7 @@ +