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  
22  package org.dbunit.operation;
23  
24  import java.io.File;
25  import java.io.FileReader;
26  import java.io.Reader;
27  
28  import org.dbunit.AbstractDatabaseIT;
29  import org.dbunit.Assertion;
30  import org.dbunit.DatabaseEnvironment;
31  import org.dbunit.TestFeature;
32  import org.dbunit.database.DatabaseConfig;
33  import org.dbunit.database.MockDatabaseConnection;
34  import org.dbunit.database.statement.MockBatchStatement;
35  import org.dbunit.database.statement.MockStatementFactory;
36  import org.dbunit.dataset.Column;
37  import org.dbunit.dataset.CompositeDataSet;
38  import org.dbunit.dataset.DefaultDataSet;
39  import org.dbunit.dataset.DefaultTable;
40  import org.dbunit.dataset.DefaultTableMetaData;
41  import org.dbunit.dataset.ForwardOnlyDataSet;
42  import org.dbunit.dataset.IDataSet;
43  import org.dbunit.dataset.ITable;
44  import org.dbunit.dataset.LowerCaseDataSet;
45  import org.dbunit.dataset.NoPrimaryKeyException;
46  import org.dbunit.dataset.datatype.DataType;
47  import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
48  import org.dbunit.dataset.xml.XmlDataSet;
49  import org.dbunit.testutil.TestUtils;
50  
51  /**
52   * @author Manuel Laflamme
53   * @version $Revision: 1162 $
54   * @since Feb 19, 2002
55   */
56  public class UpdateOperationIT extends AbstractDatabaseIT
57  {
58      public UpdateOperationIT(String s)
59      {
60          super(s);
61      }
62  
63      ////////////////////////////////////////////////////////////////////////////
64      //
65  
66      protected IDataSet getDataSet() throws Exception
67      {
68          IDataSet dataSet = super.getDataSet();
69  
70          DatabaseEnvironment environment = DatabaseEnvironment.getInstance();
71          if (environment.support(TestFeature.BLOB))
72          {
73              dataSet = new CompositeDataSet(
74                      new FlatXmlDataSetBuilder().build(TestUtils.getFile("xml/blobInsertTest.xml")),
75                      dataSet);
76          }
77  
78          if (environment.support(TestFeature.CLOB))
79          {
80              dataSet = new CompositeDataSet(
81                      new FlatXmlDataSetBuilder().build(TestUtils.getFile("xml/clobInsertTest.xml")),
82                      dataSet);
83          }
84  
85          if (environment.support(TestFeature.SDO_GEOMETRY))
86          {
87              dataSet = new CompositeDataSet(
88                      new FlatXmlDataSetBuilder().build(TestUtils.getFile("xml/sdoGeometryInsertTest.xml")),
89                      dataSet
90              );
91          }
92  
93          return dataSet;
94      }
95  
96      ////////////////////////////////////////////////////////////////////////////
97      //
98  
99      public void testMockExecute() throws Exception
100     {
101         String schemaName = "schema";
102         String tableName = "table";
103         String[] expected = {
104             "update schema.table set c2 = 1234, c3 = 'false' where c4 = 0 and c1 = 'toto'",
105             "update schema.table set c2 = 123.45, c3 = NULL where c4 = 0 and c1 = 'qwerty'",
106         };
107 
108         Column[] columns = new Column[]{
109             new Column("c1", DataType.VARCHAR),
110             new Column("c2", DataType.NUMERIC),
111             new Column("c3", DataType.VARCHAR),
112             new Column("c4", DataType.NUMERIC),
113         };
114         String[] primaryKeys = {"c4", "c1"};
115         DefaultTable table = new DefaultTable(new DefaultTableMetaData(
116                 tableName, columns, primaryKeys));
117         table.addRow(new Object[]{"toto", "1234", "false", "0"});
118         table.addRow(new Object[]{"qwerty", new Double("123.45"), null, "0"});
119         IDataSet dataSet = new DefaultDataSet(table);
120 
121         // setup mock objects
122         MockBatchStatement statement = new MockBatchStatement();
123         statement.addExpectedBatchStrings(expected);
124         statement.setExpectedExecuteBatchCalls(1);
125         statement.setExpectedClearBatchCalls(1);
126         statement.setExpectedCloseCalls(1);
127 
128         MockStatementFactory factory = new MockStatementFactory();
129         factory.setExpectedCreatePreparedStatementCalls(1);
130         factory.setupStatement(statement);
131 
132         MockDatabaseConnection connection = new MockDatabaseConnection();
133         connection.setupDataSet(dataSet);
134         connection.setupSchema(schemaName);
135         connection.setupStatementFactory(factory);
136         connection.setExpectedCloseCalls(0);
137 
138         // execute operation
139         new UpdateOperation().execute(connection, dataSet);
140 
141         statement.verify();
142         factory.verify();
143         connection.verify();
144     }
145 
146     public void testExecuteWithEscapedName() throws Exception
147     {
148         String schemaName = "schema";
149         String tableName = "table";
150         String[] expected = {
151             "update [schema].[table] set [c2] = 1234, [c3] = 'false' where [c4] = 0 and [c1] = 'toto'",
152             "update [schema].[table] set [c2] = 123.45, [c3] = NULL where [c4] = 0 and [c1] = 'qwerty'",
153         };
154 
155         Column[] columns = new Column[]{
156             new Column("c1", DataType.VARCHAR),
157             new Column("c2", DataType.NUMERIC),
158             new Column("c3", DataType.VARCHAR),
159             new Column("c4", DataType.NUMERIC),
160         };
161         String[] primaryKeys = {"c4", "c1"};
162         DefaultTable table = new DefaultTable(new DefaultTableMetaData(
163                 tableName, columns, primaryKeys));
164         table.addRow(new Object[]{"toto", "1234", "false", "0"});
165         table.addRow(new Object[]{"qwerty", new Double("123.45"), null, "0"});
166         IDataSet dataSet = new DefaultDataSet(table);
167 
168         // setup mock objects
169         MockBatchStatement statement = new MockBatchStatement();
170         statement.addExpectedBatchStrings(expected);
171         statement.setExpectedExecuteBatchCalls(1);
172         statement.setExpectedClearBatchCalls(1);
173         statement.setExpectedCloseCalls(1);
174 
175         MockStatementFactory factory = new MockStatementFactory();
176         factory.setExpectedCreatePreparedStatementCalls(1);
177         factory.setupStatement(statement);
178 
179         MockDatabaseConnection connection = new MockDatabaseConnection();
180         connection.setupDataSet(dataSet);
181         connection.setupSchema(schemaName);
182         connection.setupStatementFactory(factory);
183         connection.setExpectedCloseCalls(0);
184 
185         // execute operation
186         connection.getConfig().setProperty(
187                 DatabaseConfig.PROPERTY_ESCAPE_PATTERN, "[?]");
188         new UpdateOperation().execute(connection, dataSet);
189 
190         statement.verify();
191         factory.verify();
192         connection.verify();
193     }
194 
195     public void testExecuteWithEmptyTable() throws Exception
196     {
197         Column[] columns = {new Column("c1", DataType.VARCHAR)};
198         ITable table = new DefaultTable(new DefaultTableMetaData(
199                 "name", columns, columns));
200         IDataSet dataSet = new DefaultDataSet(table);
201 
202         // setup mock objects
203         MockStatementFactory factory = new MockStatementFactory();
204         factory.setExpectedCreatePreparedStatementCalls(0);
205 
206         MockDatabaseConnection connection = new MockDatabaseConnection();
207         connection.setupDataSet(dataSet);
208         connection.setupStatementFactory(factory);
209         connection.setExpectedCloseCalls(0);
210 
211         // execute operation
212         new UpdateOperation().execute(connection, dataSet);
213 
214         factory.verify();
215         connection.verify();
216     }
217 
218     public void testUpdateClob() throws Exception
219     {
220         // execute this test only if the target database support CLOB
221         DatabaseEnvironment environment = DatabaseEnvironment.getInstance();
222         if (environment.support(TestFeature.CLOB))
223         {
224             String tableName = "CLOB_TABLE";
225 
226             {
227                 IDataSet beforeDataSet = new FlatXmlDataSetBuilder().build(
228                         TestUtils.getFile("xml/clobInsertTest.xml"));
229 
230                 ITable tableBefore = _connection.createDataSet().getTable(tableName);
231                 assertEquals("count before", 3, _connection.getRowCount(tableName));
232                 Assertion.assertEquals(beforeDataSet.getTable(tableName), tableBefore);
233             }
234 
235             IDataSet afterDataSet = new FlatXmlDataSetBuilder().build(
236                     TestUtils.getFile("xml/clobUpdateTest.xml"));
237             DatabaseOperation.REFRESH.execute(_connection, afterDataSet);
238 
239             {
240                 ITable tableAfter = _connection.createDataSet().getTable(tableName);
241                 assertEquals("count after", 4, tableAfter.getRowCount());
242                 Assertion.assertEquals(afterDataSet.getTable(tableName), tableAfter);
243             }
244         }
245     }
246 
247     public void testUpdateBlob() throws Exception
248     {
249         // execute this test only if the target database support BLOB
250         DatabaseEnvironment environment = DatabaseEnvironment.getInstance();
251         if (environment.support(TestFeature.BLOB))
252         {
253             String tableName = "BLOB_TABLE";
254 
255             {
256                 IDataSet beforeDataSet = new FlatXmlDataSetBuilder().build(
257                         TestUtils.getFile("xml/blobInsertTest.xml"));
258 
259                 ITable tableBefore = _connection.createDataSet().getTable(tableName);
260                 assertEquals("count before", 1, _connection.getRowCount(tableName));
261                 Assertion.assertEquals(beforeDataSet.getTable(tableName), tableBefore);
262 
263 //                System.out.println("****** BEFORE *******");
264 //                FlatXmlDataSet.write(_connection.createDataSet(), System.out);
265             }
266 
267             IDataSet afterDataSet = new FlatXmlDataSetBuilder().build(
268                     TestUtils.getFile("xml/blobUpdateTest.xml"));
269             DatabaseOperation.REFRESH.execute(_connection, afterDataSet);
270 
271             {
272                 ITable tableAfter = _connection.createDataSet().getTable(tableName);
273                 assertEquals("count after", 2, tableAfter.getRowCount());
274                 Assertion.assertEquals(afterDataSet.getTable(tableName), tableAfter);
275 
276 //                System.out.println("****** AFTER *******");
277 //                FlatXmlDataSet.write(_connection.createDataSet(), System.out);
278             }
279         }
280     }
281 
282     public void testUpdateSdoGeometry() throws Exception
283     {
284         // execute this test only if the target database supports SDO_GEOMETRY
285         DatabaseEnvironment environment = DatabaseEnvironment.getInstance();
286         if (environment.support(TestFeature.SDO_GEOMETRY))
287         {
288             String tableName = "SDO_GEOMETRY_TABLE";
289 
290             {
291                 IDataSet beforeDataSet = new FlatXmlDataSetBuilder().build(
292                         TestUtils.getFile("xml/sdoGeometryInsertTest.xml"));
293 
294                 ITable tableBefore = _connection.createDataSet().getTable(tableName);
295                 assertEquals("count before", 1, _connection.getRowCount(tableName));
296                 Assertion.assertEquals(beforeDataSet.getTable(tableName), tableBefore);
297             }
298 
299             IDataSet afterDataSet = new FlatXmlDataSetBuilder().build(
300                     TestUtils.getFile("xml/sdoGeometryUpdateTest.xml"));
301             DatabaseOperation.REFRESH.execute(_connection, afterDataSet);
302 
303             {
304                 ITable tableAfter = _connection.createDataSet().getTable(tableName);
305                 assertEquals("count after", 8, tableAfter.getRowCount());
306                 Assertion.assertEquals(afterDataSet.getTable(tableName), tableAfter);
307             }
308         }
309     }
310 
311     public void testExecute() throws Exception
312     {
313         Reader in = new FileReader(
314                 TestUtils.getFile("xml/updateOperationTest.xml"));
315         IDataSet dataSet = new XmlDataSet(in);
316 
317         testExecute(dataSet);
318 
319     }
320 
321     public void testExecuteCaseInsensitive() throws Exception
322     {
323         Reader in = new FileReader(
324                 TestUtils.getFile("xml/updateOperationTest.xml"));
325         IDataSet dataSet = new XmlDataSet(in);
326 
327         testExecute(new LowerCaseDataSet(dataSet));
328     }
329 
330     public void testExecuteForwardOnly() throws Exception
331     {
332         Reader in = new FileReader(
333                 TestUtils.getFile("xml/updateOperationTest.xml"));
334         IDataSet dataSet = new XmlDataSet(in);
335 
336         testExecute(new ForwardOnlyDataSet(dataSet));
337     }
338 
339     public void testExecuteAndNoPrimaryKeys() throws Exception
340     {
341         String tableName = "TEST_TABLE";
342 
343         Reader reader = TestUtils.getFileReader("xml/updateOperationNoPKTest.xml");
344         IDataSet dataSet = new FlatXmlDataSetBuilder().build(reader);
345 
346         // verify table before
347         assertEquals("row count before", 6, _connection.getRowCount(tableName));
348 
349         try
350         {
351             DatabaseOperation.REFRESH.execute(_connection, dataSet);
352             fail("Should not be here!");
353         }
354         catch (NoPrimaryKeyException e)
355         {
356 
357         }
358 
359         // verify table after
360         assertEquals("row count before", 6, _connection.getRowCount(tableName));
361     }
362 
363     private void testExecute(IDataSet dataSet) throws Exception
364     {
365         String tableName = "PK_TABLE";
366         String[] columnNames = {"PK0", "PK1", "PK2", "NORMAL0", "NORMAL1"};
367         int modifiedRow = 1;
368 
369         // verify table before
370         ITable tableBefore = createOrderedTable(tableName, columnNames[0]);
371         assertEquals("row count before", 3, tableBefore.getRowCount());
372 
373         DatabaseOperation.UPDATE.execute(_connection, dataSet);
374 
375         ITable tableAfter = createOrderedTable(tableName, columnNames[0]);
376         assertEquals("row count after", 3, tableAfter.getRowCount());
377         for (int i = 0; i < tableAfter.getRowCount(); i++)
378         {
379             // verify modified row
380             if (i == modifiedRow)
381             {
382                 assertEquals("PK0", "1",
383                         tableAfter.getValue(i, "PK0").toString());
384                 assertEquals("PK1", "1",
385                         tableAfter.getValue(i, "PK1").toString());
386                 assertEquals("PK2", "1",
387                         tableAfter.getValue(i, "PK2").toString());
388                 assertEquals("NORMAL0", "toto",
389                         tableAfter.getValue(i, "NORMAL0").toString());
390                 assertEquals("NORMAL1", "qwerty",
391                         tableAfter.getValue(i, "NORMAL1").toString());
392             }
393             // all other row must be equals than before update
394             else
395             {
396                 for (int j = 0; j < columnNames.length; j++)
397                 {
398                     String name = columnNames[j];
399                     Object valueAfter = tableAfter.getValue(i, name);
400                     Object valueBefore = tableBefore.getValue(i, name);
401                     assertEquals("c=" + name + ",r=" + j, valueBefore, valueAfter);
402                 }
403             }
404         }
405     }
406 
407 
408 }
409 
410 
411 
412 
413 
414 
415 
416