Skip to content

Commit d5ff6d8

Browse files
committed
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.
1 parent 58dafb5 commit d5ff6d8

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

src/dsql/StmtNodes.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5329,7 +5329,8 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
53295329
store->dsqlFields = notMatched->fields;
53305330
store->dsqlValues = notMatched->values;
53315331

5332-
thisIf->trueAction = store = store->internalDsqlPass(dsqlScratch, false)->as<StoreNode>();
5332+
bool needSavePoint; // unused
5333+
thisIf->trueAction = store = store->internalDsqlPass(dsqlScratch, false, needSavePoint)->as<StoreNode>();
53335334
fb_assert(store);
53345335

53355336
if (notMatched->condition)
@@ -6436,7 +6437,7 @@ DmlNode* StoreNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* cs
64366437
return node;
64376438
}
64386439

6439-
StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool updateOrInsert)
6440+
StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool updateOrInsert, bool& needSavePoint)
64406441
{
64416442
thread_db* tdbb = JRD_get_thread_data(); // necessary?
64426443
DsqlContextStack::AutoRestore autoContext(*dsqlScratch->context);
@@ -6460,9 +6461,13 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool upd
64606461
RseNode* rse = PASS1_rse(dsqlScratch, selExpr, false);
64616462
node->dsqlRse = rse;
64626463
values = rse->dsqlSelectList;
6464+
needSavePoint = false;
64636465
}
64646466
else
6467+
{
64656468
values = doDsqlPass(dsqlScratch, dsqlValues, false);
6469+
needSavePoint = SubSelectFinder::find(values);
6470+
}
64666471

64676472
// Process relation
64686473

@@ -6598,7 +6603,14 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool upd
65986603

65996604
StmtNode* StoreNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
66006605
{
6601-
return SavepointEncloseNode::make(getPool(), dsqlScratch, internalDsqlPass(dsqlScratch, false));
6606+
bool needSavePoint;
6607+
StmtNode* node = SavepointEncloseNode::make(getPool(), dsqlScratch,
6608+
internalDsqlPass(dsqlScratch, false, needSavePoint));
6609+
6610+
if (!needSavePoint || node->is<SavepointEncloseNode>())
6611+
return node;
6612+
6613+
return FB_NEW SavepointEncloseNode(getPool(), node);
66026614
}
66036615

66046616
string StoreNode::internalPrint(NodePrinter& printer) const
@@ -7979,13 +7991,15 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
79797991
const MetaName& relation_name = relation->as<RelationSourceNode>()->dsqlName;
79807992
MetaName base_name = relation_name;
79817993

7994+
bool needSavePoint;
7995+
79827996
// Build the INSERT node.
79837997
StoreNode* insert = FB_NEW_POOL(pool) StoreNode(pool);
79847998
insert->dsqlRelation = relation;
79857999
insert->dsqlFields = fields;
79868000
insert->dsqlValues = values;
79878001
insert->dsqlReturning = returning;
7988-
insert = insert->internalDsqlPass(dsqlScratch, true)->as<StoreNode>();
8002+
insert = insert->internalDsqlPass(dsqlScratch, true, needSavePoint)->as<StoreNode>();
79898003
fb_assert(insert);
79908004

79918005
dsql_ctx* context = insert->dsqlRelation->dsqlContext;
@@ -8165,7 +8179,11 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
81658179
if (!returning)
81668180
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_INSERT);
81678181

8168-
return SavepointEncloseNode::make(getPool(), dsqlScratch, list);
8182+
StmtNode* ret = SavepointEncloseNode::make(getPool(), dsqlScratch, list);
8183+
if (!needSavePoint || ret->is<SavepointEncloseNode>())
8184+
return ret;
8185+
8186+
return FB_NEW SavepointEncloseNode(getPool(), ret);
81698187
}
81708188

81718189
string UpdateOrInsertNode::internalPrint(NodePrinter& printer) const

src/dsql/StmtNodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,7 @@ class StoreNode : public TypedNode<StmtNode, StmtNode::TYPE_STORE>
12441244
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);
12451245

12461246
virtual Firebird::string internalPrint(NodePrinter& printer) const;
1247-
StmtNode* internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool updateOrInsert);
1247+
StmtNode* internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool updateOrInsert, bool& needSavePoint);
12481248
virtual StmtNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
12491249
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
12501250
virtual StoreNode* pass1(thread_db* tdbb, CompilerScratch* csb);

0 commit comments

Comments
 (0)