📄 ibsqlmonitor.pas
字号:
FTraceDataType := PInteger(PChar(FReaderCount) - SizeOf(Integer));
FTimeStamp := PDateTime(PChar(FTraceDataType) - SizeOf(TDateTime));
FBufferSize := PInteger(PChar(FTimeStamp) - SizeOf(Integer));
FWriteLock := OpenMutex(MUTEX_ALL_ACCESS, False, PChar(MonitorHookNames[0]));
FWriteEvent := OpenLocalEvent(2);
FWriteFinishedEvent := OpenLocalEvent(3);
FReadEvent := OpenLocalEvent(4);
FReadFinishedEvent := OpenLocalEvent(5);
end
else
begin
FWriteLock := CreateMutex(@sa, False, PChar(MonitorHookNames[0]));
FWriteEvent := CreateLocalEvent(2, False);
FWriteFinishedEvent := CreateLocalEvent(3, True);
FReadEvent := CreateLocalEvent(4, False);
FReadFinishedEvent := CreateLocalEvent(5, False);
FBuffer := MapViewOfFile(FSharedBuffer, FILE_MAP_ALL_ACCESS, 0, 0, 0);
FMonitorCount := PInteger(FBuffer + cMonitorHookSize - SizeOf(Integer));
FReaderCount := PInteger(PChar(FMonitorCount) - SizeOf(Integer));
FTraceDataType := PInteger(PChar(FReaderCount) - SizeOf(Integer));
FTimeStamp := PDateTime(PChar(FTraceDataType) - SizeOf(TDateTime));
FBufferSize := PInteger(PChar(FTimeStamp) - SizeOf(Integer));
FMonitorCount^ := 0;
FReaderCount^ := 0;
FBufferSize^ := 0;
end;
{ This should never evaluate to true, if it does
there has been a hiccup somewhere. }
if FMonitorCount^ < 0 then
FMonitorCount^ := 0;
if FReaderCount^ < 0 then
FReaderCount^ := 0;
FEventsCreated := true;
{$ENDIF}
{$IFDEF LINUX}
begin
{$ENDIF}
end;
procedure TIBSQLMonitorHook.DBConnect(db: TIBDatabase);
var
st : String;
begin
if FEnabled then
begin
if not (tfConnect in FTraceFlags * db.TraceFlags) then
Exit;
st := db.Name + ': [Connect]'; {do not localize}
WriteSQLData(st, tfConnect);
end;
end;
procedure TIBSQLMonitorHook.DBDisconnect(db: TIBDatabase);
var
st: String;
begin
if FEnabled then
begin
if not (tfConnect in FTraceFlags * db.TraceFlags) then
Exit;
st := db.Name + ': [Disconnect]'; {do not localize}
WriteSQLData(st, tfConnect);
end;
end;
destructor TIBSQLMonitorHook.Destroy;
begin
if FEventsCreated then
begin
{$IFDEF MSWINDOWS}
UnmapViewOfFile(FBuffer);
CloseHandle(FSharedBuffer);
CloseHandle(FWriteEvent);
CloseHandle(FWriteFinishedEvent);
CloseHandle(FReadEvent);
CloseHandle(FReadFinishedEvent);
CloseHandle(FWriteLock);
{$ENDIF}
end;
inherited Destroy;
end;
function TIBSQLMonitorHook.GetEnabled: Boolean;
begin
Result := FEnabled;
end;
function TIBSQLMonitorHook.GetMonitorCount: Integer;
begin
Result := FMonitorCount^;
end;
function TIBSQLMonitorHook.GetTraceFlags: TTraceFlags;
begin
Result := FTraceFlags;
end;
procedure TIBSQLMonitorHook.RegisterMonitor(SQLMonitor: TIBCustomSQLMonitor);
begin
if not FEventsCreated then
try
CreateEvents;
except
SQLMonitor.Enabled := false;
end;
if not Assigned(FReaderThread) then
FReaderThread := TReaderThread.Create;
FReaderThread.AddMonitor(SQLMonitor);
end;
procedure TIBSQLMonitorHook.ReleaseMonitor(Arg: TIBCustomSQLMonitor);
begin
{$IFDEF MSWINDOWS}
FWriterThread.ReleaseMonitor(Arg.FHWnd);
{$ENDIF}
end;
procedure TIBSQLMonitorHook.SendMisc(Msg: String);
begin
if FEnabled then
WriteSQLData(Msg, tfMisc);
end;
procedure TIBSQLMonitorHook.ServiceAttach(service: TIBCustomService);
var
st: String;
begin
if FEnabled then
begin
if not (tfService in (FTraceFlags * service.TraceFlags)) then
Exit;
st := service.Name + ': [Attach]'; {do not localize}
WriteSQLData(st, tfService);
end;
end;
procedure TIBSQLMonitorHook.ServiceDetach(service: TIBCustomService);
var
st: String;
begin
if FEnabled then
begin
if not (tfService in (FTraceFlags * service.TraceFlags)) then
Exit;
st := service.Name + ': [Detach]'; {do not localize}
WriteSQLData(st, tfService);
end;
end;
procedure TIBSQLMonitorHook.ServiceQuery(service: TIBCustomService);
var
st: String;
begin
if FEnabled then
begin
if not (tfService in (FTraceFlags * service.TraceFlags)) then
Exit;
st := service.Name + ': [Query]'; {do not localize}
WriteSQLData(st, tfService);
end;
end;
procedure TIBSQLMonitorHook.ServiceStart(service: TIBCustomService);
var
st: String;
begin
if FEnabled then
begin
if not (tfService in (FTraceFlags * service.TraceFlags)) then
Exit;
st := service.Name + ': [Start]'; {do not localize}
WriteSQLData(st, tfService);
end;
end;
procedure TIBSQLMonitorHook.SetEnabled(const Value: Boolean);
begin
if FEnabled <> Value then
FEnabled := Value;
if (not FEnabled) and (Assigned(FWriterThread)) then
begin
FWriterThread.Terminate;
{$IFDEF MSWINDOWS}
FWriterThread.WaitFor;
{$ENDIF}
FreeAndNil(FWriterThread);
end;
end;
procedure TIBSQLMonitorHook.SetTraceFlags(const Value: TTraceFlags);
begin
FTraceFlags := Value
end;
procedure TIBSQLMonitorHook.SQLExecute(qry: TIBSQL);
var
st: String;
i: Integer;
begin
if FEnabled then
begin
if not ((tfQExecute in (FTraceFlags * qry.Database.TraceFlags)) or
(tfStmt in (FTraceFlags * qry.Database.TraceFlags)) ) then
Exit;
if qry.Owner is TIBCustomDataSet then
st := TIBCustomDataSet(qry.Owner).Name
else
st := qry.Name;
st := st + ': [Execute] ' + qry.SQL.Text; {do not localize}
if qry.Params.Count > 0 then begin
for i := 0 to qry.Params.Count - 1 do begin
st := st + CRLF + ' ' + qry.Params[i].Name + ' = '; {do not localize}
try
if qry.Params[i].IsNull then
st := st + '<NULL>' {do not localize}
else
if qry.Params[i].SQLType <> SQL_BLOB then
st := st + qry.Params[i].AsString
else
st := st + '<BLOB>'; {do not localize}
except
st := st + '<' + SCantPrintValue + '>'; {do not localize}
end;
end;
end;
WriteSQLData(st, tfQExecute);
end;
end;
procedure TIBSQLMonitorHook.SQLFetch(qry: TIBSQL);
var
st: String;
begin
if FEnabled then
begin
if not ((tfQFetch in (FTraceFlags * qry.Database.TraceFlags)) or
(tfStmt in (FTraceFlags * qry.Database.TraceFlags))) then
Exit;
if qry.Owner is TIBCustomDataSet then
st := TIBCustomDataSet(qry.Owner).Name
else
st := qry.Name;
st := st + ': [Fetch] ' + qry.SQL.Text; {do not localize}
if (qry.EOF) then
st := st + CRLF + ' ' + SEOFReached; {do not localize}
WriteSQLData(st, tfQFetch);
end;
end;
procedure TIBSQLMonitorHook.SQLPrepare(qry: TIBSQL);
var
st: String;
begin
if FEnabled then
begin
if not ((tfQPrepare in (FTraceFlags * qry.Database.TraceFlags)) or
(tfStmt in (FTraceFlags * qry.Database.TraceFlags))) then
Exit;
if qry.Owner is TIBCustomDataSet then
st := TIBCustomDataSet(qry.Owner).Name
else
st := qry.Name;
st := st + ': [Prepare] ' + qry.SQL.Text + CRLF; {do not localize}
try
st := st + ' Plan: ' + qry.Plan; {do not localize}
except
st := st + ' Plan: Can''t retrieve plan - too large'; {do not localize}
end;
WriteSQLData(st, tfQPrepare);
end;
end;
procedure TIBSQLMonitorHook.TRCommit(tr: TIBTransaction);
var
st: String;
begin
if FEnabled then
begin
if Assigned(tr.DefaultDatabase) and
(tfTransact in (FTraceFlags * tr.DefaultDatabase.TraceFlags)) then
begin
st := tr.Name + ': [Commit (Hard commit)]'; {do not localize}
WriteSQLData(st, tfTransact);
end;
end;
end;
procedure TIBSQLMonitorHook.TRCommitRetaining(tr: TIBTransaction);
var
st: String;
begin
if FEnabled then
begin
if Assigned(tr.DefaultDatabase) and
(tfTransact in (FTraceFlags * tr.DefaultDatabase.TraceFlags)) then
begin
st := tr.Name + ': [Commit retaining (Soft commit)]'; {do not localize}
WriteSQLData(st, tfTransact);
end;
end;
end;
procedure TIBSQLMonitorHook.TRRollback(tr: TIBTransaction);
var
st: String;
begin
if FEnabled then
begin
if Assigned(tr.DefaultDatabase) and
(tfTransact in (FTraceFlags * tr.DefaultDatabase.TraceFlags)) then
begin
st := tr.Name + ': [Rollback]'; {do not localize}
WriteSQLData(st, tfTransact);
end;
end;
end;
procedure TIBSQLMonitorHook.TRRollbackRetaining(tr: TIBTransaction);
var
st: String;
begin
if FEnabled then
begin
if Assigned(tr.DefaultDatabase) and
(tfTransact in (FTraceFlags * tr.DefaultDatabase.TraceFlags)) then
begin
st := tr.Name + ': [Rollback retaining (Soft rollback)]'; {do not localize}
WriteSQLData(st, tfTransact);
end;
end;
end;
procedure TIBSQLMonitorHook.TRStart(tr: TIBTransaction);
var
st: String;
begin
if FEnabled then
begin
if Assigned(tr.DefaultDatabase) and
(tfTransact in (FTraceFlags * tr.DefaultDatabase.TraceFlags)) then
begin
st := tr.Name + ': [Start transaction]'; {do not localize}
WriteSQLData(st, tfTransact);
end;
end;
end;
procedure TIBSQLMonitorHook.UnregisterMonitor(SQLMonitor: TIBCustomSQLMonitor);
var
Created : Boolean;
begin
FReaderThread.RemoveMonitor(SQLMonitor);
if FReaderThread.FMonitors.Count = 0 then
begin
FReaderThread.Terminate;
{ There is a possibility of a reader thread, but no writer one.
When in that situation, the reader needs to be released after
the terminate is set. To do that, create a Writer thread, send
the release code (a string of ' ' and type tfMisc) and then free
it up. }
Created := false;
if not Assigned(FWriterThread) then
begin
FWriterThread := TWriterThread.Create;
Created := true;
end;
FWriterThread.WriteSQLData(' ', tfMisc);
{$IFDEF MSWINDOWS}
FReaderThread.WaitFor;
{$ENDIF}
FreeAndNil(FReaderThread);
if Created then
begin
FWriterThread.Terminate;
{$IFDEF MSWINDOWS}
FWriterThread.WaitFor;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -