mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:03:02 +01:00
Improvement #7687 - Add LEVEL column to PLG$PROF_RECORD_SOURCES and PLG$PROF_RECORD_SOURCE_STATS_VIEW.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Also avoid start collect profiling data for a record source not from its initial node.
This commit is contained in:
parent
fc24dfa4be
commit
c86bd3d4f4
@ -265,6 +265,7 @@ Below is the list of tables that stores profile data.
|
|||||||
- `CURSOR_ID` type `INTEGER` - Cursor ID
|
- `CURSOR_ID` type `INTEGER` - Cursor ID
|
||||||
- `RECORD_SOURCE_ID` type `INTEGER` - Record source ID
|
- `RECORD_SOURCE_ID` type `INTEGER` - Record source ID
|
||||||
- `PARENT_RECORD_SOURCE_ID` type `INTEGER` - Parent record source ID
|
- `PARENT_RECORD_SOURCE_ID` type `INTEGER` - Parent record source ID
|
||||||
|
- `LEVEL` type `INTEGER` - Indentation level for the record source
|
||||||
- `ACCESS_PATH` type `VARCHAR(255) CHARACTER SET UTF8` - Access path for the record source
|
- `ACCESS_PATH` type `VARCHAR(255) CHARACTER SET UTF8` - Access path for the record source
|
||||||
- Primary key: `PROFILE_ID, STATEMENT_ID, CURSOR_ID, RECORD_SOURCE_ID`
|
- Primary key: `PROFILE_ID, STATEMENT_ID, CURSOR_ID, RECORD_SOURCE_ID`
|
||||||
|
|
||||||
@ -419,6 +420,7 @@ select rstat.profile_id,
|
|||||||
cur.column_num cursor_column_num,
|
cur.column_num cursor_column_num,
|
||||||
rstat.record_source_id,
|
rstat.record_source_id,
|
||||||
recsrc.parent_record_source_id,
|
recsrc.parent_record_source_id,
|
||||||
|
recsrc.level,
|
||||||
recsrc.access_path,
|
recsrc.access_path,
|
||||||
cast(sum(rstat.open_counter) as bigint) open_counter,
|
cast(sum(rstat.open_counter) as bigint) open_counter,
|
||||||
min(rstat.open_min_elapsed_time) open_min_elapsed_time,
|
min(rstat.open_min_elapsed_time) open_min_elapsed_time,
|
||||||
@ -461,6 +463,7 @@ select rstat.profile_id,
|
|||||||
cur.column_num,
|
cur.column_num,
|
||||||
rstat.record_source_id,
|
rstat.record_source_id,
|
||||||
recsrc.parent_record_source_id,
|
recsrc.parent_record_source_id,
|
||||||
|
recsrc.level,
|
||||||
recsrc.access_path
|
recsrc.access_path
|
||||||
order by coalesce(sum(rstat.open_total_elapsed_time), 0) + coalesce(sum(rstat.fetch_total_elapsed_time), 0) desc
|
order by coalesce(sum(rstat.open_total_elapsed_time), 0) + coalesce(sum(rstat.fetch_total_elapsed_time), 0) desc
|
||||||
```
|
```
|
||||||
|
@ -1744,7 +1744,7 @@ interface ProfilerSession : Disposable
|
|||||||
void defineCursor(int64 statementId, uint cursorId, const string name, uint line, uint column);
|
void defineCursor(int64 statementId, uint cursorId, const string name, uint line, uint column);
|
||||||
|
|
||||||
void defineRecordSource(int64 statementId, uint cursorId, uint recSourceId,
|
void defineRecordSource(int64 statementId, uint cursorId, uint recSourceId,
|
||||||
const string accessPath, uint parentRecSourceId);
|
uint level, const string accessPath, uint parentRecSourceId);
|
||||||
|
|
||||||
void onRequestStart(Status status, int64 statementId, int64 requestId,
|
void onRequestStart(Status status, int64 statementId, int64 requestId,
|
||||||
int64 callerStatementId, int64 callerRequestId, ISC_TIMESTAMP_TZ timestamp);
|
int64 callerStatementId, int64 callerRequestId, ISC_TIMESTAMP_TZ timestamp);
|
||||||
|
@ -6954,7 +6954,7 @@ namespace Firebird
|
|||||||
void (CLOOP_CARG *finish)(IProfilerSession* self, IStatus* status, ISC_TIMESTAMP_TZ timestamp) CLOOP_NOEXCEPT;
|
void (CLOOP_CARG *finish)(IProfilerSession* self, IStatus* status, ISC_TIMESTAMP_TZ timestamp) CLOOP_NOEXCEPT;
|
||||||
void (CLOOP_CARG *defineStatement)(IProfilerSession* self, IStatus* status, ISC_INT64 statementId, ISC_INT64 parentStatementId, const char* type, const char* packageName, const char* routineName, const char* sqlText) CLOOP_NOEXCEPT;
|
void (CLOOP_CARG *defineStatement)(IProfilerSession* self, IStatus* status, ISC_INT64 statementId, ISC_INT64 parentStatementId, const char* type, const char* packageName, const char* routineName, const char* sqlText) CLOOP_NOEXCEPT;
|
||||||
void (CLOOP_CARG *defineCursor)(IProfilerSession* self, ISC_INT64 statementId, unsigned cursorId, const char* name, unsigned line, unsigned column) CLOOP_NOEXCEPT;
|
void (CLOOP_CARG *defineCursor)(IProfilerSession* self, ISC_INT64 statementId, unsigned cursorId, const char* name, unsigned line, unsigned column) CLOOP_NOEXCEPT;
|
||||||
void (CLOOP_CARG *defineRecordSource)(IProfilerSession* self, ISC_INT64 statementId, unsigned cursorId, unsigned recSourceId, const char* accessPath, unsigned parentRecSourceId) CLOOP_NOEXCEPT;
|
void (CLOOP_CARG *defineRecordSource)(IProfilerSession* self, ISC_INT64 statementId, unsigned cursorId, unsigned recSourceId, unsigned level, const char* accessPath, unsigned parentRecSourceId) CLOOP_NOEXCEPT;
|
||||||
void (CLOOP_CARG *onRequestStart)(IProfilerSession* self, IStatus* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_INT64 callerStatementId, ISC_INT64 callerRequestId, ISC_TIMESTAMP_TZ timestamp) CLOOP_NOEXCEPT;
|
void (CLOOP_CARG *onRequestStart)(IProfilerSession* self, IStatus* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_INT64 callerStatementId, ISC_INT64 callerRequestId, ISC_TIMESTAMP_TZ timestamp) CLOOP_NOEXCEPT;
|
||||||
void (CLOOP_CARG *onRequestFinish)(IProfilerSession* self, IStatus* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_TIMESTAMP_TZ timestamp, IProfilerStats* stats) CLOOP_NOEXCEPT;
|
void (CLOOP_CARG *onRequestFinish)(IProfilerSession* self, IStatus* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_TIMESTAMP_TZ timestamp, IProfilerStats* stats) CLOOP_NOEXCEPT;
|
||||||
void (CLOOP_CARG *beforePsqlLineColumn)(IProfilerSession* self, ISC_INT64 statementId, ISC_INT64 requestId, unsigned line, unsigned column) CLOOP_NOEXCEPT;
|
void (CLOOP_CARG *beforePsqlLineColumn)(IProfilerSession* self, ISC_INT64 statementId, ISC_INT64 requestId, unsigned line, unsigned column) CLOOP_NOEXCEPT;
|
||||||
@ -7019,9 +7019,9 @@ namespace Firebird
|
|||||||
static_cast<VTable*>(this->cloopVTable)->defineCursor(this, statementId, cursorId, name, line, column);
|
static_cast<VTable*>(this->cloopVTable)->defineCursor(this, statementId, cursorId, name, line, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
void defineRecordSource(ISC_INT64 statementId, unsigned cursorId, unsigned recSourceId, const char* accessPath, unsigned parentRecSourceId)
|
void defineRecordSource(ISC_INT64 statementId, unsigned cursorId, unsigned recSourceId, unsigned level, const char* accessPath, unsigned parentRecSourceId)
|
||||||
{
|
{
|
||||||
static_cast<VTable*>(this->cloopVTable)->defineRecordSource(this, statementId, cursorId, recSourceId, accessPath, parentRecSourceId);
|
static_cast<VTable*>(this->cloopVTable)->defineRecordSource(this, statementId, cursorId, recSourceId, level, accessPath, parentRecSourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename StatusType> void onRequestStart(StatusType* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_INT64 callerStatementId, ISC_INT64 callerRequestId, ISC_TIMESTAMP_TZ timestamp)
|
template <typename StatusType> void onRequestStart(StatusType* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_INT64 callerStatementId, ISC_INT64 callerRequestId, ISC_TIMESTAMP_TZ timestamp)
|
||||||
@ -20528,11 +20528,11 @@ namespace Firebird
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CLOOP_CARG cloopdefineRecordSourceDispatcher(IProfilerSession* self, ISC_INT64 statementId, unsigned cursorId, unsigned recSourceId, const char* accessPath, unsigned parentRecSourceId) CLOOP_NOEXCEPT
|
static void CLOOP_CARG cloopdefineRecordSourceDispatcher(IProfilerSession* self, ISC_INT64 statementId, unsigned cursorId, unsigned recSourceId, unsigned level, const char* accessPath, unsigned parentRecSourceId) CLOOP_NOEXCEPT
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
static_cast<Name*>(self)->Name::defineRecordSource(statementId, cursorId, recSourceId, accessPath, parentRecSourceId);
|
static_cast<Name*>(self)->Name::defineRecordSource(statementId, cursorId, recSourceId, level, accessPath, parentRecSourceId);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
@ -20672,7 +20672,7 @@ namespace Firebird
|
|||||||
virtual void finish(StatusType* status, ISC_TIMESTAMP_TZ timestamp) = 0;
|
virtual void finish(StatusType* status, ISC_TIMESTAMP_TZ timestamp) = 0;
|
||||||
virtual void defineStatement(StatusType* status, ISC_INT64 statementId, ISC_INT64 parentStatementId, const char* type, const char* packageName, const char* routineName, const char* sqlText) = 0;
|
virtual void defineStatement(StatusType* status, ISC_INT64 statementId, ISC_INT64 parentStatementId, const char* type, const char* packageName, const char* routineName, const char* sqlText) = 0;
|
||||||
virtual void defineCursor(ISC_INT64 statementId, unsigned cursorId, const char* name, unsigned line, unsigned column) = 0;
|
virtual void defineCursor(ISC_INT64 statementId, unsigned cursorId, const char* name, unsigned line, unsigned column) = 0;
|
||||||
virtual void defineRecordSource(ISC_INT64 statementId, unsigned cursorId, unsigned recSourceId, const char* accessPath, unsigned parentRecSourceId) = 0;
|
virtual void defineRecordSource(ISC_INT64 statementId, unsigned cursorId, unsigned recSourceId, unsigned level, const char* accessPath, unsigned parentRecSourceId) = 0;
|
||||||
virtual void onRequestStart(StatusType* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_INT64 callerStatementId, ISC_INT64 callerRequestId, ISC_TIMESTAMP_TZ timestamp) = 0;
|
virtual void onRequestStart(StatusType* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_INT64 callerStatementId, ISC_INT64 callerRequestId, ISC_TIMESTAMP_TZ timestamp) = 0;
|
||||||
virtual void onRequestFinish(StatusType* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_TIMESTAMP_TZ timestamp, IProfilerStats* stats) = 0;
|
virtual void onRequestFinish(StatusType* status, ISC_INT64 statementId, ISC_INT64 requestId, ISC_TIMESTAMP_TZ timestamp, IProfilerStats* stats) = 0;
|
||||||
virtual void beforePsqlLineColumn(ISC_INT64 statementId, ISC_INT64 requestId, unsigned line, unsigned column) = 0;
|
virtual void beforePsqlLineColumn(ISC_INT64 statementId, ISC_INT64 requestId, unsigned line, unsigned column) = 0;
|
||||||
|
@ -727,7 +727,7 @@ type
|
|||||||
IProfilerSession_finishPtr = procedure(this: IProfilerSession; status: IStatus; timestamp: ISC_TIMESTAMP_TZ); cdecl;
|
IProfilerSession_finishPtr = procedure(this: IProfilerSession; status: IStatus; timestamp: ISC_TIMESTAMP_TZ); cdecl;
|
||||||
IProfilerSession_defineStatementPtr = procedure(this: IProfilerSession; status: IStatus; statementId: Int64; parentStatementId: Int64; type_: PAnsiChar; packageName: PAnsiChar; routineName: PAnsiChar; sqlText: PAnsiChar); cdecl;
|
IProfilerSession_defineStatementPtr = procedure(this: IProfilerSession; status: IStatus; statementId: Int64; parentStatementId: Int64; type_: PAnsiChar; packageName: PAnsiChar; routineName: PAnsiChar; sqlText: PAnsiChar); cdecl;
|
||||||
IProfilerSession_defineCursorPtr = procedure(this: IProfilerSession; statementId: Int64; cursorId: Cardinal; name: PAnsiChar; line: Cardinal; column: Cardinal); cdecl;
|
IProfilerSession_defineCursorPtr = procedure(this: IProfilerSession; statementId: Int64; cursorId: Cardinal; name: PAnsiChar; line: Cardinal; column: Cardinal); cdecl;
|
||||||
IProfilerSession_defineRecordSourcePtr = procedure(this: IProfilerSession; statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal); cdecl;
|
IProfilerSession_defineRecordSourcePtr = procedure(this: IProfilerSession; statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; level: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal); cdecl;
|
||||||
IProfilerSession_onRequestStartPtr = procedure(this: IProfilerSession; status: IStatus; statementId: Int64; requestId: Int64; callerStatementId: Int64; callerRequestId: Int64; timestamp: ISC_TIMESTAMP_TZ); cdecl;
|
IProfilerSession_onRequestStartPtr = procedure(this: IProfilerSession; status: IStatus; statementId: Int64; requestId: Int64; callerStatementId: Int64; callerRequestId: Int64; timestamp: ISC_TIMESTAMP_TZ); cdecl;
|
||||||
IProfilerSession_onRequestFinishPtr = procedure(this: IProfilerSession; status: IStatus; statementId: Int64; requestId: Int64; timestamp: ISC_TIMESTAMP_TZ; stats: IProfilerStats); cdecl;
|
IProfilerSession_onRequestFinishPtr = procedure(this: IProfilerSession; status: IStatus; statementId: Int64; requestId: Int64; timestamp: ISC_TIMESTAMP_TZ; stats: IProfilerStats); cdecl;
|
||||||
IProfilerSession_beforePsqlLineColumnPtr = procedure(this: IProfilerSession; statementId: Int64; requestId: Int64; line: Cardinal; column: Cardinal); cdecl;
|
IProfilerSession_beforePsqlLineColumnPtr = procedure(this: IProfilerSession; statementId: Int64; requestId: Int64; line: Cardinal; column: Cardinal); cdecl;
|
||||||
@ -3838,7 +3838,7 @@ type
|
|||||||
procedure finish(status: IStatus; timestamp: ISC_TIMESTAMP_TZ);
|
procedure finish(status: IStatus; timestamp: ISC_TIMESTAMP_TZ);
|
||||||
procedure defineStatement(status: IStatus; statementId: Int64; parentStatementId: Int64; type_: PAnsiChar; packageName: PAnsiChar; routineName: PAnsiChar; sqlText: PAnsiChar);
|
procedure defineStatement(status: IStatus; statementId: Int64; parentStatementId: Int64; type_: PAnsiChar; packageName: PAnsiChar; routineName: PAnsiChar; sqlText: PAnsiChar);
|
||||||
procedure defineCursor(statementId: Int64; cursorId: Cardinal; name: PAnsiChar; line: Cardinal; column: Cardinal);
|
procedure defineCursor(statementId: Int64; cursorId: Cardinal; name: PAnsiChar; line: Cardinal; column: Cardinal);
|
||||||
procedure defineRecordSource(statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal);
|
procedure defineRecordSource(statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; level: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal);
|
||||||
procedure onRequestStart(status: IStatus; statementId: Int64; requestId: Int64; callerStatementId: Int64; callerRequestId: Int64; timestamp: ISC_TIMESTAMP_TZ);
|
procedure onRequestStart(status: IStatus; statementId: Int64; requestId: Int64; callerStatementId: Int64; callerRequestId: Int64; timestamp: ISC_TIMESTAMP_TZ);
|
||||||
procedure onRequestFinish(status: IStatus; statementId: Int64; requestId: Int64; timestamp: ISC_TIMESTAMP_TZ; stats: IProfilerStats);
|
procedure onRequestFinish(status: IStatus; statementId: Int64; requestId: Int64; timestamp: ISC_TIMESTAMP_TZ; stats: IProfilerStats);
|
||||||
procedure beforePsqlLineColumn(statementId: Int64; requestId: Int64; line: Cardinal; column: Cardinal);
|
procedure beforePsqlLineColumn(statementId: Int64; requestId: Int64; line: Cardinal; column: Cardinal);
|
||||||
@ -3859,7 +3859,7 @@ type
|
|||||||
procedure finish(status: IStatus; timestamp: ISC_TIMESTAMP_TZ); virtual; abstract;
|
procedure finish(status: IStatus; timestamp: ISC_TIMESTAMP_TZ); virtual; abstract;
|
||||||
procedure defineStatement(status: IStatus; statementId: Int64; parentStatementId: Int64; type_: PAnsiChar; packageName: PAnsiChar; routineName: PAnsiChar; sqlText: PAnsiChar); virtual; abstract;
|
procedure defineStatement(status: IStatus; statementId: Int64; parentStatementId: Int64; type_: PAnsiChar; packageName: PAnsiChar; routineName: PAnsiChar; sqlText: PAnsiChar); virtual; abstract;
|
||||||
procedure defineCursor(statementId: Int64; cursorId: Cardinal; name: PAnsiChar; line: Cardinal; column: Cardinal); virtual; abstract;
|
procedure defineCursor(statementId: Int64; cursorId: Cardinal; name: PAnsiChar; line: Cardinal; column: Cardinal); virtual; abstract;
|
||||||
procedure defineRecordSource(statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal); virtual; abstract;
|
procedure defineRecordSource(statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; level: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal); virtual; abstract;
|
||||||
procedure onRequestStart(status: IStatus; statementId: Int64; requestId: Int64; callerStatementId: Int64; callerRequestId: Int64; timestamp: ISC_TIMESTAMP_TZ); virtual; abstract;
|
procedure onRequestStart(status: IStatus; statementId: Int64; requestId: Int64; callerStatementId: Int64; callerRequestId: Int64; timestamp: ISC_TIMESTAMP_TZ); virtual; abstract;
|
||||||
procedure onRequestFinish(status: IStatus; statementId: Int64; requestId: Int64; timestamp: ISC_TIMESTAMP_TZ; stats: IProfilerStats); virtual; abstract;
|
procedure onRequestFinish(status: IStatus; statementId: Int64; requestId: Int64; timestamp: ISC_TIMESTAMP_TZ; stats: IProfilerStats); virtual; abstract;
|
||||||
procedure beforePsqlLineColumn(statementId: Int64; requestId: Int64; line: Cardinal; column: Cardinal); virtual; abstract;
|
procedure beforePsqlLineColumn(statementId: Int64; requestId: Int64; line: Cardinal; column: Cardinal); virtual; abstract;
|
||||||
@ -9428,9 +9428,9 @@ begin
|
|||||||
ProfilerSessionVTable(vTable).defineCursor(Self, statementId, cursorId, name, line, column);
|
ProfilerSessionVTable(vTable).defineCursor(Self, statementId, cursorId, name, line, column);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure IProfilerSession.defineRecordSource(statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal);
|
procedure IProfilerSession.defineRecordSource(statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; level: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal);
|
||||||
begin
|
begin
|
||||||
ProfilerSessionVTable(vTable).defineRecordSource(Self, statementId, cursorId, recSourceId, accessPath, parentRecSourceId);
|
ProfilerSessionVTable(vTable).defineRecordSource(Self, statementId, cursorId, recSourceId, level, accessPath, parentRecSourceId);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure IProfilerSession.onRequestStart(status: IStatus; statementId: Int64; requestId: Int64; callerStatementId: Int64; callerRequestId: Int64; timestamp: ISC_TIMESTAMP_TZ);
|
procedure IProfilerSession.onRequestStart(status: IStatus; statementId: Int64; requestId: Int64; callerStatementId: Int64; callerRequestId: Int64; timestamp: ISC_TIMESTAMP_TZ);
|
||||||
@ -16541,10 +16541,10 @@ begin
|
|||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure IProfilerSessionImpl_defineRecordSourceDispatcher(this: IProfilerSession; statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal); cdecl;
|
procedure IProfilerSessionImpl_defineRecordSourceDispatcher(this: IProfilerSession; statementId: Int64; cursorId: Cardinal; recSourceId: Cardinal; level: Cardinal; accessPath: PAnsiChar; parentRecSourceId: Cardinal); cdecl;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
IProfilerSessionImpl(this).defineRecordSource(statementId, cursorId, recSourceId, accessPath, parentRecSourceId);
|
IProfilerSessionImpl(this).defineRecordSource(statementId, cursorId, recSourceId, level, accessPath, parentRecSourceId);
|
||||||
except
|
except
|
||||||
on e: Exception do FbException.catchException(nil, e);
|
on e: Exception do FbException.catchException(nil, e);
|
||||||
end
|
end
|
||||||
|
@ -475,15 +475,19 @@ void ProfilerManager::prepareCursor(thread_db* tdbb, Request* request, const Sel
|
|||||||
|
|
||||||
auto cursorId = select->getCursorId();
|
auto cursorId = select->getCursorId();
|
||||||
|
|
||||||
if (profileStatement->definedCursors.exist(cursorId))
|
if (!profileStatement->definedCursors.exist(cursorId))
|
||||||
return;
|
{
|
||||||
|
|
||||||
currentSession->pluginSession->defineCursor(profileStatement->id, cursorId,
|
currentSession->pluginSession->defineCursor(profileStatement->id, cursorId,
|
||||||
select->getName().nullStr(), select->getLine(), select->getColumn());
|
select->getName().nullStr(), select->getLine(), select->getColumn());
|
||||||
|
|
||||||
profileStatement->definedCursors.add(cursorId);
|
profileStatement->definedCursors.add(cursorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto recordSource = select->getAccessPath();
|
||||||
|
|
||||||
|
prepareRecSource(tdbb, request, recordSource);
|
||||||
|
}
|
||||||
|
|
||||||
void ProfilerManager::prepareRecSource(thread_db* tdbb, Request* request, const RecordSource* rsb)
|
void ProfilerManager::prepareRecSource(thread_db* tdbb, Request* request, const RecordSource* rsb)
|
||||||
{
|
{
|
||||||
auto profileStatement = getStatement(request);
|
auto profileStatement = getStatement(request);
|
||||||
@ -496,35 +500,32 @@ void ProfilerManager::prepareRecSource(thread_db* tdbb, Request* request, const
|
|||||||
|
|
||||||
fb_assert(profileStatement->definedCursors.exist(rsb->getCursorId()));
|
fb_assert(profileStatement->definedCursors.exist(rsb->getCursorId()));
|
||||||
|
|
||||||
Array<NonPooledPair<const RecordSource*, const RecordSource*>> tree;
|
struct PlanItem : PermanentStorage
|
||||||
tree.add({rsb, nullptr});
|
{
|
||||||
|
explicit PlanItem(MemoryPool& p)
|
||||||
for (unsigned pos = 0; pos < tree.getCount(); ++pos)
|
: PermanentStorage(p)
|
||||||
{
|
{
|
||||||
const auto thisRsb = tree[pos].first;
|
|
||||||
|
|
||||||
Array<const RecordSource*> children;
|
|
||||||
thisRsb->getChildren(children);
|
|
||||||
|
|
||||||
unsigned childPos = pos;
|
|
||||||
|
|
||||||
for (const auto child : children)
|
|
||||||
tree.insert(++childPos, {child, thisRsb});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NonPooledMap<ULONG, ULONG> idSequenceMap;
|
const RecordSource* recordSource = nullptr;
|
||||||
auto sequencePtr = profileStatement->cursorNextSequence.getOrPut(rsb->getCursorId());
|
const RecordSource* parentRecordSource = nullptr;
|
||||||
|
string accessPath{getPool()};
|
||||||
|
unsigned level = 0;
|
||||||
|
};
|
||||||
|
|
||||||
for (const auto& pair : tree)
|
ObjectsArray<PlanItem> planItems;
|
||||||
|
planItems.add().recordSource = rsb;
|
||||||
|
|
||||||
|
for (unsigned pos = 0; pos < planItems.getCount(); ++pos)
|
||||||
{
|
{
|
||||||
const auto cursorId = pair.first->getCursorId();
|
auto& planItem = planItems[pos];
|
||||||
const auto recSourceId = pair.first->getRecSourceId();
|
const auto thisRsb = planItem.recordSource;
|
||||||
idSequenceMap.put(recSourceId, ++*sequencePtr);
|
|
||||||
|
|
||||||
string accessPath;
|
string& accessPath = planItem.accessPath;
|
||||||
pair.first->print(tdbb, accessPath, true, 0, false);
|
thisRsb->print(tdbb, accessPath, true, 0, false);
|
||||||
|
|
||||||
constexpr auto INDENT_MARKER = "\n ";
|
constexpr auto INDENT_MARKER = "\n ";
|
||||||
|
constexpr unsigned INDENT_COUNT = 4;
|
||||||
|
|
||||||
if (accessPath.find(INDENT_MARKER) == 0)
|
if (accessPath.find(INDENT_MARKER) == 0)
|
||||||
{
|
{
|
||||||
@ -535,13 +536,44 @@ void ProfilerManager::prepareRecSource(thread_db* tdbb, Request* request, const
|
|||||||
} while ((pos = accessPath.find(INDENT_MARKER, pos + 1)) != string::npos);
|
} while ((pos = accessPath.find(INDENT_MARKER, pos + 1)) != string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (accessPath.hasData() && accessPath[0] == '\n')
|
||||||
|
accessPath.erase(0, 1);
|
||||||
|
|
||||||
|
Array<const RecordSource*> children;
|
||||||
|
thisRsb->getChildren(children);
|
||||||
|
|
||||||
|
unsigned level = planItem.level;
|
||||||
|
|
||||||
|
if (const auto lastLinePos = accessPath.find_last_of('\n'); lastLinePos != string::npos)
|
||||||
|
level += (accessPath.find_first_not_of(' ', lastLinePos + 1) - lastLinePos + 1) / INDENT_COUNT;
|
||||||
|
|
||||||
|
unsigned childPos = pos;
|
||||||
|
|
||||||
|
for (const auto child : children)
|
||||||
|
{
|
||||||
|
auto& inserted = planItems.insert(++childPos);
|
||||||
|
inserted.recordSource = child;
|
||||||
|
inserted.parentRecordSource = thisRsb;
|
||||||
|
inserted.level = level + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NonPooledMap<ULONG, ULONG> idSequenceMap;
|
||||||
|
auto sequencePtr = profileStatement->cursorNextSequence.getOrPut(rsb->getCursorId());
|
||||||
|
|
||||||
|
for (const auto& planItem : planItems)
|
||||||
|
{
|
||||||
|
const auto cursorId = planItem.recordSource->getCursorId();
|
||||||
|
const auto recSourceId = planItem.recordSource->getRecSourceId();
|
||||||
|
idSequenceMap.put(recSourceId, ++*sequencePtr);
|
||||||
|
|
||||||
ULONG parentSequence = 0;
|
ULONG parentSequence = 0;
|
||||||
|
|
||||||
if (pair.second)
|
if (planItem.parentRecordSource)
|
||||||
parentSequence = *idSequenceMap.get(pair.second->getRecSourceId());
|
parentSequence = *idSequenceMap.get(planItem.parentRecordSource->getRecSourceId());
|
||||||
|
|
||||||
currentSession->pluginSession->defineRecordSource(profileStatement->id, cursorId,
|
currentSession->pluginSession->defineRecordSource(profileStatement->id, cursorId,
|
||||||
*sequencePtr, accessPath.c_str(), parentSequence);
|
*sequencePtr, planItem.level, planItem.accessPath.c_str(), parentSequence);
|
||||||
|
|
||||||
profileStatement->recSourceSequence.put(recSourceId, *sequencePtr);
|
profileStatement->recSourceSequence.put(recSourceId, *sequencePtr);
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,6 @@ public:
|
|||||||
{
|
{
|
||||||
lastTicks = profilerManager->queryTicks();
|
lastTicks = profilerManager->queryTicks();
|
||||||
|
|
||||||
profilerManager->prepareRecSource(tdbb, request, recordSource);
|
|
||||||
|
|
||||||
if (profilerManager->currentSession->flags & Firebird::IProfilerSession::FLAG_BEFORE_EVENTS)
|
if (profilerManager->currentSession->flags & Firebird::IProfilerSession::FLAG_BEFORE_EVENTS)
|
||||||
{
|
{
|
||||||
if (event == Event::OPEN)
|
if (event == Event::OPEN)
|
||||||
@ -191,7 +189,6 @@ public:
|
|||||||
const Firebird::PathName& pluginName, const Firebird::string& description, const Firebird::string& options);
|
const Firebird::PathName& pluginName, const Firebird::string& description, const Firebird::string& options);
|
||||||
|
|
||||||
void prepareCursor(thread_db* tdbb, Request* request, const Select* select);
|
void prepareCursor(thread_db* tdbb, Request* request, const Select* select);
|
||||||
void prepareRecSource(thread_db* tdbb, Request* request, const RecordSource* rsb);
|
|
||||||
void onRequestFinish(Request* request, Stats& stats);
|
void onRequestFinish(Request* request, Stats& stats);
|
||||||
|
|
||||||
void beforePsqlLineColumn(Request* request, ULONG line, ULONG column)
|
void beforePsqlLineColumn(Request* request, ULONG line, ULONG column)
|
||||||
@ -218,52 +215,56 @@ public:
|
|||||||
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_BEFORE_EVENTS))
|
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_BEFORE_EVENTS))
|
||||||
{
|
{
|
||||||
const auto profileStatement = getStatement(request);
|
const auto profileStatement = getStatement(request);
|
||||||
const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId());
|
|
||||||
fb_assert(sequencePtr);
|
|
||||||
|
|
||||||
|
if (const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId()))
|
||||||
|
{
|
||||||
currentSession->pluginSession->beforeRecordSourceOpen(
|
currentSession->pluginSession->beforeRecordSourceOpen(
|
||||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr);
|
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void afterRecordSourceOpen(Request* request, const RecordSource* rsb, Stats& stats)
|
void afterRecordSourceOpen(Request* request, const RecordSource* rsb, Stats& stats)
|
||||||
{
|
{
|
||||||
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_AFTER_EVENTS))
|
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_AFTER_EVENTS))
|
||||||
{
|
{
|
||||||
const auto profileStatement = getStatement(request);
|
const auto profileStatement = getStatement(request);
|
||||||
const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId());
|
|
||||||
fb_assert(sequencePtr);
|
|
||||||
|
|
||||||
|
if (const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId()))
|
||||||
|
{
|
||||||
currentSession->pluginSession->afterRecordSourceOpen(
|
currentSession->pluginSession->afterRecordSourceOpen(
|
||||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr, &stats);
|
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr, &stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void beforeRecordSourceGetRecord(Request* request, const RecordSource* rsb)
|
void beforeRecordSourceGetRecord(Request* request, const RecordSource* rsb)
|
||||||
{
|
{
|
||||||
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_BEFORE_EVENTS))
|
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_BEFORE_EVENTS))
|
||||||
{
|
{
|
||||||
const auto profileStatement = getStatement(request);
|
const auto profileStatement = getStatement(request);
|
||||||
const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId());
|
|
||||||
fb_assert(sequencePtr);
|
|
||||||
|
|
||||||
|
if (const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId()))
|
||||||
|
{
|
||||||
currentSession->pluginSession->beforeRecordSourceGetRecord(
|
currentSession->pluginSession->beforeRecordSourceGetRecord(
|
||||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr);
|
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void afterRecordSourceGetRecord(Request* request, const RecordSource* rsb, Stats& stats)
|
void afterRecordSourceGetRecord(Request* request, const RecordSource* rsb, Stats& stats)
|
||||||
{
|
{
|
||||||
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_AFTER_EVENTS))
|
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_AFTER_EVENTS))
|
||||||
{
|
{
|
||||||
const auto profileStatement = getStatement(request);
|
const auto profileStatement = getStatement(request);
|
||||||
const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId());
|
|
||||||
fb_assert(sequencePtr);
|
|
||||||
|
|
||||||
|
if (const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId()))
|
||||||
|
{
|
||||||
currentSession->pluginSession->afterRecordSourceGetRecord(
|
currentSession->pluginSession->afterRecordSourceGetRecord(
|
||||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr, &stats);
|
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr, &stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isActive() const
|
bool isActive() const
|
||||||
{
|
{
|
||||||
@ -282,6 +283,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void prepareRecSource(thread_db* tdbb, Request* request, const RecordSource* rsb);
|
||||||
|
|
||||||
void cancelSession();
|
void cancelSession();
|
||||||
void finishSession(thread_db* tdbb, bool flushData);
|
void finishSession(thread_db* tdbb, bool flushData);
|
||||||
void pauseSession(bool flushData);
|
void pauseSession(bool flushData);
|
||||||
|
@ -106,6 +106,7 @@ struct Cursor
|
|||||||
struct RecordSource
|
struct RecordSource
|
||||||
{
|
{
|
||||||
Nullable<ULONG> parentId;
|
Nullable<ULONG> parentId;
|
||||||
|
unsigned level;
|
||||||
string accessPath{defaultPool()};
|
string accessPath{defaultPool()};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -181,7 +182,7 @@ public:
|
|||||||
void defineCursor(SINT64 statementId, unsigned cursorId, const char* name, unsigned line, unsigned column) override;
|
void defineCursor(SINT64 statementId, unsigned cursorId, const char* name, unsigned line, unsigned column) override;
|
||||||
|
|
||||||
void defineRecordSource(SINT64 statementId, unsigned cursorId, unsigned recSourceId,
|
void defineRecordSource(SINT64 statementId, unsigned cursorId, unsigned recSourceId,
|
||||||
const char* accessPath, unsigned parentRecordSourceId) override;
|
unsigned level, const char* accessPath, unsigned parentRecordSourceId) override;
|
||||||
|
|
||||||
void onRequestStart(ThrowStatusExceptionWrapper* status, SINT64 statementId, SINT64 requestId,
|
void onRequestStart(ThrowStatusExceptionWrapper* status, SINT64 statementId, SINT64 requestId,
|
||||||
SINT64 callerStatementId, SINT64 callerRequestId, ISC_TIMESTAMP_TZ timestamp) override;
|
SINT64 callerStatementId, SINT64 callerRequestId, ISC_TIMESTAMP_TZ timestamp) override;
|
||||||
@ -441,8 +442,8 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
|
|||||||
constexpr auto recSrcSql = R"""(
|
constexpr auto recSrcSql = R"""(
|
||||||
update or insert into plg$prof_record_sources
|
update or insert into plg$prof_record_sources
|
||||||
(profile_id, statement_id, cursor_id, record_source_id,
|
(profile_id, statement_id, cursor_id, record_source_id,
|
||||||
parent_record_source_id, access_path)
|
parent_record_source_id, level, access_path)
|
||||||
values (?, ?, ?, ?, ?, ?)
|
values (?, ?, ?, ?, ?, ?, ?)
|
||||||
matching (profile_id, statement_id, cursor_id, record_source_id)
|
matching (profile_id, statement_id, cursor_id, record_source_id)
|
||||||
)""";
|
)""";
|
||||||
|
|
||||||
@ -452,6 +453,7 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
|
|||||||
(FB_INTEGER, cursorId)
|
(FB_INTEGER, cursorId)
|
||||||
(FB_INTEGER, recordSourceId)
|
(FB_INTEGER, recordSourceId)
|
||||||
(FB_INTEGER, parentRecordSourceId)
|
(FB_INTEGER, parentRecordSourceId)
|
||||||
|
(FB_INTEGER, level)
|
||||||
(FB_INTL_VARCHAR(MAX_ACCESS_PATH_CHAR_LEN * 4, CS_UTF8), accessPath)
|
(FB_INTL_VARCHAR(MAX_ACCESS_PATH_CHAR_LEN * 4, CS_UTF8), accessPath)
|
||||||
) recSrcMessage(status, MasterInterfacePtr());
|
) recSrcMessage(status, MasterInterfacePtr());
|
||||||
recSrcMessage.clear();
|
recSrcMessage.clear();
|
||||||
@ -773,6 +775,9 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
|
|||||||
recSrcMessage->parentRecordSourceIdNull = !recSrc.parentId.specified;
|
recSrcMessage->parentRecordSourceIdNull = !recSrc.parentId.specified;
|
||||||
recSrcMessage->parentRecordSourceId = recSrc.parentId.value;
|
recSrcMessage->parentRecordSourceId = recSrc.parentId.value;
|
||||||
|
|
||||||
|
recSrcMessage->levelNull = FB_FALSE;
|
||||||
|
recSrcMessage->level = recSrc.level;
|
||||||
|
|
||||||
recSrcMessage->accessPathNull = FB_FALSE;
|
recSrcMessage->accessPathNull = FB_FALSE;
|
||||||
recSrcMessage->accessPath.set(recSrc.accessPath.c_str());
|
recSrcMessage->accessPath.set(recSrc.accessPath.c_str());
|
||||||
|
|
||||||
@ -1041,6 +1046,7 @@ void ProfilerPlugin::createMetadata(ThrowStatusExceptionWrapper* status, RefPtr<
|
|||||||
cursor_id integer not null,
|
cursor_id integer not null,
|
||||||
record_source_id integer not null,
|
record_source_id integer not null,
|
||||||
parent_record_source_id integer,
|
parent_record_source_id integer,
|
||||||
|
level integer not null,
|
||||||
access_path varchar(255) character set utf8 not null,
|
access_path varchar(255) character set utf8 not null,
|
||||||
constraint plg$prof_record_sources_pk
|
constraint plg$prof_record_sources_pk
|
||||||
primary key (profile_id, statement_id, cursor_id, record_source_id)
|
primary key (profile_id, statement_id, cursor_id, record_source_id)
|
||||||
@ -1276,6 +1282,7 @@ void ProfilerPlugin::createMetadata(ThrowStatusExceptionWrapper* status, RefPtr<
|
|||||||
cur.column_num cursor_column_num,
|
cur.column_num cursor_column_num,
|
||||||
rstat.record_source_id,
|
rstat.record_source_id,
|
||||||
recsrc.parent_record_source_id,
|
recsrc.parent_record_source_id,
|
||||||
|
recsrc.level,
|
||||||
recsrc.access_path,
|
recsrc.access_path,
|
||||||
cast(sum(rstat.open_counter) as bigint) open_counter,
|
cast(sum(rstat.open_counter) as bigint) open_counter,
|
||||||
min(rstat.open_min_elapsed_time) open_min_elapsed_time,
|
min(rstat.open_min_elapsed_time) open_min_elapsed_time,
|
||||||
@ -1318,6 +1325,7 @@ void ProfilerPlugin::createMetadata(ThrowStatusExceptionWrapper* status, RefPtr<
|
|||||||
cur.column_num,
|
cur.column_num,
|
||||||
rstat.record_source_id,
|
rstat.record_source_id,
|
||||||
recsrc.parent_record_source_id,
|
recsrc.parent_record_source_id,
|
||||||
|
recsrc.level,
|
||||||
recsrc.access_path
|
recsrc.access_path
|
||||||
order by coalesce(sum(rstat.open_total_elapsed_time), 0) + coalesce(sum(rstat.fetch_total_elapsed_time), 0) desc
|
order by coalesce(sum(rstat.open_total_elapsed_time), 0) + coalesce(sum(rstat.fetch_total_elapsed_time), 0) desc
|
||||||
)""",
|
)""",
|
||||||
@ -1440,7 +1448,7 @@ void Session::defineCursor(SINT64 statementId, unsigned cursorId, const char* na
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Session::defineRecordSource(SINT64 statementId, unsigned cursorId, unsigned recSourceId,
|
void Session::defineRecordSource(SINT64 statementId, unsigned cursorId, unsigned recSourceId,
|
||||||
const char* accessPath, unsigned parentRecordSourceId)
|
unsigned level, const char* accessPath, unsigned parentRecordSourceId)
|
||||||
{
|
{
|
||||||
const auto recSource = recordSources.put({{statementId, cursorId}, recSourceId});
|
const auto recSource = recordSources.put({{statementId, cursorId}, recSourceId});
|
||||||
fb_assert(recSource);
|
fb_assert(recSource);
|
||||||
@ -1448,6 +1456,7 @@ void Session::defineRecordSource(SINT64 statementId, unsigned cursorId, unsigned
|
|||||||
if (!recSource)
|
if (!recSource)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
recSource->level = level;
|
||||||
recSource->accessPath = accessPath;
|
recSource->accessPath = accessPath;
|
||||||
|
|
||||||
if (unsigned len = recSource->accessPath.length(); len > MAX_ACCESS_PATH_CHAR_LEN)
|
if (unsigned len = recSource->accessPath.length(); len > MAX_ACCESS_PATH_CHAR_LEN)
|
||||||
|
Loading…
Reference in New Issue
Block a user