mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:00:38 +01:00
Fix #7553 - Firebird 5 profiler error with subselects.
Some checks reported errors
continuous-integration/drone/push Build encountered an error
Some checks reported errors
continuous-integration/drone/push Build encountered an error
This commit is contained in:
parent
5205d16b9f
commit
e05d8f7d15
@ -58,9 +58,7 @@ static const int MAX_MEMBER_LIST = 1500;
|
||||
|
||||
BoolExprNode* BoolExprNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
pass2Boolean1(tdbb, csb);
|
||||
ExprNode::pass2(tdbb, csb);
|
||||
pass2Boolean2(tdbb, csb);
|
||||
pass2Boolean(tdbb, csb, [=] { ExprNode::pass2(tdbb, csb); });
|
||||
|
||||
if (nodFlags & FLAG_INVARIANT)
|
||||
{
|
||||
@ -593,14 +591,13 @@ BoolExprNode* ComparativeBoolNode::pass1(thread_db* tdbb, CompilerScratch* csb)
|
||||
return this;
|
||||
}
|
||||
|
||||
void ComparativeBoolNode::pass2Boolean1(thread_db* /*tdbb*/, CompilerScratch* csb)
|
||||
void ComparativeBoolNode::pass2Boolean(thread_db* tdbb, CompilerScratch* csb, std::function<void ()> process)
|
||||
{
|
||||
if (nodFlags & FLAG_INVARIANT)
|
||||
csb->csb_invariants.push(&impureOffset);
|
||||
}
|
||||
|
||||
void ComparativeBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
process();
|
||||
|
||||
RecordKeyNode* keyNode;
|
||||
|
||||
if (arg3)
|
||||
@ -1131,6 +1128,8 @@ BoolExprNode* ComparativeBoolNode::createRseNode(DsqlCompilerScratch* dsqlScratc
|
||||
|
||||
// Create output node.
|
||||
RseBoolNode* rseBoolNode = FB_NEW_POOL(pool) RseBoolNode(pool, rseBlrOp, rse);
|
||||
rseBoolNode->line = line;
|
||||
rseBoolNode->column = column;
|
||||
|
||||
// Finish off by cleaning up contexts
|
||||
dsqlScratch->unionContext.clear(baseUnion);
|
||||
@ -1211,8 +1210,10 @@ BoolExprNode* MissingBoolNode::pass1(thread_db* tdbb, CompilerScratch* csb)
|
||||
return BoolExprNode::pass1(tdbb, csb);
|
||||
}
|
||||
|
||||
void MissingBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
|
||||
void MissingBoolNode::pass2Boolean(thread_db* tdbb, CompilerScratch* csb, std::function<void ()> process)
|
||||
{
|
||||
process();
|
||||
|
||||
RecordKeyNode* keyNode = nodeAs<RecordKeyNode>(arg);
|
||||
|
||||
if (keyNode && keyNode->aggregate)
|
||||
@ -1433,9 +1434,7 @@ RseBoolNode::RseBoolNode(MemoryPool& pool, UCHAR aBlrOp, RecordSourceNode* aDsql
|
||||
: TypedNode<BoolExprNode, ExprNode::TYPE_RSE_BOOL>(pool),
|
||||
blrOp(aBlrOp),
|
||||
ownSavepoint(true),
|
||||
dsqlRse(aDsqlRse),
|
||||
rse(NULL),
|
||||
subQuery(NULL)
|
||||
dsqlRse(aDsqlRse)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1493,6 +1492,8 @@ BoolExprNode* RseBoolNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
void RseBoolNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
dsqlScratch->appendUChar(blrOp);
|
||||
|
||||
dsqlScratch->putDebugSrcInfo(line, column);
|
||||
GEN_rse(dsqlScratch, nodeAs<RseNode>(dsqlRse));
|
||||
}
|
||||
|
||||
@ -1580,7 +1581,7 @@ BoolExprNode* RseBoolNode::pass1(thread_db* tdbb, CompilerScratch* csb)
|
||||
return BoolExprNode::pass1(tdbb, csb);
|
||||
}
|
||||
|
||||
void RseBoolNode::pass2Boolean1(thread_db* tdbb, CompilerScratch* csb)
|
||||
void RseBoolNode::pass2Boolean(thread_db* tdbb, CompilerScratch* csb, std::function<void ()> process)
|
||||
{
|
||||
if (rse->isInvariant())
|
||||
{
|
||||
@ -1588,11 +1589,12 @@ void RseBoolNode::pass2Boolean1(thread_db* tdbb, CompilerScratch* csb)
|
||||
csb->csb_invariants.push(&impureOffset);
|
||||
}
|
||||
|
||||
rse->pass2Rse(tdbb, csb);
|
||||
}
|
||||
AutoSetCurrentCursorProfileId autoSetCurrentCursorProfileId(csb);
|
||||
|
||||
rse->pass2Rse(tdbb, csb);
|
||||
|
||||
process();
|
||||
|
||||
void RseBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
if (nodFlags & FLAG_INVARIANT)
|
||||
impureOffset = csb->allocImpure<impure_value>();
|
||||
|
||||
|
@ -117,8 +117,7 @@ public:
|
||||
virtual bool dsqlMatch(DsqlCompilerScratch* dsqlScratch, const ExprNode* other, bool ignoreMapCast) const;
|
||||
virtual bool sameAs(const ExprNode* other, bool ignoreStreams) const;
|
||||
virtual BoolExprNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual void pass2Boolean1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual void pass2Boolean2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual void pass2Boolean(thread_db* tdbb, CompilerScratch* csb, std::function<void ()> process);
|
||||
virtual bool execute(thread_db* tdbb, Request* request) const;
|
||||
|
||||
private:
|
||||
@ -168,7 +167,7 @@ public:
|
||||
|
||||
virtual BoolExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
|
||||
virtual BoolExprNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual void pass2Boolean2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual void pass2Boolean(thread_db* tdbb, CompilerScratch* csb, std::function<void ()> process);
|
||||
virtual bool execute(thread_db* tdbb, Request* request) const;
|
||||
|
||||
public:
|
||||
@ -209,7 +208,7 @@ public:
|
||||
class RseBoolNode final : public TypedNode<BoolExprNode, ExprNode::TYPE_RSE_BOOL>
|
||||
{
|
||||
public:
|
||||
RseBoolNode(MemoryPool& pool, UCHAR aBlrOp, RecordSourceNode* aDsqlRse = NULL);
|
||||
RseBoolNode(MemoryPool& pool, UCHAR aBlrOp, RecordSourceNode* aDsqlRse = nullptr);
|
||||
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);
|
||||
|
||||
@ -251,8 +250,7 @@ public:
|
||||
virtual bool dsqlMatch(DsqlCompilerScratch* dsqlScratch, const ExprNode* other, bool ignoreMapCast) const;
|
||||
virtual bool sameAs(const ExprNode* other, bool ignoreStreams) const;
|
||||
virtual BoolExprNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual void pass2Boolean1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual void pass2Boolean2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual void pass2Boolean(thread_db* tdbb, CompilerScratch* csb, std::function<void ()> process);
|
||||
virtual bool execute(thread_db* tdbb, Request* request) const;
|
||||
|
||||
private:
|
||||
|
@ -11049,7 +11049,6 @@ DmlNode* SubQueryNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
||||
SubQueryNode* node = FB_NEW_POOL(pool) SubQueryNode(pool, (blrOp == blr_from ? blr_via : blrOp));
|
||||
|
||||
node->rse = PAR_rse(tdbb, csb);
|
||||
|
||||
node->rse->flags |= RseNode::FLAG_SUB_QUERY;
|
||||
|
||||
if (blrOp != blr_count)
|
||||
@ -11112,6 +11111,9 @@ ValueExprNode* SubQueryNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
SubQueryNode* node = FB_NEW_POOL(dsqlScratch->getPool()) SubQueryNode(dsqlScratch->getPool(), blrOp, rse,
|
||||
rse->dsqlSelectList->items[0], NullNode::instance());
|
||||
|
||||
node->line = line;
|
||||
node->column = column;
|
||||
|
||||
// Finish off by cleaning up contexts.
|
||||
dsqlScratch->context->clear(base);
|
||||
|
||||
@ -11126,7 +11128,10 @@ void SubQueryNode::setParameterName(dsql_par* parameter) const
|
||||
void SubQueryNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
dsqlScratch->appendUChar(blrOp);
|
||||
|
||||
dsqlScratch->putDebugSrcInfo(line, column);
|
||||
GEN_expr(dsqlScratch, dsqlRse);
|
||||
|
||||
GEN_expr(dsqlScratch, value1);
|
||||
GEN_expr(dsqlScratch, value2);
|
||||
}
|
||||
@ -11341,6 +11346,8 @@ ValueExprNode* SubQueryNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
csb->csb_invariants.push(&impureOffset);
|
||||
}
|
||||
|
||||
AutoSetCurrentCursorProfileId autoSetCurrentCursorProfileId(csb);
|
||||
|
||||
rse->pass2Rse(tdbb, csb);
|
||||
|
||||
ValueExprNode::pass2(tdbb, csb);
|
||||
@ -11351,6 +11358,7 @@ ValueExprNode* SubQueryNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
dsc desc;
|
||||
getDesc(tdbb, csb, &desc);
|
||||
}
|
||||
|
||||
if (blrOp == blr_average && !(nodFlags & FLAG_DECFLOAT))
|
||||
nodFlags |= FLAG_DOUBLE;
|
||||
|
||||
|
@ -731,40 +731,37 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual Kind getKind()
|
||||
Kind getKind() override
|
||||
{
|
||||
return KIND_BOOLEAN;
|
||||
}
|
||||
|
||||
virtual BoolExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
BoolExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch) override
|
||||
{
|
||||
ExprNode::dsqlPass(dsqlScratch);
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual BoolExprNode* dsqlFieldRemapper(FieldRemapper& visitor)
|
||||
BoolExprNode* dsqlFieldRemapper(FieldRemapper& visitor) override
|
||||
{
|
||||
ExprNode::dsqlFieldRemapper(visitor);
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual BoolExprNode* pass1(thread_db* tdbb, CompilerScratch* csb)
|
||||
BoolExprNode* pass1(thread_db* tdbb, CompilerScratch* csb) override
|
||||
{
|
||||
ExprNode::pass1(tdbb, csb);
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual BoolExprNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
BoolExprNode* pass2(thread_db* tdbb, CompilerScratch* csb) override final;
|
||||
|
||||
virtual void pass2Boolean1(thread_db* /*tdbb*/, CompilerScratch* /*csb*/)
|
||||
virtual void pass2Boolean(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, std::function<void ()> process)
|
||||
{
|
||||
process();
|
||||
}
|
||||
|
||||
virtual void pass2Boolean2(thread_db* /*tdbb*/, CompilerScratch* /*csb*/)
|
||||
{
|
||||
}
|
||||
|
||||
virtual BoolExprNode* copy(thread_db* tdbb, NodeCopier& copier) const = 0;
|
||||
BoolExprNode* copy(thread_db* tdbb, NodeCopier& copier) const override = 0;
|
||||
virtual bool execute(thread_db* tdbb, Request* request) const = 0;
|
||||
};
|
||||
|
||||
|
@ -1297,6 +1297,8 @@ DeclareCursorNode* DeclareCursorNode::pass1(thread_db* tdbb, CompilerScratch* cs
|
||||
|
||||
DeclareCursorNode* DeclareCursorNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
AutoSetCurrentCursorProfileId autoSetCurrentCursorProfileId(csb);
|
||||
|
||||
rse->pass2Rse(tdbb, csb);
|
||||
|
||||
ExprNode::doPass2(tdbb, csb, rse.getAddress());
|
||||
@ -5061,6 +5063,8 @@ StmtNode* ForNode::pass1(thread_db* tdbb, CompilerScratch* csb)
|
||||
|
||||
StmtNode* ForNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
AutoSetCurrentCursorProfileId autoSetCurrentCursorProfileId(csb);
|
||||
|
||||
rse->pass2Rse(tdbb, csb);
|
||||
|
||||
doPass2(tdbb, csb, stall.getAddress(), this);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "../jrd/tra.h"
|
||||
#include "../jrd/ids.h"
|
||||
#include "../jrd/recsrc/Cursor.h"
|
||||
#include "../dsql/BoolNodes.h"
|
||||
#include "../jrd/dpm_proto.h"
|
||||
#include "../jrd/lck_proto.h"
|
||||
#include "../jrd/met_proto.h"
|
||||
@ -464,20 +465,20 @@ SINT64 ProfilerManager::startSession(thread_db* tdbb, Nullable<SLONG> flushInter
|
||||
return currentSession->pluginSession->getId();
|
||||
}
|
||||
|
||||
void ProfilerManager::prepareCursor(thread_db* tdbb, Request* request, const Cursor* cursor)
|
||||
void ProfilerManager::prepareCursor(thread_db* tdbb, Request* request, const Select* select)
|
||||
{
|
||||
auto profileStatement = getStatement(request);
|
||||
|
||||
if (!profileStatement)
|
||||
return;
|
||||
|
||||
auto cursorId = cursor->getCursorProfileId();
|
||||
auto cursorId = select->getCursorProfileId();
|
||||
|
||||
if (profileStatement->definedCursors.exist(cursorId))
|
||||
return;
|
||||
|
||||
currentSession->pluginSession->defineCursor(profileStatement->id, cursorId,
|
||||
cursor->getName().nullStr(), cursor->getLine(), cursor->getColumn());
|
||||
select->getName().nullStr(), select->getLine(), select->getColumn());
|
||||
|
||||
profileStatement->definedCursors.add(cursorId);
|
||||
}
|
||||
|
@ -35,9 +35,9 @@
|
||||
namespace Jrd {
|
||||
|
||||
class Attachment;
|
||||
class Cursor;
|
||||
class Request;
|
||||
class RecordSource;
|
||||
class Select;
|
||||
class thread_db;
|
||||
|
||||
class ProfilerListener;
|
||||
@ -123,7 +123,7 @@ public:
|
||||
SINT64 startSession(thread_db* tdbb, Nullable<SLONG> flushInterval,
|
||||
const Firebird::PathName& pluginName, const Firebird::string& description, const Firebird::string& options);
|
||||
|
||||
void prepareCursor(thread_db* tdbb, Request* request, const Cursor* cursor);
|
||||
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);
|
||||
|
@ -2754,6 +2754,8 @@ RseNode* RseNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
RseNode* RseNode::copy(thread_db* tdbb, NodeCopier& copier) const
|
||||
{
|
||||
RseNode* newSource = FB_NEW_POOL(*tdbb->getDefaultPool()) RseNode(*tdbb->getDefaultPool());
|
||||
newSource->line = line;
|
||||
newSource->column = column;
|
||||
|
||||
for (const auto sub : rse_relations)
|
||||
newSource->rse_relations.add(sub->copy(tdbb, copier));
|
||||
|
@ -518,7 +518,7 @@ RecordSource* CMP_post_rse(thread_db* tdbb, CompilerScratch* csb, RseNode* rse)
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
AutoSetRestore<ULONG> autoCurrentCursorProfileId(&csb->csb_currentCursorProfileId, csb->csb_nextCursorProfileId++);
|
||||
fb_assert(csb->csb_currentCursorProfileId);
|
||||
|
||||
const auto rsb = Optimizer::compile(tdbb, csb, rse);
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "../jrd/Relation.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../jrd/MetaName.h"
|
||||
#include "../common/classes/auto.h"
|
||||
#include "../common/classes/fb_pair.h"
|
||||
#include "../common/classes/NestConst.h"
|
||||
|
||||
@ -670,6 +671,17 @@ inline void CompilerScratch::csb_repeat::deactivate()
|
||||
}
|
||||
|
||||
|
||||
class AutoSetCurrentCursorProfileId : private Firebird::AutoSetRestore<ULONG>
|
||||
{
|
||||
public:
|
||||
explicit AutoSetCurrentCursorProfileId(CompilerScratch* csb)
|
||||
: AutoSetRestore(&csb->csb_currentCursorProfileId,
|
||||
(csb->csb_currentCursorProfileId == 0 ? csb->csb_nextCursorProfileId++ : csb->csb_currentCursorProfileId))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class StatusXcp
|
||||
{
|
||||
Firebird::FbLocalStatus status;
|
||||
|
@ -81,6 +81,7 @@ static void par_error(BlrReader& blrReader, const Arg::StatusVector& v, bool isS
|
||||
static PlanNode* par_plan(thread_db*, CompilerScratch*);
|
||||
static void getBlrVersion(CompilerScratch* csb);
|
||||
static void parseSubRoutines(thread_db* tdbb, CompilerScratch* csb);
|
||||
static void setNodeLineColumn(CompilerScratch* csb, DmlNode* node, ULONG blrOffset);
|
||||
|
||||
|
||||
namespace
|
||||
@ -1319,9 +1320,12 @@ RseNode* PAR_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
const ULONG blrOffset = csb->csb_blr_reader.getOffset() - 1;
|
||||
int count = (unsigned int) csb->csb_blr_reader.getByte();
|
||||
RseNode* rse = FB_NEW_POOL(*tdbb->getDefaultPool()) RseNode(*tdbb->getDefaultPool());
|
||||
|
||||
setNodeLineColumn(csb, rse, blrOffset);
|
||||
|
||||
if (rse_op == blr_lateral_rse)
|
||||
rse->flags |= RseNode::FLAG_LATERAL;
|
||||
|
||||
@ -1452,34 +1456,35 @@ RseNode* PAR_rse(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
const ULONG blrOffset = csb->csb_blr_reader.getOffset();
|
||||
const SSHORT blrOp = csb->csb_blr_reader.getByte();
|
||||
RseNode* rseNode = nullptr;
|
||||
|
||||
switch (blrOp)
|
||||
{
|
||||
case blr_rse:
|
||||
case blr_lateral_rse:
|
||||
case blr_rs_stream:
|
||||
return PAR_rse(tdbb, csb, blrOp);
|
||||
rseNode = PAR_rse(tdbb, csb, blrOp);
|
||||
break;
|
||||
|
||||
case blr_singular:
|
||||
{
|
||||
RseNode* rseNode = PAR_rse(tdbb, csb);
|
||||
rseNode = PAR_rse(tdbb, csb);
|
||||
rseNode->flags |= RseNode::FLAG_SINGULAR;
|
||||
return rseNode;
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_scrollable:
|
||||
{
|
||||
RseNode* rseNode = PAR_rse(tdbb, csb);
|
||||
rseNode = PAR_rse(tdbb, csb);
|
||||
rseNode->flags |= RseNode::FLAG_SCROLLABLE;
|
||||
return rseNode;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PAR_syntax_error(csb, "RecordSelExpr");
|
||||
}
|
||||
|
||||
return NULL; // warning
|
||||
setNodeLineColumn(csb, rseNode, blrOffset);
|
||||
|
||||
return rseNode;
|
||||
}
|
||||
|
||||
|
||||
@ -1600,10 +1605,10 @@ DmlNode* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
const ULONG blr_offset = csb->csb_blr_reader.getOffset();
|
||||
const SSHORT blr_operator = csb->csb_blr_reader.getByte();
|
||||
const ULONG blrOffset = csb->csb_blr_reader.getOffset();
|
||||
const SSHORT blrOperator = csb->csb_blr_reader.getByte();
|
||||
|
||||
if (blr_operator < 0 || blr_operator >= FB_NELEM(blr_parsers))
|
||||
if (blrOperator < 0 || blrOperator >= FB_NELEM(blr_parsers))
|
||||
{
|
||||
// NS: This error string is correct, please do not mangle it again and again.
|
||||
// The whole error message is "BLR syntax error: expected %s at offset %d, encountered %d"
|
||||
@ -1612,7 +1617,7 @@ DmlNode* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb)
|
||||
|
||||
// Dispatch on operator type.
|
||||
|
||||
switch (blr_operator)
|
||||
switch (blrOperator)
|
||||
{
|
||||
case blr_rse:
|
||||
case blr_lateral_rse:
|
||||
@ -1642,21 +1647,11 @@ DmlNode* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb)
|
||||
return PAR_parseRecordSource(tdbb, csb);
|
||||
}
|
||||
|
||||
if (!blr_parsers[blr_operator])
|
||||
if (!blr_parsers[blrOperator])
|
||||
PAR_syntax_error(csb, "valid BLR code");
|
||||
|
||||
DmlNode* node = blr_parsers[blr_operator](tdbb, *tdbb->getDefaultPool(), csb, blr_operator);
|
||||
FB_SIZE_T pos = 0;
|
||||
|
||||
if (node->getKind() == DmlNode::KIND_STATEMENT && csb->csb_dbg_info->blrToSrc.find(blr_offset, pos))
|
||||
{
|
||||
MapBlrToSrcItem& i = csb->csb_dbg_info->blrToSrc[pos];
|
||||
StmtNode* stmt = static_cast<StmtNode*>(node);
|
||||
|
||||
stmt->hasLineColumn = true;
|
||||
stmt->line = i.mbs_src_line;
|
||||
stmt->column = i.mbs_src_col;
|
||||
}
|
||||
DmlNode* node = blr_parsers[blrOperator](tdbb, *tdbb->getDefaultPool(), csb, blrOperator);
|
||||
setNodeLineColumn(csb, node, blrOffset);
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -1750,3 +1745,20 @@ static void parseSubRoutines(thread_db* tdbb, CompilerScratch* csb)
|
||||
PAR_blr(tdbb, nullptr, node->blrStart, node->blrLength, nullptr, &node->subCsb, nullptr, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set node line/column for a given blr offset.
|
||||
static void setNodeLineColumn(CompilerScratch* csb, DmlNode* node, ULONG blrOffset)
|
||||
{
|
||||
FB_SIZE_T pos;
|
||||
|
||||
if (node && csb->csb_dbg_info->blrToSrc.find(blrOffset, pos))
|
||||
{
|
||||
MapBlrToSrcItem& i = csb->csb_dbg_info->blrToSrc[pos];
|
||||
node->line = i.mbs_src_line;
|
||||
node->column = i.mbs_src_col;
|
||||
|
||||
if (node->getKind() == DmlNode::KIND_STATEMENT)
|
||||
static_cast<StmtNode*>(node)->hasLineColumn = true;
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,16 @@ namespace
|
||||
// Select implementation
|
||||
// ---------------------
|
||||
|
||||
Select::Select(const RecordSource* source, const RseNode* rse, ULONG line, ULONG column, const MetaName& cursorName)
|
||||
: m_top(source),
|
||||
m_rse(rse),
|
||||
m_cursorProfileId(source->getCursorProfileId()),
|
||||
m_cursorName(cursorName),
|
||||
m_line(line),
|
||||
m_column(column)
|
||||
{
|
||||
}
|
||||
|
||||
void Select::initializeInvariants(Request* request) const
|
||||
{
|
||||
// Initialize dependent invariants, if any
|
||||
@ -109,18 +119,32 @@ void Select::printPlan(thread_db* tdbb, string& plan, bool detailed) const
|
||||
m_top->print(tdbb, plan, detailed, 0, true);
|
||||
}
|
||||
|
||||
void Select::prepareProfiler(thread_db* tdbb, Request* request) const
|
||||
{
|
||||
const auto attachment = tdbb->getAttachment();
|
||||
|
||||
const auto profilerManager = attachment->isProfilerActive() && !request->hasInternalStatement() ?
|
||||
attachment->getProfilerManager(tdbb) :
|
||||
nullptr;
|
||||
|
||||
if (profilerManager)
|
||||
profilerManager->prepareCursor(tdbb, request, this);
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
// SubQuery implementation
|
||||
// ---------------------
|
||||
|
||||
SubQuery::SubQuery(const RecordSource* rsb, const RseNode* rse)
|
||||
: Select(rsb, rse)
|
||||
: Select(rsb, rse, rse->line, rse->column)
|
||||
{
|
||||
fb_assert(m_top);
|
||||
}
|
||||
|
||||
void SubQuery::open(thread_db* tdbb) const
|
||||
{
|
||||
prepareProfiler(tdbb, tdbb->getRequest());
|
||||
|
||||
initializeInvariants(tdbb->getRequest());
|
||||
m_top->open(tdbb);
|
||||
}
|
||||
@ -135,6 +159,8 @@ bool SubQuery::fetch(thread_db* tdbb) const
|
||||
if (!validate(tdbb))
|
||||
return false;
|
||||
|
||||
prepareProfiler(tdbb, tdbb->getRequest());
|
||||
|
||||
return m_top->getRecord(tdbb);
|
||||
}
|
||||
|
||||
@ -146,7 +172,6 @@ bool SubQuery::fetch(thread_db* tdbb) const
|
||||
Cursor::Cursor(CompilerScratch* csb, const RecordSource* rsb, const RseNode* rse,
|
||||
bool updateCounters, ULONG line, ULONG column, const MetaName& name)
|
||||
: Select(rsb, rse, line, column, name),
|
||||
m_cursorProfileId(rsb->getCursorProfileId()),
|
||||
m_updateCounters(updateCounters)
|
||||
{
|
||||
fb_assert(m_top);
|
||||
@ -409,18 +434,6 @@ void Cursor::checkState(Request* request) const
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_cursor_not_positioned) <<
|
||||
Arg::Str(m_cursorName));
|
||||
getName());
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::prepareProfiler(thread_db* tdbb, Request* request) const
|
||||
{
|
||||
const auto attachment = tdbb->getAttachment();
|
||||
|
||||
const auto profilerManager = attachment->isProfilerActive() && !request->hasInternalStatement() ?
|
||||
attachment->getProfilerManager(tdbb) :
|
||||
nullptr;
|
||||
|
||||
if (profilerManager)
|
||||
profilerManager->prepareCursor(tdbb, request, this);
|
||||
}
|
||||
|
@ -43,20 +43,27 @@ namespace Jrd
|
||||
INVARIANT = 2
|
||||
};
|
||||
|
||||
Select(const RecordSource* source, const RseNode* rse,
|
||||
ULONG line = 0, ULONG column = 0, const MetaName& cursorName = "")
|
||||
: m_top(source), m_rse(rse), m_cursorName(cursorName),
|
||||
m_line(line), m_column(column)
|
||||
{}
|
||||
Select(const RecordSource* source, const RseNode* rse, ULONG line = 0, ULONG column = 0,
|
||||
const MetaName& cursorName = {});
|
||||
|
||||
virtual ~Select()
|
||||
{}
|
||||
|
||||
ULONG getCursorProfileId() const
|
||||
{
|
||||
return m_cursorProfileId;
|
||||
}
|
||||
|
||||
const RecordSource* getAccessPath() const
|
||||
{
|
||||
return m_top;
|
||||
}
|
||||
|
||||
const MetaName& getName() const
|
||||
{
|
||||
return m_cursorName;
|
||||
}
|
||||
|
||||
ULONG getLine() const
|
||||
{
|
||||
return m_line;
|
||||
@ -73,12 +80,16 @@ namespace Jrd
|
||||
virtual void open(thread_db* tdbb) const = 0;
|
||||
virtual void close(thread_db* tdbb) const = 0;
|
||||
|
||||
protected:
|
||||
void prepareProfiler(thread_db* tdbb, Request* request) const;
|
||||
|
||||
protected:
|
||||
const RecordSource* const m_top;
|
||||
const RseNode* const m_rse;
|
||||
MetaName m_cursorName; // optional name for explicit PSQL cursors
|
||||
|
||||
private:
|
||||
const ULONG m_cursorProfileId;
|
||||
MetaName m_cursorName; // optional name for explicit PSQL cursors
|
||||
ULONG m_line = 0;
|
||||
ULONG m_column = 0;
|
||||
};
|
||||
@ -125,26 +136,12 @@ namespace Jrd
|
||||
|
||||
void checkState(Request* request) const;
|
||||
|
||||
ULONG getCursorProfileId() const
|
||||
{
|
||||
return m_cursorProfileId;
|
||||
}
|
||||
|
||||
bool isUpdateCounters() const
|
||||
{
|
||||
return m_updateCounters;
|
||||
}
|
||||
|
||||
const MetaName& getName() const
|
||||
{
|
||||
return m_cursorName;
|
||||
}
|
||||
|
||||
private:
|
||||
void prepareProfiler(thread_db* tdbb, Request* request) const;
|
||||
|
||||
private:
|
||||
const ULONG m_cursorProfileId;
|
||||
ULONG m_impure;
|
||||
const bool m_updateCounters;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user