From: James Ahlborn Date: Wed, 3 Nov 2010 12:58:43 +0000 (+0000) Subject: allow column order in tables to be configured (fixes #3097387) X-Git-Tag: jackcess-1.2.2~7 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ab5fead7ce3b2aed414e72e141d6a1b8fdd9e75d;p=jackcess.git allow column order in tables to be configured (fixes #3097387) git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@497 f203690c-595d-4dc9-a70b-905162fa7fd2 --- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4e6b33b..e5f4c95 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -20,6 +20,9 @@ Implement some tweaks which allow jackcess to be used on the Android platform. (thanks to Miha Pirnat). + + Allow column order in tables to be configured. + diff --git a/src/java/com/healthmarketscience/jackcess/Column.java b/src/java/com/healthmarketscience/jackcess/Column.java index 1eba865..0593a4b 100644 --- a/src/java/com/healthmarketscience/jackcess/Column.java +++ b/src/java/com/healthmarketscience/jackcess/Column.java @@ -145,6 +145,8 @@ public class Column implements Comparable { 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 */ @@ -178,10 +180,11 @@ public class Column implements Comparable { * @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)); } @@ -259,6 +262,10 @@ public class Column implements Comparable { _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 diff --git a/src/java/com/healthmarketscience/jackcess/Database.java b/src/java/com/healthmarketscience/jackcess/Database.java index 124fa70..c15977b 100644 --- a/src/java/com/healthmarketscience/jackcess/Database.java +++ b/src/java/com/healthmarketscience/jackcess/Database.java @@ -104,6 +104,10 @@ public class Database 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 = @@ -131,6 +135,12 @@ public class Database 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, @@ -349,6 +359,8 @@ public class Database 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 @@ -641,6 +653,7 @@ public class Database _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); @@ -759,6 +772,26 @@ public class Database _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). @@ -1561,6 +1594,25 @@ public class Database 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. diff --git a/src/java/com/healthmarketscience/jackcess/Table.java b/src/java/com/healthmarketscience/jackcess/Table.java index 36f7c66..f6e7541 100644 --- a/src/java/com/healthmarketscience/jackcess/Table.java +++ b/src/java/com/healthmarketscience/jackcess/Table.java @@ -69,7 +69,17 @@ public class Table /** 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 VAR_LEN_COLUMN_COMPARATOR = new Comparator() { @@ -80,6 +90,16 @@ public class Table } }; + /** comparator which sorts columns based on their display index */ + private static final Comparator DISPLAY_ORDER_COMPARATOR = + new Comparator() { + 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) */ @@ -1069,9 +1089,10 @@ public class Table 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 @@ -1149,6 +1170,11 @@ public class Table // 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); + } } /**