Fixed bug where adding a new row to a table whose last row had been deleted failed. git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@29 f203690c-595d-4dc9-a70b-905162fa7fd2tags/rel_1_1_3
@@ -3,7 +3,7 @@ | |||
<pomVersion>1</pomVersion> | |||
<id>jackcess</id> | |||
<name>Jackcess</name> | |||
<currentVersion>1.1.2</currentVersion> | |||
<currentVersion>1.1.3</currentVersion> | |||
<organization> | |||
<name>Health Market Science, Inc.</name> | |||
<url>http://www.healthmarketscience.com</url> |
@@ -139,6 +139,7 @@ public class Table { | |||
public void reset() { | |||
_rowsLeftOnPage = 0; | |||
_ownedPages.reset(); | |||
_currentRowInPage = 0; | |||
} | |||
/** | |||
@@ -147,6 +148,19 @@ public class Table { | |||
public Map<String, Object> getNextRow() throws IOException { | |||
return getNextRow(null); | |||
} | |||
/** | |||
* Delete the current row (retrieved by a call to {@link #getNextRow}). | |||
*/ | |||
public void deleteCurrentRow() throws IOException { | |||
if (_currentRowInPage == 0) { | |||
throw new IllegalStateException("Must call getNextRow first"); | |||
} | |||
int index = _format.OFFSET_DATA_ROW_LOCATION_BLOCK + (_currentRowInPage - 1) * | |||
_format.SIZE_ROW_LOCATION + 1; | |||
_buffer.put(index, (byte) (_buffer.get(index) | 0xc0)); | |||
_pageChannel.writePage(_buffer, _ownedPages.getCurrentPageNumber()); | |||
} | |||
/** | |||
* @param columnNames Only column names in this collection will be returned | |||
@@ -384,6 +398,10 @@ public class Table { | |||
if (rowCount > 0) { | |||
rowLocation = dataPage.getShort(_format.OFFSET_DATA_ROW_LOCATION_BLOCK + | |||
(rowCount - 1) * _format.SIZE_ROW_LOCATION); | |||
if (rowLocation < 0) { | |||
// Deleted row | |||
rowLocation &= ~0xc000; | |||
} | |||
} | |||
rowLocation -= rowSize; | |||
dataPage.putShort(_format.OFFSET_DATA_ROW_LOCATION_BLOCK + |
@@ -128,7 +128,11 @@ public abstract class UsageMap { | |||
public List<Integer> getPageNumbers() { | |||
return _pageNumbers; | |||
} | |||
public Integer getCurrentPageNumber() { | |||
return _pageNumbers.get(_currentPageIndex - 1); | |||
} | |||
protected void setStartOffset(int startOffset) { | |||
_startOffset = startOffset; | |||
} | |||
@@ -166,8 +170,8 @@ public abstract class UsageMap { | |||
*/ | |||
public boolean getNextPage(ByteBuffer buffer) throws IOException { | |||
if (_pageNumbers.size() > _currentPageIndex) { | |||
Integer pageNumber = (Integer) _pageNumbers.get(_currentPageIndex++); | |||
_pageChannel.readPage(buffer, pageNumber.intValue()); | |||
Integer pageNumber = _pageNumbers.get(_currentPageIndex++); | |||
_pageChannel.readPage(buffer, pageNumber); | |||
return true; | |||
} else { | |||
return false; |
@@ -103,16 +103,8 @@ public class DatabaseTest extends TestCase { | |||
public void testWriteAndRead() throws Exception { | |||
Database db = create(); | |||
createTestTable(db); | |||
Object[] row = new Object[9]; | |||
row[0] = "Tim"; | |||
row[1] = "R"; | |||
row[2] = "McCune"; | |||
Object[] row = createTestRow(); | |||
row[3] = null; | |||
row[4] = new Byte((byte) 0xad); | |||
row[5] = new Double(555.66d); | |||
row[6] = new Float(777.88d); | |||
row[7] = new Short((short) 999); | |||
row[8] = new Date(); | |||
Table table = db.getTable("Test"); | |||
int count = 1000; | |||
for (int i = 0; i < count; i++) { | |||
@@ -136,16 +128,7 @@ public class DatabaseTest extends TestCase { | |||
createTestTable(db); | |||
int count = 1000; | |||
List<Object[]> rows = new ArrayList<Object[]>(count); | |||
Object[] row = new Object[9]; | |||
row[0] = "Tim"; | |||
row[1] = "R"; | |||
row[2] = "McCune"; | |||
row[3] = new Integer(1234); | |||
row[4] = new Byte((byte) 0xad); | |||
row[5] = new Double(555.66d); | |||
row[6] = new Float(777.88d); | |||
row[7] = new Short((short) 999); | |||
row[8] = new Date(); | |||
Object[] row = createTestRow(); | |||
for (int i = 0; i < count; i++) { | |||
rows.add(row); | |||
} | |||
@@ -163,6 +146,57 @@ public class DatabaseTest extends TestCase { | |||
assertEquals(row[7], readRow.get("H")); | |||
} | |||
} | |||
public void testDeleteCurrentRow() throws Exception { | |||
Database db = create(); | |||
createTestTable(db); | |||
Object[] row = createTestRow(); | |||
Table table = db.getTable("Test"); | |||
for (int i = 0; i < 10; i++) { | |||
row[3] = i; | |||
table.addRow(row); | |||
} | |||
row[3] = 1974; | |||
assertEquals(10, countRows(table)); | |||
table.reset(); | |||
table.getNextRow(); | |||
table.deleteCurrentRow(); | |||
assertEquals(9, countRows(table)); | |||
table.reset(); | |||
table.getNextRow(); | |||
table.deleteCurrentRow(); | |||
assertEquals(8, countRows(table)); | |||
table.reset(); | |||
for (int i = 0; i < 8; i++) { | |||
table.getNextRow(); | |||
} | |||
table.deleteCurrentRow(); | |||
assertEquals(7, countRows(table)); | |||
table.addRow(row); | |||
assertEquals(8, countRows(table)); | |||
table.reset(); | |||
for (int i = 0; i < 3; i++) { | |||
table.getNextRow(); | |||
} | |||
table.deleteCurrentRow(); | |||
assertEquals(7, countRows(table)); | |||
table.reset(); | |||
assertEquals(2, table.getNextRow().get("D")); | |||
} | |||
private int countRows(Table table) throws Exception { | |||
table.reset(); | |||
int rtn = 0; | |||
while (table.getNextRow() != null) { | |||
rtn++; | |||
} | |||
return rtn; | |||
} | |||
private Object[] createTestRow() { | |||
return new Object[] {"Tim", "R", "McCune", 1234, (byte) 0xad, 555.66d, | |||
777.88f, (short) 999, new Date()}; | |||
} | |||
private void createTestTable(Database db) throws Exception { | |||
List<Column> columns = new ArrayList<Column>(); |