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;
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();
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();
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; }
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 */
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
_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);
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);
}
}
+ 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()};