8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 21:23:04 +01:00

Refactor: SelectNode dsqlPass / genBlr.

This commit is contained in:
Adriano dos Santos Fernandes 2023-09-18 20:27:13 -03:00
parent 0f083fd086
commit 8c57b29f1c
3 changed files with 78 additions and 67 deletions

View File

@ -4943,7 +4943,7 @@ ForNode* ForNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
dsqlScratch->cursors.push(dsqlCursor); dsqlScratch->cursors.push(dsqlCursor);
} }
else else
node->rse = dsqlSelect->dsqlPass(dsqlScratch)->rse; node->rse = dsqlSelect->dsqlProcess(dsqlScratch);
node->dsqlInto = dsqlPassArray(dsqlScratch, dsqlInto); node->dsqlInto = dsqlPassArray(dsqlScratch, dsqlInto);
@ -5576,7 +5576,7 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
dsqlSelect->selectExpr = selectExpr; dsqlSelect->selectExpr = selectExpr;
const auto mergeNode = FB_NEW_POOL(pool) MergeNode(pool); const auto mergeNode = FB_NEW_POOL(pool) MergeNode(pool);
mergeNode->rse = dsqlSelect->dsqlPass(dsqlScratch)->rse; mergeNode->rse = dsqlSelect->dsqlProcess(dsqlScratch);
// Get the already processed relations. // Get the already processed relations.
const auto processedRse = nodeAs<RseNode>(mergeNode->rse->dsqlStreams->items[0]); const auto processedRse = nodeAs<RseNode>(mergeNode->rse->dsqlStreams->items[0]);
@ -8189,7 +8189,7 @@ const StmtNode* StoreNode::store(thread_db* tdbb, Request* request, WhichTrigger
//-------------------- //--------------------
SelectNode* SelectNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) RseNode* SelectNode::dsqlProcess(DsqlCompilerScratch* dsqlScratch)
{ {
const auto statement = dsqlScratch->getDsqlStatement(); const auto statement = dsqlScratch->getDsqlStatement();
@ -8198,7 +8198,7 @@ SelectNode* SelectNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
node->optimizeForFirstRows = optimizeForFirstRows; node->optimizeForFirstRows = optimizeForFirstRows;
const DsqlContextStack::iterator base(*dsqlScratch->context); const DsqlContextStack::iterator base(*dsqlScratch->context);
node->rse = PASS1_rse(dsqlScratch, selectExpr, this); const auto processedRse = PASS1_rse(dsqlScratch, selectExpr, this);
dsqlScratch->context->clear(base); dsqlScratch->context->clear(base);
if (forUpdate) if (forUpdate)
@ -8212,10 +8212,76 @@ SelectNode* SelectNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
// stored procedure occurs in the select list. In these cases all of stored procedure is // stored procedure occurs in the select list. In these cases all of stored procedure is
// executed under savepoint for open cursor. // executed under savepoint for open cursor.
if (node->rse->dsqlOrder || node->rse->dsqlDistinct) if (processedRse->dsqlOrder || processedRse->dsqlDistinct)
statement->setFlags(statement->getFlags() & ~DsqlStatement::FLAG_NO_BATCH); statement->setFlags(statement->getFlags() & ~DsqlStatement::FLAG_NO_BATCH);
} }
return processedRse;
}
SelectNode* SelectNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
const auto statement = dsqlScratch->getDsqlStatement();
const auto node = FB_NEW_POOL(dsqlScratch->getPool()) SelectNode(dsqlScratch->getPool());
node->optimizeForFirstRows = optimizeForFirstRows;
node->forUpdate = forUpdate;
node->withLock = withLock;
node->skipLocked = skipLocked;
node->rse = dsqlProcess(dsqlScratch);
// Set up parameter for things in the select list.
for (auto item : node->rse->dsqlSelectList->items)
{
const auto parameter = MAKE_parameter(statement->getReceiveMsg(), true, true, 0, item);
parameter->par_node = item;
DsqlDescMaker::fromNode(dsqlScratch, &parameter->par_desc, item);
}
// Set up parameter to handle EOF.
const auto parameterEof = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, nullptr);
statement->setEof(parameterEof);
parameterEof->par_desc.dsc_dtype = dtype_short;
parameterEof->par_desc.dsc_scale = 0;
parameterEof->par_desc.dsc_length = sizeof(SSHORT);
// Save DBKEYs for possible update later.
if (forUpdate && !node->rse->dsqlDistinct)
{
for (const auto item : node->rse->dsqlStreams->items)
{
//// TODO: LocalTableSourceNode
if (auto relNode = nodeAs<RelationSourceNode>(item))
{
dsql_ctx* context = relNode->dsqlContext;
if (const auto* const relation = context->ctx_relation)
{
// Set up dbkey.
auto parameter = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, nullptr);
parameter->par_dbkey_relname = relation->rel_name;
parameter->par_context = context;
parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = relation->rel_dbkey_length;
// Set up record version.
parameter = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, nullptr);
parameter->par_rec_version_relname = relation->rel_name;
parameter->par_context = context;
parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = sizeof(SINT64);
}
}
}
}
return node; return node;
} }
@ -8236,64 +8302,8 @@ string SelectNode::internalPrint(NodePrinter& printer) const
// Generate BLR for a SELECT statement. // Generate BLR for a SELECT statement.
void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch) void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{ {
fb_assert(rse);
const auto statement = dsqlScratch->getDsqlStatement(); const auto statement = dsqlScratch->getDsqlStatement();
// Set up parameter for things in the select list.
for (auto item : rse->dsqlSelectList->items)
{
const auto parameter = MAKE_parameter(statement->getReceiveMsg(), true, true, 0, item);
parameter->par_node = item;
DsqlDescMaker::fromNode(dsqlScratch, &parameter->par_desc, item);
}
// Set up parameter to handle EOF.
const auto parameterEof = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, nullptr);
statement->setEof(parameterEof);
parameterEof->par_desc.dsc_dtype = dtype_short;
parameterEof->par_desc.dsc_scale = 0;
parameterEof->par_desc.dsc_length = sizeof(SSHORT);
// Save DBKEYs for possible update later.
NonPooledMap<dsql_par*, dsql_ctx*> paramContexts(*getDefaultMemoryPool());
if (forUpdate && !rse->dsqlDistinct)
{
for (const auto item : rse->dsqlStreams->items)
{
//// TODO: LocalTableSourceNode
if (auto relNode = nodeAs<RelationSourceNode>(item))
{
dsql_ctx* context = relNode->dsqlContext;
if (const auto* const relation = context->ctx_relation)
{
// Set up dbkey.
auto parameter = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, nullptr);
parameter->par_dbkey_relname = relation->rel_name;
paramContexts.put(parameter, context);
parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = relation->rel_dbkey_length;
// Set up record version.
parameter = MAKE_parameter(statement->getReceiveMsg(), false, false, 0, nullptr);
parameter->par_rec_version_relname = relation->rel_name;
paramContexts.put(parameter, context);
parameter->par_desc.dsc_dtype = dtype_text;
parameter->par_desc.dsc_ttype() = ttype_binary;
parameter->par_desc.dsc_length = sizeof(SINT64);
}
}
}
}
// Generate definitions for the messages. // Generate definitions for the messages.
GEN_port(dsqlScratch, statement->getReceiveMsg()); GEN_port(dsqlScratch, statement->getReceiveMsg());
@ -8348,21 +8358,19 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
GEN_parameter(dsqlScratch, parameter); GEN_parameter(dsqlScratch, parameter);
} }
dsql_ctx* context; if (parameter->par_dbkey_relname.hasData() && parameter->par_context)
if (parameter->par_dbkey_relname.hasData() && paramContexts.get(parameter, context))
{ {
dsqlScratch->appendUChar(blr_assignment); dsqlScratch->appendUChar(blr_assignment);
dsqlScratch->appendUChar(blr_dbkey); dsqlScratch->appendUChar(blr_dbkey);
GEN_stuff_context(dsqlScratch, context); GEN_stuff_context(dsqlScratch, parameter->par_context);
GEN_parameter(dsqlScratch, parameter); GEN_parameter(dsqlScratch, parameter);
} }
if (parameter->par_rec_version_relname.hasData() && paramContexts.get(parameter, context)) if (parameter->par_rec_version_relname.hasData() && parameter->par_context)
{ {
dsqlScratch->appendUChar(blr_assignment); dsqlScratch->appendUChar(blr_assignment);
dsqlScratch->appendUChar(blr_record_version); dsqlScratch->appendUChar(blr_record_version);
GEN_stuff_context(dsqlScratch, context); GEN_stuff_context(dsqlScratch, parameter->par_context);
GEN_parameter(dsqlScratch, parameter); GEN_parameter(dsqlScratch, parameter);
} }
} }

