1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.dbunit.database.search;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.junit.jupiter.api.Assertions.fail;
25
26 import java.io.File;
27 import java.sql.Connection;
28 import java.util.HashSet;
29 import java.util.Set;
30 import java.util.TreeSet;
31
32 import org.dbunit.AbstractDatabaseIT;
33 import org.dbunit.DdlExecutor;
34 import org.dbunit.HypersonicEnvironment;
35 import org.dbunit.database.DatabaseConnection;
36 import org.dbunit.database.PrimaryKeyFilter.PkTableMap;
37 import org.dbunit.dataset.IDataSet;
38 import org.dbunit.dataset.NoSuchTableException;
39 import org.dbunit.testutil.TestUtils;
40 import org.dbunit.util.search.SearchException;
41 import org.junit.jupiter.api.Test;
42
43
44
45
46
47
48
49 class TablesDependencyHelperIT extends AbstractDatabaseIT
50 {
51
52
53
54
55
56
57
58
59 private void refreshConnection() throws Exception
60 {
61 _connection.close();
62 _connection = getDatabaseTester().getConnection();
63 setUpDatabaseConfig(_connection.getConfig());
64 }
65
66
67 @Test
68 void testGetDependentTables_withSingleRootTable_returnsDependentTablesInFkOrder() throws Exception
69 {
70 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
71 "H", "F", "G", "A", "D");
72 DdlExecutor.executeDdlFile(
73 TestUtils.getFile(
74 "sql/" + ImportNodesFilterSearchCallbackIT.SQL_FILE),
75 _connection.getConnection(), false);
76 try
77 {
78 final String[][] allInput =
79 ImportNodesFilterSearchCallbackIT.SINGLE_INPUT;
80 final String[][] allExpectedOutput =
81 ImportNodesFilterSearchCallbackIT.SINGLE_OUTPUT;
82 for (int i = 0; i < allInput.length; i++)
83 {
84 final String[] input = allInput[i];
85 final String[] expectedOutput = allExpectedOutput[i];
86 final String[] actualOutput = TablesDependencyHelper
87 .getDependentTables(_connection, input[0]);
88 assertThat(actualOutput).as("output didn't match for i=" + i + ".")
89 .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
90 .containsExactly(expectedOutput);
91 }
92 }
93 finally
94 {
95 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
96 "H", "F", "G", "A", "D");
97 refreshConnection();
98 }
99 }
100
101 @Test
102 void testGetDependentTables_whenRootTableDoesNotExist_throwsSearchException()
103 throws Exception
104 {
105 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
106 "H", "F", "G", "A", "D");
107 DdlExecutor.executeDdlFile(
108 TestUtils.getFile(
109 "sql/" + ImportNodesFilterSearchCallbackIT.SQL_FILE),
110 _connection.getConnection(), false);
111 try
112 {
113 TablesDependencyHelper.getDependentTables(_connection,
114 "XXXXXX_TABLE_NON_EXISTING");
115 fail("Should not be able to get the dependent tables for a non existing input table");
116 }
117 catch (final SearchException expected)
118 {
119 final Throwable cause = expected.getCause();
120 assertThat(cause).isInstanceOf(NoSuchTableException.class);
121
122 final String expectedSchema =
123 getEnvironment().getProfile().getSchema();
124 final String expectedMessage =
125 "The table 'XXXXXX_TABLE_NON_EXISTING' does not exist in schema '"
126 + expectedSchema + "'";
127 assertThat(cause.getMessage())
128 .as("NoSuchTableException message.")
129 .isEqualToIgnoringCase(expectedMessage);
130 }
131 finally
132 {
133 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
134 "H", "F", "G", "A", "D");
135 refreshConnection();
136 }
137 }
138
139 @Test
140 void testGetDependentTables_withMultipleRootTables_returnsDependentTablesInFkOrder() throws Exception
141 {
142 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
143 "H", "F", "G", "A", "D");
144 DdlExecutor.executeDdlFile(
145 TestUtils.getFile(
146 "sql/" + ImportNodesFilterSearchCallbackIT.SQL_FILE),
147 _connection.getConnection(), false);
148 try
149 {
150 final String[][] allInput =
151 ImportNodesFilterSearchCallbackIT.COMPOUND_INPUT;
152 final String[][] allExpectedOutput =
153 ImportNodesFilterSearchCallbackIT.COMPOUND_OUTPUT;
154 for (int i = 0; i < allInput.length; i++)
155 {
156 final String[] input = allInput[i];
157 final String[] expectedOutput = allExpectedOutput[i];
158 final String[] actualOutput = TablesDependencyHelper
159 .getDependentTables(_connection, input);
160 assertThat(actualOutput).as("output didn't match for i=" + i + ".")
161 .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
162 .containsExactly(expectedOutput);
163 }
164 }
165 finally
166 {
167 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
168 "H", "F", "G", "A", "D");
169 refreshConnection();
170 }
171 }
172
173 @Test
174 void testGetAllDependentTables_withSingleRootTable_returnsAllDependentTablesInOrder() throws Exception
175 {
176 DdlExecutor.dropTables(_connection.getConnection(), "C", "D", "E",
177 "A", "B", "F");
178 DdlExecutor.executeDdlFile(
179 TestUtils.getFile(
180 "sql/" + ImportAndExportKeysSearchCallbackIT.SQL_FILE),
181 _connection.getConnection(), false);
182 try
183 {
184 final String[][] allInput =
185 ImportAndExportKeysSearchCallbackIT.SINGLE_INPUT;
186 final String[][] allExpectedOutput =
187 ImportAndExportKeysSearchCallbackIT.SINGLE_OUTPUT;
188 for (int i = 0; i < allInput.length; i++)
189 {
190 final String[] input = allInput[i];
191 final String[] expectedOutput = allExpectedOutput[i];
192 final String[] actualOutput = TablesDependencyHelper
193 .getAllDependentTables(_connection, input[0]);
194 assertThat(actualOutput).as("output didn't match for i=" + i + ".")
195 .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
196 .containsExactly(expectedOutput);
197 }
198 }
199 finally
200 {
201 DdlExecutor.dropTables(_connection.getConnection(), "C", "D", "E",
202 "A", "B", "F");
203 refreshConnection();
204 }
205 }
206
207 @Test
208 void testGetAllDependentTables_withMultipleRootTables_returnsAllDependentTablesInOrder() throws Exception
209 {
210 DdlExecutor.dropTables(_connection.getConnection(), "C", "D", "E",
211 "A", "B", "F");
212 DdlExecutor.executeDdlFile(
213 TestUtils.getFile(
214 "sql/" + ImportAndExportKeysSearchCallbackIT.SQL_FILE),
215 _connection.getConnection(), false);
216 try
217 {
218 final String[][] allInput =
219 ImportAndExportKeysSearchCallbackIT.COMPOUND_INPUT;
220 final String[][] allExpectedOutput =
221 ImportAndExportKeysSearchCallbackIT.COMPOUND_OUTPUT;
222 for (int i = 0; i < allInput.length; i++)
223 {
224 final String[] input = allInput[i];
225 final String[] expectedOutput = allExpectedOutput[i];
226 final String[] actualOutput = TablesDependencyHelper
227 .getAllDependentTables(_connection, input);
228 assertThat(actualOutput).as("output didn't match for i=" + i + ".")
229 .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
230 .containsExactly(expectedOutput);
231 }
232 }
233 finally
234 {
235 DdlExecutor.dropTables(_connection.getConnection(), "C", "D", "E",
236 "A", "B", "F");
237 refreshConnection();
238 }
239 }
240
241 @Test
242 void testGetDirectDependentTables_withMultiHopChain_excludesTransitivePrerequisites()
243 throws Exception
244 {
245 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
246 "H", "F", "G", "A", "D");
247 DdlExecutor.executeDdlFile(
248 TestUtils.getFile(
249 "sql/" + ImportNodesFilterSearchCallbackIT.SQL_FILE),
250 _connection.getConnection(), false);
251 try
252 {
253
254
255
256
257
258
259 final Set<String> actualOutput = TablesDependencyHelper
260 .getDirectDependentTables(_connection, "C");
261
262 assertThat(actualOutput)
263 .as("C's direct FK targets must be exactly {C, A, F}, "
264 + "excluding D which is only reachable transitively via A.")
265 .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
266 .containsExactlyInAnyOrder("C", "A", "F");
267 }
268 finally
269 {
270 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
271 "H", "F", "G", "A", "D");
272 refreshConnection();
273 }
274 }
275
276 @Test
277 void testGetDirectDependsOnTables_withMultiHopChain_excludesTransitiveDependents()
278 throws Exception
279 {
280 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
281 "H", "F", "G", "A", "D");
282 DdlExecutor.executeDdlFile(
283 TestUtils.getFile(
284 "sql/" + ImportNodesFilterSearchCallbackIT.SQL_FILE),
285 _connection.getConnection(), false);
286 try
287 {
288
289
290
291
292
293
294
295 final Set<String> actualOutput = TablesDependencyHelper
296 .getDirectDependsOnTables(_connection, "A");
297
298 assertThat(actualOutput)
299 .as("Tables with a direct FK to A must be exactly {A, C, E, G}, "
300 + "excluding B which only depends on A transitively via C.")
301 .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
302 .containsExactlyInAnyOrder("A", "C", "E", "G");
303 }
304 finally
305 {
306 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
307 "H", "F", "G", "A", "D");
308 refreshConnection();
309 }
310 }
311
312 @Test
313 void testGetAllDataset_withSingleTableInput_returnsDataSetContainingDependentTables() throws Exception
314 {
315 DdlExecutor.dropTables(_connection.getConnection(), "C", "D", "E",
316 "A", "B", "F");
317 DdlExecutor.executeDdlFile(
318 TestUtils.getFile(
319 "sql/" + ImportAndExportKeysSearchCallbackIT.SQL_FILE),
320 _connection.getConnection(), false);
321 try
322 {
323 final String[][] allInput =
324 ImportAndExportKeysSearchCallbackIT.SINGLE_INPUT;
325 final String[][] allExpectedOutput =
326 ImportAndExportKeysSearchCallbackIT.SINGLE_OUTPUT;
327 for (int i = 0; i < allInput.length; i++)
328 {
329 final String[] input = allInput[i];
330 final String[] expectedOutput = allExpectedOutput[i];
331 final IDataSet actualOutput = TablesDependencyHelper
332 .getAllDataset(_connection, input[0], new HashSet<>());
333 final String[] actualOutputTables =
334 actualOutput.getTableNames();
335 assertThat(actualOutputTables)
336 .as("output didn't match for i=" + i + ".")
337 .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
338 .containsExactly(expectedOutput);
339 }
340 }
341 finally
342 {
343 DdlExecutor.dropTables(_connection.getConnection(), "C", "D", "E",
344 "A", "B", "F");
345 refreshConnection();
346 }
347 }
348
349 @Test
350 void testGetAllDataset_withTableInSeparateSchema_returnsDataSetContainingDependentTables() throws Exception
351 {
352
353 final Connection hsqlConn =
354 HypersonicEnvironment.createJdbcConnection("mem:schema_test");
355 DdlExecutor.executeDdlFile(
356 TestUtils.getFile("sql/hypersonic_switch_schema.sql"),
357 hsqlConn, false);
358 DdlExecutor.executeDdlFile(
359 TestUtils.getFile(
360 "sql/" + ImportAndExportKeysSearchCallbackIT.SQL_FILE),
361 hsqlConn, false);
362 final org.dbunit.database.IDatabaseConnection hsqlDbConn =
363 new DatabaseConnection(hsqlConn);
364 try
365 {
366 final String[][] allInputWithSchema =
367 ImportAndExportKeysSearchCallbackIT
368 .getSingleInputWithSchema("TEST_SCHEMA");
369 final String[][] allExpectedOutput =
370 ImportAndExportKeysSearchCallbackIT.SINGLE_OUTPUT;
371 for (int i = 0; i < allInputWithSchema.length; i++)
372 {
373 final String[] input = allInputWithSchema[i];
374 final String[] expectedOutput = allExpectedOutput[i];
375 final IDataSet actualOutput = TablesDependencyHelper
376 .getAllDataset(hsqlDbConn, input[0], new HashSet<>());
377 final String[] actualOutputTables =
378 actualOutput.getTableNames();
379 assertThat(actualOutputTables)
380 .as("output didn't match for i=" + i + ".")
381 .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
382 .containsExactly(expectedOutput);
383 }
384 }
385 finally
386 {
387 DdlExecutor.dropTables(hsqlConn, "C", "D", "E", "A", "B", "F");
388 HypersonicEnvironment.shutdown(hsqlConn);
389 }
390 }
391
392
393
394
395
396
397
398 @Test
399 void testGetAllDataset_withMultipleTableInputs_returnsDataSetPreservingDependencyOrder() throws Exception
400 {
401 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
402 "H", "F", "G", "A", "D");
403 DdlExecutor.executeDdlFile(
404 TestUtils.getFile(
405 "sql/" + ImportNodesFilterSearchCallbackIT.SQL_FILE),
406 _connection.getConnection(), false);
407 try
408 {
409 final String[][] allInput =
410 ImportNodesFilterSearchCallbackIT.COMPOUND_INPUT;
411 final String[][] allExpectedOutput =
412 ImportNodesFilterSearchCallbackIT.COMPOUND_OUTPUT;
413 for (int i = 0; i < allInput.length; i++)
414 {
415 final String[] input = allInput[i];
416 final PkTableMap inputMap = new PkTableMap();
417 for (int j = 0; j < input.length; j++)
418 {
419 inputMap.put(input[j], new TreeSet<>());
420 }
421
422 final String[] expectedOutput = allExpectedOutput[i];
423 final IDataSet actualOutput = TablesDependencyHelper
424 .getDataset(_connection, inputMap);
425 final String[] actualOutputArray =
426 actualOutput.getTableNames();
427 assertThat(actualOutputArray)
428 .as("output didn't match for i=" + i + ".")
429 .usingElementComparator(String.CASE_INSENSITIVE_ORDER)
430 .containsExactly(expectedOutput);
431 }
432 }
433 finally
434 {
435 DdlExecutor.dropTables(_connection.getConnection(), "B", "C", "E",
436 "H", "F", "G", "A", "D");
437 refreshConnection();
438 }
439 }
440
441 }