View Javadoc
1   /*
2   Copyright (c) 2008 Health Market Science, Inc.
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.List;
21  import java.util.Random;
22  
23  import junit.framework.TestCase;
24  
25  import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;
26  import com.healthmarketscience.jackcess.impl.TableImpl;
27  import com.healthmarketscience.jackcess.impl.IndexImpl;
28  import static com.healthmarketscience.jackcess.TestUtil.*;
29  
30  /**
31   * @author james
32   */
33  public class BigIndexTest extends TestCase {
34  
35    public BigIndexTest(String name) {
36      super(name);
37    }
38    
39    public void testComplexIndex() throws Exception
40    {
41      for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.COMP_INDEX, true)) {
42        // this file has an index with "compressed" entries and node pages
43        Database db = openMem(testDB);
44        TableImpl t = (TableImpl)db.getTable("Table1");
45        IndexImpl index = t.getIndex("CD_AGENTE");
46        assertFalse(index.isInitialized());
47        assertEquals(512, countRows(t));
48        assertEquals(512, index.getIndexData().getEntryCount());
49        db.close();
50      }
51    }
52  
53    public void testBigIndex() throws Exception
54    {
55      for (final TestDB testDB : TestDB.getSupportedForBasename(Basename.BIG_INDEX)) {
56      // this file has an index with "compressed" entries and node pages
57        Database db = openMem(testDB);
58        TableImpl t = (TableImpl)db.getTable("Table1");
59        IndexImpl index = t.getIndex("col1");
60        assertFalse(index.isInitialized());
61        assertEquals(0, countRows(t));
62        assertEquals(0, index.getIndexData().getEntryCount());
63        db.close();
64  
65        TestUtil.setTestAutoSync(false);
66        try {
67  
68          String extraText = " some random text to fill out the index and make it fill up pages with lots of extra bytes so i will keep typing until i think that i probably have enough text in the index entry so that i do not need to add as many entries in order";
69  
70          // copy to temp file and attempt to edit
71          db = openMem(testDB);
72          t = (TableImpl)db.getTable("Table1");
73          index = t.getIndex("col1");
74  
75          // add 2,000 (pseudo) random entries to the table
76          Random rand = new Random(13L);
77          for(int i = 0; i < 2000; ++i) {
78            if((i == 850) || (i == 1850)) {
79              int end = i + 50;
80              List<Object[]> rows = new ArrayList<Object[]>(50);
81              for(; i < end; ++i) {
82                int nextInt = rand.nextInt(Integer.MAX_VALUE);
83                String nextVal = "" + nextInt + extraText;
84                if(((i + 1) % 333) == 0) {
85                  nextVal = null;
86                }
87                rows.add(new Object[]{nextVal,
88                                      "this is some row data " + nextInt});
89              }
90              t.addRows(rows);
91              --i;
92            } else {
93              int nextInt = rand.nextInt(Integer.MAX_VALUE);
94              String nextVal = "" + nextInt + extraText;
95              if(((i + 1) % 333) == 0) {
96                nextVal = null;
97              }
98              t.addRow(nextVal, "this is some row data " + nextInt);
99            }
100         }
101 
102         index.getIndexData().validate();
103 
104         db.flush();
105         t = null;
106         System.gc();
107         
108         t = (TableImpl)db.getTable("Table1");
109         index = t.getIndex("col1");
110 
111         // make sure all entries are there and correctly ordered
112         String firstValue = "      ";
113         String prevValue = firstValue;
114         int rowCount = 0;
115         List<String> firstTwo = new ArrayList<String>();
116         for(Row row : CursorBuilder.createCursor(index)) {
117           String origVal = row.getString("col1");
118           String val = origVal;
119           if(val == null) {
120             val = firstValue;
121           }
122           assertTrue("" + prevValue + " <= " + val + " " + rowCount,
123                      prevValue.compareTo(val) <= 0);
124           if(firstTwo.size() < 2) {
125             firstTwo.add(origVal);
126           }
127           prevValue = val;
128           ++rowCount;
129         }
130 
131         assertEquals(2000, rowCount);
132 
133         index.getIndexData().validate();
134 
135         // delete an entry in the middle
136         Cursor cursor = CursorBuilder.createCursor(index);
137         for(int i = 0; i < (rowCount / 2); ++i) {
138           assertTrue(cursor.moveToNextRow());
139         }
140         cursor.deleteCurrentRow();
141         --rowCount;
142 
143         // remove all but the first two entries (from the end)
144         cursor.afterLast();
145         for(int i = 0; i < (rowCount - 2); ++i) {
146           assertTrue(cursor.moveToPreviousRow());
147           cursor.deleteCurrentRow();
148         }
149 
150         index.getIndexData().validate();
151 
152         List<String> found = new ArrayList<String>();
153         for(Row row : CursorBuilder.createCursor(index)) {
154           found.add(row.getString("col1"));
155         }
156 
157         assertEquals(firstTwo, found);
158 
159         // remove remaining entries
160         cursor = CursorBuilder.createCursor(t);
161         for(int i = 0; i < 2; ++i) {
162           assertTrue(cursor.moveToNextRow());
163           cursor.deleteCurrentRow();
164         }
165 
166         assertFalse(cursor.moveToNextRow());
167         assertFalse(cursor.moveToPreviousRow());
168 
169         index.getIndexData().validate();
170 
171         // add 50 (pseudo) random entries to the table
172         rand = new Random(42L);
173         for(int i = 0; i < 50; ++i) {
174           int nextInt = rand.nextInt(Integer.MAX_VALUE);
175           String nextVal = "some prefix " + nextInt + extraText;
176           if(((i + 1) % 3333) == 0) {
177             nextVal = null;
178           }
179           t.addRow(nextVal, "this is some row data " + nextInt);
180         }
181 
182         index.getIndexData().validate();
183 
184         cursor = CursorBuilder.createCursor(index);
185         while(cursor.moveToNextRow()) {
186           cursor.deleteCurrentRow();
187         }
188 
189         index.getIndexData().validate();
190 
191         db.close();
192 
193       } finally {
194         TestUtil.clearTestAutoSync();
195       }
196     }
197   }
198 
199 }