summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2008-03-24 17:06:24 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2008-03-24 17:06:24 +0000
commitfefc08596f2fd8e2c51150d14d78b0caa417ed4e (patch)
tree388974750bc2d4e320feecc2ab83b39a70c03e8d
parentd0c37f811ddea274b5860941d52456d2678d0aaa (diff)
downloadjackcess-fefc08596f2fd8e2c51150d14d78b0caa417ed4e.tar.gz
jackcess-fefc08596f2fd8e2c51150d14d78b0caa417ed4e.zip
Need to store auto-number values back into row so that indexes can be
updated correctly. git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@296 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--src/changes/changes.xml6
-rw-r--r--src/java/com/healthmarketscience/jackcess/Database.java4
-rw-r--r--src/java/com/healthmarketscience/jackcess/Table.java85
-rw-r--r--test/data/test.mdbbin2904064 -> 3035136 bytes
-rw-r--r--test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java25
5 files changed, 89 insertions, 31 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 7225789..0223e4b 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -5,6 +5,12 @@
<author email="jahlborn@users.sf.net">James Ahlborn</author>
</properties>
<body>
+ <release version="1.1.14" date="TBD">
+ <action dev="jahlborn" type="fix">
+ Need to store auto-number values back into row so that indexes can be
+ updated correctly.
+ </action>
+ </release>
<release version="1.1.13" date="2008-03-21">
<action dev="jahlborn" type="fix" issue="1913775">
More fixes for index parsing. Believe index names are now correctly
diff --git a/src/java/com/healthmarketscience/jackcess/Database.java b/src/java/com/healthmarketscience/jackcess/Database.java
index d3485d8..f49972d 100644
--- a/src/java/com/healthmarketscience/jackcess/Database.java
+++ b/src/java/com/healthmarketscience/jackcess/Database.java
@@ -851,9 +851,7 @@ public class Database
// may have null fields. We always want to add the
// same number of columns to the table each time.
//
- Object[] data = new Object[columnNames.length];
- String[] splitData = line.split(delim);
- System.arraycopy(splitData, 0, data, 0, splitData.length);
+ Object[] data = Table.dupeRow(line.split(delim), columnNames.length);
rows.add(filter.filterRow(data));
if (rows.size() == COPY_TABLE_BATCH_SIZE) {
table.addRows(rows);
diff --git a/src/java/com/healthmarketscience/jackcess/Table.java b/src/java/com/healthmarketscience/jackcess/Table.java
index c69fc89..5e8a247 100644
--- a/src/java/com/healthmarketscience/jackcess/Table.java
+++ b/src/java/com/healthmarketscience/jackcess/Table.java
@@ -1102,6 +1102,13 @@ public class Table
/**
* Add a single row to this table and write it to disk
+ * <p>
+ * Note, if this table has an auto-number column, the value written will be
+ * put back into the given row array.
+ *
+ * @param row row values for a single row. the row will be modified if
+ * this table contains an auto-number column, otherwise it
+ * will not be modified.
*/
public void addRow(Object... row) throws IOException {
addRows(Collections.singletonList(row), _singleRowBufferH);
@@ -1111,7 +1118,13 @@ public class Table
* Add multiple rows to this table, only writing to disk after all
* rows have been written, and every time a data page is filled. This
* is much more efficient than calling <code>addRow</code> multiple times.
- * @param rows List of Object[] row values
+ * <p>
+ * Note, if this table has an auto-number column, the values written will be
+ * put back into the given row arrays.
+ *
+ * @param rows List of Object[] row values. the rows will be modified if
+ * this table contains an auto-number column, otherwise they
+ * will not be modified.
*/
public void addRows(List<? extends Object[]> rows) throws IOException {
addRows(rows, _multiRowBufferH);
@@ -1119,21 +1132,35 @@ public class Table
/**
* Add multiple rows to this table, only writing to disk after all
- * rows have been written, and every time a data page is filled. This
- * is much more efficient than calling <code>addRow</code> multiple times.
- * @param rows List of Object[] row values
+ * rows have been written, and every time a data page is filled.
+ * @param inRows List of Object[] row values
* @param writeRowBufferH TempBufferHolder used to generate buffers for
* writing the row data
*/
- private void addRows(List<? extends Object[]> rows,
+ private void addRows(List<? extends Object[]> inRows,
TempBufferHolder writeRowBufferH)
throws IOException
{
+ // copy the input rows to a modifiable list so we can update the elements
+ List<Object[]> rows = new ArrayList<Object[]>(inRows);
ByteBuffer[] rowData = new ByteBuffer[rows.size()];
- Iterator<? extends Object[]> iter = rows.iterator();
- for (int i = 0; iter.hasNext(); i++) {
- rowData[i] = createRow(iter.next(), getFormat().MAX_ROW_SIZE,
+ for (int i = 0; i < rows.size(); i++) {
+
+ // we need to make sure the row is the right length (fill with null).
+ // note, if the row is copied the caller will not be able to access any
+ // generated auto-number value, but if they need that info they should
+ // use a row array of the right size!
+ Object[] row = rows.get(i);
+ if(row.length < _columns.size()) {
+ row = dupeRow(row, _columns.size());
+ // we copied the row, so put the copy back into the rows list
+ rows.set(i, row);
+ }
+
+ // write the row of data to a temporary buffer
+ rowData[i] = createRow(row, getFormat().MAX_ROW_SIZE,
writeRowBufferH.getPageBuffer(getPageChannel()));
+
if (rowData[i].limit() > getFormat().MAX_ROW_SIZE) {
throw new IOException("Row size " + rowData[i].limit() +
" is too large");
@@ -1254,7 +1281,15 @@ public class Table
}
/**
- * Serialize a row of Objects into a byte buffer
+ * Serialize a row of Objects into a byte buffer.
+ * <p>
+ * Note, if this table has an auto-number column, the value written will be
+ * put back into the given row array.
+ *
+ * @param rowArray row data, expected to be correct length for this table
+ * @param maxRowSize max size the data can be for this row
+ * @param buffer buffer to which to write the row data
+ * @return the given buffer, filled with the row data
*/
ByteBuffer createRow(Object[] rowArray, int maxRowSize, ByteBuffer buffer)
throws IOException
@@ -1262,15 +1297,6 @@ public class Table
buffer.putShort(_maxColumnCount);
NullMask nullMask = new NullMask(_maxColumnCount);
- List<Object> row = new ArrayList<Object>(_columns.size());
- for(Object rowValue : rowArray) {
- row.add(rowValue);
- }
- //Append null for arrays that are too small
- for (int i = rowArray.length; i < _columns.size(); i++) {
- row.add(null);
- }
-
//Fixed length column data comes first
int fixedDataStart = buffer.position();
int fixedDataEnd = fixedDataStart;
@@ -1278,7 +1304,7 @@ public class Table
if(!col.isVariableLength()) {
- Object rowValue = row.get(col.getColumnIndex());
+ Object rowValue = rowArray[col.getColumnIndex()];
if (col.getType() == DataType.BOOLEAN) {
@@ -1290,8 +1316,13 @@ public class Table
} else {
if(col.isAutoNumber()) {
+
// ignore given row value, use next autonumber
rowValue = getNextAutoNumber();
+
+ // we need to stick this back in the row so that the indexes get
+ // updated correctly (and caller can get the generated value)
+ rowArray[col.getColumnIndex()] = rowValue;
}
if(rowValue != null) {
@@ -1329,7 +1360,7 @@ public class Table
int varColumnOffsetsIndex = 0;
for (Column varCol : _varColumns) {
short offset = (short) buffer.position();
- Object rowValue = row.get(varCol.getColumnIndex());
+ Object rowValue = rowArray[varCol.getColumnIndex()];
if (rowValue != null) {
// we have a value
nullMask.markNotNull(varCol);
@@ -1576,6 +1607,16 @@ public class Table
}
return numAutoNumCols;
}
+
+ /**
+ * Duplicates and returns a row of data, optionally with a longer length
+ * filled with {@code null}.
+ */
+ static Object[] dupeRow(Object[] row, int newRowLength) {
+ Object[] copy = new Object[newRowLength];
+ System.arraycopy(row, 0, copy, 0, row.length);
+ return copy;
+ }
/** various statuses for the row data */
private enum RowStatus {
@@ -1714,9 +1755,7 @@ public class Table
}
public Object[] getRowValues() {
- Object[] copy = new Object[_rowValues.length];
- System.arraycopy(_rowValues, 0, copy, 0, _rowValues.length);
- return copy;
+ return dupeRow(_rowValues, _rowValues.length);
}
public RowId getHeaderRowId() {
diff --git a/test/data/test.mdb b/test/data/test.mdb
index 89a05a1..23124d6 100644
--- a/test/data/test.mdb
+++ b/test/data/test.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 90c57b1..5592e8c 100644
--- a/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java
+++ b/test/src/java/com/healthmarketscience/jackcess/DatabaseTest.java
@@ -169,7 +169,7 @@ public class DatabaseTest extends TestCase {
public void testGetNextRow() throws Exception {
Database db = open();
- assertEquals(2, db.getTableNames().size());
+ assertEquals(3, db.getTableNames().size());
Table table = db.getTable("Table1");
Map<String, Object> row = table.getNextRow();
@@ -702,6 +702,23 @@ public class DatabaseTest extends TestCase {
.addColumn(new ColumnBuilder("b", DataType.TEXT).toColumn())
.toTable(db);
+ doTestAutoNumber(table);
+
+ db.close();
+ }
+
+ public void testAutoNumberPK() throws Exception {
+ Database db = openCopy(new File("test/data/test.mdb"));
+
+ Table table = db.getTable("Table3");
+
+ doTestAutoNumber(table);
+
+ db.close();
+ }
+
+ private void doTestAutoNumber(Table table) throws Exception
+ {
table.addRow(null, "row1");
table.addRow(13, "row2");
table.addRow("flubber", "row3");
@@ -732,10 +749,8 @@ public class DatabaseTest extends TestCase {
"b", "row5"));
assertTable(expectedRows, table);
-
- db.close();
- }
-
+ }
+
public void testWriteAndReadDate() throws Exception {
Database db = create();