8
0
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

Also avoid start collect profiling data for a record source not from its initial node.
This commit is contained in:
Adriano dos Santos Fernandes 2023-07-28 06:43:51 -03:00
parent fc24dfa4be
commit c86bd3d4f4
7 changed files with 113 additions and 66 deletions

View File

@ -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
```

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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)