unit Aurelius.Sql.Metadata;

{$I Aurelius.Inc}

interface

uses
  DB, Generics.Collections;

type
  TTableMetadata = class;
  TDatabaseMetadata = class;

  TMetadataInfo = class abstract
  end;

  TColumnMetadata = class(TMetadataInfo)
  strict private
    FName: string;
    FNotNull: Boolean;
    FFieldType: TFieldType;
    FDataType: string;
    FLength: Integer;
    FPrecision: Integer;
    FScale: Integer;
    FAutoGenerated: boolean;
    {$IFDEF AUTOREFCOUNT}[Weak]{$ENDIF}
    FTable: TTableMetadata;
  public
    constructor Create(ATable: TTableMetadata);
    property Table: TTableMetadata read FTable;
    property Name: string read FName write FName;
    property NotNull: Boolean read FNotNull write FNotNull;
    property FieldType: TFieldType read FFieldType write FFieldType; // temporary, this can be removed in a future version - don't use
    property DataType: string read FDataType write FDataType;
    property Length: Integer read FLength write FLength;
    property Precision: Integer read FPrecision write FPrecision;
    property Scale: Integer read FScale write FScale;
    property AutoGenerated: boolean read FAutoGenerated write FAutoGenerated;
  end;

  TUniqueKeyMetadata = class(TMetadataInfo)
  strict private
    FName: string;
    {$IFDEF AUTOREFCOUNT}[Weak]{$ENDIF}
    FTable: TTableMetadata;
    FColumns: TList<TColumnMetadata>;
  public
    constructor Create(ATable: TTableMetadata);
    destructor Destroy; override;
    property Name: string read FName write FName;
    property Table: TTableMetadata read FTable;
    property Columns: TList<TColumnMetadata> read FColumns;
  end;

  TDBIndexMetadata = class(TMetadataInfo)
  strict private
    FName: string;
    {$IFDEF AUTOREFCOUNT}[Weak]{$ENDIF}
    FTable: TTableMetadata;
    FColumns: TList<TColumnMetadata>;
  public
    constructor Create(ATable: TTableMetadata);
    destructor Destroy; override;
    property Name: string read FName write FName;
    property Table: TTableMetadata read FTable;
    property Columns: TList<TColumnMetadata> read FColumns;
  end;

  TSequenceMetadata = class(TMetadataInfo)
  strict private
    FName: string;
    FInitialValue: Integer;
    FIncrement: Integer;
    {$IFDEF AUTOREFCOUNT}[Weak]{$ENDIF}
    FDatabase: TDatabaseMetadata;
  public
    constructor Create(ADatabase: TDatabaseMetadata);
    property Name: string read FName write FName;
    property InitialValue: Integer read FInitialValue write FInitialValue;
    property Increment: Integer read FIncrement write FIncrement;
    property Database: TDatabaseMetadata read FDatabase;
  end;

  TForeignKeyMetadata = class(TMetadataInfo)
  strict private
    FName: string;
    {$IFDEF AUTOREFCOUNT}[Weak]{$ENDIF}
    FFromTable: TTableMetadata;
    FFromColumns: TList<TColumnMetadata>;
    {$IFDEF AUTOREFCOUNT}[Weak]{$ENDIF}
    FToTable: TTableMetadata;
    FToColumns: TList<TColumnMetadata>;
  public
    constructor Create(AFromTable: TTableMetadata);
    property Name: string read FName write FName;
    property FromTable: TTableMetadata read FFromTable;
    property FromColumns: TList<TColumnMetadata> read FFromColumns write FFromColumns;
    property ToTable: TTableMetadata read FToTable write FToTable;
    property ToColumns: TList<TColumnMetadata> read FToColumns write FToColumns;
    destructor Destroy; override;
  end;

  TTableMetadata = class(TMetadataInfo)
  strict private
    {$IFDEF AUTOREFCOUNT}[Weak]{$ENDIF}
    FDatabase: TDatabaseMetadata;
    FName: string;
    FSchema: string;
    FColumns: TList<TColumnMetadata>;
    FIdColumns: TList<TColumnMetadata>;
    FUniqueKeys: TList<TUniqueKeyMetadata>;
    FForeignKeys: TList<TForeignKeyMetadata>;
    FDBIndexes: TList<TDBIndexMetadata>;
  public
    constructor Create(ADatabase: TDatabaseMetadata);
    destructor Destroy; override;
    property Database: TDatabaseMetadata read FDatabase;
    property Name: string read FName write FName;
    property Schema: string read FSchema write FSchema;
    property Columns: TList<TColumnMetadata> read FColumns;
    property IdColumns: TList<TColumnMetadata> read FIdColumns;
    property UniqueKeys: TList<TUniqueKeyMetadata> read FUniqueKeys;
    property ForeignKeys: TList<TForeignKeyMetadata> read FForeignKeys;
    property DBIndexes: TList<TDBIndexMetadata> read FDBIndexes;
  end;

  TDatabaseMetadata = class(TMetadataInfo)
  strict private
    FTables: TList<TTableMetadata>;
    FSequences: TList<TSequenceMetadata>;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Clear;
    property Tables: TList<TTableMetadata> read FTables;
    property Sequences: TList<TSequenceMetadata> read FSequences;
  end;

