View Javadoc
1   /*
2    *
3    * The DbUnit Database Testing Framework
4    * Copyright (C)2002-2004, DbUnit.org
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   */
21  package org.dbunit.operation;
22  
23  import static org.assertj.core.api.Assertions.assertThat;
24  import static org.junit.jupiter.api.Assertions.fail;
25  
26  import java.io.Reader;
27  import java.nio.charset.StandardCharsets;
28  import java.nio.file.Files;
29  
30  import org.dbunit.AbstractDatabaseIT;
31  import org.dbunit.Assertion;
32  import org.dbunit.DatabaseEnvironment;
33  import org.dbunit.TestFeature;
34  import org.dbunit.database.DatabaseConfig;
35  import org.dbunit.dataset.Column;
36  import org.dbunit.dataset.CompositeDataSet;
37  import org.dbunit.dataset.DefaultDataSet;
38  import org.dbunit.dataset.DefaultTable;
39  import org.dbunit.dataset.ForwardOnlyDataSet;
40  import org.dbunit.dataset.IDataSet;
41  import org.dbunit.dataset.ITable;
42  import org.dbunit.dataset.LowerCaseDataSet;
43  import org.dbunit.dataset.NoPrimaryKeyException;
44  import org.dbunit.dataset.datatype.DataType;
45  import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
46  import org.dbunit.dataset.xml.XmlDataSet;
47  import org.dbunit.testutil.TestUtils;
48  import org.junit.jupiter.api.Test;
49  
50  /**
51   * @author Manuel Laflamme
52   * @version $Revision$
53   * @since Feb 19, 2002
54   */
55  class UpdateOperationIT extends AbstractDatabaseIT
56  {
57  
58      ////////////////////////////////////////////////////////////////////////////
59      //
60  
61      @Override
62      protected IDataSet getDataSet() throws Exception
63      {
64          IDataSet dataSet = super.getDataSet();
65  
66          final DatabaseEnvironment environment =
67                  DatabaseEnvironment.getInstance();
68          if (environment.support(TestFeature.BLOB))
69          {
70              dataSet = new CompositeDataSet(
71                      new FlatXmlDataSetBuilder()
72                              .build(TestUtils.getFile("xml/blobInsertTest.xml")),
73                      dataSet);
74          }
75  
76          if (environment.support(TestFeature.CLOB))
77          {
78              dataSet = new CompositeDataSet(
79                      new FlatXmlDataSetBuilder()
80                              .build(TestUtils.getFile("xml/clobInsertTest.xml")),
81                      dataSet);
82          }
83  
84          if (environment.support(TestFeature.SDO_GEOMETRY))
85          {
86              dataSet = new CompositeDataSet(
87                      new FlatXmlDataSetBuilder().build(
88                              TestUtils.getFile("xml/sdoGeometryInsertTest.xml")),
89                      dataSet);
90          }
91  
92          if (environment.support(TestFeature.XML_TYPE))
93          {
94              dataSet = new CompositeDataSet(
95                      new FlatXmlDataSetBuilder().build(
96                              TestUtils.getFile("xml/xmlTypeInsertTest.xml")),
97                      dataSet);
98          }
99  
100         return dataSet;
101     }
102 
103     ////////////////////////////////////////////////////////////////////////////
104     //
105 
106     @Test
107     void testExecute_withClobData_updatesClobSuccessfully() throws Exception
108     {
109         // execute this test only if the target database support CLOB
110         final DatabaseEnvironment environment =
111                 DatabaseEnvironment.getInstance();
112         if (environment.support(TestFeature.CLOB))
113         {
114             final String tableName = "CLOB_TABLE";
115 
116             {
117                 final IDataSet beforeDataSet = new FlatXmlDataSetBuilder()
118                         .build(TestUtils.getFile("xml/clobInsertTest.xml"));
119 
120                 final ITable tableBefore =
121                         _connection.createDataSet().getTable(tableName);
122                 assertThat(_connection.getRowCount(tableName))
123                         .as("count before").isEqualTo(3);
124                 Assertion.assertEquals(beforeDataSet.getTable(tableName),
125                         tableBefore);
126             }
127 
128             final IDataSet afterDataSet = new FlatXmlDataSetBuilder()
129                     .build(TestUtils.getFile("xml/clobUpdateTest.xml"));
130             DatabaseOperation.REFRESH.execute(_connection, afterDataSet);
131 
132             {
133                 final ITable tableAfter =
134                         _connection.createDataSet().getTable(tableName);
135                 assertThat(tableAfter.getRowCount()).as("count after")
136                         .isEqualTo(4);
137                 Assertion.assertEquals(afterDataSet.getTable(tableName),
138                         tableAfter);
139             }
140         }
141     }
142 
143     @Test
144     void testExecute_withBlobData_updatesBlobSuccessfully() throws Exception
145     {
146         // execute this test only if the target database support BLOB
147         final DatabaseEnvironment environment =
148                 DatabaseEnvironment.getInstance();
149         if (environment.support(TestFeature.BLOB))
150         {
151             final String tableName = "BLOB_TABLE";
152 
153             {
154                 final IDataSet beforeDataSet = new FlatXmlDataSetBuilder()
155                         .build(TestUtils.getFile("xml/blobInsertTest.xml"));
156 
157                 final ITable tableBefore =
158                         _connection.createDataSet().getTable(tableName);
159                 assertThat(_connection.getRowCount(tableName))
160                         .as("count before").isEqualTo(3);
161                 Assertion.assertEquals(beforeDataSet.getTable(tableName),
162                         tableBefore);
163 
164                 // System.out.println("****** BEFORE *******");
165                 // FlatXmlDataSet.write(_connection.createDataSet(),
166                 // System.out);
167             }
168 
169             final IDataSet afterDataSet = new FlatXmlDataSetBuilder()
170                     .build(TestUtils.getFile("xml/blobUpdateTest.xml"));
171             DatabaseOperation.REFRESH.execute(_connection, afterDataSet);
172 
173             {
174                 final ITable tableAfter =
175                         _connection.createDataSet().getTable(tableName);
176                 assertThat(tableAfter.getRowCount()).as("count after")
177                         .isEqualTo(4);
178                 Assertion.assertEquals(afterDataSet.getTable(tableName),
179                         tableAfter);
180 
181                 // System.out.println("****** AFTER *******");
182                 // FlatXmlDataSet.write(_connection.createDataSet(),
183                 // System.out);
184             }
185         }
186     }
187 
188     @Test
189     void testExecute_withSdoGeometryData_updatesSdoGeometrySuccessfully() throws Exception
190     {
191         // execute this test only if the target database supports SDO_GEOMETRY
192         final DatabaseEnvironment environment =
193                 DatabaseEnvironment.getInstance();
194         if (environment.support(TestFeature.SDO_GEOMETRY))
195         {
196             final String tableName = "SDO_GEOMETRY_TABLE";
197 
198             {
199                 final IDataSet beforeDataSet =
200                         new FlatXmlDataSetBuilder().build(TestUtils
201                                 .getFile("xml/sdoGeometryInsertTest.xml"));
202 
203                 final ITable tableBefore =
204                         _connection.createDataSet().getTable(tableName);
205                 assertThat(_connection.getRowCount(tableName))
206                         .as("count before").isEqualTo(1);
207                 Assertion.assertEquals(beforeDataSet.getTable(tableName),
208                         tableBefore);
209             }
210 
211             final IDataSet afterDataSet = new FlatXmlDataSetBuilder()
212                     .build(TestUtils.getFile("xml/sdoGeometryUpdateTest.xml"));
213             DatabaseOperation.REFRESH.execute(_connection, afterDataSet);
214 
215             {
216                 final ITable tableAfter =
217                         _connection.createDataSet().getTable(tableName);
218                 assertThat(tableAfter.getRowCount()).as("count after")
219                         .isEqualTo(8);
220                 Assertion.assertEquals(afterDataSet.getTable(tableName),
221                         tableAfter);
222             }
223         }
224     }
225 
226     @Test
227     void testExecute_withXmlTypeData_updatesXmlTypeSuccessfully() throws Exception
228     {
229         // execute this test only if the target database support XML_TYPE
230         final DatabaseEnvironment environment =
231                 DatabaseEnvironment.getInstance();
232         if (environment.support(TestFeature.XML_TYPE))
233         {
234             final String tableName = "XML_TYPE_TABLE";
235 
236             {
237                 final IDataSet beforeDataSet = new FlatXmlDataSetBuilder()
238                         .build(TestUtils.getFile("xml/xmlTypeInsertTest.xml"));
239 
240                 final ITable tableBefore =
241                         _connection.createDataSet().getTable(tableName);
242                 assertThat(_connection.getRowCount(tableName))
243                         .as("count before").isEqualTo(3);
244                 Assertion.assertEquals(beforeDataSet.getTable(tableName),
245                         tableBefore);
246             }
247 
248             final IDataSet afterDataSet = new FlatXmlDataSetBuilder()
249                     .build(TestUtils.getFile("xml/xmlTypeUpdateTest.xml"));
250             DatabaseOperation.REFRESH.execute(_connection, afterDataSet);
251 
252             {
253                 final ITable tableAfter =
254                         _connection.createDataSet().getTable(tableName);
255                 assertThat(tableAfter.getRowCount()).as("count after")
256                         .isEqualTo(4);
257                 Assertion.assertEquals(afterDataSet.getTable(tableName),
258                         tableAfter);
259             }
260         }
261     }
262 
263     @Test
264     void testExecute_withXmlDataSet_updatesMatchingRow() throws Exception
265     {
266         final IDataSet dataSet;
267         try (Reader in = Files.newBufferedReader(
268                 TestUtils.getFile("xml/updateOperationTest.xml").toPath(), StandardCharsets.UTF_8))
269         {
270             dataSet = new XmlDataSet(in);
271         }
272 
273         testExecute(dataSet);
274 
275     }
276 
277     @Test
278     void testExecute_withLowerCaseDataSet_updatesMatchingRow() throws Exception
279     {
280         final IDataSet dataSet;
281         try (Reader in = Files.newBufferedReader(
282                 TestUtils.getFile("xml/updateOperationTest.xml").toPath(), StandardCharsets.UTF_8))
283         {
284             dataSet = new XmlDataSet(in);
285         }
286 
287         testExecute(new LowerCaseDataSet(dataSet));
288     }
289 
290     @Test
291     void testExecute_withForwardOnlyDataSet_updatesMatchingRow() throws Exception
292     {
293         final IDataSet dataSet;
294         try (Reader in = Files.newBufferedReader(
295                 TestUtils.getFile("xml/updateOperationTest.xml").toPath(), StandardCharsets.UTF_8))
296         {
297             dataSet = new XmlDataSet(in);
298         }
299 
300         testExecute(new ForwardOnlyDataSet(dataSet));
301     }
302 
303     @Test
304     void testExecute_withTableHavingNoPrimaryKey_throwsNoPrimaryKeyException() throws Exception
305     {
306         final String tableName = "TEST_TABLE";
307 
308         final Reader reader =
309                 TestUtils.getFileReader("xml/updateOperationNoPKTest.xml");
310         final IDataSet dataSet = new FlatXmlDataSetBuilder().build(reader);
311 
312         // verify table before
313         assertThat(_connection.getRowCount(tableName)).as("row count before")
314                 .isEqualTo(6);
315 
316         try
317         {
318             DatabaseOperation.REFRESH.execute(_connection, dataSet);
319             fail("Should not be here!");
320         } catch (final NoPrimaryKeyException e)
321         {
322 
323         }
324 
325         // verify table after
326         assertThat(_connection.getRowCount(tableName)).as("row count before")
327                 .isEqualTo(6);
328     }
329 
330     @Test
331     void testExecute_batchedStatements_allRowsUpdated() throws Exception
332     {
333         final String tableName = "PK_TABLE";
334         final IDataSet dataSet;
335         try (Reader in = Files.newBufferedReader(
336                 TestUtils.getFile("xml/updateOperationTest.xml").toPath(), StandardCharsets.UTF_8))
337         {
338             dataSet = new XmlDataSet(in);
339         }
340 
341         _connection.getConfig().setFeature(DatabaseConfig.FEATURE_BATCHED_STATEMENTS, true);
342 
343         final ITable tableBefore = createOrderedTable(tableName, "PK0");
344         assertThat(tableBefore.getRowCount()).as("row count before.").isEqualTo(3);
345 
346         DatabaseOperation.UPDATE.execute(_connection, dataSet);
347 
348         final ITable tableAfter = createOrderedTable(tableName, "PK0");
349         assertThat(tableAfter.getRowCount()).as("row count after.").isEqualTo(3);
350         assertThat(tableAfter.getValue(1, "NORMAL0")).as("NORMAL0.").hasToString("toto");
351         assertThat(tableAfter.getValue(1, "NORMAL1")).as("NORMAL1.").hasToString("qwerty");
352     }
353 
354     @Test
355     void testExecute_nullValues_updatedAsNull() throws Exception
356     {
357         final String tableName = "PK_TABLE";
358         final Column[] columns = new Column[]{
359                 new Column("PK0", DataType.NUMERIC),
360                 new Column("PK1", DataType.NUMERIC),
361                 new Column("PK2", DataType.NUMERIC),
362                 new Column("NORMAL0", DataType.VARCHAR),
363                 new Column("NORMAL1", DataType.VARCHAR)
364         };
365         final DefaultTable table = new DefaultTable(tableName, columns);
366         table.addRow(new Object[]{0, 0, 0, "updatedValue", null});
367         final IDataSet dataSet = new DefaultDataSet(table);
368 
369         DatabaseOperation.UPDATE.execute(_connection, dataSet);
370 
371         final ITable actual = createOrderedTable(tableName, "PK0");
372         assertThat(actual.getValue(0, "NORMAL0")).as("NORMAL0.").hasToString("updatedValue");
373         assertThat(actual.getValue(0, "NORMAL1")).as("NORMAL1.").isNull();
374     }
375 
376     @Test
377     void testExecute_emptyStringWithAllowEmptyFields_updatedAsEmptyString() throws Exception
378     {
379         final String tableName = "PK_TABLE";
380         final Column[] columns = new Column[]{
381                 new Column("PK0", DataType.NUMERIC),
382                 new Column("PK1", DataType.NUMERIC),
383                 new Column("PK2", DataType.NUMERIC),
384                 new Column("NORMAL0", DataType.VARCHAR),
385                 new Column("NORMAL1", DataType.VARCHAR)
386         };
387         final DefaultTable table = new DefaultTable(tableName, columns);
388         table.addRow(new Object[]{0, 0, 0, "", "keepValue"});
389         final IDataSet dataSet = new DefaultDataSet(table);
390 
391         _connection.getConfig().setFeature(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, true);
392 
393         DatabaseOperation.UPDATE.execute(_connection, dataSet);
394 
395         final ITable actual = createOrderedTable(tableName, "PK0");
396         assertThat(actual.getRowCount()).as("row count.").isEqualTo(3);
397         assertThat(actual.getValue(0, "NORMAL1")).as("NORMAL1.").hasToString("keepValue");
398     }
399 
400     private void testExecute(final IDataSet dataSet) throws Exception
401     {
402         final String tableName = "PK_TABLE";
403         final String[] columnNames =
404                 {"PK0", "PK1", "PK2", "NORMAL0", "NORMAL1"};
405         final int modifiedRow = 1;
406 
407         // verify table before
408         final ITable tableBefore =
409                 createOrderedTable(tableName, columnNames[0]);
410         assertThat(tableBefore.getRowCount()).as("row count before")
411                 .isEqualTo(3);
412 
413         DatabaseOperation.UPDATE.execute(_connection, dataSet);
414 
415         final ITable tableAfter = createOrderedTable(tableName, columnNames[0]);
416         assertThat(tableAfter.getRowCount()).as("row count after").isEqualTo(3);
417         for (int i = 0; i < tableAfter.getRowCount(); i++)
418         {
419             // verify modified row
420             if (i == modifiedRow)
421             {
422                 assertThat(tableAfter.getValue(i, "PK0")).as("PK0")
423                         .hasToString("1");
424                 assertThat(tableAfter.getValue(i, "PK1")).as("PK1")
425                         .hasToString("1");
426                 assertThat(tableAfter.getValue(i, "PK2")).as("PK2")
427                         .hasToString("1");
428                 assertThat(tableAfter.getValue(i, "NORMAL0")).as("NORMAL0")
429                         .hasToString("toto");
430                 assertThat(tableAfter.getValue(i, "NORMAL1")).as("NORMAL1")
431                         .hasToString("qwerty");
432             }
433             // all other row must be equals than before update
434             else
435             {
436                 for (int j = 0; j < columnNames.length; j++)
437                 {
438                     final String name = columnNames[j];
439                     final Object valueAfter = tableAfter.getValue(i, name);
440                     final Object valueBefore = tableBefore.getValue(i, name);
441                     assertThat(valueAfter).as("c=" + name + ",r=" + j)
442                             .isEqualTo(valueBefore);
443                 }
444             }
445         }
446     }
447 
448 }