
//////////////////////////////////////////////////
//  SQL Server Data Access Components
//  Copyright © 1998-2007 Core Lab. All right reserved.
//  SQL Monitor
//////////////////////////////////////////////////

{$IFNDEF CLR}

{$I Sdac.inc}

unit MSSQLMonitor;
{$ENDIF}

interface

uses
  SysUtils, Classes, DB, DBAccess, DASQLMonitor;

type
  TTypeInfo = record
    Name: string;
    DataType: TFieldType;
  end;

const
  // Obsolete, needs to change to DB.FieldTypeNames
  ArrTypeInfoCount = 16 {$IFDEF VER5P}+ 2{$ENDIF}{$IFDEF VER10P} + 1{$ENDIF};
  ArrTypeInfo: array [0..ArrTypeInfoCount - 1] of TTypeInfo = (
    (Name: 'Unknown';  DataType: ftUnknown),
    (Name: 'String';   DataType: ftString),
    (Name: 'WideString';DataType: ftWideString),
    (Name: 'Smallint'; DataType: ftSmallint),
    (Name: 'Integer';  DataType: ftInteger),
    (Name: 'Word';     DataType: ftWord),
    (Name: 'LargeInt'; DataType: ftLargeInt),
    (Name: 'Boolean';  DataType: ftBoolean),
    (Name: 'Float';    DataType: ftFloat),
    (Name: 'Currency'; DataType: ftCurrency),
    (Name: 'BCD';      DataType: ftBCD),
    (Name: 'DateTime'; DataType: ftDateTime),
    (Name: 'Memo';     DataType: ftMemo),
  {$IFDEF VER10P}
    (Name: 'WideMemo'; DataType: ftWideMemo),
  {$ENDIF}
    (Name: 'Bytes';    DataType: ftBytes),
    (Name: 'VarBytes'; DataType: ftVarBytes),
    (Name: 'Blob';     DataType: ftBlob){$IFDEF VER5P},
    (Name: 'GUID';     DataType: ftGuid),
    (Name: 'Variant';  DataType: ftVariant){$ENDIF}
  );

function GetArrTypeInfoIdx(DataType: TFieldType): integer; overload;
function GetArrTypeInfoIdx(Name: string): integer; overload;

type

{ TMSSQLMonitor }

  TMSSQLMonitorClass = class of TMSSQLMonitor;

  TMSSQLMonitor = class(TCustomDASQLMonitor)
  protected
    procedure InternalTRSavepoint(Connection: TCustomDAConnection; Savepoint: string);
    procedure InternalTRRollbackToSavepoint(Connection: TCustomDAConnection; Savepoint: string);
    procedure InternalInfoMessage(Connection: TCustomDAConnection; MessageText: string);

    class function GetMonitor: TCustomDASQLMonitor; override;

  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    class function GetParamDataType(Param: TDAParam): string; override;

    class procedure TRSavepoint(Connection: TCustomDAConnection; Savepoint: string);
    class procedure TRRollbackToSavepoint(Connection: TCustomDAConnection; Savepoint: string);

    class procedure InfoMessage(Connection: TCustomDAConnection; MessageText: string);

    class function GetCaption: string; override;
  
  published
    property Active default True;
    property Options;
    property OnSQL;
    property TraceFlags;
  end;

implementation

uses
  MemDS, MSAccess, OLEDBAccess;

var
  MSMonitor: TMSSQLMonitor;

function GetArrTypeInfoIdx(DataType: TFieldType): integer; 
var
  i: integer;
begin
  if DataType = ftFixedChar then
    DataType := ftString;

  Result := - 1;
  for i := 0 to ArrTypeInfoCount - 1 do
    if ArrTypeInfo[i].DataType = DataType then 
    begin
      Result := i;
      Break;
    end;
end;

function GetArrTypeInfoIdx(Name: string): integer; 
var
  i: integer;
begin
  Result := - 1;
  for i := 0 to ArrTypeInfoCount - 1 do
    if ArrTypeInfo[i].Name = Name then 
    begin
      Result := i;
      Break;
    end;
end;

{ TMSSQLMonitor }

class procedure TMSSQLMonitor.TRSavepoint(Connection: TCustomDAConnection; Savepoint: string);
begin
  if GetMonitor <> nil then
    TMSSQLMonitor(GetMonitor).InternalTRSavepoint(Connection, Savepoint);
end;

class procedure TMSSQLMonitor.TRRollbackToSavepoint(Connection: TCustomDAConnection; Savepoint: string);
begin
  if GetMonitor <> nil then
    TMSSQLMonitor(GetMonitor).InternalTRRollbackToSavepoint(Connection, Savepoint);
end;

class procedure TMSSQLMonitor.InfoMessage(Connection: TCustomDAConnection; MessageText: string);
begin
  if (GetMonitor <> nil) then
    TMSSQLMonitor(GetMonitor).InternalInfoMessage(Connection, MessageText);
end;

class function TMSSQLMonitor.GetMonitor: TCustomDASQLMonitor;
begin
  Result := MSMonitor;
end;

class function TMSSQLMonitor.GetCaption: string;
begin
  Result := 'MS SQL';
end;

procedure TMSSQLMonitor.InternalTRSavepoint(Connection: TCustomDAConnection; Savepoint: string);
var
  St: string;
begin
  if Active then begin
    St := 'Savepoint ' + Savepoint + ': ' + Connection.Username + '@' + Connection.Server;

    if (moSQLMonitor in Options) and (tfTransact in TraceFlags) then
      AddStatement(St);

    if Assigned(FOnSQLEvent) then
      FOnSQLEvent(Connection, St, tfTransact);
  end;
end;

procedure TMSSQLMonitor.InternalTRRollbackToSavepoint(Connection: TCustomDAConnection; Savepoint: string);
var
  St: string;
begin
  if Active then begin
    St := 'Rollback to savepoint ' + Savepoint + ': ' + Connection.Username + '@' + Connection.Server;

    if (moSQLMonitor in Options) and (tfTransact in TraceFlags) then
      AddStatement(St);

    if Assigned(FOnSQLEvent) then
      FOnSQLEvent(Connection, St, tfTransact);
  end;
end;

procedure TMSSQLMonitor.InternalInfoMessage(Connection: TCustomDAConnection; MessageText: string);
var
  St: string;
begin
  if Active then begin
    St := 'Info Message: ' + MessageText + ': ' + Connection.Username + '@' + Connection.Server;

    if (moSQLMonitor in Options) and (tfMisc in TraceFlags) then
      AddStatement(St);
      
    if Assigned(FOnSQLEvent) then
      FOnSQLEvent(Connection, St, tfMisc);
  end;
end;

class function TMSSQLMonitor.GetParamDataType(Param: TDAParam): string;
begin
  if Param.DataType = TFieldType(ftMSXML) then
    Result := 'XML'
  else
{$IFDEF D8} // Copied from inherited to avoid D8 Internal linker error: ILLK8903
  begin
    Result := FieldTypeNames[Param.DataType];
    if Param.DataType in [ftString,ftFixedChar,ftWideString] then
      Result := Result + '[' + IntToStr(Length(Param.AsString)) + ']';
  end;
{$ELSE}
    Result := inherited GetParamDataType(Param);
{$ENDIF}
end;

constructor TMSSQLMonitor.Create(AOwner: TComponent);
begin
  inherited;

  if MSMonitor = nil then
    MSMonitor := Self;
end;

destructor TMSSQLMonitor.Destroy;
begin
  if MSMonitor = Self then
    MSMonitor := nil;

  inherited;
end;

initialization

end.
 