View File

@ -1326,6 +1326,8 @@ public:
} }
public: public:
RseNode* dsqlProcess(DsqlCompilerScratch* dsqlScratch);
Firebird::string internalPrint(NodePrinter& printer) const override; Firebird::string internalPrint(NodePrinter& printer) const override;
SelectNode* dsqlPass(DsqlCompilerScratch* dsqlScratch) override; SelectNode* dsqlPass(DsqlCompilerScratch* dsqlScratch) override;
void genBlr(DsqlCompilerScratch* dsqlScratch) override; void genBlr(DsqlCompilerScratch* dsqlScratch) override;

View File

@ -554,6 +554,7 @@ public:
dsql_msg* par_message = nullptr; // Parent message dsql_msg* par_message = nullptr; // Parent message
dsql_par* par_null = nullptr; // Null parameter, if used dsql_par* par_null = nullptr; // Null parameter, if used
ValueExprNode* par_node = nullptr; // Associated value node, if any ValueExprNode* par_node = nullptr; // Associated value node, if any
dsql_ctx* par_context = nullptr; // Context for SELECT FOR UPDATE
MetaName par_dbkey_relname; // Context of internally requested dbkey MetaName par_dbkey_relname; // Context of internally requested dbkey
MetaName par_rec_version_relname; // Context of internally requested rec. version MetaName par_rec_version_relname; // Context of internally requested rec. version
MetaName par_name; // Parameter name, if any MetaName par_name; // Parameter name, if any