View Javadoc
1   /*
2   Copyright (c) 2016 James Ahlborn
3   
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7   
8       http://www.apache.org/licenses/LICENSE-2.0
9   
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15  */
16  
17  package com.healthmarketscience.jackcess;
18  
19  import java.util.ArrayList;
20  import java.util.Arrays;
21  import java.util.LinkedHashMap;
22  import java.util.List;
23  import java.util.Map;
24  
25  import com.healthmarketscience.jackcess.Database.FileFormat;
26  import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
27  import com.healthmarketscience.jackcess.impl.DatabaseImpl;
28  import com.healthmarketscience.jackcess.impl.TableImpl;
29  import junit.framework.TestCase;
30  import static com.healthmarketscience.jackcess.TestUtil.*;
31  
32  /**
33   *
34   * @author James Ahlborn
35   */
36  public class TableUpdaterTest extends TestCase
37  {
38  
39    public TableUpdaterTest(String name) throws Exception {
40      super(name);
41    }
42  
43    public void testTableUpdating() throws Exception {
44      for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
45        Database db = create(fileFormat);
46  
47        doTestUpdating(db, false, true);
48   
49        db.close();
50      }    
51    }
52  
53    public void testTableUpdatingOneToOne() throws Exception {
54      for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
55        Database db = create(fileFormat);
56  
57        doTestUpdating(db, true, true);
58   
59        db.close();
60      }    
61    }
62  
63    public void testTableUpdatingNoEnforce() throws Exception {
64      for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
65        Database db = create(fileFormat);
66  
67        doTestUpdating(db, false, false);
68   
69        db.close();
70      }    
71    }
72  
73    private void doTestUpdating(Database db, boolean oneToOne, boolean enforce) 
74      throws Exception
75    {
76      Table t1 = new TableBuilder("TestTable")
77        .addColumn(new ColumnBuilder("id", DataType.LONG))
78        .toTable(db);
79        
80      Table t2 = new TableBuilder("TestTable2")
81        .addColumn(new ColumnBuilder("id2", DataType.LONG))
82        .toTable(db);
83  
84      int t1idxs = 1;
85      new IndexBuilder(IndexBuilder.PRIMARY_KEY_NAME)
86        .addColumns("id").setPrimaryKey()
87        .addToTable(t1);
88      new ColumnBuilder("data", DataType.TEXT)
89        .addToTable(t1);
90      new ColumnBuilder("bigdata", DataType.MEMO)
91        .addToTable(t1);
92  
93      new ColumnBuilder("data2", DataType.TEXT)
94        .addToTable(t2);
95      new ColumnBuilder("bigdata2", DataType.MEMO)
96        .addToTable(t2);
97  
98      int t2idxs = 0;
99      if(oneToOne) {
100       ++t2idxs;
101       new IndexBuilder(IndexBuilder.PRIMARY_KEY_NAME)
102         .addColumns("id2").setPrimaryKey()
103         .addToTable(t2);
104     }
105 
106     RelationshipBuilder rb = new RelationshipBuilder("TestTable", "TestTable2")
107       .addColumns("id", "id2");
108     if(enforce) {
109       ++t1idxs;
110       ++t2idxs;      
111       rb.setReferentialIntegrity()
112         .setCascadeDeletes();
113     }
114 
115     Relationship rel = rb.toRelationship(db);
116 
117     assertEquals("TestTableTestTable2", rel.getName());
118     assertSame(t1, rel.getFromTable());
119     assertEquals(Arrays.asList(t1.getColumn("id")), rel.getFromColumns());
120     assertSame(t2, rel.getToTable());
121     assertEquals(Arrays.asList(t2.getColumn("id2")), rel.getToColumns());
122     assertEquals(oneToOne, rel.isOneToOne());
123     assertEquals(enforce, rel.hasReferentialIntegrity());
124     assertEquals(enforce, rel.cascadeDeletes());
125     assertFalse(rel.cascadeUpdates());
126     assertEquals(Relationship.JoinType.INNER, rel.getJoinType());
127 
128     assertEquals(t1idxs, t1.getIndexes().size());
129     assertEquals(1, ((TableImpl)t1).getIndexDatas().size());
130 
131     assertEquals(t2idxs, t2.getIndexes().size());
132     assertEquals((t2idxs > 0 ? 1 : 0), ((TableImpl)t2).getIndexDatas().size());
133 
134     ((DatabaseImpl)db).getPageChannel().startWrite();
135     try {
136 
137       for(int i = 0; i < 10; ++i) {
138         t1.addRow(i, "row" + i, "row-data" + i);
139       }
140 
141       for(int i = 0; i < 10; ++i) {
142         t2.addRow(i, "row2_" + i, "row-data2_" + i);
143       }
144 
145     } finally {
146       ((DatabaseImpl)db).getPageChannel().finishWrite();
147     }
148 
149     try {
150       t2.addRow(10, "row10", "row-data10");
151       if(enforce) {
152         fail("ConstraintViolationException should have been thrown");
153       } 
154     } catch(ConstraintViolationException cv) {
155       // success
156       if(!enforce) { throw cv; }
157     }
158 
159     Row r1 = CursorBuilder.findRowByPrimaryKey(t1, 5);
160     t1.deleteRow(r1);
161    
162     int id = 0;
163     for(Row r : t1) {
164       assertEquals(id, r.get("id"));
165       ++id;
166       if(id == 5) {
167         ++id;
168       }
169     }
170  
171     id = 0;
172     for(Row r : t2) {
173       assertEquals(id, r.get("id2"));
174       ++id;
175       if(enforce && (id == 5)) {
176         ++id;
177       }
178     }
179   }
180 
181   public void testInvalidUpdate() throws Exception
182   {
183     for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
184       Database db = create(fileFormat);
185 
186       Table t1 = new TableBuilder("TestTable")
187         .addColumn(new ColumnBuilder("id", DataType.LONG))
188         .toTable(db);
189 
190       try {
191         new ColumnBuilder("ID", DataType.TEXT)
192           .addToTable(t1);
193         fail("created table with no columns?");
194       } catch(IllegalArgumentException e) {
195         // success
196       }
197 
198       Table t2 = new TableBuilder("TestTable2")
199         .addColumn(new ColumnBuilder("id2", DataType.LONG))
200         .toTable(db);
201 
202       try {
203         new RelationshipBuilder(t1, t2)
204           .toRelationship(db);
205         fail("created rel with no columns?");
206       } catch(IllegalArgumentException e) {
207         // success
208       }
209 
210       try {
211         new RelationshipBuilder("TestTable", "TestTable2")
212           .addColumns("id", "id")
213           .toRelationship(db);
214         fail("created rel with wrong columns?");
215       } catch(IllegalArgumentException e) {
216         // success
217       }
218  
219       db.close();
220     }    
221   }
222 
223   public void testUpdateLargeTableDef() throws Exception
224   {
225     for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
226       Database db = create(fileFormat);
227 
228       final int numColumns = 89;
229 
230       Table t = new TableBuilder("test")
231         .addColumn(new ColumnBuilder("first", DataType.TEXT))
232         .toTable(db);
233 
234       List<String> colNames = new ArrayList<String>();
235       colNames.add("first");
236       for(int i = 0; i < numColumns; ++i) {
237         String colName = "MyColumnName" + i;
238         colNames.add(colName);
239         DataType type = (((i % 3) == 0) ? DataType.MEMO : DataType.TEXT);
240         new ColumnBuilder(colName, type)
241           .addToTable(t);
242       }
243 
244       List<String> row = new ArrayList<String>();
245       Map<String,Object> expectedRowData = new LinkedHashMap<String, Object>();
246       for(int i = 0; i < colNames.size(); ++i) {
247         String value = "" + i + " some row data";
248         row.add(value);
249         expectedRowData.put(colNames.get(i), value);
250       }
251 
252       t.addRow(row.toArray());
253 
254       t.reset();
255       assertEquals(expectedRowData, t.getNextRow());
256 
257       db.close();
258     }
259   } 
260 }