@@ -2410,6 +2410,9 @@ void EraseNode::genBlr(DsqlCompilerScratch* dsqlScratch)
24102410 GEN_port (dsqlScratch, dsqlScratch->recordKeyMessage );
24112411
24122412 std::optional<USHORT> tableNumber;
2413+ const bool useInternalAutoTrans =
2414+ (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK) &&
2415+ dsqlReturning && !dsqlScratch->isPsql () && dsqlCursorName.isEmpty ();
24132416
24142417 const bool skipLocked = dsqlRse && dsqlRse->hasSkipLocked ();
24152418
@@ -2430,6 +2433,13 @@ void EraseNode::genBlr(DsqlCompilerScratch* dsqlScratch)
24302433 }
24312434 }
24322435
2436+ if (useInternalAutoTrans)
2437+ {
2438+ dsqlScratch->appendUChar (blr_auto_trans);
2439+ dsqlScratch->appendUChar (0 );
2440+ dsqlScratch->appendUChar (blr_begin);
2441+ }
2442+
24332443 if (dsqlRse)
24342444 {
24352445 dsqlScratch->appendUChar (blr_for);
@@ -2460,6 +2470,9 @@ void EraseNode::genBlr(DsqlCompilerScratch* dsqlScratch)
24602470
24612471 if (!dsqlScratch->isPsql () && dsqlCursorName.isEmpty ())
24622472 {
2473+ if (useInternalAutoTrans)
2474+ dsqlScratch->appendUChar (blr_end);
2475+
24632476 dsqlGenReturningLocalTableCursor (dsqlScratch, dsqlReturning, tableNumber.value ());
24642477
24652478 if (!skipLocked)
@@ -4713,16 +4726,12 @@ DmlNode* InAutonomousTransactionNode::parse(thread_db* tdbb, MemoryPool& pool, C
47134726
47144727InAutonomousTransactionNode* InAutonomousTransactionNode::dsqlPass (DsqlCompilerScratch* dsqlScratch)
47154728{
4716- const bool autoTrans = dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK;
4717- dsqlScratch->flags |= DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK;
4729+ AutoSetRestoreFlag autoTrans (&dsqlScratch->flags , DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK, true );
47184730
47194731 InAutonomousTransactionNode* node = FB_NEW_POOL (dsqlScratch->getPool ()) InAutonomousTransactionNode (
47204732 dsqlScratch->getPool ());
47214733 node->action = action->dsqlPass (dsqlScratch);
47224734
4723- if (!autoTrans)
4724- dsqlScratch->flags &= ~DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK;
4725-
47264735 return node;
47274736}
47284737
@@ -4737,9 +4746,33 @@ string InAutonomousTransactionNode::internalPrint(NodePrinter& printer) const
47374746
47384747void InAutonomousTransactionNode::genBlr (DsqlCompilerScratch* dsqlScratch)
47394748{
4740- dsqlScratch->appendUChar (blr_auto_trans);
4741- dsqlScratch->appendUChar (0 ); // to extend syntax in the future
4742- action->genBlr (dsqlScratch);
4749+ bool useInternalAutoTrans = false ;
4750+
4751+ if (dsqlScratch && !dsqlScratch->isPsql ())
4752+ {
4753+ if (const auto modifyNode = nodeAs<ModifyNode>(action))
4754+ useInternalAutoTrans = modifyNode->dsqlReturning && modifyNode->dsqlCursorName .isEmpty ();
4755+ else if (const auto eraseNode = nodeAs<EraseNode>(action))
4756+ useInternalAutoTrans = eraseNode->dsqlReturning && eraseNode->dsqlCursorName .isEmpty ();
4757+ else if (const auto storeNode = nodeAs<StoreNode>(action))
4758+ useInternalAutoTrans = storeNode->dsqlReturning != nullptr ;
4759+ else if (const auto updateOrInsertNode = nodeAs<UpdateOrInsertNode>(action))
4760+ useInternalAutoTrans = updateOrInsertNode->returning != nullptr ;
4761+ else if (const auto mergeNode = nodeAs<MergeNode>(action))
4762+ useInternalAutoTrans = mergeNode->returning != nullptr ;
4763+ }
4764+
4765+ if (useInternalAutoTrans)
4766+ {
4767+ AutoSetRestoreFlag autoTrans (&dsqlScratch->flags , DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK, true );
4768+ action->genBlr (dsqlScratch);
4769+ }
4770+ else
4771+ {
4772+ dsqlScratch->appendUChar (blr_auto_trans);
4773+ dsqlScratch->appendUChar (0 ); // to extend syntax in the future
4774+ action->genBlr (dsqlScratch);
4775+ }
47434776}
47444777
47454778InAutonomousTransactionNode* InAutonomousTransactionNode::pass1 (thread_db* tdbb, CompilerScratch* csb)
@@ -7246,6 +7279,9 @@ string MergeNode::internalPrint(NodePrinter& printer) const
72467279void MergeNode::genBlr (DsqlCompilerScratch* dsqlScratch)
72477280{
72487281 std::optional<USHORT> tableNumber;
7282+ const bool useInternalAutoTrans =
7283+ (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK) &&
7284+ returning && !dsqlScratch->isPsql ();
72497285
72507286 if (returning && !dsqlScratch->isPsql ())
72517287 {
@@ -7255,6 +7291,13 @@ void MergeNode::genBlr(DsqlCompilerScratch* dsqlScratch)
72557291 dsqlGenReturningLocalTableDecl (dsqlScratch, tableNumber.value ());
72567292 }
72577293
7294+ if (useInternalAutoTrans)
7295+ {
7296+ dsqlScratch->appendUChar (blr_auto_trans);
7297+ dsqlScratch->appendUChar (0 );
7298+ dsqlScratch->appendUChar (blr_begin);
7299+ }
7300+
72587301 // Put src info for blr_for.
72597302 if (hasLineColumn)
72607303 dsqlScratch->putDebugSrcInfo (line, column);
@@ -7493,6 +7536,9 @@ void MergeNode::genBlr(DsqlCompilerScratch* dsqlScratch)
74937536 dsqlScratch->appendUChar (blr_end);
74947537 }
74957538
7539+ if (useInternalAutoTrans)
7540+ dsqlScratch->appendUChar (blr_end);
7541+
74967542 if (returning && !dsqlScratch->isPsql ())
74977543 {
74987544 dsqlGenReturningLocalTableCursor (dsqlScratch, returning, tableNumber.value ());
@@ -7949,6 +7995,15 @@ string ModifyNode::internalPrint(NodePrinter& printer) const
79497995
79507996void ModifyNode::genBlr (DsqlCompilerScratch* dsqlScratch)
79517997{
7998+ const bool useInternalAutoTrans =
7999+ (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK) &&
8000+ dsqlReturning && !dsqlScratch->isPsql () && dsqlCursorName.isEmpty () &&
8001+ dsqlReturningLocalTableNumber.has_value () &&
8002+ !(dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT);
8003+ const bool deferUpdateOrInsertLocalTableDecl =
8004+ (dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT) &&
8005+ (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK);
8006+
79528007 if (dsqlScratch->recordKeyMessage )
79538008 {
79548009 GEN_port (dsqlScratch, dsqlScratch->recordKeyMessage );
@@ -7957,14 +8012,24 @@ void ModifyNode::genBlr(DsqlCompilerScratch* dsqlScratch)
79578012 if (dsqlReturning && !dsqlScratch->isPsql ())
79588013 {
79598014 if (dsqlCursorName.isEmpty ())
7960- dsqlGenReturningLocalTableDecl (dsqlScratch, dsqlReturningLocalTableNumber.value ());
8015+ {
8016+ if (!deferUpdateOrInsertLocalTableDecl)
8017+ dsqlGenReturningLocalTableDecl (dsqlScratch, dsqlReturningLocalTableNumber.value ());
8018+ }
79618019 else
79628020 {
79638021 dsqlScratch->appendUChar (blr_send);
79648022 dsqlScratch->appendUChar (dsqlScratch->getDsqlStatement ()->getReceiveMsg ()->msg_number );
79658023 }
79668024 }
79678025
8026+ if (useInternalAutoTrans)
8027+ {
8028+ dsqlScratch->appendUChar (blr_auto_trans);
8029+ dsqlScratch->appendUChar (0 );
8030+ dsqlScratch->appendUChar (blr_begin);
8031+ }
8032+
79688033 if (dsqlRse)
79698034 {
79708035 dsqlScratch->appendUChar (blr_for);
@@ -8002,6 +8067,9 @@ void ModifyNode::genBlr(DsqlCompilerScratch* dsqlScratch)
80028067 !(dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT) &&
80038068 dsqlCursorName.isEmpty ())
80048069 {
8070+ if (useInternalAutoTrans)
8071+ dsqlScratch->appendUChar (blr_end);
8072+
80058073 dsqlGenReturningLocalTableCursor (dsqlScratch, dsqlReturning, dsqlReturningLocalTableNumber.value ());
80068074 }
80078075 }
@@ -9002,6 +9070,11 @@ string StoreNode::internalPrint(NodePrinter& printer) const
90029070
90039071void StoreNode::genBlr (DsqlCompilerScratch* dsqlScratch)
90049072{
9073+ const bool useInternalAutoTrans =
9074+ (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK) &&
9075+ dsqlReturning && !dsqlScratch->isPsql () && dsqlReturningLocalTableNumber.has_value () &&
9076+ !(dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT);
9077+
90059078 if (dsqlReturning && !dsqlScratch->isPsql ())
90069079 {
90079080 if (dsqlRse)
@@ -9013,6 +9086,13 @@ void StoreNode::genBlr(DsqlCompilerScratch* dsqlScratch)
90139086 }
90149087 }
90159088
9089+ if (useInternalAutoTrans)
9090+ {
9091+ dsqlScratch->appendUChar (blr_auto_trans);
9092+ dsqlScratch->appendUChar (0 );
9093+ dsqlScratch->appendUChar (blr_begin);
9094+ }
9095+
90169096 if (dsqlRse)
90179097 {
90189098 dsqlScratch->appendUChar (blr_for);
@@ -9035,10 +9115,18 @@ void StoreNode::genBlr(DsqlCompilerScratch* dsqlScratch)
90359115
90369116 if (dsqlReturningLocalTableNumber.has_value ())
90379117 {
9118+ const bool deferUpdateOrInsertCursor =
9119+ (dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT) &&
9120+ (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK);
9121+
90389122 if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT)
90399123 dsqlScratch->appendUChar (blr_end); // close blr_if (blr_eql, blr_internal_info)
90409124
9041- dsqlGenReturningLocalTableCursor (dsqlScratch, dsqlReturning, dsqlReturningLocalTableNumber.value ());
9125+ if (useInternalAutoTrans)
9126+ dsqlScratch->appendUChar (blr_end);
9127+
9128+ if (!deferUpdateOrInsertCursor)
9129+ dsqlGenReturningLocalTableCursor (dsqlScratch, dsqlReturning, dsqlReturningLocalTableNumber.value ());
90429130 }
90439131 }
90449132 else if (overrideClause.has_value ())
@@ -10745,6 +10833,19 @@ string UpdateOrInsertNode::internalPrint(NodePrinter& printer) const
1074510833
1074610834void UpdateOrInsertNode::genBlr (DsqlCompilerScratch* dsqlScratch)
1074710835{
10836+ const bool useInternalAutoTrans =
10837+ (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK) &&
10838+ storeNode->dsqlReturningLocalTableNumber .has_value () && !dsqlScratch->isPsql ();
10839+
10840+ if (useInternalAutoTrans)
10841+ {
10842+ dsqlGenReturningLocalTableDecl (dsqlScratch, storeNode->dsqlReturningLocalTableNumber .value ());
10843+
10844+ dsqlScratch->appendUChar (blr_auto_trans);
10845+ dsqlScratch->appendUChar (0 );
10846+ dsqlScratch->appendUChar (blr_begin);
10847+ }
10848+
1074810849 dsqlScratch->appendUChar (blr_begin);
1074910850
1075010851 for (auto & varAssign : varAssignments)
@@ -10777,6 +10878,13 @@ void UpdateOrInsertNode::genBlr(DsqlCompilerScratch* dsqlScratch)
1077710878 dsqlScratch->appendUChar (blr_end); // blr_if
1077810879
1077910880 dsqlScratch->appendUChar (blr_end);
10881+
10882+ if (useInternalAutoTrans)
10883+ {
10884+ dsqlScratch->appendUChar (blr_end);
10885+ dsqlGenReturningLocalTableCursor (dsqlScratch, storeNode->dsqlReturning ,
10886+ storeNode->dsqlReturningLocalTableNumber .value ());
10887+ }
1078010888}
1078110889
1078210890
@@ -10959,21 +11067,23 @@ void UserSavepointNode::execute(thread_db* tdbb, DsqlRequest* request, jrd_tra**
1095911067
1096011068StmtNode* UsingNode::dsqlPass (DsqlCompilerScratch* dsqlScratch)
1096111069{
10962- // USING without parameters and subroutines is useless
10963- if (parameters.isEmpty () && !localDeclList)
11070+ // USING without parameters, subroutines or autonomous transaction is useless
11071+ if (parameters.isEmpty () && !localDeclList && !inAutonomousTransaction )
1096411072 {
1096511073 ERRD_post (Arg::Gds (isc_sqlerr) << Arg::Num (-104 ) <<
10966- Arg::Gds (isc_dsql_using_requires_params_subroutines ));
11074+ Arg::Gds (isc_dsql_using_statement_must_contain_clause ));
1096711075 }
1096811076
1096911077 dsqlScratch->flags |= DsqlCompilerScratch::FLAG_USING_STATEMENT;
11078+ dsqlScratch->reserveInitialVarNumbers (parameters.getCount ());
1097011079
1097111080 const auto statement = dsqlScratch->getDsqlStatement ();
1097211081 unsigned index = 0 ;
1097311082
1097411083 const auto node = FB_NEW_POOL (dsqlScratch->getPool ()) UsingNode (dsqlScratch->getPool ());
1097511084
1097611085 node->parameters = parameters;
11086+ node->inAutonomousTransaction = inAutonomousTransaction;
1097711087
1097811088 for (auto newParam : node->parameters )
1097911089 {
@@ -11036,6 +11146,7 @@ string UsingNode::internalPrint(NodePrinter& printer) const
1103611146 NODE_PRINT (printer, parameters);
1103711147 NODE_PRINT (printer, localDeclList);
1103811148 NODE_PRINT (printer, body);
11149+ NODE_PRINT (printer, inAutonomousTransaction);
1103911150
1104011151 return " UsingNode" ;
1104111152}
0 commit comments