Implement some tweaks which allow jackcess to be used on the Android
platform. (thanks to Miha Pirnat).
</action>
+ <action dev="jahlborn" type="update" issue="3097387">
+ Allow column order in tables to be configured.
+ </action>
</release>
<release version="1.2.1" date="2010-08-01">
<action dev="jahlborn" type="add" issue="3005272">
private short _columnNumber;
/** index of the data for this column within a list of row data */
private int _columnIndex;
+ /** display index of the data for this column */
+ private int _displayIndex;
/** Column name */
private String _name;
/** the offset of the fixed data in the row */
* @param buffer Buffer containing column definition
* @param offset Offset in the buffer at which the column definition starts
*/
- public Column(Table table, ByteBuffer buffer, int offset)
+ public Column(Table table, ByteBuffer buffer, int offset, int displayIndex)
throws IOException
{
_table = table;
+ _displayIndex = displayIndex;
if (LOG.isDebugEnabled()) {
LOG.debug("Column def block:\n" + ByteUtil.toHexString(buffer, offset, 25));
}
_columnIndex = newColumnIndex;
}
+ public int getDisplayIndex() {
+ return _displayIndex;
+ }
+
/**
* Also sets the length and the variable length flag, inferred from the
* type. For types with scale/precision, sets the scale and precision to
public static final String DEFAULT_RESOURCE_PATH =
"com/healthmarketscience/jackcess/";
+ /** the default sort order for table columns. */
+ public static final Table.ColumnOrder DEFAULT_COLUMN_ORDER =
+ Table.ColumnOrder.DATA;
+
/** (boolean) system property which can be used to disable the default big
index support. */
public static final String USE_BIG_INDEX_PROPERTY =
public static final String BROKEN_NIO_PROPERTY =
"com.healthmarketscience.jackcess.brokenNio";
+ /** system property which can be used to set the default sort order for
+ table columns. Value should be one {@link Table.ColumnOrder} enum
+ values. */
+ public static final String COLUMN_ORDER_PROPERTY =
+ "com.healthmarketscience.jackcess.columnOrder";
+
/** default error handler used if none provided (just rethrows exception) */
public static final ErrorHandler DEFAULT_ERROR_HANDLER = new ErrorHandler() {
public Object handleRowError(Column column,
private Charset _charset;
/** timezone to use when handling dates */
private TimeZone _timeZone;
+ /** the ordering used for table columns */
+ private Table.ColumnOrder _columnOrder;
/**
* Open an existing Database. If the existing file is not writeable, the
_format = JetFormat.getFormat(channel);
_charset = ((charset == null) ? getDefaultCharset(_format) : charset);
+ _columnOrder = getDefaultColumnOrder();
_fileFormat = fileFormat;
_pageChannel = new PageChannel(channel, _format, autoSync);
_timeZone = ((timeZone == null) ? getDefaultTimeZone() : timeZone);
_charset = newCharset;
}
+ /**
+ * Gets currently configured {@link Table.ColumnOrder} (always non-{@code
+ * null}).
+ */
+ public Table.ColumnOrder getColumnOrder()
+ {
+ return _columnOrder;
+ }
+
+ /**
+ * Sets a new Table.ColumnOrder. If {@code null}, resets to the value
+ * returned by {@link #getDefaultColumnOrder}.
+ */
+ public void setColumnOrder(Table.ColumnOrder newColumnOrder) {
+ if(newColumnOrder == null) {
+ newColumnOrder = getDefaultColumnOrder();
+ }
+ _columnOrder = newColumnOrder;
+ }
+
/**
* Returns the FileFormat of this database (which may involve inspecting the
* database itself).
return format.CHARSET;
}
+ /**
+ * Returns the default Table.ColumnOrder. This defaults to
+ * {@link #DEFAULT_COLUMN_ORDER}, but can be overridden using the system
+ * property {@value #COLUMN_ORDER_PROPERTY}.
+ */
+ public static Table.ColumnOrder getDefaultColumnOrder()
+ {
+ String coProp = System.getProperty(COLUMN_ORDER_PROPERTY);
+ if(coProp != null) {
+ coProp = coProp.trim();
+ if(coProp.length() > 0) {
+ return Table.ColumnOrder.valueOf(coProp);
+ }
+ }
+
+ // use default order
+ return DEFAULT_COLUMN_ORDER;
+ }
+
/**
* Copies the given InputStream to the given channel using the most
* efficient means possible.
/** Table type code for user tables */
public static final byte TYPE_USER = 0x4e;
- /** comparator which sorts variable length columns vased on their index into
+ /** enum which controls the ordering of the columns in a table. */
+ public enum ColumnOrder {
+ /** columns are ordered based on the order of the data in the table (this
+ order does not change as columns are added to the table). */
+ DATA,
+ /** columns are ordered based on the "display" order (this order can be
+ changed arbitrarily) */
+ DISPLAY;
+ }
+
+ /** comparator which sorts variable length columns based on their index into
the variable length offset table */
private static final Comparator<Column> VAR_LEN_COLUMN_COMPARATOR =
new Comparator<Column>() {
}
};
+ /** comparator which sorts columns based on their display index */
+ private static final Comparator<Column> DISPLAY_ORDER_COMPARATOR =
+ new Comparator<Column>() {
+ public int compare(Column c1, Column c2) {
+ return ((c1.getDisplayIndex() < c2.getDisplayIndex()) ? -1 :
+ ((c1.getDisplayIndex() > c2.getDisplayIndex()) ? 1 :
+ 0));
+ }
+ };
+
/** owning database */
private final Database _database;
/** Type of the table (either TYPE_SYSTEM or TYPE_USER) */
int colOffset = getFormat().OFFSET_INDEX_DEF_BLOCK +
_indexCount * getFormat().SIZE_INDEX_DEFINITION;
+ int dispIndex = 0;
for (int i = 0; i < columnCount; i++) {
Column column = new Column(this, tableBuffer,
- colOffset + (i * getFormat().SIZE_COLUMN_HEADER));
+ colOffset + (i * getFormat().SIZE_COLUMN_HEADER), dispIndex++);
_columns.add(column);
if(column.isVariableLength()) {
// also shove it in the variable columns list, which is ordered
// reset to end of index info
tableBuffer.position(idxEndOffset);
+
+ // re-sort columns if necessary
+ if(getDatabase().getColumnOrder() != ColumnOrder.DATA) {
+ Collections.sort(_columns, DISPLAY_ORDER_COMPARATOR);
+ }
}
/**