aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2007-11-19 05:02:37 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2007-11-19 05:02:37 +0000
commit5bbf41da2dd6042820c88d8866e26df46665cfa3 (patch)
tree35e719a15551da5229d932fb5ec44ca2aee8c180
parent588da3ba5eb273dc5920173b4a87049223639eb6 (diff)
downloadjackcess-5bbf41da2dd6042820c88d8866e26df46665cfa3.tar.gz
jackcess-5bbf41da2dd6042820c88d8866e26df46665cfa3.zip
work toward separating table iteration state from the Table class
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@176 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--src/java/com/healthmarketscience/jackcess/Cursor.java32
-rw-r--r--src/java/com/healthmarketscience/jackcess/RowId.java60
-rw-r--r--src/java/com/healthmarketscience/jackcess/Table.java128
3 files changed, 178 insertions, 42 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/Cursor.java b/src/java/com/healthmarketscience/jackcess/Cursor.java
new file mode 100644
index 0000000..3a161db
--- /dev/null
+++ b/src/java/com/healthmarketscience/jackcess/Cursor.java
@@ -0,0 +1,32 @@
+// Copyright (c) 2007 Health Market Science, Inc.
+
+package com.healthmarketscience.jackcess;
+
+/**
+ * Describe class Cursor here.
+ *
+ *
+ * @author james
+ */
+public class Cursor {
+
+ /** owning table */
+ private final Table _table;
+// /** Number of the current row in a data page */
+// private int _currentRowInPage = INVALID_ROW_NUMBER;
+// /** Number of rows left to be read on the current page */
+// private short _rowsLeftOnPage = 0;
+// /** State used for reading the table rows */
+// private RowState _rowState;
+// /** Iterator over the pages that this table owns */
+// private UsageMap.PageIterator _ownedPagesIterator;
+
+ /**
+ * Creates a new <code>Cursor</code> instance.
+ *
+ */
+ public Cursor(Table table) {
+ _table = table;
+ }
+
+}
diff --git a/src/java/com/healthmarketscience/jackcess/RowId.java b/src/java/com/healthmarketscience/jackcess/RowId.java
new file mode 100644
index 0000000..6ef7bc3
--- /dev/null
+++ b/src/java/com/healthmarketscience/jackcess/RowId.java
@@ -0,0 +1,60 @@
+// Copyright (c) 2007 Health Market Science, Inc.
+
+package com.healthmarketscience.jackcess;
+
+import org.apache.commons.lang.builder.CompareToBuilder;
+
+
+/**
+ * Uniquely identifies a row of data within the access database.
+ *
+ * @author james
+ */
+public class RowId implements Comparable<RowId>
+{
+ private final int _pageNumber;
+ private final int _rowNumber;
+
+ /**
+ * Creates a new <code>RowId</code> instance.
+ *
+ */
+ public RowId(int pageNumber,int rowNumber) {
+ _pageNumber = pageNumber;
+ _rowNumber = rowNumber;
+ }
+
+ public int getPageNumber() {
+ return _pageNumber;
+ }
+
+ public int getRowNumber() {
+ return _rowNumber;
+ }
+
+ public int compareTo(RowId other) {
+ return new CompareToBuilder()
+ .append(getPageNumber(), other.getPageNumber())
+ .append(getRowNumber(), other.getRowNumber())
+ .toComparison();
+ }
+
+ @Override
+ public int hashCode() {
+ return getPageNumber() ^ getRowNumber();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return ((this == o) ||
+ ((o != null) && (getClass() == o.getClass()) &&
+ (getPageNumber() == ((RowId)o).getPageNumber()) &&
+ (getRowNumber() == ((RowId)o).getRowNumber())));
+ }
+
+ @Override
+ public String toString() {
+ return getPageNumber() + ":" + getRowNumber();
+ }
+
+}
diff --git a/src/java/com/healthmarketscience/jackcess/Table.java b/src/java/com/healthmarketscience/jackcess/Table.java
index 9fdc5c5..08d7a2b 100644
--- a/src/java/com/healthmarketscience/jackcess/Table.java
+++ b/src/java/com/healthmarketscience/jackcess/Table.java
@@ -83,8 +83,6 @@ public class Table
private RowState _rowState;
/** Type of the table (either TYPE_SYSTEM or TYPE_USER) */
private byte _tableType;
- /** Number of the current row in a data page */
- private int _currentRowInPage = INVALID_ROW_NUMBER;
/** Number of indexes on the table */
private int _indexCount;
/** Number of index slots for the table */
@@ -237,7 +235,6 @@ public class Table
*/
public void reset() {
_rowsLeftOnPage = 0;
- _currentRowInPage = INVALID_ROW_NUMBER;
_ownedPagesIterator.reset();
_rowState.reset();
}
@@ -246,7 +243,7 @@ public class Table
* Delete the current row (retrieved by a call to {@link #getNextRow}).
*/
public void deleteCurrentRow() throws IOException {
- if (_currentRowInPage == INVALID_ROW_NUMBER) {
+ if (_rowState.getRowNumber() == INVALID_ROW_NUMBER) {
throw new IllegalStateException("Must call getNextRow first");
}
@@ -260,7 +257,8 @@ public class Table
// delete flag always gets set in the "root" page (even if overflow row)
ByteBuffer rowBuffer = _rowState.getPage(getPageChannel());
int pageNumber = _rowState.getPageNumber();
- int rowIndex = getRowStartOffset(_currentRowInPage, getFormat());
+ int rowNumber = _rowState.getRowNumber();
+ int rowIndex = getRowStartOffset(rowNumber, getFormat());
rowBuffer.putShort(rowIndex, (short)(rowBuffer.getShort(rowIndex)
| DELETED_ROW_MASK | OVERFLOW_ROW_MASK));
writeDataPage(rowBuffer, pageNumber);
@@ -268,8 +266,7 @@ public class Table
// update the indexes
for(Index index : _indexes) {
- index.deleteRow(_rowState.getRowValues(), pageNumber,
- (byte)_currentRowInPage);
+ index.deleteRow(_rowState.getRowValues(), pageNumber, (byte)rowNumber);
}
// make sure table def gets updated
@@ -310,11 +307,11 @@ public class Table
throws IOException
{
// set row state to correct page
- rowState.setPage(pageChannel, pageNumber);
+ rowState.reset();
+ rowState.setPage(pageChannel, pageNumber, rowNum);
// position at correct row
- ByteBuffer rowBuffer = positionAtRow(rowState, rowNum, pageChannel,
- format);
+ ByteBuffer rowBuffer = positionAtRow(rowState, pageChannel, format);
if(rowBuffer == null) {
// note, row state will indicate that row was deleted
return null;
@@ -334,11 +331,11 @@ public class Table
throws IOException
{
// set row state to correct page
- rowState.setPage(pageChannel, pageNumber);
+ rowState.reset();
+ rowState.setPage(pageChannel, pageNumber, rowNum);
// position at correct row
- ByteBuffer rowBuffer = positionAtRow(rowState, rowNum, pageChannel,
- format);
+ ByteBuffer rowBuffer = positionAtRow(rowState, pageChannel, format);
if(rowBuffer == null) {
// note, row state will indicate that row was deleted
return null;
@@ -456,22 +453,22 @@ public class Table
*/
private ByteBuffer positionAtNextRow() throws IOException {
+ // prepare to read next row
+ _rowState.reset();
+
// loop until we find the next valid row or run out of pages
while(true) {
if (_rowsLeftOnPage == 0) {
- // reset row number
- _currentRowInPage = INVALID_ROW_NUMBER;
-
- int nextPageNumber = _ownedPagesIterator.getNextPage();
- if (nextPageNumber == PageChannel.INVALID_PAGE_NUMBER) {
+ // load next page
+ ByteBuffer rowBuffer = _rowState.setPage(
+ getPageChannel(), _ownedPagesIterator.getNextPage(),
+ INVALID_ROW_NUMBER);
+ if(rowBuffer == null) {
//No more owned pages. No more rows.
return null;
- }
-
- // load new page
- ByteBuffer rowBuffer = _rowState.setPage(getPageChannel(), nextPageNumber);
+ }
if(rowBuffer.get() != PageTypes.DATA) {
//Only interested in data pages
continue;
@@ -486,11 +483,11 @@ public class Table
}
// move to next row
- _currentRowInPage++;
+ _rowState.nextRowInPage();
_rowsLeftOnPage--;
ByteBuffer rowBuffer =
- positionAtRow(_rowState, _currentRowInPage, getPageChannel(), getFormat());
+ positionAtRow(_rowState, getPageChannel(), getFormat());
if(rowBuffer != null) {
// we found a non-deleted row, return it
return rowBuffer;
@@ -503,18 +500,20 @@ public class Table
* according to the given row number and row end, following overflow row
* pointers as necessary.
*
- * @return a ByteBuffer narrowed to the next row, or null if row was deleted
+ * @return a ByteBuffer narrowed to the actual row data, or null if row was
+ * deleted
*/
- private static ByteBuffer positionAtRow(RowState rowState, int rowNum,
+ private static ByteBuffer positionAtRow(RowState rowState,
PageChannel pageChannel,
JetFormat format)
throws IOException
{
// reset row state
- rowState.reset();
+ rowState.resetDuringSearch();
while(true) {
ByteBuffer rowBuffer = rowState.getFinalPage(pageChannel);
+ int rowNum = rowState.getFinalRowNumber();
// note, we don't use findRowStart here cause we need the unmasked value
short rowStart = rowBuffer.getShort(getRowStartOffset(rowNum, format));
@@ -556,10 +555,8 @@ public class Table
// page/row
int overflowRowNum = rowBuffer.get(rowStart);
int overflowPageNum = ByteUtil.get3ByteInt(rowBuffer, rowStart + 1);
- rowState.setOverflowPage(pageChannel, overflowPageNum);
-
- // reset row number and move to overflow page
- rowNum = overflowRowNum;
+ rowState.setOverflowPage(pageChannel, overflowPageNum,
+ overflowRowNum);
} else {
@@ -1436,18 +1433,23 @@ public class Table
{
/** Buffer used for reading the row data pages */
private TempPageHolder _rowBufferH;
+ /** row number of the main row */
+ private int _rowNumber;
/** true if the current row is an overflow row */
- public boolean _overflow;
+ private boolean _overflow;
/** true if the current row is a deleted row */
- public boolean _deleted;
+ private boolean _deleted;
/** buffer used for reading overflow pages */
- public TempPageHolder _overflowRowBufferH =
+ private TempPageHolder _overflowRowBufferH =
TempPageHolder.newHolder(false);
/** the row buffer which contains the final data (after following any
overflow pointers) */
- public ByteBuffer _finalRowBuffer;
+ private ByteBuffer _finalRowBuffer;
+ /** the row number which contains the final data (after following any
+ overflow pointers) */
+ private int _finalRowNumber;
/** values read from the last row */
- public Object[] _rowValues;
+ private Object[] _rowValues;
public RowState(boolean hardRowBuffer, int colCount) {
_rowBufferH = TempPageHolder.newHolder(hardRowBuffer);
@@ -1455,16 +1457,33 @@ public class Table
}
public void reset() {
- _finalRowBuffer = null;
- _deleted = false;
- _overflow = false;
+ resetDuringSearch();
Arrays.fill(_rowValues, null);
}
+ public void resetDuringSearch() {
+ resetNewPage();
+ resetNewRow();
+ }
+
+ private void resetNewRow() {
+ _finalRowNumber = INVALID_ROW_NUMBER;
+ }
+
+ private void resetNewPage() {
+ _finalRowBuffer = null;
+ _deleted = false;
+ _overflow = false;
+ }
+
public int getPageNumber() {
return _rowBufferH.getPageNumber();
}
+ public int getRowNumber() {
+ return _rowNumber;
+ }
+
public ByteBuffer getFinalPage(PageChannel pageChannel)
throws IOException
{
@@ -1475,6 +1494,13 @@ public class Table
return _finalRowBuffer;
}
+ public int getFinalRowNumber() {
+ if(_finalRowNumber == INVALID_ROW_NUMBER) {
+ _finalRowNumber = _rowNumber;
+ }
+ return _finalRowNumber;
+ }
+
public void setDeleted(boolean deleted) {
_deleted = deleted;
}
@@ -1505,19 +1531,37 @@ public class Table
return _rowBufferH.getPage(pageChannel);
}
- public ByteBuffer setPage(PageChannel pageChannel, int pageNumber)
+ public void nextRowInPage() {
+ setRowNumber(_rowNumber + 1);
+ }
+
+ public void setRowNumber(int rowNumber) {
+ resetNewRow();
+ _rowNumber = rowNumber;
+ _finalRowNumber = rowNumber;
+ }
+
+ public ByteBuffer setPage(PageChannel pageChannel, int pageNumber,
+ int rowNumber)
throws IOException
{
- reset();
+ resetNewPage();
+ setRowNumber(rowNumber);
+ if(pageNumber == PageChannel.INVALID_PAGE_NUMBER) {
+ _rowBufferH.invalidate();
+ return null;
+ }
_finalRowBuffer = _rowBufferH.setPage(pageChannel, pageNumber);
return _finalRowBuffer;
}
- public ByteBuffer setOverflowPage(PageChannel pageChannel, int pageNumber)
+ public ByteBuffer setOverflowPage(PageChannel pageChannel, int pageNumber,
+ int rowNumber)
throws IOException
{
_overflow = true;
_finalRowBuffer = _overflowRowBufferH.setPage(pageChannel, pageNumber);
+ _finalRowNumber = rowNumber;
return _finalRowBuffer;
}