@@ -7536,7 +7536,11 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch,
75367536 else
75377537 {
75387538 values = doDsqlPass (dsqlScratch, dsqlValues, false );
7539- needSavePoint = SubSelectFinder::find (dsqlScratch->getPool (), values);
7539+ // If this INSERT belongs to some PSQL code block and has subqueries
7540+ // inside its VALUES part, signal the caller to create a savepoint frame.
7541+ // See bug #5613 (aka CORE-5337) for details.
7542+ needSavePoint = (dsqlScratch->flags & DsqlCompilerScratch::FLAG_BLOCK) &&
7543+ SubSelectFinder::find (dsqlScratch->getPool (), values);
75407544 }
75417545
75427546 // Process relation
@@ -7681,13 +7685,9 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch,
76817685StmtNode* StoreNode::dsqlPass (DsqlCompilerScratch* dsqlScratch)
76827686{
76837687 bool needSavePoint;
7684- StmtNode* node = SavepointEncloseNode::make (dsqlScratch->getPool (), dsqlScratch,
7685- internalDsqlPass (dsqlScratch, false , needSavePoint));
7688+ const auto node = internalDsqlPass (dsqlScratch, false , needSavePoint);
76867689
7687- if (!needSavePoint || nodeIs<SavepointEncloseNode>(node))
7688- return node;
7689-
7690- return FB_NEW_POOL (dsqlScratch->getPool ()) SavepointEncloseNode (dsqlScratch->getPool (), node);
7690+ return SavepointEncloseNode::make (dsqlScratch->getPool (), dsqlScratch, node, needSavePoint);
76917691}
76927692
76937693string StoreNode::internalPrint (NodePrinter& printer) const
@@ -8758,12 +8758,18 @@ DmlNode* SavepointEncloseNode::parse(thread_db* tdbb, MemoryPool& pool, Compiler
87588758 return node;
87598759}
87608760
8761- StmtNode* SavepointEncloseNode::make (MemoryPool& pool, DsqlCompilerScratch* dsqlScratch, StmtNode* node)
8761+ StmtNode* SavepointEncloseNode::make (MemoryPool& pool, DsqlCompilerScratch* dsqlScratch, StmtNode* node, bool force )
87628762{
8763- // Add savepoint wrapper around the statement having error handlers
8763+ // Add savepoint wrapper around the statement having error handlers, or if requested explicitly
87648764
8765- return dsqlScratch->errorHandlers ?
8766- FB_NEW_POOL (pool) SavepointEncloseNode (pool, node) : node;
8765+ if (dsqlScratch->errorHandlers || force)
8766+ {
8767+ // Ensure that savepoints are never created around a DSQL statement
8768+ fb_assert (dsqlScratch->flags & DsqlCompilerScratch::FLAG_BLOCK);
8769+ return FB_NEW_POOL (pool) SavepointEncloseNode (pool, node);
8770+ }
8771+
8772+ return node;
87678773}
87688774
87698775SavepointEncloseNode* SavepointEncloseNode::dsqlPass (DsqlCompilerScratch* dsqlScratch)
@@ -9417,7 +9423,7 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
94179423 if (!returning)
94189424 dsqlScratch->getDsqlStatement ()->setType (DsqlStatement::TYPE_INSERT);
94199425
9420- return SavepointEncloseNode::make (dsqlScratch->getPool (), dsqlScratch, node);
9426+ return SavepointEncloseNode::make (dsqlScratch->getPool (), dsqlScratch, node, needSavePoint );
94219427}
94229428
94239429string UpdateOrInsertNode::internalPrint (NodePrinter& printer) const
0 commit comments