]> source.dussan.org Git - jackcess.git/commitdiff
handle more tables with more idnex slots than actual indexes (fix bug 1530312)
authorJames Ahlborn <jtahlborn@yahoo.com>
Sun, 30 Jul 2006 03:22:36 +0000 (03:22 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Sun, 30 Jul 2006 03:22:36 +0000 (03:22 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@78 f203690c-595d-4dc9-a70b-905162fa7fd2

src/java/com/healthmarketscience/jackcess/JetFormat.java
src/java/com/healthmarketscience/jackcess/Table.java
test/data/indexTest.mdb [new file with mode: 0644]
test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java

index dc127b1f972ac52f371452af2dc94ccd64f8d092..ec5c73ebd2d94d8da979c429fd447056171cb5b9 100644 (file)
@@ -68,6 +68,7 @@ public abstract class JetFormat {
   public final int OFFSET_MAX_COLS;
   public final int OFFSET_NUM_VAR_COLS;
   public final int OFFSET_NUM_COLS;
+  public final int OFFSET_NUM_INDEX_SLOTS;
   public final int OFFSET_NUM_INDEXES;
   public final int OFFSET_OWNED_PAGES;
   public final int OFFSET_FREE_SPACE_PAGES;
@@ -151,6 +152,7 @@ public abstract class JetFormat {
     OFFSET_MAX_COLS = defineOffsetMaxCols();
     OFFSET_NUM_VAR_COLS = defineOffsetNumVarCols();
     OFFSET_NUM_COLS = defineOffsetNumCols();
+    OFFSET_NUM_INDEX_SLOTS = defineOffsetNumIndexSlots();
     OFFSET_NUM_INDEXES = defineOffsetNumIndexes();
     OFFSET_OWNED_PAGES = defineOffsetOwnedPages();
     OFFSET_FREE_SPACE_PAGES = defineOffsetFreeSpacePages();
@@ -213,6 +215,7 @@ public abstract class JetFormat {
   protected abstract int defineOffsetMaxCols();
   protected abstract int defineOffsetNumVarCols();
   protected abstract int defineOffsetNumCols();
+  protected abstract int defineOffsetNumIndexSlots();
   protected abstract int defineOffsetNumIndexes();
   protected abstract int defineOffsetOwnedPages();
   protected abstract int defineOffsetFreeSpacePages();
@@ -276,6 +279,7 @@ public abstract class JetFormat {
     protected int defineOffsetMaxCols() { return 41; }
     protected int defineOffsetNumVarCols() { return 43; }
     protected int defineOffsetNumCols() { return 45; }
+    protected int defineOffsetNumIndexSlots() { return 47; }
     protected int defineOffsetNumIndexes() { return 51; }
     protected int defineOffsetOwnedPages() { return 55; }
     protected int defineOffsetFreeSpacePages() { return 59; }
index c1bf4554fbb44e15639a3c1ae0ce10053741a4b9..9637c4ead6725953af9ee97e9db762442079809d 100644 (file)
@@ -63,6 +63,8 @@ public class Table {
   private int _currentRowInPage;
   /** Number of indexes on the table */
   private int _indexCount;
+  /** Number of index slots for the table */
+  private int _indexSlotCount;
   /** Offset index in the buffer where the last row read started */
   private short _lastRowStart;
   /** Number of rows in the table */
@@ -164,6 +166,13 @@ public class Table {
   public List<Index> getIndexes() {
     return Collections.unmodifiableList(_indexes);
   }
+
+  /**
+   * Only called by unit tests
+   */
+  int getIndexSlotCount() {
+    return _indexSlotCount;
+  }
   
   /**
    * After calling this method, getNextRow will return the first row in the table
@@ -334,6 +343,7 @@ public class Table {
     _maxColumnCount = _buffer.getShort(_format.OFFSET_MAX_COLS);
     _maxVarColumnCount = _buffer.getShort(_format.OFFSET_NUM_VAR_COLS);
     _columnCount = _buffer.getShort(_format.OFFSET_NUM_COLS);
+    _indexSlotCount = _buffer.getInt(_format.OFFSET_NUM_INDEX_SLOTS);
     _indexCount = _buffer.getInt(_format.OFFSET_NUM_INDEXES);
     
     byte rowNum = _buffer.get(_format.OFFSET_OWNED_PAGES);
@@ -379,14 +389,34 @@ public class Table {
     int idxOffset = _buffer.position();
     _buffer.position(idxOffset +
                      (_format.OFFSET_INDEX_NUMBER_BLOCK * _indexCount));
-    for (int i = 0; i < _indexCount; i++) {
-      Index index = _indexes.get(i);
+
+    // there are _indexSlotCount blocks here, we ignore any slot with an index
+    // number greater than the number of actual indexes
+    int curIndex = 0;
+    for (int i = 0; i < _indexSlotCount; i++) {
+      
       _buffer.getInt(); //Forward past Unknown
-      index.setIndexNumber(_buffer.getInt());
+      int indexNumber = _buffer.getInt();
       _buffer.position(_buffer.position() + 15);
-      index.setPrimaryKey(_buffer.get() == 1);
+      byte indexType = _buffer.get();
       _buffer.position(_buffer.position() + 4);
+
+      if(indexNumber < _indexCount) {
+        Index index = _indexes.get(curIndex++);
+        index.setIndexNumber(indexNumber);
+        index.setPrimaryKey(indexType == 1);
+      }
     }
+
+    // for each empty index slot, there is some weird sort of name
+    for(int i = 0; i < (_indexSlotCount - _indexCount); ++i) {
+      int skipBytes = _buffer.getShort();
+      _buffer.position(_buffer.position() + skipBytes);
+    }
+
+    // read actual index names
+    // FIXME, we still are not always getting the names matched correctly with
+    // the index info, some weird indexing we are not figuring out yet
     for (int i = 0; i < _indexCount; i++) {
       byte[] nameBytes = new byte[_buffer.getShort()];
       _buffer.get(nameBytes);
diff --git a/test/data/indexTest.mdb b/test/data/indexTest.mdb
new file mode 100644 (file)
index 0000000..7e8bd98
Binary files /dev/null and b/test/data/indexTest.mdb differ
index f22edcb0331ec8b7499205faf3ca45293f7bc430..084fa65abc85a831f050b6a79f78c3679ef0869e 100644 (file)
@@ -423,6 +423,23 @@ public class DatabaseTest extends TestCase {
     }
   }
 
+  public void testIndexSlots() throws Exception
+  {
+    Database mdb = Database.open(new File("test/data/indexTest.mdb"));
+
+    Table table = mdb.getTable("Table1");
+    assertEquals(4, table.getIndexes().size());
+    assertEquals(4, table.getIndexSlotCount());
+
+    table = mdb.getTable("Table2");
+    assertEquals(2, table.getIndexes().size());
+    assertEquals(3, table.getIndexSlotCount());
+
+    table = mdb.getTable("Table3");
+    assertEquals(2, table.getIndexes().size());
+    assertEquals(3, table.getIndexSlotCount());
+ }
+  
   private Object[] createTestRow() {
     return new Object[] {"Tim", "R", "McCune", 1234, (byte) 0xad, 555.66d,
         777.88f, (short) 999, new Date()};