mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 22:43:04 +01:00
Generate savepoint around blr_store for non-cursor INSERT's (INSERT INTO ... VALUES (...) ) with sub-select in VALUES list.
It fixes bug CORE-5337 : The subquery in the insert list expressions ignore the changes made earlier in the same executable block. Note, existing procedures and triggers should be recompiled to have new BLR code.
This commit is contained in:
parent
58dafb5ba2
commit
d5ff6d82c2
@ -5329,7 +5329,8 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
store->dsqlFields = notMatched->fields;
|
||||
store->dsqlValues = notMatched->values;
|
||||
|
||||
thisIf->trueAction = store = store->internalDsqlPass(dsqlScratch, false)->as<StoreNode>();
|
||||
bool needSavePoint; // unused
|
||||
thisIf->trueAction = store = store->internalDsqlPass(dsqlScratch, false, needSavePoint)->as<StoreNode>();
|
||||
fb_assert(store);
|
||||
|
||||
if (notMatched->condition)
|
||||
@ -6436,7 +6437,7 @@ DmlNode* StoreNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* cs
|
||||
return node;
|
||||
}
|
||||
|
||||
StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool updateOrInsert)
|
||||
StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool updateOrInsert, bool& needSavePoint)
|
||||
{
|
||||
thread_db* tdbb = JRD_get_thread_data(); // necessary?
|
||||
DsqlContextStack::AutoRestore autoContext(*dsqlScratch->context);
|
||||
@ -6460,9 +6461,13 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool upd
|
||||
RseNode* rse = PASS1_rse(dsqlScratch, selExpr, false);
|
||||
node->dsqlRse = rse;
|
||||
values = rse->dsqlSelectList;
|
||||
needSavePoint = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
values = doDsqlPass(dsqlScratch, dsqlValues, false);
|
||||
needSavePoint = SubSelectFinder::find(values);
|
||||
}
|
||||
|
||||
// Process relation
|
||||
|
||||
@ -6598,7 +6603,14 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool upd
|
||||
|
||||
StmtNode* StoreNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
return SavepointEncloseNode::make(getPool(), dsqlScratch, internalDsqlPass(dsqlScratch, false));
|
||||
bool needSavePoint;
|
||||
StmtNode* node = SavepointEncloseNode::make(getPool(), dsqlScratch,
|
||||
internalDsqlPass(dsqlScratch, false, needSavePoint));
|
||||
|
||||
if (!needSavePoint || node->is<SavepointEncloseNode>())
|
||||
return node;
|
||||
|
||||
return FB_NEW SavepointEncloseNode(getPool(), node);
|
||||
}
|
||||
|
||||
string StoreNode::internalPrint(NodePrinter& printer) const
|
||||
@ -7979,13 +7991,15 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
const MetaName& relation_name = relation->as<RelationSourceNode>()->dsqlName;
|
||||
MetaName base_name = relation_name;
|
||||
|
||||
bool needSavePoint;
|
||||
|
||||
// Build the INSERT node.
|
||||
StoreNode* insert = FB_NEW_POOL(pool) StoreNode(pool);
|
||||
insert->dsqlRelation = relation;
|
||||
insert->dsqlFields = fields;
|
||||
insert->dsqlValues = values;
|
||||
insert->dsqlReturning = returning;
|
||||
insert = insert->internalDsqlPass(dsqlScratch, true)->as<StoreNode>();
|
||||
insert = insert->internalDsqlPass(dsqlScratch, true, needSavePoint)->as<StoreNode>();
|
||||
fb_assert(insert);
|
||||
|
||||
dsql_ctx* context = insert->dsqlRelation->dsqlContext;
|
||||
@ -8165,7 +8179,11 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
if (!returning)
|
||||
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_INSERT);
|
||||
|
||||
return SavepointEncloseNode::make(getPool(), dsqlScratch, list);
|
||||
StmtNode* ret = SavepointEncloseNode::make(getPool(), dsqlScratch, list);
|
||||
if (!needSavePoint || ret->is<SavepointEncloseNode>())
|
||||
return ret;
|
||||
|
||||
return FB_NEW SavepointEncloseNode(getPool(), ret);
|
||||
}
|
||||
|
||||
string UpdateOrInsertNode::internalPrint(NodePrinter& printer) const
|
||||
|
@ -1244,7 +1244,7 @@ public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);
|
||||
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
StmtNode* internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool updateOrInsert);
|
||||
StmtNode* internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool updateOrInsert, bool& needSavePoint);
|
||||
virtual StmtNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual StoreNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
|
Loading…
Reference in New Issue
Block a user