11using System ;
2- using System . Collections . Generic ;
32using System . Linq ;
4- using System . Text . RegularExpressions ;
3+ using System . Text ;
54using System . Threading ;
65using System . Threading . Tasks ;
76using DotNetProjects . Migrator . Framework . Data . Common ;
1918
2019namespace Migrator . Tests . Database . DerivedDatabaseIntegrationTestServices ;
2120
21+
22+ /// <summary>
23+ /// We use the tablespace users since the server container is recreated before the test runs (once per github workflow run)
24+ /// </summary>
25+ /// <param name="timeProvider"></param>
26+ /// <param name="databaseNameService"></param>
2227public class OracleDatabaseIntegrationTestService (
2328 TimeProvider timeProvider ,
2429 IDatabaseNameService databaseNameService )
2530 : DatabaseIntegrationTestServiceBase ( databaseNameService ) , IDatabaseIntegrationTestService
2631{
27- private const string TableSpacePrefix = "TS_" ;
2832 private const string UserStringKey = "User Id" ;
2933 private const string PasswordStringKey = "Password" ;
3034 private const string ReplaceString = "RandomStringThatIsNotQuotedByTheBuilderDoNotChange" ;
3135 private readonly MappingSchema _mappingSchema = new MappingSchemaFactory ( ) . CreateOracleMappingSchema ( ) ;
32- private Regex _tablespaceRegex = new ( "^TS_TESTS_" ) ;
3336
3437 /// <summary>
3538 /// Creates an oracle database for test purposes.
@@ -61,8 +64,6 @@ public class OracleDatabaseIntegrationTestService(
6164 /// <exception cref="NotImplementedException"></exception>
6265 public override async Task < DatabaseInfo > CreateTestDatabaseAsync ( DatabaseConnectionConfig databaseConnectionConfig , CancellationToken cancellationToken )
6366 {
64- DataConnection context ;
65-
6667 var tempDatabaseConnectionConfig = databaseConnectionConfig . Adapt < DatabaseConnectionConfig > ( ) ;
6768
6869 var connectionStringBuilder = new OracleConnectionStringBuilder ( )
@@ -82,15 +83,12 @@ public override async Task<DatabaseInfo> CreateTestDatabaseAsync(DatabaseConnect
8283
8384 var tempUserName = DatabaseNameService . CreateDatabaseName ( ) ;
8485
85- List < string > userNames ;
86-
8786 var dataOptions = new DataOptions ( ) . UseOracle ( databaseConnectionConfig . ConnectionString )
8887 . UseMappingSchema ( _mappingSchema ) ;
8988
90- using ( context = new DataConnection ( dataOptions ) )
91- {
92- userNames = await context . QueryToListAsync < string > ( "SELECT username FROM all_users" , cancellationToken ) ;
93- }
89+ using var context = new DataConnection ( dataOptions ) ;
90+
91+ var userNames = await context . GetTable < AllUsers > ( ) . Select ( x => x . UserName ) . ToListAsync ( cancellationToken ) ;
9492
9593 var toBeDeletedUsers = userNames . Where ( x =>
9694 {
@@ -112,49 +110,33 @@ await Parallel.ForEachAsync(
112110 } ;
113111
114112 await DropDatabaseAsync ( databaseInfoToBeDeleted , cancellationTokenInner ) ;
115-
116113 } ) ;
117114
118- using ( context = new DataConnection ( dataOptions ) )
119- {
120- // To be on the safe side we check for table spaces used in tests that have not been deleted for any reason (possible connection issues/concurrent deletion attempts - there is
121- // no transaction for DDL in Oracle etc.).
122- var tableSpaceNames = await context . GetTable < DBADataFiles > ( )
123- . Select ( x => x . TablespaceName )
124- . ToListAsync ( cancellationToken ) ;
125-
126- var toBeDeletedTableSpaces = tableSpaceNames
127- . Where ( x =>
128- {
129- var replacedTablespaceString = _tablespaceRegex . Replace ( x , "" ) ;
130- var creationDate = DatabaseNameService . ReadTimeStampFromString ( replacedTablespaceString ) ;
131- return creationDate . HasValue && creationDate . Value < timeProvider . GetUtcNow ( ) . Subtract ( _MinTimeSpanBeforeDatabaseDeletion ) ;
132- } ) ;
115+ var stringBuilder = new StringBuilder ( ) ;
116+ stringBuilder . Append ( $ "CREATE USER \" { tempUserName } \" IDENTIFIED BY \" { tempUserName } \" ") ;
117+ stringBuilder . AppendLine ( $ "DEFAULT TABLESPACE users") ;
118+ stringBuilder . AppendLine ( $ "TEMPORARY TABLESPACE TEMP") ;
119+ stringBuilder . AppendLine ( $ "QUOTA UNLIMITED ON users") ;
133120
134- foreach ( var toBeDeletedTableSpace in toBeDeletedTableSpaces )
135- {
136- await context . ExecuteAsync ( $ "DROP TABLESPACE { toBeDeletedTableSpace } INCLUDING CONTENTS AND DATAFILES", cancellationToken ) ;
137- }
121+ await context . ExecuteAsync ( stringBuilder . ToString ( ) , cancellationToken ) ;
138122
139- await context . ExecuteAsync ( $ "CREATE USER \" { tempUserName } \" IDENTIFIED BY \" { tempUserName } \" ", cancellationToken ) ;
123+ var privileges = new [ ]
124+ {
125+ "CONNECT" ,
126+ "CREATE SESSION" ,
127+ "RESOURCE" ,
128+ "UNLIMITED TABLESPACE"
129+ } ;
140130
141- var privileges = new [ ]
142- {
143- "CONNECT" ,
144- "CREATE SESSION" ,
145- "RESOURCE" ,
146- "UNLIMITED TABLESPACE"
147- } ;
148-
149- await context . ExecuteAsync ( $ "GRANT { string . Join ( ", " , privileges ) } TO \" { tempUserName } \" ", cancellationToken ) ;
150- await context . ExecuteAsync ( $ "GRANT SELECT ON SYS.V_$SESSION TO \" { tempUserName } \" ", cancellationToken ) ;
151- }
131+ await context . ExecuteAsync ( $ "GRANT { string . Join ( ", " , privileges ) } TO \" { tempUserName } \" ", cancellationToken ) ;
132+ await context . ExecuteAsync ( $ "GRANT SELECT ON SYS.GV_$SESSION TO \" { tempUserName } \" ", cancellationToken ) ;
152133
153134 connectionStringBuilder . Add ( UserStringKey , ReplaceString ) ;
154135 connectionStringBuilder . Add ( PasswordStringKey , ReplaceString ) ;
155136
156137 tempDatabaseConnectionConfig . ConnectionString = connectionStringBuilder . ConnectionString ;
157138 tempDatabaseConnectionConfig . ConnectionString = tempDatabaseConnectionConfig . ConnectionString . Replace ( ReplaceString , $ "\" { tempUserName } \" ") ;
139+ tempDatabaseConnectionConfig . Schema = tempUserName ;
158140
159141 var databaseInfo = new DatabaseInfo
160142 {
@@ -168,16 +150,18 @@ await Parallel.ForEachAsync(
168150
169151 public override async Task DropDatabaseAsync ( DatabaseInfo databaseInfo , CancellationToken cancellationToken )
170152 {
153+ ArgumentNullException . ThrowIfNull ( databaseInfo ) ;
154+
171155 var creationDate = ReadTimeStampFromDatabaseName ( databaseInfo . SchemaName ) ;
172156
173157 var dataOptions = new DataOptions ( ) . UseOracle ( databaseInfo . DatabaseConnectionConfigMaster . ConnectionString )
174158 . UseMappingSchema ( _mappingSchema ) ;
175159
160+ using var context = new DataConnection ( dataOptions ) ;
161+
176162 var maxAttempts = 4 ;
177163 var delayBetweenAttempts = TimeSpan . FromSeconds ( 1 ) ;
178164
179- using var context = new DataConnection ( dataOptions ) ;
180-
181165 for ( var i = 0 ; i < maxAttempts ; i ++ )
182166 {
183167 try
@@ -192,6 +176,13 @@ public override async Task DropDatabaseAsync(DatabaseInfo databaseInfo, Cancella
192176 await context . ExecuteAsync ( killStatement , cancellationToken ) ;
193177 }
194178
179+ var userExists = context . GetTable < AllUsers > ( ) . Any ( x => x . UserName == databaseInfo . SchemaName ) ;
180+
181+ if ( ! userExists )
182+ {
183+ break ;
184+ }
185+
195186 await context . ExecuteAsync ( $ "DROP USER \" { databaseInfo . SchemaName } \" CASCADE", cancellationToken ) ;
196187 }
197188 catch
@@ -207,19 +198,13 @@ public override async Task DropDatabaseAsync(DatabaseInfo databaseInfo, Cancella
207198 {
208199 break ;
209200 }
210- }
211201
212- await Task . Delay ( delayBetweenAttempts , cancellationToken ) ;
202+ await Task . Delay ( delayBetweenAttempts , cancellationToken ) ;
213203
214- delayBetweenAttempts = delayBetweenAttempts . Add ( TimeSpan . FromSeconds ( 1 ) ) ;
204+ delayBetweenAttempts = delayBetweenAttempts . Add ( TimeSpan . FromSeconds ( 1 ) ) ;
205+ }
215206 }
216207
217- var tablespaceName = $ "{ TableSpacePrefix } { databaseInfo . SchemaName } ";
218-
219- var tablespaces = await context . GetTable < DBADataFiles > ( ) . ToListAsync ( cancellationToken ) ;
220-
221- await context . ExecuteAsync ( $ "DROP TABLESPACE { tablespaceName } INCLUDING CONTENTS AND DATAFILES", cancellationToken ) ;
222-
223208 await context . ExecuteAsync ( $ "PURGE RECYCLEBIN", cancellationToken ) ;
224209 }
225- }
210+ }
0 commit comments