using Npgsql; using ServerDatabase.Utils; namespace ServerDatabase; public class CommandHandler : ICommandHandler where TClass : class, new() { internal List Tables = new(); internal List _Parameters = new(); internal List _Values = new(); internal List _ValuesOld = new(); internal List _ParametersOld = new(); public IReadOnlyList Parameters { get => _Parameters.AsReadOnly(); } public IReadOnlyList Values { get => _Values.AsReadOnly(); } private Order? Order = null; private IBetterTable _betterTable; private string? ctc = null; private char table_as = 'A'; private ICommandHandler? _CommandHandlerParent = null; private ICommandHandler? _Child = null; public char TableAsLetter { get => table_as; } public string? CTC { get => ctc; } public ICommandHandler? CommandHandlerParent { get => _CommandHandlerParent; } public ICommandHandler? Child { get => _Child; } public IBetterTable BetterTable { get => _betterTable; } internal CommandHandler(IBetterTable betterTable) { this._betterTable = betterTable; } private CommandHandler(IBetterTable betterTable, char TableAs, ICommandHandler ch) { this._betterTable = betterTable; this._CommandHandlerParent = ch; this.table_as = TableAs; } internal CommandHandler WithFilter(IBetterParameter p) { _Parameters.Add(p); return this; } internal CommandHandler WithValue(IBetterParameter p) { _Values.Add(p); return this; } internal CommandHandler WithValue(Parameter p) { _ValuesOld.Add(p); return this; } public CommandHandler WithFilter(TableColumn column, T value, string sign = "=") where T : notnull { return WithFilter(new BetterParameter() { Column = column.Name, Sign = sign, Value = value, }); } public CommandHandler WithValue(TableColumn column, T value) where T : notnull { return WithValue(new BetterParameter() { Column = column.Name, Sign = "=", Value = value, }); } public CommandHandler AscendBy(TableColumn column) where T : notnull { Order = column.GetAssendingOrder(); return this; } public CommandHandler DescendBy(TableColumn column) where T : notnull { Order = column.GetDecendingOrder(); return this; } public CommandHandler WithCrossTableCheck(TableColumn column1, Table Table, TableColumn column2) where TCol : class, new() where T : notnull { return WithCrossTableCheck(column1, "=", Table,column2); } public CommandHandler WithCrossTableCheck(TableColumn column1, string sign, Table Table, TableColumn column2) where TCol : class, new() where T : notnull { ctc = $"{table_as}.{column1.Name} {sign} {(char)(table_as + 1)}.{column2.Name}"; CommandHandler child = new CommandHandler(Table, (char)(table_as + 1), this); _Child = child; return child; } public T Read(TableColumn column) where T : notnull { string command = $"SELECT {TableAsLetter}.{column.Name} FROM {_betterTable.Name} AS {TableAsLetter}"; ICommandHandler? pc = this; ICommandHandler? c = this.CommandHandlerParent; while (c is not null) { command += $", {c.BetterTable.Name} AS {c.TableAsLetter}"; pc = c; c = c.CommandHandlerParent; } command += " WHERE"; if (string.IsNullOrEmpty(_betterTable.DatabaseHandler.DB) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.IP) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.Uname) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.PW)) throw new Exception("Database conection not fully defined"); using NpgsqlConnection con = new(_betterTable.DatabaseHandler.ConectionString); con.Open(); using NpgsqlCommand cmd = new(); cmd.Connection = con; char col_char = 'A'; string vals = ""; while (pc is not null) { foreach (IBetterParameter param in pc.Parameters) { vals += $"{pc.TableAsLetter}.{param.Column} {param.Sign} @{col_char} AND "; cmd.Parameters.Add(param.CreateParameter(col_char.ToString())); col_char++; } if (pc.CTC is not null) vals += pc.CTC + " AND "; pc = pc.Child; } if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5); if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}"; command += ";"; cmd.CommandText = command; object? temp = cmd.ExecuteScalar(); con.Close(); if (temp is DBNull || temp is null) return default!; if (typeof(T).IsEnum) return (T?)Enum.Parse(typeof(T), temp.ToString()!)!; if (typeof(T).IsNullableEnum()) return (T?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T))!, temp.ToString()!)!; return (T?)temp!; } public (T, T2) Read(TableColumn column, TableColumn column2) where T : notnull where T2 : notnull { string command = $"SELECT {TableAsLetter}.{column.Name}, {TableAsLetter}.{column2.Name} FROM {_betterTable.Name} AS {TableAsLetter}"; ICommandHandler? pc = this; ICommandHandler? c = this.CommandHandlerParent; while (c is not null) { command += $", {c.BetterTable.Name} AS {c.TableAsLetter}"; pc = c; c = c.CommandHandlerParent; } command += " WHERE"; if (string.IsNullOrEmpty(_betterTable.DatabaseHandler.DB) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.IP) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.Uname) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.PW)) throw new Exception("Database conection not fully defined"); using NpgsqlConnection con = new(_betterTable.DatabaseHandler.ConectionString); con.Open(); using NpgsqlCommand cmd = new(); cmd.Connection = con; char col_char = 'A'; string vals = ""; while (pc is not null) { foreach (IBetterParameter param in pc.Parameters) { vals += $"{pc.TableAsLetter}.{param.Column} {param.Sign} @{col_char} AND "; cmd.Parameters.Add(param.CreateParameter(col_char.ToString())); col_char++; } if (pc.CTC is not null) vals += pc.CTC + " AND "; pc = pc.Child; } if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5); if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}"; command += ";"; cmd.CommandText = command; NpgsqlDataReader reader = cmd.ExecuteReader(); reader.Read(); object?[] temp = new object[reader.FieldCount]; for (int i = 0; i < reader.FieldCount; i++) { string colname = reader.GetName(i); object val = reader.GetValue(i); if (i == 0) { if (typeof(T).IsEnum) temp[i] = (T?)Enum.Parse(typeof(T), val.ToString()!)!; if (typeof(T).IsNullableEnum()) temp[i] = (T?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T))!, val.ToString()!)!; } else if (i == 1) { if (typeof(T2).IsEnum) temp[i] = (T2?)Enum.Parse(typeof(T2), val.ToString()!)!; if (typeof(T2).IsNullableEnum()) temp[i] = (T2?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T2))!, val.ToString()!)!; } if (temp[i] is null) temp[i] = val; } con.Close(); return ((T)temp[0]!, (T2)temp[1]!); } public (T, T2, T3) Read(TableColumn column, TableColumn column2, TableColumn column3) where T : notnull where T2 : notnull where T3 : notnull { string command = $"SELECT {TableAsLetter}.{column.Name}, {TableAsLetter}.{column2.Name}, {TableAsLetter}.{column3.Name} FROM {_betterTable.Name} AS {TableAsLetter}"; ICommandHandler? pc = this; ICommandHandler? c = this.CommandHandlerParent; while (c is not null) { command += $", {c.BetterTable.Name} AS {c.TableAsLetter}"; pc = c; c = c.CommandHandlerParent; } command += " WHERE"; if (string.IsNullOrEmpty(_betterTable.DatabaseHandler.DB) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.IP) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.Uname) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.PW)) throw new Exception("Database conection not fully defined"); using NpgsqlConnection con = new(_betterTable.DatabaseHandler.ConectionString); con.Open(); using NpgsqlCommand cmd = new(); cmd.Connection = con; char col_char = 'A'; string vals = ""; while (pc is not null) { foreach (IBetterParameter param in pc.Parameters) { vals += $"{pc.TableAsLetter}.{param.Column} {param.Sign} @{col_char} AND "; cmd.Parameters.Add(param.CreateParameter(col_char.ToString())); col_char++; } if (pc.CTC is not null) vals += pc.CTC + " AND "; pc = pc.Child; } if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5); if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}"; command += ";"; cmd.CommandText = command; NpgsqlDataReader reader = cmd.ExecuteReader(); reader.Read(); object?[] temp = new object[reader.FieldCount]; for (int i = 0; i < reader.FieldCount; i++) { string colname = reader.GetName(i); object val = reader.GetValue(i); if (i == 0) { if (typeof(T).IsEnum) temp[i] = (T?)Enum.Parse(typeof(T), val.ToString()!)!; if (typeof(T).IsNullableEnum()) temp[i] = (T?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T))!, val.ToString()!)!; } else if (i == 1) { if (typeof(T2).IsEnum) temp[i] = (T2?)Enum.Parse(typeof(T2), val.ToString()!)!; if (typeof(T2).IsNullableEnum()) temp[i] = (T2?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T2))!, val.ToString()!)!; } else if (i == 2) { if (typeof(T3).IsEnum) temp[i] = (T3?)Enum.Parse(typeof(T3), val.ToString()!)!; if (typeof(T3).IsNullableEnum()) temp[i] = (T3?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T3))!, val.ToString()!)!; } if (temp[i] is null) temp[i] = val; } con.Close(); return ((T)temp[0]!, (T2)temp[1]!, (T3)temp[2]!); } public (T, T2, T3)[] ReadColumns(TableColumn column, TableColumn column2, TableColumn column3) where T : notnull where T2 : notnull where T3 : notnull { string command = $"SELECT {TableAsLetter}.{column.Name}, {TableAsLetter}.{column2.Name}, {TableAsLetter}.{column3.Name} FROM {_betterTable.Name} AS {TableAsLetter}"; ICommandHandler? pc = this; ICommandHandler? c = this.CommandHandlerParent; while (c is not null) { command += $", {c.BetterTable.Name} AS {c.TableAsLetter}"; pc = c; c = c.CommandHandlerParent; } command += " WHERE"; if (string.IsNullOrEmpty(_betterTable.DatabaseHandler.DB) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.IP) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.Uname) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.PW)) throw new Exception("Database conection not fully defined"); using NpgsqlConnection con = new(_betterTable.DatabaseHandler.ConectionString); con.Open(); using NpgsqlCommand cmd = new(); cmd.Connection = con; char col_char = 'A'; string vals = ""; while (pc is not null) { foreach (IBetterParameter param in pc.Parameters) { vals += $"{pc.TableAsLetter}.{param.Column} {param.Sign} @{col_char} AND "; cmd.Parameters.Add(param.CreateParameter(col_char.ToString())); col_char++; } if (pc.CTC is not null) vals += pc.CTC + " AND "; pc = pc.Child; } if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5); if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}"; command += ";"; cmd.CommandText = command; NpgsqlDataReader reader = cmd.ExecuteReader(); List<(T, T2, T3)> l = new(); while (reader.Read()) { object?[] temp = new object[reader.FieldCount]; for (int i = 0; i < reader.FieldCount; i++) { object val = reader.GetValue(i); if (i == 0) { if (typeof(T).IsEnum) temp[i] = (T?)Enum.Parse(typeof(T), val.ToString()!)!; if (typeof(T).IsNullableEnum()) temp[i] = (T?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T))!, val.ToString()!)!; } else if (i == 1) { if (typeof(T2).IsEnum) temp[i] = (T2?)Enum.Parse(typeof(T2), val.ToString()!)!; if (typeof(T2).IsNullableEnum()) temp[i] = (T2?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T2))!, val.ToString()!)!; } else if (i == 2) { if (typeof(T3).IsEnum) temp[i] = (T3?)Enum.Parse(typeof(T3), val.ToString()!)!; if (typeof(T3).IsNullableEnum()) temp[i] = (T3?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T3))!, val.ToString()!)!; } if (temp[i] is null) temp[i] = val; } l.Add(new((T)temp[0]!, (T2)temp[1]!, (T3)temp[2]!)); } con.Close(); return l.ToArray(); } public void Update() { string command = $"UPDATE {BetterTable.Name} AS {TableAsLetter} SET "; ICommandHandler? pc = this; ICommandHandler? c = this.CommandHandlerParent; using NpgsqlConnection con = new(_betterTable.DatabaseHandler.ConectionString); con.Open(); using NpgsqlCommand cmd = new(); cmd.Connection = con; string vals = ""; char col_char = 'A'; foreach (IBetterParameter param in Values) { vals += $"{param.Column} = @{col_char}, "; cmd.Parameters.Add(param.CreateParameter(col_char.ToString())); col_char++; } command += vals.Remove(vals.Length - 2, 2) + " "; string from = ""; if (c is not null) from += "FROM "; while (c is not null) { from += $"{c.BetterTable.Name} AS {c.TableAsLetter}, "; pc = c; c = c.CommandHandlerParent; } if (from.Length > 0) command += from.Remove(from.Length - 2, 2); vals = ""; while (pc is not null) { foreach (IBetterParameter param in pc.Parameters) { vals += $"{pc.TableAsLetter}.{param.Column} {param.Sign} @{col_char} AND "; cmd.Parameters.Add(param.CreateParameter(col_char.ToString())); col_char++; } if (pc.CTC is not null) vals += pc.CTC + " AND "; pc = pc.Child; } if (!string.IsNullOrWhiteSpace(vals)) { vals = vals.Remove(vals.Length - 4, 4); command += "WHERE " + vals; } command = command.Remove(command.Length - 1, 1) + ";"; cmd.CommandText = command; cmd.Prepare(); cmd.ExecuteNonQuery(); con.Close(); } }