summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/java/com/healthmarketscience/jackcess/JetFormat.java4
-rw-r--r--src/java/com/healthmarketscience/jackcess/Table.java38
-rw-r--r--test/data/indexTest.mdbbin0 -> 196608 bytes
-rw-r--r--test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java17
4 files changed, 55 insertions, 4 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/JetFormat.java b/src/java/com/healthmarketscience/jackcess/JetFormat.java
index dc127b1..ec5c73e 100644
--- a/src/java/com/healthmarketscience/jackcess/JetFormat.java
+++ b/src/java/com/healthmarketscience/jackcess/JetFormat.java
@@ -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; }
diff --git a/src/java/com/healthmarketscience/jackcess/Table.java b/src/java/com/healthmarketscience/jackcess/Table.java
index c1bf455..9637c4e 100644
--- a/src/java/com/healthmarketscience/jackcess/Table.java
+++ b/src/java/com/healthmarketscience/jackcess/Table.java
@@ -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
index 0000000..7e8bd98
--- /dev/null
+++ b/test/data/indexTest.mdb
Binary files differ
diff --git a/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java b/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java
index f22edcb..084fa65 100644
--- a/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java
+++ b/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java
@@ -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()};