implementation

{ TTableMetadata }

constructor TTableMetadata.Create(ADatabase: TDatabaseMetadata);
begin
  FColumns := TObjectList<TColumnMetadata>.Create(true);
  FUniqueKeys := TObjectList<TUniqueKeyMetadata>.Create(true);
  FForeignKeys := TObjectList<TForeignKeyMetadata>.Create(true);
  FDBIndexes := TObjectList<TDBIndexMetadata>.Create(true);
  FIdColumns := TList<TColumnMetadata>.Create;
  FDatabase := ADatabase;
end;

destructor TTableMetadata.Destroy;
begin
  FIdColumns.Free;
  FColumns.Free;
  FUniqueKeys.Free;
  FForeignKeys.Free;
  FDBIndexes.Free;
  inherited;
end;

{ TForeignKeyMetadata }

constructor TForeignKeyMetadata.Create(AFromTable: TTableMetadata);
begin
  FFromColumns := TList<TColumnMetadata>.Create;
  FToColumns := TList<TColumnMetadata>.Create;
  FFromTable := AFromTable;
end;

destructor TForeignKeyMetadata.Destroy;
begin
  FFromColumns.Free;
  FToColumns.Free;
  inherited;
end;

{ TUniqueKeyMetadata }

constructor TUniqueKeyMetadata.Create(ATable: TTableMetadata);
begin
  FColumns := TList<TColumnMetadata>.Create;
  FTable := ATable;
end;

destructor TUniqueKeyMetadata.Destroy;
begin
  FColumns.Free;
  inherited;
end;

{ TDatabaseMetadata }

procedure TDatabaseMetadata.Clear;
begin
  Tables.Clear;
  Sequences.Clear;
end;

constructor TDatabaseMetadata.Create;
begin
  FTables := TObjectList<TTableMetadata>.Create(true);
  FSequences := TObjectList<TSequenceMetadata>.Create(true);
end;

destructor TDatabaseMetadata.Destroy;
begin
  FSequences.Free;
  FTables.Free;
  inherited;
end;

{ TColumnMetadata }

constructor TColumnMetadata.Create(ATable: TTableMetadata);
begin
  FTable := ATable;
end;

{ TSequenceMetadata }

constructor TSequenceMetadata.Create(ADatabase: TDatabaseMetadata);
begin
  FDatabase := ADatabase;
end;

{ TDBIndexMetadata }

constructor TDBIndexMetadata.Create(ATable: TTableMetadata);
begin
  FColumns := TList<TColumnMetadata>.Create;
  FTable := ATable;
end;

destructor TDBIndexMetadata.Destroy;
begin
  FColumns.Free;
  inherited;
end;

end.
