ServerDatabase/Database/Table.cs

664 lines
27 KiB
C#
Raw Normal View History

2023-06-28 12:44:59 -04:00
using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Npgsql;
using ServerDatabase.Utils;
2024-03-22 12:11:19 -04:00
using ServerDatabase.Utils.Enums;
2023-06-28 12:44:59 -04:00
namespace ServerDatabase;
2024-03-22 12:11:19 -04:00
public class Table<TRow> : IBetterTable where TRow : class, new()
2023-06-28 12:44:59 -04:00
{
public Table(string Name, Database DB)
{
if (Name == "table_versions") throw new ArgumentException("The table name 'table_versions' is not allowed", nameof(Name));
this.Name = Name;
DatabaseHandler = DB;
}
internal Table(Database DB)
{
this.Name = "table_versions";
DatabaseHandler = DB;
}
2024-03-22 12:11:19 -04:00
public CommandHandler CreateCommand()
{
return new CommandHandler(this);
}
2023-06-28 12:44:59 -04:00
public Table<TRow> WithColumn(ITableColumn Column, string name)
{
Colums_.Add(Column);
colnamesraw.Add(Column.Name, name);
return this;
}
public void AddColumn(ITableColumn Column, string name)
{
colnamesraw.Add(Column.Name, name);
Colums_.Add(Column);
}
public IReadOnlyList<ITableColumn> GetMissingColumns(out IReadOnlyList<ITableColumn> UpdatedColumns, out string[] ExtraColumns)
2023-06-28 12:44:59 -04:00
{
List<ITableColumn> coll = new(Colums_);
List<ITableColumn> col = new(Colums_);
List<string> co = new();
2023-06-28 12:44:59 -04:00
foreach (DataRow row in DatabaseHandler.CreateConnection().GetSchema("Columns", new[] { DatabaseHandler.DB, null, Name }).Rows)
{
string name = row.Field<string>("COLUMN_NAME")!,
ty = row.Field<string>("DATA_TYPE")!;
IEnumerable<ITableColumn> t = Colums_.Where(s => s.Name == name);
if (t.Any())
{
col.Remove(t.First());
if (t.First()!.GetDatabaseTypeStr() == ty) coll.Remove(t.First());
}
else
{
co.Add(name);
}
2023-06-28 12:44:59 -04:00
}
UpdatedColumns = coll;
ExtraColumns = co.ToArray();
2023-06-28 12:44:59 -04:00
return col.AsReadOnly();
}
public void UpdateTable()
{
Console.WriteLine("Verifying Table: {0}", Name);
bool i = true;
IReadOnlyList<ITableColumn> m = GetMissingColumns(out IReadOnlyList<ITableColumn> n, out string[] o);
2023-06-28 12:44:59 -04:00
if (m.Any())
{
if (i)
{
i = false;
Console.WriteLine("Fixing Table: {0}", Name);
}
2023-06-28 12:44:59 -04:00
if (DatabaseHandler.Read<long>(
$"SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema LIKE 'public' AND table_type LIKE 'BASE TABLE' AND table_name = '{Name}';") ==
0)
{
Create();
}
else
{
foreach (ITableColumn col in m)
{
try
{
if (col.IsPrimaryKey) throw new Exception($"DELETE THE TABLE '{Name}' TO FIX TABLE GENERATION");
string sql = $"ALTER TABLE IF EXISTS public.{Name} ADD COLUMN {col.Name} {col.GetDatabaseTypeStr()}";
sql += " NOT NULL";
if (col.GetDefaultStr() is not null) sql += $" DEFAULT {col.GetDefaultStr()}";
sql += ";";
DatabaseHandler.ExecuteNonQuery(sql);
}
catch (Exception e)
{
Console.WriteLine("Posible fail to set default for public.{0}.{1}", Name, col.Name);
}
}
}
}
if (n.Any())
{
if (i)
{
i = false;
Console.WriteLine("Fixing Table: {0}", Name);
}
2023-06-28 12:44:59 -04:00
foreach (ITableColumn col in n)
{
string sql = $"ALTER TABLE public.{Name} ALTER COLUMN {col.Name} TYPE {col.GetDatabaseTypeStr()};";
DatabaseHandler.ExecuteNonQuery(sql);
if (col.GetDefaultStr() is not null)
{
try
{
sql = $"ALTER TABLE IF EXISTS public.{Name} ALTER COLUMN {col.Name} SET DEFAULT {col.GetDefaultStr()};";
DatabaseHandler.ExecuteNonQuery(sql);
}
catch (Exception e)
{
Console.WriteLine("Failed to set default for public.{0}.{1}\nSQL: {2}", Name, col.Name, sql);
}
}
}
}
if (o.Any())
{
if (i)
{
i = false;
Console.WriteLine("Fixing Table: {0}", Name);
}
foreach (string c in o)
{
DatabaseHandler.ExecuteNonQuery($"ALTER TABLE IF EXISTS {Name} DROP COLUMN IF EXISTS {c};");
}
}
2023-06-28 12:44:59 -04:00
}
public Table<TRow> DropColumn<TType>(TableColumn<TType> Column) where TType : notnull
{
Colums_.Remove(Column);
return this;
}
private Dictionary<string, string> colnamesraw = new();
private List<ITableColumn> Colums_ { get; set; } = new();
public IReadOnlyList<ITableColumn> Colums => Colums_.AsReadOnly();
public string Name { get; set; } = default!;
public Database DatabaseHandler { get; set; } = default!;
public void Insert(params Parameter[] Parameters)
{
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
string vals = "";
List<ITableColumn> l = new List<ITableColumn>(Colums_);
foreach (Parameter param in Parameters)
{
l.Remove(l.Where(s => s.Name == param.PGParameter.ParameterName).First());
vals += "@" + param.PGParameter.ParameterName + ", ";
cmd.Parameters.Add(param.PGParameter);
}
foreach (ITableColumn cop in l)
{
var param = cop.CreateDefaultParameter();
vals += "@" + param.PGParameter.ParameterName + ", ";
cmd.Parameters.Add(param.PGParameter);
}
vals = vals.Remove(vals.Length - 2, 2);
cmd.CommandText = $"INSERT INTO {Name} ({vals.Replace("@", "")}) VALUES({vals})";
cmd.Prepare();
cmd.ExecuteNonQuery();
con.Close();
}
public void DeleteRow(Parameter Parameter)
{
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
cmd.Parameters.Add(Parameter.PGParameter);
cmd.CommandText = $"DELETE FROM {Name} WHERE {Parameter.PGParameter.ParameterName} IN (@{Parameter.PGParameter.ParameterName});";
cmd.Prepare();
cmd.ExecuteNonQuery();
con.Close();
}
public void DeleteRows()
{
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
cmd.CommandText = $"DELETE FROM {Name};";
cmd.Prepare();
cmd.ExecuteNonQuery();
con.Close();
}
2023-06-28 12:44:59 -04:00
public void Create()
{
Console.WriteLine("Making Table: {0}", Name);
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
2024-03-22 12:11:19 -04:00
string command = $"CREATE TABLE IF NOT EXISTS public.{Name}(";
List<string> Keys = new();
List<Tuple<ITableColumn, IForeignKey>> FKeys = new();
2023-06-28 12:44:59 -04:00
foreach (ITableColumn column in Colums_)
{
command += $"{column.Name} {column.GetDatabaseTypeStr()}";
2024-03-22 12:11:19 -04:00
if (column.IsPrimaryKey) Keys.Add(column.Name);
2023-06-28 12:44:59 -04:00
command += " NOT NULL, ";
2024-03-22 12:11:19 -04:00
if (column.ForeignKeys.Length > 0)
{
foreach (IForeignKey Fkey in column.ForeignKeys)
{
FKeys.Add(new(column, Fkey));
}
}
}
if (Keys.Count > 0)
{
string key = $"CONSTRAINT {Name}_pkey PRIMARY KEY (";
foreach (var Key in Keys)
{
key += Key + ", ";
}
key = key.Remove(key.Length - 2, 2);
key += "), ";
command += key;
2023-06-28 12:44:59 -04:00
}
2024-03-22 12:11:19 -04:00
if (FKeys.Count > 0)
{
foreach (Tuple<ITableColumn, IForeignKey> K in FKeys)
{
string key = $"CONSTRAINT {Name}_{K.Item1.Name}_{K.Item2.Table.Name}_{K.Item2.Column.Name}_fkey FOREIGN KEY ({K.Item1.Name}) REFERENCES public.{K.Item2.Table.Name} ({K.Item2.Column.Name}) MATCH ";
if (K.Item2.MatchType == KeyMatchType.Full) key += "FULL ON UPDATE ";
else key += "SIMPLE ON UPDATE ";
switch (K.Item2.OnUpdate)
{
case ConstraintAction.None:
key += "NO ACTION ON DELETE ";
break;
case ConstraintAction.Cascade:
key += "CASCADE ON DELETE ";
break;
case ConstraintAction.Restrict:
key += "RESTRICT ON DELETE ";
break;
case ConstraintAction.SetDefault:
key += "SET DEFAULT ON DELETE ";
break;
}
switch (K.Item2.OnDelete)
{
case ConstraintAction.None:
key += "NO ACTION ";
break;
case ConstraintAction.Cascade:
key += "CASCADE ";
break;
case ConstraintAction.Restrict:
key += "RESTRICT ";
break;
case ConstraintAction.SetDefault:
key += "SET DEFAULT ";
break;
}
if (K.Item2.Deferrable) key += "DEFERRABLE ";
if (K.Item2.Deferred) key += "INITIALLY DEFERRED ";
if (!K.Item2.Validated) key += "NOT VALID ";
key = key.Remove(key.Length - 1, 1) + ", ";
command += key;
}
}
command = command.Remove(command.Length - 2, 2);
command += ");";
2023-06-28 12:44:59 -04:00
cmd.CommandText = command;
cmd.Prepare();
cmd.ExecuteNonQuery();
con.Close();
2024-03-22 12:11:19 -04:00
DatabaseHandler.ExecuteNonQuery($"ALTER TABLE IF EXISTS public.{Name} OWNER to \"{DatabaseHandler.Uname}\";");
2023-06-28 12:44:59 -04:00
}
2024-03-22 12:11:19 -04:00
public bool TryRead<T>(TableColumn<T> column, Order order, [NotNullWhen(true)]out T? result, params Parameter[] Parameters) where T : notnull
2023-06-28 12:44:59 -04:00
{
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
string vals = "";
string command = $"SELECT {column.Name} FROM {Name} WHERE";
foreach (Parameter param in Parameters)
{
vals += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName} AND ";
cmd.Parameters.Add(param.PGParameter);
}
if (command.EndsWith(";")) command = command.Remove(command.Length - 1, 1);
if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5);
if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}";
if (order is not null) command += $" ORDER BY {order.Type} ";
if (order is not null && order.Assending) command += "ASC";
else { if (order is not null) command += "DESC"; }
command += ";";
cmd.CommandText = command;
//object? temp = cmd.ExecuteScalar();
object? temp = null;
try
{
temp = cmd.ExecuteScalar();
}
catch
{
result = default(T);
return false;
}
con.Close();
if (temp is DBNull || temp is null)
{
result = default(T);
return false;
}
if (typeof(T).IsEnum)
{
result = (T)Enum.Parse(typeof(T), temp.ToString()!)!;
return true;
}
/*
if (typeof(T).IsNullableEnum())
{
result = (T?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T))!, temp.ToString()!)!;
return true;
}
*/
result = (T)temp!;
return true;
}
public bool TryReadRow(out TRow row, params Parameter[] Parameters) => TryReadRow(null, out row, Parameters);
public bool TryReadRow(Order order, out TRow row, params Parameter[] Parameters)
{
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
string command = $"SELECT * FROM {Name} WHERE";
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
string vals = "";
foreach (Parameter param in Parameters)
{
vals += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName} AND ";
cmd.Parameters.Add(param.PGParameter);
}
if (command.EndsWith(";")) command = command.Remove(command.Length - 1, 1);
if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5);
if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}";
if (order is not null) command += $" ORDER BY {order.Type} ";
if (order is not null && order.Assending) command += "ASC";
else { if (order is not null) command += "DESC"; }
command += ";";
cmd.CommandText = command;
NpgsqlDataReader reader = cmd.ExecuteReader();
TRow Row = new();
reader.Read();
bool r = false;
for (int i = 0; i < reader.FieldCount; i++)
{
r = true;
string colname = reader.GetName(i);
object? val = null;
try
{
val = reader.GetValue(i);
}
catch
{
row = default(TRow);
return false;
}
if (colnamesraw.ContainsKey(colname))
{
if (val is DBNull || val is null)
{
row = default(TRow);
return false;
}
PropertyInfo? pi = Row.GetType()
.GetProperty(colnamesraw[colname]);
if (pi is null)
{
Console.WriteLine("Could not find row {0}", colnamesraw[colname]);
continue;
}
pi.SetValue(Row, val, null);
}
}
row = Row;
return r;
}
2024-03-22 12:11:19 -04:00
public bool TryReadRows([NotNullWhen(true)]out TRow[]? rows, params Parameter[] Parameters) => TryReadRows(null!, out rows, Parameters);
2024-03-22 12:11:19 -04:00
public bool TryReadRows(Order order, [NotNullWhen(true)]out TRow[]? rows, params Parameter[] Parameters)
{
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
string command = $"SELECT * FROM {Name} WHERE";
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
string vals = "";
foreach (Parameter param in Parameters)
{
vals += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName} AND ";
cmd.Parameters.Add(param.PGParameter);
}
if (command.EndsWith(";")) command = command.Remove(command.Length - 1, 1);
if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5);
if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}";
if (order is not null) command += $" ORDER BY {order.Type} ";
if (order is not null && order.Assending) command += "ASC";
else { if (order is not null) command += "DESC"; }
command += ";";
cmd.CommandText = command;
NpgsqlDataReader reader = cmd.ExecuteReader();
List<TRow> Rows = new();
while (reader.Read())
{
2024-03-22 12:11:19 -04:00
TRow Row = new();
for (int i = 0; i < reader.FieldCount; i++)
{
string colname = reader.GetName(i);
object? val = reader.GetValue(i);
if (colnamesraw.ContainsKey(colname))
{
PropertyInfo? pi = Row.GetType()
.GetProperty(colnamesraw[colname]);
if (pi is null)
{
Console.WriteLine("Could not find row {0}", colnamesraw[colname]);
continue;
}
pi.SetValue(Row, val, null);
}
}
2024-03-22 12:11:19 -04:00
Rows.Add(Row);
}
rows = Rows.ToArray();
return Rows.Any();
}
2024-03-22 12:11:19 -04:00
public bool TryRead<T>(TableColumn<T> column, [NotNullWhen(true)]out T? result, params Parameter[] Parameters) where T : notnull
2023-06-28 12:44:59 -04:00
{
return TryRead(column, null!, out result, Parameters);
}
public void Update<Ttype>(TableColumn<Ttype> condiction_column, Ttype condiction_value, params Parameter[] Parameters) where Ttype : notnull
{
Update(condiction_column, condiction_value, "=", Parameters);
}
public void Update<Ttype>(TableColumn<Ttype> condiction_column, Ttype condiction_value, string Sign, params Parameter[] Parameters) where Ttype : notnull
{
2024-03-22 12:11:19 -04:00
CommandHandler command = CreateCommand().WithFilter(condiction_column, condiction_value, Sign);
foreach (var Parameter in Parameters)
2023-06-28 12:44:59 -04:00
{
2024-03-22 12:11:19 -04:00
command.WithValue(Parameter);
2023-06-28 12:44:59 -04:00
}
2024-03-22 12:11:19 -04:00
command.Update();
2023-06-28 12:44:59 -04:00
}
public TRow ReadRow(params Parameter[] Parameters) => ReadRow(null, Parameters);
public TRow ReadRow(Order order, params Parameter[] Parameters)
{
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
string command = $"SELECT * FROM {Name} WHERE";
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
string vals = "";
foreach (Parameter param in Parameters)
{
vals += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName} AND ";
cmd.Parameters.Add(param.PGParameter);
}
if (command.EndsWith(";")) command = command.Remove(command.Length - 1, 1);
if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5);
if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}";
if (order is not null) command += $" ORDER BY {order.Type} ";
if (order is not null && order.Assending) command += "ASC";
else { if (order is not null) command += "DESC"; }
command += ";";
cmd.CommandText = command;
NpgsqlDataReader reader = cmd.ExecuteReader();
TRow Row = new();
reader.Read();
for (int i = 0; i < reader.FieldCount; i++)
{
string colname = reader.GetName(i);
object? val = reader.GetValue(i);
if (colnamesraw.ContainsKey(colname))
{
PropertyInfo? pi = Row.GetType()
.GetProperty(colnamesraw[colname]);
if (pi is null)
{
Console.WriteLine("Could not find row {0}", colnamesraw[colname]);
continue;
}
pi.SetValue(Row, val, null);
}
}
return Row;
}
2024-03-22 12:11:19 -04:00
public TColumn[] ReadColumn<TColumn>(TableColumn<TColumn> column, params Parameter[] Parameters) where TColumn : notnull => ReadColumn(column, uint.MaxValue, null, Parameters);
public TColumn[] ReadColumn<TColumn>(TableColumn<TColumn> column, uint NumRows, params Parameter[] Parameters) where TColumn : notnull => ReadColumn(column, NumRows, null, Parameters);
public TColumn[] ReadColumn<TColumn>(TableColumn<TColumn> column, Order? Order, params Parameter[] Parameters) where TColumn : notnull => ReadColumn(column, uint.MaxValue, Order, Parameters);
public TColumn[] ReadColumn<TColumn>(TableColumn<TColumn> column, uint NumRows, Order? order, params Parameter[] Parameters) where TColumn : notnull
{
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
string command = $"SELECT {column.Name} FROM {Name} WHERE";
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
string vals = "";
foreach (Parameter param in Parameters)
{
vals += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName} AND ";
cmd.Parameters.Add(param.PGParameter);
}
if (command.EndsWith(";")) command = command.Remove(command.Length - 1, 1);
if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5);
if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}";
if (command.EndsWith("WHERE")) command = command.Remove(command.Length - 6, 6);
if (order is not null) command += $" ORDER BY {order.Type} ";
if (order is not null && order.Assending) command += "ASC";
else { if (order is not null) command += "DESC"; }
command += $" LIMIT {NumRows};";
cmd.CommandText = command;
NpgsqlDataReader reader = cmd.ExecuteReader();
List<TColumn> Rows = new();
for (int j = 0; j < NumRows; j++)
{
if (!reader.Read()) break;
Rows.Add((TColumn)reader.GetValue(0));
}
return Rows.ToArray();
}
public TRow[] ReadRows(params Parameter[] Parameters) => ReadRows(uint.MaxValue, null, Parameters);
2023-06-28 12:44:59 -04:00
public TRow[] ReadRows(uint NumRows, params Parameter[] Parameters) => ReadRows(NumRows, null, Parameters);
2024-03-22 12:11:19 -04:00
public TRow[] ReadRows(Order? Order, params Parameter[] Parameters) => ReadRows(uint.MaxValue, Order, Parameters);
public TRow[] ReadRows(uint NumRows, Order? order, params Parameter[] Parameters)
2023-06-28 12:44:59 -04:00
{
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
string command = $"SELECT * FROM {Name} WHERE";
con.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = con;
string vals = "";
foreach (Parameter param in Parameters)
{
vals += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName} AND ";
cmd.Parameters.Add(param.PGParameter);
}
if (command.EndsWith(";")) command = command.Remove(command.Length - 1, 1);
if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5);
if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}";
2024-03-22 12:11:19 -04:00
if (command.EndsWith("WHERE")) command = command.Remove(command.Length - 6, 6);
2023-06-28 12:44:59 -04:00
if (order is not null) command += $" ORDER BY {order.Type} ";
if (order is not null && order.Assending) command += "ASC";
else { if (order is not null) command += "DESC"; }
command += $" LIMIT {NumRows};";
cmd.CommandText = command;
NpgsqlDataReader reader = cmd.ExecuteReader();
List<TRow> Rows = new();
for (int j = 0; j < NumRows; j++)
{
if (!reader.Read()) break;
TRow Row = new();
2023-06-28 12:44:59 -04:00
for (int i = 0; i < reader.FieldCount; i++)
{
string colname = reader.GetName(i);
object? val = reader.GetValue(i);
if (colnamesraw.ContainsKey(colname))
{
PropertyInfo? pi = Row.GetType()
.GetProperty(colnamesraw[colname]);
if (pi is null)
{
Console.WriteLine("Could not find row {0}", colnamesraw[colname]);
continue;
}
pi.SetValue(Row, val, null);
}
}
Rows.Add(Row);
2023-06-28 12:44:59 -04:00
}
return Rows.ToArray();
}
public T Read<T>(TableColumn<T> column, params Parameter[] Parameters) where T : notnull
{
if (Parameters is null) throw new ArgumentNullException(nameof(Parameters));
return DatabaseHandler.Read<T>($"SELECT {column.Name} FROM {Name} WHERE", (Order?)null, Parameters);
}
public T Read<T>(TableColumn<T> column, Order order, params Parameter[] Parameters) where T : notnull
{
if (Parameters is null) throw new ArgumentNullException(nameof(Parameters));
return DatabaseHandler.Read<T>($"SELECT {column.Name} FROM {Name} WHERE", order, Parameters);
}
}