mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 22:43:03 +01:00
Refactor: SelectNode (DSQL) and blr_select (JRD) has no relation with each other.
This commit is contained in:
parent
8693554daf
commit
0278a9bfdb
@ -1445,6 +1445,7 @@ public:
|
||||
TYPE_RETURN,
|
||||
TYPE_SAVEPOINT,
|
||||
TYPE_SELECT,
|
||||
TYPE_SELECT_MESSAGE,
|
||||
TYPE_SESSION_MANAGEMENT_WRAPPER,
|
||||
TYPE_SET_GENERATOR,
|
||||
TYPE_STALL,
|
||||
|
@ -1236,7 +1236,7 @@ DeclareCursorNode* DeclareCursorNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
|
||||
SelectExprNode* dt = FB_NEW_POOL(dsqlScratch->getPool()) SelectExprNode(dsqlScratch->getPool());
|
||||
dt->dsqlFlags = RecordSourceNode::DFLAG_DERIVED | RecordSourceNode::DFLAG_CURSOR;
|
||||
dt->querySpec = dsqlSelect->dsqlExpr;
|
||||
dt->querySpec = dsqlSelect->selectExpr;
|
||||
dt->alias = dsqlName.c_str();
|
||||
|
||||
rse = PASS1_derived_table(dsqlScratch, dt, NULL, dsqlSelect);
|
||||
@ -4933,7 +4933,7 @@ ForNode* ForNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
|
||||
SelectExprNode* dt = FB_NEW_POOL(dsqlScratch->getPool()) SelectExprNode(dsqlScratch->getPool());
|
||||
dt->dsqlFlags = RecordSourceNode::DFLAG_DERIVED | RecordSourceNode::DFLAG_CURSOR;
|
||||
dt->querySpec = dsqlSelect->dsqlExpr;
|
||||
dt->querySpec = dsqlSelect->selectExpr;
|
||||
dt->alias = dsqlCursor->dsqlName.c_str();
|
||||
|
||||
node->rse = PASS1_derived_table(dsqlScratch, dt, NULL, dsqlSelect);
|
||||
@ -4943,7 +4943,7 @@ ForNode* ForNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
dsqlScratch->cursors.push(dsqlCursor);
|
||||
}
|
||||
else
|
||||
node->rse = dsqlSelect->dsqlPass(dsqlScratch)->dsqlRse;
|
||||
node->rse = dsqlSelect->dsqlPass(dsqlScratch)->rse;
|
||||
|
||||
node->dsqlInto = dsqlPassArray(dsqlScratch, dsqlInto);
|
||||
|
||||
@ -5573,10 +5573,10 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
selectExpr->dsqlFlags |= RecordSourceNode::DFLAG_SINGLETON;
|
||||
|
||||
const auto dsqlSelect = FB_NEW_POOL(pool) SelectNode(pool);
|
||||
dsqlSelect->dsqlExpr = selectExpr;
|
||||
dsqlSelect->selectExpr = selectExpr;
|
||||
|
||||
const auto mergeNode = FB_NEW_POOL(pool) MergeNode(pool);
|
||||
mergeNode->rse = dsqlSelect->dsqlPass(dsqlScratch)->dsqlRse;
|
||||
mergeNode->rse = dsqlSelect->dsqlPass(dsqlScratch)->rse;
|
||||
|
||||
// Get the already processed relations.
|
||||
const auto processedRse = nodeAs<RseNode>(mergeNode->rse->dsqlStreams->items[0]);
|
||||
@ -8189,35 +8189,17 @@ const StmtNode* StoreNode::store(thread_db* tdbb, Request* request, WhichTrigger
|
||||
//--------------------
|
||||
|
||||
|
||||
static RegisterNode<SelectNode> regSelectNode({blr_select});
|
||||
|
||||
DmlNode* SelectNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR /*blrOp*/)
|
||||
{
|
||||
SelectNode* node = FB_NEW_POOL(pool) SelectNode(pool);
|
||||
|
||||
while (csb->csb_blr_reader.peekByte() != blr_end)
|
||||
{
|
||||
if (csb->csb_blr_reader.peekByte() != blr_receive)
|
||||
PAR_syntax_error(csb, "blr_receive");
|
||||
node->statements.add(PAR_parse_stmt(tdbb, csb));
|
||||
}
|
||||
|
||||
csb->csb_blr_reader.getByte(); // skip blr_end
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
SelectNode* SelectNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
SelectNode* node = FB_NEW_POOL(dsqlScratch->getPool()) SelectNode(dsqlScratch->getPool());
|
||||
node->dsqlForUpdate = dsqlForUpdate;
|
||||
node->dsqlOptimizeForFirstRows = dsqlOptimizeForFirstRows;
|
||||
node->forUpdate = forUpdate;
|
||||
node->optimizeForFirstRows = optimizeForFirstRows;
|
||||
|
||||
const DsqlContextStack::iterator base(*dsqlScratch->context);
|
||||
node->dsqlRse = PASS1_rse(dsqlScratch, dsqlExpr, this);
|
||||
node->rse = PASS1_rse(dsqlScratch, selectExpr, this);
|
||||
dsqlScratch->context->clear(base);
|
||||
|
||||
if (dsqlForUpdate)
|
||||
if (forUpdate)
|
||||
{
|
||||
dsqlScratch->getDsqlStatement()->setType(DsqlStatement::TYPE_SELECT_UPD);
|
||||
dsqlScratch->getDsqlStatement()->addFlags(DsqlStatement::FLAG_NO_BATCH);
|
||||
@ -8228,9 +8210,7 @@ SelectNode* SelectNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
// stored procedure occurs in the select list. In these cases all of stored procedure is
|
||||
// executed under savepoint for open cursor.
|
||||
|
||||
RseNode* rseNode = nodeAs<RseNode>(node->dsqlRse);
|
||||
|
||||
if (rseNode->dsqlOrder || rseNode->dsqlDistinct)
|
||||
if (node->rse->dsqlOrder || node->rse->dsqlDistinct)
|
||||
{
|
||||
dsqlScratch->getDsqlStatement()->setFlags(
|
||||
dsqlScratch->getDsqlStatement()->getFlags() & ~DsqlStatement::FLAG_NO_BATCH);
|
||||
@ -8244,11 +8224,12 @@ string SelectNode::internalPrint(NodePrinter& printer) const
|
||||
{
|
||||
StmtNode::internalPrint(printer);
|
||||
|
||||
NODE_PRINT(printer, dsqlExpr);
|
||||
NODE_PRINT(printer, dsqlForUpdate);
|
||||
NODE_PRINT(printer, dsqlWithLock);
|
||||
NODE_PRINT(printer, dsqlRse);
|
||||
NODE_PRINT(printer, statements);
|
||||
NODE_PRINT(printer, selectExpr);
|
||||
NODE_PRINT(printer, optimizeForFirstRows);
|
||||
NODE_PRINT(printer, forUpdate);
|
||||
NODE_PRINT(printer, withLock);
|
||||
NODE_PRINT(printer, skipLocked);
|
||||
NODE_PRINT(printer, rse);
|
||||
|
||||
return "SelectNode";
|
||||
}
|
||||
@ -8256,10 +8237,9 @@ string SelectNode::internalPrint(NodePrinter& printer) const
|
||||
// Generate BLR for a SELECT statement.
|
||||
void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
RseNode* const rse = nodeAs<RseNode>(dsqlRse);
|
||||
fb_assert(rse);
|
||||
|
||||
DsqlStatement* const statement = dsqlScratch->getDsqlStatement();
|
||||
const auto statement = dsqlScratch->getDsqlStatement();
|
||||
|
||||
// Set up parameter for things in the select list.
|
||||
ValueListNode* list = rse->dsqlSelectList;
|
||||
@ -8284,7 +8264,7 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GenericMap<NonPooled<dsql_par*, dsql_ctx*> > paramContexts(*getDefaultMemoryPool());
|
||||
dsql_ctx* context;
|
||||
|
||||
if (dsqlForUpdate && !rse->dsqlDistinct)
|
||||
if (forUpdate && !rse->dsqlDistinct)
|
||||
{
|
||||
RecSourceListNode* streamList = rse->dsqlStreams;
|
||||
|
||||
@ -8345,7 +8325,7 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
|
||||
dsqlScratch->appendUChar(blr_for);
|
||||
dsqlScratch->appendUChar(blr_stall);
|
||||
GEN_rse(dsqlScratch, dsqlRse);
|
||||
GEN_rse(dsqlScratch, rse);
|
||||
|
||||
dsqlScratch->appendUChar(blr_send);
|
||||
dsqlScratch->appendUChar(message->msg_number);
|
||||
@ -8401,26 +8381,57 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GEN_parameter(dsqlScratch, statement->getEof());
|
||||
}
|
||||
|
||||
SelectNode* SelectNode::pass1(thread_db* tdbb, CompilerScratch* csb)
|
||||
|
||||
//--------------------
|
||||
|
||||
|
||||
static RegisterNode<SelectMessageNode> regSelectMessageNode({blr_select});
|
||||
|
||||
DmlNode* SelectMessageNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR /*blrOp*/)
|
||||
{
|
||||
for (NestConst<StmtNode>* i = statements.begin(); i != statements.end(); ++i)
|
||||
doPass1(tdbb, csb, i->getAddress());
|
||||
const auto node = FB_NEW_POOL(pool) SelectMessageNode(pool);
|
||||
|
||||
while (csb->csb_blr_reader.peekByte() != blr_end)
|
||||
{
|
||||
if (csb->csb_blr_reader.peekByte() != blr_receive)
|
||||
PAR_syntax_error(csb, "blr_receive");
|
||||
node->statements.add(PAR_parse_stmt(tdbb, csb));
|
||||
}
|
||||
|
||||
csb->csb_blr_reader.getByte(); // skip blr_end
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
string SelectMessageNode::internalPrint(NodePrinter& printer) const
|
||||
{
|
||||
StmtNode::internalPrint(printer);
|
||||
|
||||
NODE_PRINT(printer, statements);
|
||||
|
||||
return "SelectMessageNode";
|
||||
}
|
||||
|
||||
SelectMessageNode* SelectMessageNode::pass1(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
for (auto statement : statements)
|
||||
doPass1(tdbb, csb, statement.getAddress());
|
||||
return this;
|
||||
}
|
||||
|
||||
SelectNode* SelectNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
SelectMessageNode* SelectMessageNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
for (NestConst<StmtNode>* i = statements.begin(); i != statements.end(); ++i)
|
||||
doPass2(tdbb, csb, i->getAddress(), this);
|
||||
for (auto statement : statements)
|
||||
doPass2(tdbb, csb, statement.getAddress(), this);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Execute a SELECT statement. This is more than a little obscure.
|
||||
// Execute a blr_select statement. This is more than a little obscure.
|
||||
// We first set up the SELECT statement as the "message" and stall on receive (waiting for user send).
|
||||
// EXE_send will then loop thru the sub-statements of select looking for the appropriate RECEIVE
|
||||
// statement. When (or if) it finds it, it will set it up the next statement to be executed.
|
||||
// The RECEIVE, then, will be entered with the operation "req_proceed".
|
||||
const StmtNode* SelectNode::execute(thread_db* /*tdbb*/, Request* request, ExeState* /*exeState*/) const
|
||||
const StmtNode* SelectMessageNode::execute(thread_db* /*tdbb*/, Request* request, ExeState* /*exeState*/) const
|
||||
{
|
||||
switch (request->req_operation)
|
||||
{
|
||||
|
@ -1318,11 +1318,34 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class SelectNode final : public TypedNode<StmtNode, StmtNode::TYPE_SELECT>
|
||||
class SelectNode final : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_SELECT>
|
||||
{
|
||||
public:
|
||||
explicit SelectNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_SELECT>(pool),
|
||||
: TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_SELECT>(pool)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
Firebird::string internalPrint(NodePrinter& printer) const override;
|
||||
SelectNode* dsqlPass(DsqlCompilerScratch* dsqlScratch) override;
|
||||
void genBlr(DsqlCompilerScratch* dsqlScratch) override;
|
||||
|
||||
public:
|
||||
NestConst<SelectExprNode> selectExpr;
|
||||
NestConst<RseNode> rse;
|
||||
TriState optimizeForFirstRows;
|
||||
bool forUpdate = false;
|
||||
bool withLock = false;
|
||||
bool skipLocked = false;
|
||||
};
|
||||
|
||||
|
||||
class SelectMessageNode final : public TypedNode<StmtNode, StmtNode::TYPE_SELECT_MESSAGE>
|
||||
{
|
||||
public:
|
||||
explicit SelectMessageNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_SELECT_MESSAGE>(pool),
|
||||
statements(pool)
|
||||
{
|
||||
}
|
||||
@ -1330,21 +1353,25 @@ public:
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);
|
||||
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
virtual SelectNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual SelectNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual SelectNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const StmtNode* execute(thread_db* tdbb, Request* request, ExeState* exeState) const;
|
||||
Firebird::string internalPrint(NodePrinter& printer) const override;
|
||||
|
||||
SelectMessageNode* dsqlPass(DsqlCompilerScratch* dsqlScratch) override
|
||||
{
|
||||
fb_assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void genBlr(DsqlCompilerScratch* dsqlScratch) override
|
||||
{
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
SelectMessageNode* pass1(thread_db* tdbb, CompilerScratch* csb) override;
|
||||
SelectMessageNode* pass2(thread_db* tdbb, CompilerScratch* csb) override;
|
||||
const StmtNode* execute(thread_db* tdbb, Request* request, ExeState* exeState) const override;
|
||||
|
||||
public:
|
||||
NestConst<SelectExprNode> dsqlExpr;
|
||||
NestConst<RseNode> dsqlRse;
|
||||
Firebird::Array<NestConst<StmtNode>> statements;
|
||||
bool dsqlForUpdate = false;
|
||||
bool dsqlWithLock = false;
|
||||
bool dsqlSkipLocked = false;
|
||||
TriState dsqlOptimizeForFirstRows;
|
||||
};
|
||||
|
||||
|
||||
|
@ -5801,11 +5801,11 @@ select
|
||||
: select_expr for_update_clause lock_clause optimize_clause
|
||||
{
|
||||
SelectNode* node = newNode<SelectNode>();
|
||||
node->dsqlExpr = $1;
|
||||
node->dsqlForUpdate = $2;
|
||||
node->dsqlWithLock = $3.first;
|
||||
node->dsqlSkipLocked = $3.second;
|
||||
node->dsqlOptimizeForFirstRows = $4;
|
||||
node->selectExpr = $1;
|
||||
node->forUpdate = $2;
|
||||
node->withLock = $3.first;
|
||||
node->skipLocked = $3.second;
|
||||
node->optimizeForFirstRows = $4;
|
||||
$$ = node;
|
||||
}
|
||||
;
|
||||
|
@ -585,15 +585,15 @@ RseNode* PASS1_rse(DsqlCompilerScratch* dsqlScratch,
|
||||
DEV_BLKCHK(dsqlScratch, dsql_type_req);
|
||||
DEV_BLKCHK(input, dsql_type_nod);
|
||||
|
||||
const bool updateLock = select ? select->dsqlWithLock : false;
|
||||
const bool skipLocked = select ? select->dsqlSkipLocked : false;
|
||||
const bool updateLock = select ? select->withLock : false;
|
||||
const bool skipLocked = select ? select->skipLocked : false;
|
||||
|
||||
dsqlScratch->scopeLevel++;
|
||||
RseNode* node = pass1_rse(dsqlScratch, input, NULL, NULL, updateLock, skipLocked, 0);
|
||||
dsqlScratch->scopeLevel--;
|
||||
|
||||
if (select)
|
||||
node->firstRows = select->dsqlOptimizeForFirstRows;
|
||||
node->firstRows = select->optimizeForFirstRows;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -855,31 +855,24 @@ void EXE_send(thread_db* tdbb, Request* request, USHORT msg, ULONG length, const
|
||||
if (!(request->req_flags & req_active))
|
||||
ERR_post(Arg::Gds(isc_req_sync));
|
||||
|
||||
const StmtNode* message = NULL;
|
||||
const StmtNode* node;
|
||||
|
||||
if (request->req_operation != Request::req_receive)
|
||||
ERR_post(Arg::Gds(isc_req_sync));
|
||||
node = request->req_message;
|
||||
|
||||
jrd_tra* transaction = request->req_transaction;
|
||||
|
||||
const SelectNode* selectNode;
|
||||
const auto node = request->req_message;
|
||||
const StmtNode* message = nullptr;
|
||||
|
||||
if (nodeIs<MessageNode>(node))
|
||||
message = node;
|
||||
else if ((selectNode = nodeAs<SelectNode>(node)))
|
||||
else if (const auto* const selectMessageNode = nodeAs<SelectMessageNode>(node))
|
||||
{
|
||||
const NestConst<StmtNode>* ptr = selectNode->statements.begin();
|
||||
|
||||
for (const NestConst<StmtNode>* end = selectNode->statements.end(); ptr != end; ++ptr)
|
||||
for (const auto statement : selectMessageNode->statements)
|
||||
{
|
||||
const ReceiveNode* receiveNode = nodeAs<ReceiveNode>(*ptr);
|
||||
const auto receiveNode = nodeAs<ReceiveNode>(statement);
|
||||
message = receiveNode->message;
|
||||
|
||||
if (nodeAs<MessageNode>(message)->messageNumber == msg)
|
||||
{
|
||||
request->req_next = *ptr;
|
||||
request->req_next = statement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -887,7 +880,7 @@ void EXE_send(thread_db* tdbb, Request* request, USHORT msg, ULONG length, const
|
||||
else
|
||||
BUGCHECK(167); // msg 167 invalid SEND request
|
||||
|
||||
const Format* format = nodeAs<MessageNode>(message)->format;
|
||||
const auto format = nodeAs<MessageNode>(message)->format;
|
||||
|
||||
if (msg != nodeAs<MessageNode>(message)->messageNumber)
|
||||
ERR_post(Arg::Gds(isc_req_sync));
|
||||
@ -897,7 +890,7 @@ void EXE_send(thread_db* tdbb, Request* request, USHORT msg, ULONG length, const
|
||||
|
||||
memcpy(request->getImpure<UCHAR>(message->impureOffset), buffer, length);
|
||||
|
||||
execute_looper(tdbb, request, transaction, request->req_next, Request::req_proceed);
|
||||
execute_looper(tdbb, request, request->req_transaction, request->req_next, Request::req_proceed);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user