TBoldUniDACConnection.CreateAnotherDatabaseConnection (Source/Persistence/UniDAC/BoldUniDACInterfaces.pas) creates a TUniConnection with no owner, assigns the current connection's settings to it and wraps it in a new TBoldUniDACConnection - but nothing ever frees that TUniConnection. The code itself carries the question: TUniConnection.Create(nil); // owner ?. Found while fixing #90.
Symptom
Every extra connection handed out by CreateAnotherDatabaseConnection leaks its TUniConnection (and the provider objects behind it) when the wrapper is freed. Users of the path: TBoldDbCopy (one per source and destination), the threaded DB validator (one per worker), and any application code that wants a second connection on the same settings.
Root cause
The FireDAC adapter solves the same lifetime with an ownership flag: TBoldFireDACConnection.CreateAnotherDatabaseConnection sets fOwnsConnection := True on the new wrapper and Destroy frees the TFDConnection when the flag is set. The UniDAC adapter has no such flag; its destructor only releases the cached objects (#90) and leaves fUniConnection alone - correct for the normal case, where the component belongs to the TBoldDatabaseAdapterUniDAC, wrong for the connection the wrapper created itself.
Separate from this issue: the callers themselves (TBoldDbCopy, TBoldDbValidator worker) drop the returned interface without freeing the wrapper object, which is not reference counted - so the wrapper leaks on both adapters regardless. That is a caller-side defect and is not changed here.
Fix
TBoldUniDACConnection: add fOwnsConnection; CreateAnotherDatabaseConnection sets it on the wrapper it returns; Destroy frees fUniConnection when it is set. Same shape as the FireDAC adapter.
Files changed
Testing
TBoldUniDACConnection.CreateAnotherDatabaseConnection(Source/Persistence/UniDAC/BoldUniDACInterfaces.pas) creates aTUniConnectionwith no owner, assigns the current connection's settings to it and wraps it in a newTBoldUniDACConnection- but nothing ever frees thatTUniConnection. The code itself carries the question:TUniConnection.Create(nil); // owner ?. Found while fixing #90.Symptom
Every extra connection handed out by
CreateAnotherDatabaseConnectionleaks itsTUniConnection(and the provider objects behind it) when the wrapper is freed. Users of the path:TBoldDbCopy(one per source and destination), the threaded DB validator (one per worker), and any application code that wants a second connection on the same settings.Root cause
The FireDAC adapter solves the same lifetime with an ownership flag:
TBoldFireDACConnection.CreateAnotherDatabaseConnectionsetsfOwnsConnection := Trueon the new wrapper andDestroyfrees theTFDConnectionwhen the flag is set. The UniDAC adapter has no such flag; its destructor only releases the cached objects (#90) and leavesfUniConnectionalone - correct for the normal case, where the component belongs to theTBoldDatabaseAdapterUniDAC, wrong for the connection the wrapper created itself.Separate from this issue: the callers themselves (
TBoldDbCopy,TBoldDbValidatorworker) drop the returned interface without freeing the wrapper object, which is not reference counted - so the wrapper leaks on both adapters regardless. That is a caller-side defect and is not changed here.Fix
TBoldUniDACConnection: addfOwnsConnection;CreateAnotherDatabaseConnectionsets it on the wrapper it returns;DestroyfreesfUniConnectionwhen it is set. Same shape as the FireDAC adapter.Files changed
Source/Persistence/UniDAC/BoldUniDACInterfaces.pasUnitTest/Code/Persistence/UniDAC/Test.PersistenceUniDAC.pas(regression test,DebugUniDACconfiguration, Compile and run the UniDAC adapter tests without requiring UniDAC (stub units + DebugUniDAC configuration) #89)Testing
TestCreateAnotherDatabaseConnectionOwnsItsConnection- create and free an extra connection throughIBoldDatabase; after a warm-up pass the allocated-block count must not grow — failed withallocated blocks grew by 380(TUniConnection x 2and its transaction/option objects in the FastMM report)Test.PersistenceUniDAC7/7 on SQL Server, no FastMM shutdown reportDebugbuild unaffected (UniDAC sources are not on its path)