From 18c2b054fe90c8e69dfeea4b552548bf517c62e9 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Tue, 19 Mar 2013 04:28:28 +0000 Subject: [PATCH] create ComplexValue.Id and stash RowId for simpler updates/deletes git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/jackcess-2@697 f203690c-595d-4dc9-a70b-905162fa7fd2 --- TODO.txt | 2 +- .../complex/AttachmentColumnInfo.java | 9 +- .../jackcess/complex/ComplexColumnInfo.java | 198 ++++++++++++------ .../jackcess/complex/ComplexValue.java | 31 ++- .../complex/MultiValueColumnInfo.java | 7 +- .../complex/UnsupportedColumnInfo.java | 7 +- .../complex/VersionHistoryColumnInfo.java | 13 +- .../jackcess/impl/ColumnImpl.java | 9 + .../jackcess/impl/RowImpl.java | 2 +- .../jackcess/impl/TableImpl.java | 73 ++++++- .../jackcess/util/Joiner.java | 7 +- 11 files changed, 262 insertions(+), 96 deletions(-) diff --git a/TODO.txt b/TODO.txt index 3e896a0..4c86b7a 100644 --- a/TODO.txt +++ b/TODO.txt @@ -45,4 +45,4 @@ Refactor goals: * add unit tests for Row update/delete methods, add/update *FromMap methods * add reason to unsupop throws for indexes * remove static methods in CursorImpl/IndexCursorImpl -- add RowId to ComplexValue +* create ComplexValue.Id and keep RowId diff --git a/src/java/com/healthmarketscience/jackcess/complex/AttachmentColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/AttachmentColumnInfo.java index 0a07e9d..f715d7c 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/AttachmentColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/AttachmentColumnInfo.java @@ -21,7 +21,6 @@ package com.healthmarketscience.jackcess.complex; import java.io.IOException; import java.util.Date; -import java.util.Map; import com.healthmarketscience.jackcess.Column; import com.healthmarketscience.jackcess.Row; @@ -133,7 +132,7 @@ public class AttachmentColumnInfo extends ComplexColumnInfo @Override protected AttachmentImpl toValue(ComplexValueForeignKey complexValueFk, Row rawValue) { - int id = (Integer)getPrimaryKeyColumn().getRowValue(rawValue); + ComplexValue.Id id = getValueId(rawValue); String url = (String)getFileUrlColumn().getRowValue(rawValue); String name = (String)getFileNameColumn().getRowValue(rawValue); String type = (String)getFileTypeColumn().getRowValue(rawValue); @@ -158,7 +157,7 @@ public class AttachmentColumnInfo extends ComplexColumnInfo } public static Attachment newAttachment(byte[] data) { - return newAttachment(INVALID_COMPLEX_VALUE_ID, data); + return newAttachment(INVALID_FK, data); } public static Attachment newAttachment(ComplexValueForeignKey complexValueFk, @@ -170,7 +169,7 @@ public class AttachmentColumnInfo extends ComplexColumnInfo String url, String name, String type, byte[] data, Date timeStamp, Integer flags) { - return newAttachment(INVALID_COMPLEX_VALUE_ID, url, name, type, data, + return newAttachment(INVALID_FK, url, name, type, data, timeStamp, flags); } @@ -193,7 +192,7 @@ public class AttachmentColumnInfo extends ComplexColumnInfo private Date _timeStamp; private Integer _flags; - private AttachmentImpl(int id, ComplexValueForeignKey complexValueFk, + private AttachmentImpl(Id id, ComplexValueForeignKey complexValueFk, String url, String name, String type, byte[] data, Date timeStamp, Integer flags) { diff --git a/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java index 376c25a..ae17510 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/ComplexColumnInfo.java @@ -32,8 +32,12 @@ import com.healthmarketscience.jackcess.CursorBuilder; import com.healthmarketscience.jackcess.DataType; import com.healthmarketscience.jackcess.Database; import com.healthmarketscience.jackcess.IndexCursor; -import com.healthmarketscience.jackcess.Table; import com.healthmarketscience.jackcess.Row; +import com.healthmarketscience.jackcess.RowId; +import com.healthmarketscience.jackcess.RuntimeIOException; +import com.healthmarketscience.jackcess.Table; +import com.healthmarketscience.jackcess.impl.ColumnImpl; +import com.healthmarketscience.jackcess.impl.TableImpl; /** * Base class for the additional information tracked for complex columns. @@ -42,9 +46,11 @@ import com.healthmarketscience.jackcess.Row; */ public abstract class ComplexColumnInfo { - public static final int INVALID_ID = -1; - public static final ComplexValueForeignKey INVALID_COMPLEX_VALUE_ID = - new ComplexValueForeignKey(null, INVALID_ID); + private static final int INVALID_ID_VALUE = -1; + public static final ComplexValue.Id INVALID_ID = new ComplexValueIdImpl( + INVALID_ID_VALUE, null); + public static final ComplexValueForeignKey INVALID_FK = + new ComplexValueForeignKey(null, INVALID_ID_VALUE); private final Column _column; private final int _complexTypeId; @@ -52,7 +58,6 @@ public abstract class ComplexColumnInfo private final List _typeCols; private final Column _pkCol; private final Column _complexValFkCol; - private IndexCursor _pkCursor; private IndexCursor _complexValIdCursor; protected ComplexColumnInfo(Column column, int complexTypeId, @@ -181,16 +186,18 @@ public abstract class ComplexColumnInfo return values; } - public int addRawValue(Row rawValue) throws IOException { - Object[] row = _flatTable.asRow(rawValue); + public ComplexValue.Id addRawValue(Map rawValue) + throws IOException + { + Object[] row = ((TableImpl)_flatTable).asRowWithRowId(rawValue); _flatTable.addRow(row); - return (Integer)_pkCol.getRowValue(row); + return getValueId(row); } - public int addValue(V value) throws IOException { + public ComplexValue.Id addValue(V value) throws IOException { Object[] row = asRow(newRowArray(), value); _flatTable.addRow(row); - int id = (Integer)_pkCol.getRowValue(row); + ComplexValue.Id id = getValueId(row); value.setId(id); return id; } @@ -201,14 +208,13 @@ public abstract class ComplexColumnInfo } } - public int updateRawValue(Row rawValue) throws IOException { - Integer id = (Integer)_pkCol.getRowValue(rawValue); - updateRow(id, _flatTable.asUpdateRow(rawValue)); - return id; + public ComplexValue.Id updateRawValue(Row rawValue) throws IOException { + _flatTable.updateRow(rawValue); + return getValueId(rawValue); } - public int updateValue(V value) throws IOException { - int id = value.getId(); + public ComplexValue.Id updateValue(V value) throws IOException { + ComplexValue.Id id = value.getId(); updateRow(id, asRow(newRowArray(), value)); return id; } @@ -220,11 +226,11 @@ public abstract class ComplexColumnInfo } public void deleteRawValue(Row rawValue) throws IOException { - deleteRow((Integer)_pkCol.getRowValue(rawValue)); + deleteRow(rawValue.getId()); } public void deleteValue(V value) throws IOException { - deleteRow(value.getId()); + deleteRow(value.getId().getRowId()); } public void deleteValues(Collection values) throws IOException { @@ -241,11 +247,8 @@ public abstract class ComplexColumnInfo entryIter.next(); entryIter.remove(); } - } catch(RuntimeException e) { - if(e.getCause() instanceof IOException) { - throw (IOException)e.getCause(); - } - throw e; + } catch(RuntimeIOException e) { + throw (IOException)e.getCause(); } } @@ -255,40 +258,38 @@ public abstract class ComplexColumnInfo deleteAllValues(complexValueFk.get()); } - private void moveToRow(Integer id) throws IOException { - if(_pkCursor == null) { - _pkCursor = new CursorBuilder(_flatTable) - .setIndexByColumns(_pkCol) - .toIndexCursor(); - } - - if(!_pkCursor.findFirstRowByEntry(id)) { - throw new IllegalArgumentException("Row with id " + id + - " does not exist"); - } - } - - private void updateRow(Integer id, Object[] row) throws IOException { - moveToRow(id); - _pkCursor.updateCurrentRow(row); + private void updateRow(ComplexValue.Id id, Object[] row) throws IOException { + ((TableImpl)_flatTable).updateRow(id.getRowId(), row); } - private void deleteRow(Integer id) throws IOException { - moveToRow(id); - _pkCursor.deleteCurrentRow(); + private void deleteRow(RowId rowId) throws IOException { + ((TableImpl)_flatTable).deleteRow(rowId); } + protected ComplexValueIdImpl getValueId(Row row) { + int idVal = (Integer)getPrimaryKeyColumn().getRowValue(row); + return new ComplexValueIdImpl(idVal, row.getId()); + } + + protected ComplexValueIdImpl getValueId(Object[] row) { + int idVal = (Integer)getPrimaryKeyColumn().getRowValue(row); + return new ComplexValueIdImpl(idVal, (RowId)row[row.length - 1]); + } + protected Object[] asRow(Object[] row, V value) { - int id = value.getId(); - _pkCol.setRowValue(row, ((id != INVALID_ID) ? id : Column.AUTO_NUMBER)); - int cId = value.getComplexValueForeignKey().get(); + ComplexValue.Id id = value.getId(); + _pkCol.setRowValue( + row, ((id != INVALID_ID) ? id : Column.AUTO_NUMBER)); + ComplexValueForeignKey cFk = value.getComplexValueForeignKey(); _complexValFkCol.setRowValue( - row, ((cId != INVALID_ID) ? cId : Column.AUTO_NUMBER)); + row, ((cFk != INVALID_FK) ? cFk : Column.AUTO_NUMBER)); return row; } private Object[] newRowArray() { - return new Object[_flatTable.getColumnCount()]; + Object[] row = new Object[_flatTable.getColumnCount() + 1]; + row[row.length - 1] = ColumnImpl.RETURN_ROW_ID; + return row; } @Override @@ -307,14 +308,7 @@ public abstract class ComplexColumnInfo // each "flat"" table has the columns from the "type" table, plus some // others. separate the "flat" columns into these 2 buckets for(Column col : flatTable.getColumns()) { - boolean found = false; - try { - typeObjTable.getColumn(col.getName()); - found = true; - } catch(IllegalArgumentException e) { - // FIXME better way to test this? - } - if(found) { + if(((TableImpl)typeObjTable).hasColumn(col.getName())) { typeCols.add(col); } else { otherCols.add(col); @@ -331,19 +325,23 @@ public abstract class ComplexColumnInfo protected static abstract class ComplexValueImpl implements ComplexValue { - private int _id; + private Id _id; private ComplexValueForeignKey _complexValueFk; - protected ComplexValueImpl(int id, ComplexValueForeignKey complexValueFk) { + protected ComplexValueImpl(Id id, ComplexValueForeignKey complexValueFk) { _id = id; _complexValueFk = complexValueFk; } - public int getId() { + public Id getId() { return _id; } - public void setId(int id) { + public void setId(Id id) { + if(_id == id) { + // harmless, ignore + return; + } if(_id != INVALID_ID) { throw new IllegalStateException("id may not be reset"); } @@ -356,7 +354,11 @@ public abstract class ComplexColumnInfo public void setComplexValueForeignKey(ComplexValueForeignKey complexValueFk) { - if(_complexValueFk != INVALID_COMPLEX_VALUE_ID) { + if(_complexValueFk == complexValueFk) { + // harmless, ignore + return; + } + if(_complexValueFk != INVALID_FK) { throw new IllegalStateException("complexValueFk may not be reset"); } _complexValueFk = complexValueFk; @@ -368,7 +370,7 @@ public abstract class ComplexColumnInfo @Override public int hashCode() { - return ((_id * 37) ^ _complexValueFk.hashCode()); + return ((_id.get() * 37) ^ _complexValueFk.hashCode()); } @Override @@ -379,5 +381,79 @@ public abstract class ComplexColumnInfo _complexValueFk.equals(((ComplexValueImpl)o)._complexValueFk))); } } + + /** + * Implementation of ComplexValue.Id. + */ + private static final class ComplexValueIdImpl extends ComplexValue.Id + { + private static final long serialVersionUID = 20130318L; + + private final int _value; + private final RowId _rowId; + + protected ComplexValueIdImpl(int value, RowId rowId) { + _value = value; + _rowId = rowId; + } + + @Override + public int get() { + return _value; + } + + @Override + public RowId getRowId() { + return _rowId; + } + + @Override + public byte byteValue() { + return (byte)get(); + } + + @Override + public short shortValue() { + return (short)get(); + } + + @Override + public int intValue() { + return get(); + } + + @Override + public long longValue() { + return get(); + } + + @Override + public float floatValue() { + return get(); + } + + @Override + public double doubleValue() { + return get(); + } + + @Override + public int hashCode() { + return _value; + } + + @Override + public boolean equals(Object o) { + return ((this == o) || + ((o != null) && (getClass() == o.getClass()) && + (_value == ((ComplexValueIdImpl)o)._value))); + } + + @Override + public String toString() + { + return String.valueOf(_value); + } + } } diff --git a/src/java/com/healthmarketscience/jackcess/complex/ComplexValue.java b/src/java/com/healthmarketscience/jackcess/complex/ComplexValue.java index beaea04..4513f07 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/ComplexValue.java +++ b/src/java/com/healthmarketscience/jackcess/complex/ComplexValue.java @@ -22,6 +22,7 @@ package com.healthmarketscience.jackcess.complex; import java.io.IOException; import com.healthmarketscience.jackcess.Column; +import com.healthmarketscience.jackcess.RowId; /** * Base interface for a value in a complex column (where there may be multiple @@ -38,15 +39,19 @@ public interface ComplexValue * @return the current id or {@link ComplexColumnInfo#INVALID_ID} for a new, * unsaved value. */ - public int getId(); + public Id getId(); - public void setId(int newId); + /** + * Called once when a new ComplexValue is saved to set the new unique + * identifier. + */ + public void setId(Id newId); /** * Returns the foreign key identifier for this complex value (this value is * the same for all values in the same row of the main table). * - * @return the current id or {@link ComplexColumnInfo#INVALID_COMPLEX_VALUE_ID} + * @return the current id or {@link ComplexColumnInfo#INVALID_FK} * for a new, unsaved value. */ public ComplexValueForeignKey getComplexValueForeignKey(); @@ -69,4 +74,24 @@ public interface ComplexValue */ public void delete() throws IOException; + + /** + * Identifier for a ComplexValue. Only valid for comparing complex values + * for the same column. + */ + public abstract class Id extends Number + { + private static final long serialVersionUID = 20130318L; + + /** + * Returns the unique identifier of this complex value (this value is unique + * among all values in all rows of the main table for the complex column). + */ + public abstract int get(); + + /** + * Returns the rowId of this ComplexValue within the secondary table. + */ + public abstract RowId getRowId(); + } } diff --git a/src/java/com/healthmarketscience/jackcess/complex/MultiValueColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/MultiValueColumnInfo.java index 9add8c7..4089153 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/MultiValueColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/MultiValueColumnInfo.java @@ -20,7 +20,6 @@ USA package com.healthmarketscience.jackcess.complex; import java.io.IOException; -import java.util.Map; import com.healthmarketscience.jackcess.Column; import com.healthmarketscience.jackcess.Table; @@ -59,7 +58,7 @@ public class MultiValueColumnInfo extends ComplexColumnInfo ComplexValueForeignKey complexValueFk, Row rawValue) { - int id = (Integer)getPrimaryKeyColumn().getRowValue(rawValue); + ComplexValue.Id id = getValueId(rawValue); Object value = getValueColumn().getRowValue(rawValue); return new SingleValueImpl(id, complexValueFk, value); @@ -73,7 +72,7 @@ public class MultiValueColumnInfo extends ComplexColumnInfo } public static SingleValue newSingleValue(Object value) { - return newSingleValue(INVALID_COMPLEX_VALUE_ID, value); + return newSingleValue(INVALID_FK, value); } public static SingleValue newSingleValue( @@ -87,7 +86,7 @@ public class MultiValueColumnInfo extends ComplexColumnInfo { private Object _value; - private SingleValueImpl(int id, ComplexValueForeignKey complexValueFk, + private SingleValueImpl(Id id, ComplexValueForeignKey complexValueFk, Object value) { super(id, complexValueFk); diff --git a/src/java/com/healthmarketscience/jackcess/complex/UnsupportedColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/UnsupportedColumnInfo.java index 071da06..b0b6924 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/UnsupportedColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/UnsupportedColumnInfo.java @@ -27,7 +27,6 @@ import java.util.Map; import com.healthmarketscience.jackcess.Column; import com.healthmarketscience.jackcess.Table; import com.healthmarketscience.jackcess.Row; -import com.healthmarketscience.jackcess.impl.RowImpl; /** * Complex column info for an unsupported complex type. @@ -59,7 +58,7 @@ public class UnsupportedColumnInfo extends ComplexColumnInfo ComplexValueForeignKey complexValueFk, Row rawValue) { - int id = (Integer)getPrimaryKeyColumn().getRowValue(rawValue); + ComplexValue.Id id = getValueId(rawValue); Map values = new LinkedHashMap(); for(Column col : getValueColumns()) { @@ -82,7 +81,7 @@ public class UnsupportedColumnInfo extends ComplexColumnInfo } public static UnsupportedValue newValue(Map values) { - return newValue(INVALID_COMPLEX_VALUE_ID, values); + return newValue(INVALID_FK, values); } public static UnsupportedValue newValue( @@ -96,7 +95,7 @@ public class UnsupportedColumnInfo extends ComplexColumnInfo { private Map _values; - private UnsupportedValueImpl(int id, ComplexValueForeignKey complexValueFk, + private UnsupportedValueImpl(Id id, ComplexValueForeignKey complexValueFk, Map values) { super(id, complexValueFk); diff --git a/src/java/com/healthmarketscience/jackcess/complex/VersionHistoryColumnInfo.java b/src/java/com/healthmarketscience/jackcess/complex/VersionHistoryColumnInfo.java index e29dd38..60c6fb7 100644 --- a/src/java/com/healthmarketscience/jackcess/complex/VersionHistoryColumnInfo.java +++ b/src/java/com/healthmarketscience/jackcess/complex/VersionHistoryColumnInfo.java @@ -23,7 +23,6 @@ import java.io.IOException; import java.util.Collections; import java.util.Date; import java.util.List; -import java.util.Map; import com.healthmarketscience.jackcess.Column; import com.healthmarketscience.jackcess.Row; @@ -96,7 +95,7 @@ public class VersionHistoryColumnInfo extends ComplexColumnInfo } @Override - public int updateValue(Version value) throws IOException { + public ComplexValue.Id updateValue(Version value) throws IOException { throw new UnsupportedOperationException( "This column does not support value updates"); } @@ -129,7 +128,7 @@ public class VersionHistoryColumnInfo extends ComplexColumnInfo @Override protected VersionImpl toValue(ComplexValueForeignKey complexValueFk, Row rawValue) { - int id = (Integer)getPrimaryKeyColumn().getRowValue(rawValue); + ComplexValue.Id id = getValueId(rawValue); String value = (String)getValueColumn().getRowValue(rawValue); Date modifiedDate = (Date)getModifiedDateColumn().getRowValue(rawValue); @@ -145,7 +144,7 @@ public class VersionHistoryColumnInfo extends ComplexColumnInfo } public static Version newVersion(String value, Date modifiedDate) { - return newVersion(INVALID_COMPLEX_VALUE_ID, value, modifiedDate); + return newVersion(INVALID_FK, value, modifiedDate); } public static Version newVersion(ComplexValueForeignKey complexValueFk, @@ -159,7 +158,7 @@ public class VersionHistoryColumnInfo extends ComplexColumnInfo private final String _value; private final Date _modifiedDate; - private VersionImpl(int id, ComplexValueForeignKey complexValueFk, + private VersionImpl(Id id, ComplexValueForeignKey complexValueFk, String value, Date modifiedDate) { super(id, complexValueFk); @@ -187,8 +186,8 @@ public class VersionHistoryColumnInfo extends ComplexColumnInfo // use id, then complexValueFk to break ties (although we really // shouldn't be comparing across different columns) - int id1 = getId(); - int id2 = o.getId(); + int id1 = getId().get(); + int id2 = o.getId().get(); if(id1 != id2) { return ((id1 > id2) ? -1 : 1); } diff --git a/src/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java index e46d0af..2038556 100644 --- a/src/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java +++ b/src/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java @@ -73,6 +73,15 @@ import com.healthmarketscience.jackcess.ColumnBuilder; public class ColumnImpl implements Column, Comparable { private static final Log LOG = LogFactory.getLog(ColumnImpl.class); + + /** + * Placeholder object for adding rows which indicates that the caller wants + * the RowId of the new row. Must be added as an extra value at the end of + * the row values array. + * @see TableImpl#asRowWithRowId + * @usage _intermediate_field_ + */ + public static final Object RETURN_ROW_ID = ""; /** * Access stores numeric dates in days. Java stores them in milliseconds. diff --git a/src/java/com/healthmarketscience/jackcess/impl/RowImpl.java b/src/java/com/healthmarketscience/jackcess/impl/RowImpl.java index f24327f..898508a 100644 --- a/src/java/com/healthmarketscience/jackcess/impl/RowImpl.java +++ b/src/java/com/healthmarketscience/jackcess/impl/RowImpl.java @@ -60,6 +60,6 @@ public class RowImpl extends LinkedHashMap implements Row @Override public String toString() { - return "Row id=[" + _id + "], content=" + super.toString(); + return "Row[" + _id + "] " + super.toString(); } } diff --git a/src/java/com/healthmarketscience/jackcess/impl/TableImpl.java b/src/java/com/healthmarketscience/jackcess/impl/TableImpl.java index 34b8846..919c17f 100644 --- a/src/java/com/healthmarketscience/jackcess/impl/TableImpl.java +++ b/src/java/com/healthmarketscience/jackcess/impl/TableImpl.java @@ -49,6 +49,7 @@ import com.healthmarketscience.jackcess.Index; import com.healthmarketscience.jackcess.IndexBuilder; import com.healthmarketscience.jackcess.PropertyMap; import com.healthmarketscience.jackcess.Row; +import com.healthmarketscience.jackcess.RowId; import com.healthmarketscience.jackcess.Table; import com.healthmarketscience.jackcess.util.ErrorHandler; import org.apache.commons.logging.Log; @@ -380,6 +381,15 @@ public class TableImpl implements Table throw new IllegalArgumentException("Column with name " + name + " does not exist in this table"); } + + public boolean hasColumn(String name) { + for(ColumnImpl column : _columns) { + if(column.getName().equalsIgnoreCase(name)) { + return true; + } + } + return false; + } public PropertyMap getProperties() throws IOException { if(_props == null) { @@ -465,10 +475,22 @@ public class TableImpl implements Table } public Row deleteRow(Row row) throws IOException { - deleteRow(getDefaultCursor().getRowState(), (RowIdImpl)row.getId()); + deleteRow(row.getId()); return row; } + /** + * Delete the row with the given id. Provided RowId must have previously + * been returned from this Table. + * @return the given rowId + * @throws IllegalStateException if the given row is not valid + * @usage _intermediate_method_ + */ + public RowId deleteRow(RowId rowId) throws IOException { + deleteRow(getDefaultCursor().getRowState(), (RowIdImpl)rowId); + return rowId; + } + /** * Delete the row for the given rowId. * @usage _advanced_method_ @@ -1241,22 +1263,41 @@ public class TableImpl implements Table } public Object[] asRow(Map rowMap) { - return asRow(rowMap, null); + return asRow(rowMap, null, false); + } + + /** + * Converts a map of columnName -> columnValue to an array of row values + * appropriate for a call to {@link #addRow(Object...)}, where the generated + * RowId will be an extra value at the end of the array. + * @see ColumnImpl#RETURN_ROW_ID + * @usage _intermediate_method_ + */ + public Object[] asRowWithRowId(Map rowMap) { + return asRow(rowMap, null, true); } public Object[] asUpdateRow(Map rowMap) { - return asRow(rowMap, Column.KEEP_VALUE); + return asRow(rowMap, Column.KEEP_VALUE, false); } /** * Converts a map of columnName -> columnValue to an array of row values. */ - private Object[] asRow(Map rowMap, Object defaultValue) + private Object[] asRow(Map rowMap, Object defaultValue, + boolean returnRowId) { - Object[] row = new Object[_columns.size()]; + int len = _columns.size(); + if(returnRowId) { + ++len; + } + Object[] row = new Object[len]; if(defaultValue != null) { Arrays.fill(row, defaultValue); } + if(returnRowId) { + row[len - 1] = ColumnImpl.RETURN_ROW_ID; + } if(rowMap == null) { return row; } @@ -1334,6 +1375,7 @@ public class TableImpl implements Table List dupeRows = null; ByteBuffer[] rowData = new ByteBuffer[rows.size()]; + int numCols = _columns.size(); for (int i = 0; i < rows.size(); i++) { // we need to make sure the row is the right length and is an Object[] @@ -1342,8 +1384,8 @@ public class TableImpl implements Table // they need that info they should use a row array of the right // size/type! Object[] row = rows.get(i); - if((row.length < _columns.size()) || (row.getClass() != Object[].class)) { - row = dupeRow(row, _columns.size()); + if((row.length < numCols) || (row.getClass() != Object[].class)) { + row = dupeRow(row, numCols); // copy the input rows to a modifiable list so we can update the // elements if(dupeRows == null) { @@ -1390,6 +1432,11 @@ public class TableImpl implements Table for(IndexData indexData : _indexDatas) { indexData.addRow(row, rowId); } + + // return rowTd if desired + if((row.length > numCols) && (row[numCols] == ColumnImpl.RETURN_ROW_ID)) { + row[numCols] = rowId; + } } writeDataPage(dataPage, pageNumber); @@ -1405,6 +1452,18 @@ public class TableImpl implements Table getDefaultCursor().getRowState(), (RowIdImpl)row.getId(), row); } + /** + * Update the row with the given id. Provided RowId must have previously + * been returned from this Table. + * @return the given row, updated with the current row values + * @throws IllegalStateException if the given row is not valid, or deleted. + * @usage _intermediate_method_ + */ + public Object[] updateRow(RowId rowId, Object... row) throws IOException { + return updateRow( + getDefaultCursor().getRowState(), (RowIdImpl)rowId, row); + } + public > M updateRowFromMap( RowState rowState, RowIdImpl rowId, M row) throws IOException diff --git a/src/java/com/healthmarketscience/jackcess/util/Joiner.java b/src/java/com/healthmarketscience/jackcess/util/Joiner.java index d43ff1b..91794db 100644 --- a/src/java/com/healthmarketscience/jackcess/util/Joiner.java +++ b/src/java/com/healthmarketscience/jackcess/util/Joiner.java @@ -29,8 +29,9 @@ import java.util.Map; import com.healthmarketscience.jackcess.CursorBuilder; import com.healthmarketscience.jackcess.Index; import com.healthmarketscience.jackcess.IndexCursor; -import com.healthmarketscience.jackcess.Table; import com.healthmarketscience.jackcess.Row; +import com.healthmarketscience.jackcess.RuntimeIOException; +import com.healthmarketscience.jackcess.Table; import com.healthmarketscience.jackcess.impl.IndexImpl; /** @@ -191,7 +192,7 @@ public class Joiner * @param columnNames desired columns in the from table row */ public Iterator findRows(Map fromRow, - Collection columnNames) + Collection columnNames) { toEntryValues(fromRow); return _toCursor.entryIterator(columnNames, _entryValues); @@ -207,7 +208,7 @@ public class Joiner * @usage _intermediate_method_ */ public Iterator findRows(Object[] fromRow, - Collection columnNames) + Collection columnNames) { toEntryValues(fromRow); return _toCursor.entryIterator(columnNames, _entryValues); -- 2.39.5