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 ) ;
}
2023-08-25 12:15:28 -04:00
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_ ) ;
2023-08-25 12:15:28 -04:00
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 ( ) ) ;
}
2023-08-25 12:15:28 -04:00
else
{
co . Add ( name ) ;
}
2023-06-28 12:44:59 -04:00
}
UpdatedColumns = coll ;
2023-08-25 12:15:28 -04:00
ExtraColumns = co . ToArray ( ) ;
2023-06-28 12:44:59 -04:00
return col . AsReadOnly ( ) ;
}
public void UpdateTable ( )
{
2023-08-25 12:15:28 -04:00
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 ( ) )
{
2023-08-25 12:15:28 -04:00
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 ( ) )
{
2023-08-25 12:15:28 -04:00
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 ) ;
}
}
}
}
2023-08-25 12:15:28 -04:00
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 ( ) ;
}
2023-08-25 12:15:28 -04:00
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 ) ;
2023-08-25 12:15:28 -04:00
2024-03-22 12:11:19 -04:00
public bool TryReadRows ( Order order , [ NotNullWhen ( true ) ] out TRow [ ] ? rows , params Parameter [ ] Parameters )
2023-08-25 12:15:28 -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}" ;
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 ( ) ;
2023-08-25 12:15:28 -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 ) ;
}
}
2024-03-22 12:11:19 -04:00
Rows . Add ( Row ) ;
2023-08-25 12:15:28 -04:00
}
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 ;
2023-08-25 12:15:28 -04:00
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 ) ;
}
}
2023-08-25 12:15:28 -04:00
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 ) ;
}
}