1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package com.healthmarketscience.jackcess;
29
30 import java.io.File;
31 import java.io.FileInputStream;
32 import java.io.FileNotFoundException;
33 import java.io.FileOutputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37 import java.io.PrintWriter;
38 import java.math.BigDecimal;
39 import java.nio.ByteBuffer;
40 import java.sql.Types;
41 import java.text.DateFormat;
42 import java.text.SimpleDateFormat;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Calendar;
46 import java.util.Collections;
47 import java.util.Date;
48 import java.util.HashSet;
49 import java.util.LinkedHashMap;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.Set;
53 import java.util.UUID;
54
55 import junit.framework.TestCase;
56
57
58
59
60 public class DatabaseTest extends TestCase {
61
62 static boolean _autoSync = Database.DEFAULT_AUTO_SYNC;
63
64 public DatabaseTest(String name) throws Exception {
65 super(name);
66 }
67
68 static Database open() throws Exception {
69 return open(new File("test/data/test.mdb"));
70 }
71
72 static Database open(File file) throws Exception {
73 return Database.open(file, true, _autoSync);
74 }
75
76 static Database create() throws Exception {
77 return create(false);
78 }
79
80 static Database create(boolean keep) throws Exception {
81 return Database.create(createTempFile(keep), _autoSync);
82 }
83
84 static Database openCopy(File srcFile) throws Exception {
85 return openCopy(srcFile, false);
86 }
87
88 static Database openCopy(File srcFile, boolean keep) throws Exception {
89 File tmp = createTempFile(keep);
90 copyFile(srcFile, tmp);
91 return Database.open(tmp, false, _autoSync);
92 }
93
94 public void testInvalidTableDefs() throws Exception {
95 Database db = create();
96
97 try {
98 db.createTable("test", Collections.<Column>emptyList());
99 fail("created table with no columns?");
100 } catch(IllegalArgumentException e) {
101
102 }
103
104 try {
105 new TableBuilder("test")
106 .addColumn(new ColumnBuilder("A", DataType.TEXT).toColumn())
107 .addColumn(new ColumnBuilder("a", DataType.MEMO).toColumn())
108 .toTable(db);
109 fail("created table with duplicate column names?");
110 } catch(IllegalArgumentException e) {
111
112 }
113
114 try {
115 new TableBuilder("test")
116 .addColumn(new ColumnBuilder("A", DataType.TEXT)
117 .setLengthInUnits(352).toColumn())
118 .toTable(db);
119 fail("created table with invalid column length?");
120 } catch(IllegalArgumentException e) {
121
122 }
123
124 new TableBuilder("test")
125 .addColumn(new ColumnBuilder("A", DataType.TEXT).toColumn())
126 .toTable(db);
127
128
129 try {
130 new TableBuilder("Test")
131 .addColumn(new ColumnBuilder("A", DataType.TEXT).toColumn())
132 .toTable(db);
133 fail("create duplicate tables?");
134 } catch(IllegalArgumentException e) {
135
136 }
137
138 }
139
140 public void testReadDeletedRows() throws Exception {
141 Table table = open(new File("test/data/delTest.mdb")).getTable("Table");
142 int rows = 0;
143 while (table.getNextRow() != null) {
144 rows++;
145 }
146 assertEquals(2, rows);
147 }
148
149 public void testGetColumns() throws Exception {
150 List columns = open().getTable("Table1").getColumns();
151 assertEquals(9, columns.size());
152 checkColumn(columns, 0, "A", DataType.TEXT);
153 checkColumn(columns, 1, "B", DataType.TEXT);
154 checkColumn(columns, 2, "C", DataType.BYTE);
155 checkColumn(columns, 3, "D", DataType.INT);
156 checkColumn(columns, 4, "E", DataType.LONG);
157 checkColumn(columns, 5, "F", DataType.DOUBLE);
158 checkColumn(columns, 6, "G", DataType.SHORT_DATE_TIME);
159 checkColumn(columns, 7, "H", DataType.MONEY);
160 checkColumn(columns, 8, "I", DataType.BOOLEAN);
161 }
162
163 static void checkColumn(List columns, int columnNumber, String name,
164 DataType dataType)
165 throws Exception
166 {
167 Column column = (Column) columns.get(columnNumber);
168 assertEquals(name, column.getName());
169 assertEquals(dataType, column.getType());
170 }
171
172 public void testGetNextRow() throws Exception {
173 Database db = open();
174 assertEquals(3, db.getTableNames().size());
175 Table table = db.getTable("Table1");
176
177 Map<String, Object> row = table.getNextRow();
178 assertEquals("abcdefg", row.get("A"));
179 assertEquals("hijklmnop", row.get("B"));
180 assertEquals(new Byte((byte) 2), row.get("C"));
181 assertEquals(new Short((short) 222), row.get("D"));
182 assertEquals(new Integer(333333333), row.get("E"));
183 assertEquals(new Double(444.555d), row.get("F"));
184 Calendar cal = Calendar.getInstance();
185 cal.setTime((Date) row.get("G"));
186 assertEquals(Calendar.SEPTEMBER, cal.get(Calendar.MONTH));
187 assertEquals(21, cal.get(Calendar.DAY_OF_MONTH));
188 assertEquals(1974, cal.get(Calendar.YEAR));
189 assertEquals(0, cal.get(Calendar.HOUR_OF_DAY));
190 assertEquals(0, cal.get(Calendar.MINUTE));
191 assertEquals(0, cal.get(Calendar.SECOND));
192 assertEquals(0, cal.get(Calendar.MILLISECOND));
193 assertEquals(Boolean.TRUE, row.get("I"));
194
195 row = table.getNextRow();
196 assertEquals("a", row.get("A"));
197 assertEquals("b", row.get("B"));
198 assertEquals(new Byte((byte) 0), row.get("C"));
199 assertEquals(new Short((short) 0), row.get("D"));
200 assertEquals(new Integer(0), row.get("E"));
201 assertEquals(new Double(0d), row.get("F"));
202 cal = Calendar.getInstance();
203 cal.setTime((Date) row.get("G"));
204 assertEquals(Calendar.DECEMBER, cal.get(Calendar.MONTH));
205 assertEquals(12, cal.get(Calendar.DAY_OF_MONTH));
206 assertEquals(1981, cal.get(Calendar.YEAR));
207 assertEquals(0, cal.get(Calendar.HOUR_OF_DAY));
208 assertEquals(0, cal.get(Calendar.MINUTE));
209 assertEquals(0, cal.get(Calendar.SECOND));
210 assertEquals(0, cal.get(Calendar.MILLISECOND));
211 assertEquals(Boolean.FALSE, row.get("I"));
212 }
213
214 public void testCreate() throws Exception {
215 Database db = create();
216 assertEquals(0, db.getTableNames().size());
217 }
218
219 public void testWriteAndRead() throws Exception {
220 Database db = create();
221 createTestTable(db);
222 Object[] row = createTestRow();
223 row[3] = null;
224 Table table = db.getTable("Test");
225 int count = 1000;
226 for (int i = 0; i < count; i++) {
227 table.addRow(row);
228 }
229 for (int i = 0; i < count; i++) {
230 Map<String, Object> readRow = table.getNextRow();
231 assertEquals(row[0], readRow.get("A"));
232 assertEquals(row[1], readRow.get("B"));
233 assertEquals(row[2], readRow.get("C"));
234 assertEquals(row[3], readRow.get("D"));
235 assertEquals(row[4], readRow.get("E"));
236 assertEquals(row[5], readRow.get("F"));
237 assertEquals(row[6], readRow.get("G"));
238 assertEquals(row[7], readRow.get("H"));
239 }
240 }
241
242 public void testWriteAndReadInBatch() throws Exception {
243 Database db = create();
244 createTestTable(db);
245 int count = 1000;
246 List<Object[]> rows = new ArrayList<Object[]>(count);
247 Object[] row = createTestRow();
248 for (int i = 0; i < count; i++) {
249 rows.add(row);
250 }
251 Table table = db.getTable("Test");
252 table.addRows(rows);
253 for (int i = 0; i < count; i++) {
254 Map<String, Object> readRow = table.getNextRow();
255 assertEquals(row[0], readRow.get("A"));
256 assertEquals(row[1], readRow.get("B"));
257 assertEquals(row[2], readRow.get("C"));
258 assertEquals(row[3], readRow.get("D"));
259 assertEquals(row[4], readRow.get("E"));
260 assertEquals(row[5], readRow.get("F"));
261 assertEquals(row[6], readRow.get("G"));
262 assertEquals(row[7], readRow.get("H"));
263 }
264 }
265
266 public void testDeleteCurrentRow() throws Exception {
267
268
269 Database db = create();
270 createTestTable(db);
271 Object[] row1 = createTestRow("Tim1");
272 Object[] row2 = createTestRow("Tim2");
273 Object[] row3 = createTestRow("Tim3");
274 Table table = db.getTable("Test");
275 table.addRows(Arrays.asList(row1, row2, row3));
276 assertRowCount(3, table);
277
278 table.reset();
279 table.getNextRow();
280 table.getNextRow();
281 table.deleteCurrentRow();
282
283 table.reset();
284
285 Map<String, Object> outRow = table.getNextRow();
286 assertEquals("Tim1", outRow.get("A"));
287 outRow = table.getNextRow();
288 assertEquals("Tim3", outRow.get("A"));
289 assertRowCount(2, table);
290
291
292 db = create();
293 createTestTable(db);
294 Object[] row = createTestRow();
295 table = db.getTable("Test");
296 for (int i = 0; i < 10; i++) {
297 row[3] = i;
298 table.addRow(row);
299 }
300 row[3] = 1974;
301 assertRowCount(10, table);
302 table.reset();
303 table.getNextRow();
304 table.deleteCurrentRow();
305 assertRowCount(9, table);
306 table.reset();
307 table.getNextRow();
308 table.deleteCurrentRow();
309 assertRowCount(8, table);
310 table.reset();
311 for (int i = 0; i < 8; i++) {
312 table.getNextRow();
313 }
314 table.deleteCurrentRow();
315 assertRowCount(7, table);
316 table.addRow(row);
317 assertRowCount(8, table);
318 table.reset();
319 for (int i = 0; i < 3; i++) {
320 table.getNextRow();
321 }
322 table.deleteCurrentRow();
323 assertRowCount(7, table);
324 table.reset();
325 assertEquals(2, table.getNextRow().get("D"));
326 }
327
328 public void testReadLongValue() throws Exception {
329
330 Database db = open(new File("test/data/test2.mdb"));
331 Table table = db.getTable("MSP_PROJECTS");
332 Map<String, Object> row = table.getNextRow();
333 assertEquals("Jon Iles this is a a vawesrasoih aksdkl fas dlkjflkasjd flkjaslkdjflkajlksj dfl lkasjdf lkjaskldfj lkas dlk lkjsjdfkl; aslkdf lkasjkldjf lka skldf lka sdkjfl;kasjd falksjdfljaslkdjf laskjdfk jalskjd flkj aslkdjflkjkjasljdflkjas jf;lkasjd fjkas dasdf asd fasdf asdf asdmhf lksaiyudfoi jasodfj902384jsdf9 aw90se fisajldkfj lkasj dlkfslkd jflksjadf as", row.get("PROJ_PROP_AUTHOR"));
334 assertEquals("T", row.get("PROJ_PROP_COMPANY"));
335 assertEquals("Standard", row.get("PROJ_INFO_CAL_NAME"));
336 assertEquals("Project1", row.get("PROJ_PROP_TITLE"));
337 byte[] foundBinaryData = (byte[])row.get("RESERVED_BINARY_DATA");
338 byte[] expectedBinaryData =
339 toByteArray(new File("test/data/test2BinData.dat"));
340 assertTrue(Arrays.equals(expectedBinaryData, foundBinaryData));
341 }
342
343 public void testWriteLongValue() throws Exception {
344
345 Database db = create();
346
347 Table table =
348 new TableBuilder("test")
349 .addColumn(new ColumnBuilder("A", DataType.TEXT).toColumn())
350 .addColumn(new ColumnBuilder("B", DataType.MEMO).toColumn())
351 .addColumn(new ColumnBuilder("C", DataType.OLE).toColumn())
352 .toTable(db);
353
354 String testStr = "This is a test";
355 StringBuilder strBuf = new StringBuilder();
356 for(int i = 0; i < 2030; ++i) {
357 char c = (char)('a' + (i % 26));
358 strBuf.append(c);
359 }
360 String longMemo = strBuf.toString();
361 byte[] oleValue = toByteArray(new File("test/data/test2BinData.dat"));
362
363
364 table.addRow(testStr, testStr, null);
365 table.addRow(testStr, longMemo, oleValue);
366
367 table.reset();
368
369 Map<String, Object> row = table.getNextRow();
370
371 assertEquals(testStr, row.get("A"));
372 assertEquals(testStr, row.get("B"));
373 assertNull(row.get("C"));
374
375 row = table.getNextRow();
376
377 assertEquals(testStr, row.get("A"));
378 assertEquals(longMemo, row.get("B"));
379 assertTrue(Arrays.equals(oleValue, (byte[])row.get("C")));
380
381 }
382
383 public void testMissingFile() throws Exception {
384 File bogusFile = new File("fooby-dooby.mdb");
385 assertTrue(!bogusFile.exists());
386 try {
387 Database db = open(bogusFile);
388 fail("FileNotFoundException should have been thrown");
389 } catch(FileNotFoundException e) {
390 }
391 assertTrue(!bogusFile.exists());
392 }
393
394 public void testReadWithDeletedCols() throws Exception {
395 Table table = open(new File("test/data/delColTest.mdb")).getTable("Table1");
396
397 Map<String, Object> expectedRow0 = new LinkedHashMap<String, Object>();
398 expectedRow0.put("id", 0);
399 expectedRow0.put("id2", 2);
400 expectedRow0.put("data", "foo");
401 expectedRow0.put("data2", "foo2");
402
403 Map<String, Object> expectedRow1 = new LinkedHashMap<String, Object>();
404 expectedRow1.put("id", 3);
405 expectedRow1.put("id2", 5);
406 expectedRow1.put("data", "bar");
407 expectedRow1.put("data2", "bar2");
408
409 int rowNum = 0;
410 Map<String, Object> row = null;
411 while ((row = table.getNextRow()) != null) {
412 if(rowNum == 0) {
413 assertEquals(expectedRow0, row);
414 } else if(rowNum == 1) {
415 assertEquals(expectedRow1, row);
416 } else if(rowNum >= 2) {
417 fail("should only have 2 rows");
418 }
419 rowNum++;
420 }
421 }
422
423 public void testCurrency() throws Exception {
424 Database db = create();
425
426 Table table = new TableBuilder("test")
427 .addColumn(new ColumnBuilder("A", DataType.MONEY).toColumn())
428 .toTable(db);
429
430 table.addRow(new BigDecimal("-2341234.03450"));
431 table.addRow(37L);
432 table.addRow("10000.45");
433
434 table.reset();
435
436 List<Object> foundValues = new ArrayList<Object>();
437 Map<String, Object> row = null;
438 while((row = table.getNextRow()) != null) {
439 foundValues.add(row.get("A"));
440 }
441
442 assertEquals(Arrays.asList(
443 new BigDecimal("-2341234.0345"),
444 new BigDecimal("37.0000"),
445 new BigDecimal("10000.4500")),
446 foundValues);
447
448 try {
449 table.addRow(new BigDecimal("342523234145343543.3453"));
450 fail("IOException should have been thrown");
451 } catch(IOException e) {
452
453 }
454 }
455
456 public void testGUID() throws Exception
457 {
458 Database db = create();
459
460 Table table = new TableBuilder("test")
461 .addColumn(new ColumnBuilder("A", DataType.GUID).toColumn())
462 .toTable(db);
463
464 table.addRow("{32A59F01-AA34-3E29-453F-4523453CD2E6}");
465 table.addRow("{32a59f01-aa34-3e29-453f-4523453cd2e6}");
466 table.addRow("{11111111-1111-1111-1111-111111111111}");
467 table.addRow(" {FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF} ");
468 table.addRow(UUID.fromString("32a59f01-1234-3e29-4aaf-4523453cd2e6"));
469
470 table.reset();
471
472 List<Object> foundValues = new ArrayList<Object>();
473 Map<String, Object> row = null;
474 while((row = table.getNextRow()) != null) {
475 foundValues.add(row.get("A"));
476 }
477
478 assertEquals(Arrays.asList(
479 "{32A59F01-AA34-3E29-453F-4523453CD2E6}",
480 "{32A59F01-AA34-3E29-453F-4523453CD2E6}",
481 "{11111111-1111-1111-1111-111111111111}",
482 "{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}",
483 "{32A59F01-1234-3E29-4AAF-4523453CD2E6}"),
484 foundValues);
485
486 try {
487 table.addRow("3245234");
488 fail("IOException should have been thrown");
489 } catch(IOException e) {
490
491 }
492 }
493
494 public void testNumeric() throws Exception
495 {
496 Database db = create();
497
498 Column col = new ColumnBuilder("A", DataType.NUMERIC)
499 .setScale(4).setPrecision(8).toColumn();
500 assertTrue(col.isVariableLength());
501
502 Table table = new TableBuilder("test")
503 .addColumn(col)
504 .addColumn(new ColumnBuilder("B", DataType.NUMERIC)
505 .setScale(8).setPrecision(28).toColumn())
506 .toTable(db);
507
508 table.addRow(new BigDecimal("-1234.03450"),
509 new BigDecimal("23923434453436.36234219"));
510 table.addRow(37L, 37L);
511 table.addRow("1000.45", "-3452345321000");
512
513 table.reset();
514
515 List<Object> foundSmallValues = new ArrayList<Object>();
516 List<Object> foundBigValues = new ArrayList<Object>();
517 Map<String, Object> row = null;
518 while((row = table.getNextRow()) != null) {
519 foundSmallValues.add(row.get("A"));
520 foundBigValues.add(row.get("B"));
521 }
522
523 assertEquals(Arrays.asList(
524 new BigDecimal("-1234.0345"),
525 new BigDecimal("37.0000"),
526 new BigDecimal("1000.4500")),
527 foundSmallValues);
528 assertEquals(Arrays.asList(
529 new BigDecimal("23923434453436.36234219"),
530 new BigDecimal("37.00000000"),
531 new BigDecimal("-3452345321000.00000000")),
532 foundBigValues);
533
534 try {
535 table.addRow(new BigDecimal("3245234.234"),
536 new BigDecimal("3245234.234"));
537 fail("IOException should have been thrown");
538 } catch(IOException e) {
539
540 }
541 }
542
543 public void testFixedNumeric() throws Exception
544 {
545 Database db = openCopy(new File("test/data/fixedNumericTest.mdb"));
546 Table t = db.getTable("test");
547
548 boolean first = true;
549 for(Column col : t.getColumns()) {
550 if(first) {
551 assertTrue(col.isVariableLength());
552 assertEquals(DataType.MEMO, col.getType());
553 first = false;
554 } else {
555 assertFalse(col.isVariableLength());
556 assertEquals(DataType.NUMERIC, col.getType());
557 }
558 }
559
560 Map<String, Object> row = t.getNextRow();
561 assertEquals("some data", row.get("col1"));
562 assertEquals(new BigDecimal("1"), row.get("col2"));
563 assertEquals(new BigDecimal("0"), row.get("col3"));
564 assertEquals(new BigDecimal("0"), row.get("col4"));
565 assertEquals(new BigDecimal("4"), row.get("col5"));
566 assertEquals(new BigDecimal("-1"), row.get("col6"));
567 assertEquals(new BigDecimal("1"), row.get("col7"));
568
569 Object[] tmpRow = new Object[]{
570 "foo", new BigDecimal("1"), new BigDecimal(3), new BigDecimal("13"),
571 new BigDecimal("-17"), new BigDecimal("0"), new BigDecimal("8734")};
572 t.addRow(tmpRow);
573 t.reset();
574
575 t.getNextRow();
576 row = t.getNextRow();
577 assertEquals(tmpRow[0], row.get("col1"));
578 assertEquals(tmpRow[1], row.get("col2"));
579 assertEquals(tmpRow[2], row.get("col3"));
580 assertEquals(tmpRow[3], row.get("col4"));
581 assertEquals(tmpRow[4], row.get("col5"));
582 assertEquals(tmpRow[5], row.get("col6"));
583 assertEquals(tmpRow[6], row.get("col7"));
584
585 db.close();
586
587 }
588
589 public void testMultiPageTableDef() throws Exception
590 {
591 List<Column> columns = open().getTable("Table2").getColumns();
592 assertEquals(89, columns.size());
593 }
594
595 public void testOverflow() throws Exception
596 {
597 Database mdb = open(new File("test/data/overflowTest.mdb"));
598 Table table = mdb.getTable("Table1");
599
600
601 table.getNextRow();
602 table.getNextRow();
603
604 Map<String, Object> row = table.getNextRow();
605 assertEquals(Arrays.<Object>asList(
606 null, "row3col3", null, null, null, null, null,
607 "row3col9", null),
608 new ArrayList<Object>(row.values()));
609
610 table.getNextRow();
611
612 row = table.getNextRow();
613 assertEquals(Arrays.<Object>asList(
614 null, "row5col2", null, null, null, null, null, null,
615 null),
616 new ArrayList<Object>(row.values()));
617
618 table.reset();
619 assertRowCount(7, table);
620
621 }
622
623 public void testLongValueAsMiddleColumn() throws Exception
624 {
625
626 Database db = create();
627 Table newTable = new TableBuilder("NewTable")
628 .addColumn(new ColumnBuilder("a").setSQLType(Types.INTEGER).toColumn())
629 .addColumn(new ColumnBuilder("b").setSQLType(Types.LONGVARCHAR).toColumn())
630 .addColumn(new ColumnBuilder("c").setSQLType(Types.VARCHAR).toColumn())
631 .toTable(db);
632
633 String lval = createString(2000);
634 String tval = createString(40);
635 newTable.addRow(new Integer(1), lval, tval);
636
637 newTable = db.getTable("NewTable");
638 Map<String, Object> readRow = newTable.getNextRow();
639 assertEquals(new Integer(1), readRow.get("a"));
640 assertEquals(lval, readRow.get("b"));
641 assertEquals(tval, readRow.get("c"));
642
643 }
644
645
646 public void testUsageMapPromotion() throws Exception {
647 Database db = openCopy(new File("test/data/testPromotion.mdb"));
648 Table t = db.getTable("jobDB1");
649
650 String lval = createString(255);
651
652 for(int i = 0; i < 1000; ++i) {
653 t.addRow(i, 13, 57, 47.0d, lval, lval, lval, lval, lval, lval);
654 }
655
656 Set<Integer> ids = new HashSet<Integer>();
657 for(Map<String,Object> row : t) {
658 ids.add((Integer)row.get("ID"));
659 }
660 assertEquals(1000, ids.size());
661
662 db.close();
663 }
664
665
666 public void testLargeTableDef() throws Exception {
667 final int numColumns = 90;
668 Database db = create();
669
670 List<Column> columns = new ArrayList<Column>();
671 List<String> colNames = new ArrayList<String>();
672 for(int i = 0; i < numColumns; ++i) {
673 String colName = "MyColumnName" + i;
674 colNames.add(colName);
675 columns.add(new ColumnBuilder(colName, DataType.TEXT).toColumn());
676 }
677
678 db.createTable("test", columns);
679
680 Table t = db.getTable("test");
681
682 List<String> row = new ArrayList<String>();
683 Map<String,Object> expectedRowData = new LinkedHashMap<String, Object>();
684 for(int i = 0; i < numColumns; ++i) {
685 String value = "" + i + " some row data";
686 row.add(value);
687 expectedRowData.put(colNames.get(i), value);
688 }
689
690 t.addRow(row.toArray());
691
692 t.reset();
693 assertEquals(expectedRowData, t.getNextRow());
694
695 db.close();
696 }
697
698 public void testAutoNumber() throws Exception {
699 Database db = create();
700
701 Table table = new TableBuilder("test")
702 .addColumn(new ColumnBuilder("a", DataType.LONG)
703 .setAutoNumber(true).toColumn())
704 .addColumn(new ColumnBuilder("b", DataType.TEXT).toColumn())
705 .toTable(db);
706
707 doTestAutoNumber(table);
708
709 db.close();
710 }
711
712 public void testAutoNumberPK() throws Exception {
713 Database db = openCopy(new File("test/data/test.mdb"));
714
715 Table table = db.getTable("Table3");
716
717 doTestAutoNumber(table);
718
719 db.close();
720 }
721
722 private void doTestAutoNumber(Table table) throws Exception
723 {
724 table.addRow(null, "row1");
725 table.addRow(13, "row2");
726 table.addRow("flubber", "row3");
727
728 table.reset();
729
730 table.addRow(Column.AUTO_NUMBER, "row4");
731 table.addRow(Column.AUTO_NUMBER, "row5");
732
733 table.reset();
734
735 List<Map<String, Object>> expectedRows =
736 createExpectedTable(
737 createExpectedRow(
738 "a", 1,
739 "b", "row1"),
740 createExpectedRow(
741 "a", 2,
742 "b", "row2"),
743 createExpectedRow(
744 "a", 3,
745 "b", "row3"),
746 createExpectedRow(
747 "a", 4,
748 "b", "row4"),
749 createExpectedRow(
750 "a", 5,
751 "b", "row5"));
752
753 assertTable(expectedRows, table);
754 }
755
756 public void testWriteAndReadDate() throws Exception {
757 Database db = create();
758
759 Table table = new TableBuilder("test")
760 .addColumn(new ColumnBuilder("name", DataType.TEXT).toColumn())
761 .addColumn(new ColumnBuilder("date", DataType.SHORT_DATE_TIME)
762 .toColumn())
763 .toTable(db);
764
765
766
767 long curTimeNoMillis = (System.currentTimeMillis() / 1000L);
768 curTimeNoMillis *= 1000L;
769
770 DateFormat df = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
771 List<Date> dates =
772 new ArrayList<Date>(
773 Arrays.asList(
774 df.parse("19801231 00:00:00"),
775 df.parse("19930513 14:43:27"),
776 null,
777 df.parse("20210102 02:37:00"),
778 new Date(curTimeNoMillis)));
779
780 Calendar c = Calendar.getInstance();
781 for(int year = 1801; year < 2050; year +=3) {
782 for(int month = 0; month <= 12; ++month) {
783 for(int day = 1; day < 29; day += 3) {
784 c.clear();
785 c.set(Calendar.YEAR, year);
786 c.set(Calendar.MONTH, month);
787 c.set(Calendar.DAY_OF_MONTH, day);
788 dates.add(c.getTime());
789 }
790 }
791 }
792
793 for(Date d : dates) {
794 table.addRow("row " + d, d);
795 }
796
797 List<Date> foundDates = new ArrayList<Date>();
798 for(Map<String,Object> row : table) {
799 foundDates.add((Date)row.get("date"));
800 }
801
802 assertEquals(dates.size(), foundDates.size());
803 for(int i = 0; i < dates.size(); ++i) {
804 Date expected = dates.get(i);
805 Date found = foundDates.get(i);
806 if(expected == null) {
807 assertNull(found);
808 } else {
809
810
811
812 long expTime = expected.getTime();
813 long foundTime = found.getTime();
814 try {
815 assertTrue((expTime == foundTime) ||
816 (Math.abs(expTime - foundTime) <= 1));
817 } catch(Error e) {
818 System.err.println("Expected " + expTime + ", found " + foundTime);
819 throw e;
820 }
821 }
822 }
823 }
824
825 static Object[] createTestRow(String col1Val) {
826 return new Object[] {col1Val, "R", "McCune", 1234, (byte) 0xad, 555.66d,
827 777.88f, (short) 999, new Date()};
828 }
829
830 static Object[] createTestRow() {
831 return createTestRow("Tim");
832 }
833
834 static void createTestTable(Database db) throws Exception {
835 new TableBuilder("test")
836 .addColumn(new ColumnBuilder("A", DataType.TEXT).toColumn())
837 .addColumn(new ColumnBuilder("B", DataType.TEXT).toColumn())
838 .addColumn(new ColumnBuilder("C", DataType.TEXT).toColumn())
839 .addColumn(new ColumnBuilder("D", DataType.LONG).toColumn())
840 .addColumn(new ColumnBuilder("E", DataType.BYTE).toColumn())
841 .addColumn(new ColumnBuilder("F", DataType.DOUBLE).toColumn())
842 .addColumn(new ColumnBuilder("G", DataType.FLOAT).toColumn())
843 .addColumn(new ColumnBuilder("H", DataType.INT).toColumn())
844 .addColumn(new ColumnBuilder("I", DataType.SHORT_DATE_TIME).toColumn())
845 .toTable(db);
846 }
847
848 static String createString(int len) {
849 StringBuilder builder = new StringBuilder(len);
850 for(int i = 0; i < len; ++i) {
851 builder.append((char)('a' + (i % 26)));
852 }
853 String str = builder.toString();
854 return str;
855 }
856
857 static void assertRowCount(int expectedRowCount, Table table)
858 throws Exception
859 {
860 assertEquals(expectedRowCount, countRows(table));
861 assertEquals(expectedRowCount, table.getRowCount());
862 }
863
864 static int countRows(Table table) throws Exception {
865 int rtn = 0;
866 for(Map<String, Object> row : Cursor.createCursor(table)) {
867 rtn++;
868 }
869 return rtn;
870 }
871
872 static void assertTable(List<Map<String, Object>> expectedTable, Table table)
873 {
874 List<Map<String, Object>> foundTable =
875 new ArrayList<Map<String, Object>>();
876 for(Map<String, Object> row : Cursor.createCursor(table)) {
877 foundTable.add(row);
878 }
879 assertEquals(expectedTable, foundTable);
880 }
881
882 static Map<String, Object> createExpectedRow(Object... rowElements) {
883 Map<String, Object> row = new LinkedHashMap<String, Object>();
884 for(int i = 0; i < rowElements.length; i += 2) {
885 row.put((String)rowElements[i],
886 rowElements[i + 1]);
887 }
888 return row;
889 }
890
891 @SuppressWarnings("unchecked")
892 static List<Map<String, Object>> createExpectedTable(Map... rows) {
893 return Arrays.<Map<String, Object>>asList(rows);
894 }
895
896 static void dumpDatabase(Database mdb) throws Exception {
897 dumpDatabase(mdb, new PrintWriter(System.out, true));
898 }
899
900 static void dumpTable(Table table) throws Exception {
901 dumpTable(table, new PrintWriter(System.out, true));
902 }
903
904 static void dumpDatabase(Database mdb, PrintWriter writer) throws Exception {
905 writer.println("DATABASE:");
906 for(Table table : mdb) {
907 dumpTable(table, writer);
908 }
909 }
910
911 static void dumpTable(Table table, PrintWriter writer) throws Exception {
912
913 for(Index index : table.getIndexes()) {
914 index.initialize();
915 }
916
917 writer.println("TABLE: " + table.getName());
918 List<String> colNames = new ArrayList<String>();
919 for(Column col : table.getColumns()) {
920 colNames.add(col.getName());
921 }
922 writer.println("COLUMNS: " + colNames);
923 for(Map<String, Object> row : Cursor.createCursor(table)) {
924
925
926 for(Map.Entry<String, Object> entry : row.entrySet()) {
927 Object v = entry.getValue();
928 if(v instanceof byte[]) {
929 byte[] bv = (byte[])v;
930 entry.setValue(ByteUtil.toHexString(ByteBuffer.wrap(bv), bv.length));
931 }
932 }
933
934 writer.println(row);
935 }
936 }
937
938 static void copyFile(File srcFile, File dstFile)
939 throws IOException
940 {
941
942
943 byte[] buf = new byte[1024];
944 OutputStream ostream = new FileOutputStream(dstFile);
945 InputStream istream = new FileInputStream(srcFile);
946 try {
947 int numBytes = 0;
948 while((numBytes = istream.read(buf)) >= 0) {
949 ostream.write(buf, 0, numBytes);
950 }
951 } finally {
952 ostream.close();
953 }
954 }
955
956 static File createTempFile(boolean keep) throws Exception {
957 File tmp = File.createTempFile("databaseTest", ".mdb");
958 if(keep) {
959 System.out.println("Created " + tmp);
960 } else {
961 tmp.deleteOnExit();
962 }
963 return tmp;
964 }
965
966 static byte[] toByteArray(File file)
967 throws IOException
968 {
969
970
971 FileInputStream istream = new FileInputStream(file);
972 try {
973 byte[] bytes = new byte[(int)file.length()];
974 istream.read(bytes);
975 return bytes;
976 } finally {
977 istream.close();
978 }
979 }
980
981 }