mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:03:03 +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
|
||||
- `RECORD_SOURCE_ID` type `INTEGER` - 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
|
||||
- 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,
|
||||
rstat.record_source_id,
|
||||
recsrc.parent_record_source_id,
|
||||
recsrc.level,
|
||||
recsrc.access_path,
|
||||
cast(sum(rstat.open_counter) as bigint) open_counter,
|
||||
min(rstat.open_min_elapsed_time) open_min_elapsed_time,
|
||||
@ -461,6 +463,7 @@ select rstat.profile_id,
|
||||
cur.column_num,
|
||||
rstat.record_source_id,
|
||||
recsrc.parent_record_source_id,
|
||||
recsrc.level,
|
||||
recsrc.access_path
|
||||
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 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,
|
||||
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 *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 *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 *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;
|
||||
@ -7019,9 +7019,9 @@ namespace Firebird
|
||||
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)
|
||||
@ -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
|
||||
{
|
||||
static_cast<Name*>(self)->Name::defineRecordSource(statementId, cursorId, recSourceId, accessPath, parentRecSourceId);
|
||||
static_cast<Name*>(self)->Name::defineRecordSource(statementId, cursorId, recSourceId, level, accessPath, parentRecSourceId);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -20672,7 +20672,7 @@ namespace Firebird
|
||||
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 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 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;
|
||||
|
@ -727,7 +727,7 @@ type
|
||||
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_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_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;
|
||||
@ -3838,7 +3838,7 @@ type
|
||||
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 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 onRequestFinish(status: IStatus; statementId: Int64; requestId: Int64; timestamp: ISC_TIMESTAMP_TZ; stats: IProfilerStats);
|
||||
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 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 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 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;
|
||||
@ -9428,9 +9428,9 @@ begin
|
||||
ProfilerSessionVTable(vTable).defineCursor(Self, statementId, cursorId, name, line, column);
|
||||
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
|
||||
ProfilerSessionVTable(vTable).defineRecordSource(Self, statementId, cursorId, recSourceId, accessPath, parentRecSourceId);
|
||||
ProfilerSessionVTable(vTable).defineRecordSource(Self, statementId, cursorId, recSourceId, level, accessPath, parentRecSourceId);
|
||||
end;
|
||||
|
||||
procedure IProfilerSession.onRequestStart(status: IStatus; statementId: Int64; requestId: Int64; callerStatementId: Int64; callerRequestId: Int64; timestamp: ISC_TIMESTAMP_TZ);
|
||||
@ -16541,10 +16541,10 @@ begin
|
||||
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
|
||||
try
|
||||
IProfilerSessionImpl(this).defineRecordSource(statementId, cursorId, recSourceId, accessPath, parentRecSourceId);
|
||||
IProfilerSessionImpl(this).defineRecordSource(statementId, cursorId, recSourceId, level, accessPath, parentRecSourceId);
|
||||
except
|
||||
on e: Exception do FbException.catchException(nil, e);
|
||||
end
|
||||
|
@ -475,13 +475,17 @@ void ProfilerManager::prepareCursor(thread_db* tdbb, Request* request, const Sel
|
||||
|
||||
auto cursorId = select->getCursorId();
|
||||
|
||||
if (profileStatement->definedCursors.exist(cursorId))
|
||||
return;
|
||||
if (!profileStatement->definedCursors.exist(cursorId))
|
||||
{
|
||||
currentSession->pluginSession->defineCursor(profileStatement->id, cursorId,
|
||||
select->getName().nullStr(), select->getLine(), select->getColumn());
|
||||
|
||||
currentSession->pluginSession->defineCursor(profileStatement->id, cursorId,
|
||||
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)
|
||||
@ -496,35 +500,32 @@ void ProfilerManager::prepareRecSource(thread_db* tdbb, Request* request, const
|
||||
|
||||
fb_assert(profileStatement->definedCursors.exist(rsb->getCursorId()));
|
||||
|
||||
Array<NonPooledPair<const RecordSource*, const RecordSource*>> tree;
|
||||
tree.add({rsb, nullptr});
|
||||
|
||||
for (unsigned pos = 0; pos < tree.getCount(); ++pos)
|
||||
struct PlanItem : PermanentStorage
|
||||
{
|
||||
const auto thisRsb = tree[pos].first;
|
||||
explicit PlanItem(MemoryPool& p)
|
||||
: PermanentStorage(p)
|
||||
{
|
||||
}
|
||||
|
||||
Array<const RecordSource*> children;
|
||||
thisRsb->getChildren(children);
|
||||
const RecordSource* recordSource = nullptr;
|
||||
const RecordSource* parentRecordSource = nullptr;
|
||||
string accessPath{getPool()};
|
||||
unsigned level = 0;
|
||||
};
|
||||
|
||||
unsigned childPos = pos;
|
||||
ObjectsArray<PlanItem> planItems;
|
||||
planItems.add().recordSource = rsb;
|
||||
|
||||
for (const auto child : children)
|
||||
tree.insert(++childPos, {child, thisRsb});
|
||||
}
|
||||
|
||||
NonPooledMap<ULONG, ULONG> idSequenceMap;
|
||||
auto sequencePtr = profileStatement->cursorNextSequence.getOrPut(rsb->getCursorId());
|
||||
|
||||
for (const auto& pair : tree)
|
||||
for (unsigned pos = 0; pos < planItems.getCount(); ++pos)
|
||||
{
|
||||
const auto cursorId = pair.first->getCursorId();
|
||||
const auto recSourceId = pair.first->getRecSourceId();
|
||||
idSequenceMap.put(recSourceId, ++*sequencePtr);
|
||||
auto& planItem = planItems[pos];
|
||||
const auto thisRsb = planItem.recordSource;
|
||||
|
||||
string accessPath;
|
||||
pair.first->print(tdbb, accessPath, true, 0, false);
|
||||
string& accessPath = planItem.accessPath;
|
||||
thisRsb->print(tdbb, accessPath, true, 0, false);
|
||||
|
||||
constexpr auto INDENT_MARKER = "\n ";
|
||||
constexpr unsigned INDENT_COUNT = 4;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (pair.second)
|
||||
parentSequence = *idSequenceMap.get(pair.second->getRecSourceId());
|
||||
if (planItem.parentRecordSource)
|
||||
parentSequence = *idSequenceMap.get(planItem.parentRecordSource->getRecSourceId());
|
||||
|
||||
currentSession->pluginSession->defineRecordSource(profileStatement->id, cursorId,
|
||||
*sequencePtr, accessPath.c_str(), parentSequence);
|
||||
*sequencePtr, planItem.level, planItem.accessPath.c_str(), parentSequence);
|
||||
|
||||
profileStatement->recSourceSequence.put(recSourceId, *sequencePtr);
|
||||
}
|
||||
|
@ -94,8 +94,6 @@ public:
|
||||
{
|
||||
lastTicks = profilerManager->queryTicks();
|
||||
|
||||
profilerManager->prepareRecSource(tdbb, request, recordSource);
|
||||
|
||||
if (profilerManager->currentSession->flags & Firebird::IProfilerSession::FLAG_BEFORE_EVENTS)
|
||||
{
|
||||
if (event == Event::OPEN)
|
||||
@ -191,7 +189,6 @@ public:
|
||||
const Firebird::PathName& pluginName, const Firebird::string& description, const Firebird::string& options);
|
||||
|
||||
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 beforePsqlLineColumn(Request* request, ULONG line, ULONG column)
|
||||
@ -218,11 +215,12 @@ public:
|
||||
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_BEFORE_EVENTS))
|
||||
{
|
||||
const auto profileStatement = getStatement(request);
|
||||
const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId());
|
||||
fb_assert(sequencePtr);
|
||||
|
||||
currentSession->pluginSession->beforeRecordSourceOpen(
|
||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr);
|
||||
if (const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId()))
|
||||
{
|
||||
currentSession->pluginSession->beforeRecordSourceOpen(
|
||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,11 +229,12 @@ public:
|
||||
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_AFTER_EVENTS))
|
||||
{
|
||||
const auto profileStatement = getStatement(request);
|
||||
const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId());
|
||||
fb_assert(sequencePtr);
|
||||
|
||||
currentSession->pluginSession->afterRecordSourceOpen(
|
||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr, &stats);
|
||||
if (const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId()))
|
||||
{
|
||||
currentSession->pluginSession->afterRecordSourceOpen(
|
||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr, &stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,11 +243,12 @@ public:
|
||||
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_BEFORE_EVENTS))
|
||||
{
|
||||
const auto profileStatement = getStatement(request);
|
||||
const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId());
|
||||
fb_assert(sequencePtr);
|
||||
|
||||
currentSession->pluginSession->beforeRecordSourceGetRecord(
|
||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr);
|
||||
if (const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId()))
|
||||
{
|
||||
currentSession->pluginSession->beforeRecordSourceGetRecord(
|
||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,11 +257,12 @@ public:
|
||||
if (const auto profileRequestId = getRequest(request, Firebird::IProfilerSession::FLAG_AFTER_EVENTS))
|
||||
{
|
||||
const auto profileStatement = getStatement(request);
|
||||
const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId());
|
||||
fb_assert(sequencePtr);
|
||||
|
||||
currentSession->pluginSession->afterRecordSourceGetRecord(
|
||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr, &stats);
|
||||
if (const auto sequencePtr = profileStatement->recSourceSequence.get(rsb->getRecSourceId()))
|
||||
{
|
||||
currentSession->pluginSession->afterRecordSourceGetRecord(
|
||||
profileStatement->id, profileRequestId, rsb->getCursorId(), *sequencePtr, &stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,6 +283,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void prepareRecSource(thread_db* tdbb, Request* request, const RecordSource* rsb);
|
||||
|
||||
void cancelSession();
|
||||
void finishSession(thread_db* tdbb, bool flushData);
|
||||
void pauseSession(bool flushData);
|
||||
|
@ -106,6 +106,7 @@ struct Cursor
|
||||
struct RecordSource
|
||||
{
|
||||
Nullable<ULONG> parentId;
|
||||
unsigned level;
|
||||
string accessPath{defaultPool()};
|
||||
};
|
||||
|
||||
@ -181,7 +182,7 @@ public:
|
||||
void defineCursor(SINT64 statementId, unsigned cursorId, const char* name, unsigned line, unsigned column) override;
|
||||
|
||||
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,
|
||||
SINT64 callerStatementId, SINT64 callerRequestId, ISC_TIMESTAMP_TZ timestamp) override;
|
||||
@ -441,8 +442,8 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
|
||||
constexpr auto recSrcSql = R"""(
|
||||
update or insert into plg$prof_record_sources
|
||||
(profile_id, statement_id, cursor_id, record_source_id,
|
||||
parent_record_source_id, access_path)
|
||||
values (?, ?, ?, ?, ?, ?)
|
||||
parent_record_source_id, level, access_path)
|
||||
values (?, ?, ?, ?, ?, ?, ?)
|
||||
matching (profile_id, statement_id, cursor_id, record_source_id)
|
||||
)""";
|
||||
|
||||
@ -452,6 +453,7 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
|
||||
(FB_INTEGER, cursorId)
|
||||
(FB_INTEGER, recordSourceId)
|
||||
(FB_INTEGER, parentRecordSourceId)
|
||||
(FB_INTEGER, level)
|
||||
(FB_INTL_VARCHAR(MAX_ACCESS_PATH_CHAR_LEN * 4, CS_UTF8), accessPath)
|
||||
) recSrcMessage(status, MasterInterfacePtr());
|
||||
recSrcMessage.clear();
|
||||
@ -773,6 +775,9 @@ void ProfilerPlugin::flush(ThrowStatusExceptionWrapper* status)
|
||||
recSrcMessage->parentRecordSourceIdNull = !recSrc.parentId.specified;
|
||||
recSrcMessage->parentRecordSourceId = recSrc.parentId.value;
|
||||
|
||||
recSrcMessage->levelNull = FB_FALSE;
|
||||
recSrcMessage->level = recSrc.level;
|
||||
|
||||
recSrcMessage->accessPathNull = FB_FALSE;
|
||||
recSrcMessage->accessPath.set(recSrc.accessPath.c_str());
|
||||
|
||||
@ -1041,6 +1046,7 @@ void ProfilerPlugin::createMetadata(ThrowStatusExceptionWrapper* status, RefPtr<
|
||||
cursor_id integer not null,
|
||||
record_source_id integer not null,
|
||||
parent_record_source_id integer,
|
||||
level integer not null,
|
||||
access_path varchar(255) character set utf8 not null,
|
||||
constraint plg$prof_record_sources_pk
|
||||
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,
|
||||
rstat.record_source_id,
|
||||
recsrc.parent_record_source_id,
|
||||
recsrc.level,
|
||||
recsrc.access_path,
|
||||
cast(sum(rstat.open_counter) as bigint) open_counter,
|
||||
min(rstat.open_min_elapsed_time) open_min_elapsed_time,
|
||||
@ -1318,6 +1325,7 @@ void ProfilerPlugin::createMetadata(ThrowStatusExceptionWrapper* status, RefPtr<
|
||||
cur.column_num,
|
||||
rstat.record_source_id,
|
||||
recsrc.parent_record_source_id,
|
||||
recsrc.level,
|
||||
recsrc.access_path
|
||||
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,
|
||||
const char* accessPath, unsigned parentRecordSourceId)
|
||||
unsigned level, const char* accessPath, unsigned parentRecordSourceId)
|
||||
{
|
||||
const auto recSource = recordSources.put({{statementId, cursorId}, recSourceId});
|
||||
fb_assert(recSource);
|
||||
@ -1448,6 +1456,7 @@ void Session::defineRecordSource(SINT64 statementId, unsigned cursorId, unsigned
|
||||
if (!recSource)
|
||||
return;
|
||||
|
||||
recSource->level = level;
|
||||
recSource->accessPath = accessPath;
|
||||
|
||||
if (unsigned len = recSource->accessPath.length(); len > MAX_ACCESS_PATH_CHAR_LEN)
|
||||
|
Loading…
Reference in New Issue
Block a user