View Javadoc
1   /*
2   Copyright (c) 2015 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.impl;
18  
19  import java.time.Instant;
20  import java.time.LocalDateTime;
21  import java.time.ZoneOffset;
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.Map;
25  
26  import com.healthmarketscience.jackcess.Column;
27  import com.healthmarketscience.jackcess.ColumnBuilder;
28  import com.healthmarketscience.jackcess.Cursor;
29  import com.healthmarketscience.jackcess.CursorBuilder;
30  import com.healthmarketscience.jackcess.DataType;
31  import com.healthmarketscience.jackcess.Database;
32  import static com.healthmarketscience.jackcess.Database.*;
33  import com.healthmarketscience.jackcess.Row;
34  import com.healthmarketscience.jackcess.Table;
35  import com.healthmarketscience.jackcess.TableBuilder;
36  import static com.healthmarketscience.jackcess.TestUtil.*;
37  import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
38  import com.healthmarketscience.jackcess.util.RowFilterTest;
39  import junit.framework.TestCase;
40  
41  /**
42   *
43   * @author James Ahlborn
44   */
45  public class DatabaseReadWriteTest extends TestCase
46  {
47  
48    public DatabaseReadWriteTest(String name) throws Exception {
49      super(name);
50    }
51  
52    public void testWriteAndRead() throws Exception {
53      for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
54        Database db = create(fileFormat);
55        doTestWriteAndRead(db);
56        db.close();
57      }
58    }
59  
60    public void testWriteAndReadInMem() throws Exception {
61      for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
62        Database db = createMem(fileFormat);
63        doTestWriteAndRead(db);
64        db.close();
65      }
66    }
67  
68    private static void doTestWriteAndRead(Database db) throws Exception {
69        createTestTable(db);
70        Object[] row = createTestRow();
71        row[3] = null;
72        Table table = db.getTable("Test");
73        int count = 1000;
74        ((DatabaseImpl)db).getPageChannel().startWrite();
75        try {
76          for (int i = 0; i < count; i++) {
77            table.addRow(row);
78          }
79        } finally {
80          ((DatabaseImpl)db).getPageChannel().finishWrite();
81        }
82        for (int i = 0; i < count; i++) {
83          Map<String, Object> readRow = table.getNextRow();
84          assertEquals(row[0], readRow.get("A"));
85          assertEquals(row[1], readRow.get("B"));
86          assertEquals(row[2], readRow.get("C"));
87          assertEquals(row[3], readRow.get("D"));
88          assertEquals(row[4], readRow.get("E"));
89          assertEquals(row[5], readRow.get("F"));
90          assertEquals(row[6], readRow.get("G"));
91          assertEquals(row[7], readRow.get("H"));
92        }
93    }
94  
95    public void testWriteAndReadInBatch() throws Exception {
96      for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
97        Database db = createMem(fileFormat);
98        createTestTable(db);
99        int count = 1000;
100       List<Object[]> rows = new ArrayList<Object[]>(count);
101       Object[] row = createTestRow();
102       for (int i = 0; i < count; i++) {
103         rows.add(row);
104       }
105       Table table = db.getTable("Test");
106       table.addRows(rows);
107       for (int i = 0; i < count; i++) {
108         Map<String, Object> readRow = table.getNextRow();
109         assertEquals(row[0], readRow.get("A"));
110         assertEquals(row[1], readRow.get("B"));
111         assertEquals(row[2], readRow.get("C"));
112         assertEquals(row[3], readRow.get("D"));
113         assertEquals(row[4], readRow.get("E"));
114         assertEquals(row[5], readRow.get("F"));
115         assertEquals(row[6], readRow.get("G"));
116         assertEquals(row[7], readRow.get("H"));
117       }
118 
119       db.close();
120     }
121   }
122 
123   public void testUpdateRow() throws Exception
124   {
125     for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
126       Database db = createMem(fileFormat);
127 
128       Table t = new TableBuilder("test")
129         .addColumn(new ColumnBuilder("name", DataType.TEXT))
130         .addColumn(new ColumnBuilder("id", DataType.LONG)
131                    .setAutoNumber(true))
132         .addColumn(new ColumnBuilder("data", DataType.TEXT)
133                    .setLength(JetFormat.TEXT_FIELD_MAX_LENGTH))
134         .toTable(db);
135 
136       for(int i = 0; i < 10; ++i) {
137         t.addRow("row" + i, Column.AUTO_NUMBER, "initial data");
138       }
139 
140       Cursor c = CursorBuilder.createCursor(t);
141       c.reset();
142       c.moveNextRows(2);
143       Map<String,Object> row = c.getCurrentRow();
144 
145       assertEquals(createExpectedRow("name", "row1",
146                                      "id", 2,
147                                      "data", "initial data"),
148                    row);
149 
150       Map<String,Object> newRow = createExpectedRow(
151           "name", Column.KEEP_VALUE,
152           "id", Column.AUTO_NUMBER,
153           "data", "new data");
154       assertSame(newRow, c.updateCurrentRowFromMap(newRow));
155       assertEquals(createExpectedRow("name", "row1",
156                                      "id", 2,
157                                      "data", "new data"),
158                    newRow);
159 
160       c.moveNextRows(3);
161       row = c.getCurrentRow();
162 
163       assertEquals(createExpectedRow("name", "row4",
164                                      "id", 5,
165                                      "data", "initial data"),
166                    row);
167 
168       c.updateCurrentRow(Column.KEEP_VALUE, Column.AUTO_NUMBER, "a larger amount of new data");
169 
170       c.reset();
171       c.moveNextRows(2);
172       row = c.getCurrentRow();
173 
174       assertEquals(createExpectedRow("name", "row1",
175                                      "id", 2,
176                                      "data", "new data"),
177                    row);
178 
179       c.moveNextRows(3);
180       row = c.getCurrentRow();
181 
182       assertEquals(createExpectedRow("name", "row4",
183                                      "id", 5,
184                                      "data", "a larger amount of new data"),
185                    row);
186 
187       t.reset();
188 
189       String str = createString(100);
190       for(int i = 10; i < 50; ++i) {
191         t.addRow("row" + i, Column.AUTO_NUMBER, "big data_" + str);
192       }
193 
194       c.reset();
195       c.moveNextRows(9);
196       row = c.getCurrentRow();
197 
198       assertEquals(createExpectedRow("name", "row8",
199                                      "id", 9,
200                                      "data", "initial data"),
201                    row);
202 
203       String newText = "updated big data_" + createString(200);
204 
205       c.setCurrentRowValue(t.getColumn("data"), newText);
206 
207       c.reset();
208       c.moveNextRows(9);
209       row = c.getCurrentRow();
210 
211       assertEquals(createExpectedRow("name", "row8",
212                                      "id", 9,
213                                      "data", newText),
214                    row);
215 
216       List<Row> rows = RowFilterTest.toList(t);
217       assertEquals(50, rows.size());
218 
219       for(Row r : rows) {
220         r.put("data", "final data " + r.get("id"));
221       }
222 
223       for(Row r : rows) {
224         assertSame(r, t.updateRow(r));
225       }
226 
227       t.reset();
228 
229       for(Row r : t) {
230         assertEquals("final data " + r.get("id"), r.get("data"));
231       }
232 
233       db.close();
234     }
235   }
236 
237   public void testDateMath()
238   {
239     long now = System.currentTimeMillis();
240 
241     // test around current time
242     doTestDateMath(now);
243 
244     // test around the unix epoch
245     doTestDateMath(0L);
246 
247     // test around the access epoch
248     doTestDateMath(-ColumnImpl.MILLIS_BETWEEN_EPOCH_AND_1900);
249   }
250 
251   private static void doTestDateMath(long testTime)
252   {
253     final long timeRange = 100000000L;
254     final long timeStep = 37L;
255 
256     for(long time = testTime - timeRange; time < testTime + timeRange;
257         time += timeStep) {
258       double accTime = ColumnImpl.toLocalDateDouble(time);
259       long newTime = ColumnImpl.fromLocalDateDouble(accTime);
260       assertEquals(time, newTime);
261 
262       Instant inst = Instant.ofEpochMilli(time);
263       LocalDateTime ldt = LocalDateTime.ofInstant(inst, ZoneOffset.UTC);
264 
265       accTime = ColumnImpl.toDateDouble(ldt);
266       LocalDateTime newLdt = ColumnImpl.ldtFromLocalDateDouble(accTime);
267       assertEquals(ldt, newLdt);
268     }
269   }
270 }